#include #include #include #include "xmlpromptgenerator.h" #include "xmlencodinghandler.h" #include "readfile.h" #include "replace.h" #include "getword.h" #include "pathresolver.h" #include "catalogresolver.h" #include "xmlschemaparser.h" XmlPromptGenerator::XmlPromptGenerator( const std::string& catalogPath, const std::string& basePath, const std::string& auxPath) : d(new PromptGeneratorData()) { XML_SetUserData(p, d.get()); d->p = p; d->catalogPath = catalogPath; d->auxPath = auxPath; d->elementDeclRecurseLevel = 0; d->rootElement = true; d->dtdFound = false; XML_SetParamEntityParsing(p, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); XML_SetElementHandler(p, starthandler, endhandler); XML_SetDoctypeDeclHandler(p, doctypedeclstarthandler, doctypedeclendhandler); XML_SetElementDeclHandler(p, elementdeclhandler); XML_SetAttlistDeclHandler(p, attlistdeclhandler); XML_SetEntityDeclHandler(p, entitydeclhandler); XML_SetExternalEntityRefHandlerArg(p, d.get()); XML_SetExternalEntityRefHandler(p, externalentityrefhandler); XML_SetBase(p, basePath.c_str()); if (!auxPath.empty()) XML_UseForeignDTD(p, true); } XmlPromptGenerator::~XmlPromptGenerator() { } void XMLCALL XmlPromptGenerator::starthandler( void *data, const XML_Char *el, const XML_Char **attr) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; d->push(el); std::string parent, element; parent = d->getParent(); element = el; // update elementMap if (d->elementMap.find(parent) == d->elementMap.end()) { std::set childSet; childSet.insert(element); d->elementMap.insert(make_pair(parent, childSet)); } else d->elementMap[parent].insert(element); std::string attributeName, attributeValue; // update attributeMap // case 1: element unknown, no attributes if (!(*attr) && d->attributeMap.find(element) == d->attributeMap.end()) { std::map > currentAttributeMap; d->attributeMap.insert(make_pair(element, currentAttributeMap)); } for (; *attr; attr += 2) { attributeName = *attr; attributeValue = *(attr + 1); d->attributeMap[element][attributeName].insert(attributeValue); /* // TBD: may not be xsi: check for http://www.w3.org/2001/XMLSchema-instance while (d->rootElement && strstr((const char *)attr, "xsi:noNamespaceSchemaLocation")) { std::string schemaPath = PathResolver::run(attributeValue, d->auxPath); std::string buffer; if (!ReadFile::run(schemaPath, buffer)) break; XmlSchemaParser xsp(d, true); if (!xsp.parse(buffer)) break; XML_StopParser(d->p, false); return; } */ } d->rootElement = false; } void XMLCALL XmlPromptGenerator::endhandler(void *data, const XML_Char *el) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; d->pop(); } bool XmlPromptGenerator::getDtdFound() { return d->dtdFound; } void XmlPromptGenerator::getAttributeMap( std::map > > &attributeMap) { attributeMap = d->attributeMap; } void XmlPromptGenerator::getRequiredAttributeMap( std::map >& requiredAttributeMap) { requiredAttributeMap = d->requiredAttributeMap; } void XmlPromptGenerator::getElementMap( std::map > &elementMap) { elementMap = d->elementMap; } void XmlPromptGenerator::getEntitySet( std::set &entitySet) { entitySet = d->entitySet; } // handlers for DOCTYPE handling void XMLCALL XmlPromptGenerator::doctypedeclstarthandler( void *data, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; } void XMLCALL XmlPromptGenerator::doctypedeclendhandler(void *data) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; if (!d->elementMap.empty()) { d->dtdFound = true; XML_StopParser(d->p, false); } } void XMLCALL XmlPromptGenerator::elementdeclhandler( void *data, const XML_Char *name, XML_Content *model) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; d->elementDeclRecurseLevel += 1; std::string myElement = name; unsigned num = model->numchildren; for (unsigned i = 0; i < num; i++) { XML_Content myContent = model->children[i]; XML_Char *myName = myContent.name; if (myName) d->elementMap[myElement].insert((const char *)myName); else { // recurse XmlPromptGenerator::elementdeclhandler((void *)d, name, &myContent); } } d->elementDeclRecurseLevel -= 1; // only one call to XML_FreeContentModel per content tree if (d->elementDeclRecurseLevel == 0) { XML_FreeContentModel(d->p, model); } } void XMLCALL XmlPromptGenerator::attlistdeclhandler( void *data, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; std::set attributeValues; if (*att_type == '(') // change to exclude _known_ identifiers? { size_t len; char *s, *word; s = (char *)att_type; while ((word = GetWord::run(&s, &len)) != NULL) { std::string currentValue(word, len); attributeValues.insert(currentValue); } } if (attributeValues.empty()) { d->attributeMap[elname][attname].insert(""); return; } std::set::iterator it; for (it = attributeValues.begin(); it != attributeValues.end(); it++) d->attributeMap[elname][attname].insert(*it); if (isrequired) { d->requiredAttributeMap[elname].insert(attname); } } int XMLCALL XmlPromptGenerator::externalentityrefhandler( XML_Parser p, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId) { PromptGeneratorData *d; d = (PromptGeneratorData *)p; // arg is set to user data in c'tor std::string buffer; // auxPath req'd? if (!systemId && !publicId) { ReadFile::run(d->auxPath, buffer); if (buffer.empty()) { return false; } std::string encoding = XmlEncodingHandler::get(buffer); XML_Parser dtdParser = XML_ExternalEntityParserCreate(d->p, context, encoding.c_str()); if (!dtdParser) return false; XML_SetBase(dtdParser, d->auxPath.c_str()); return XML_Parse(dtdParser, buffer.c_str(), buffer.size(), true); } std::string stdPublicId; if (publicId) stdPublicId = publicId; std::string stdSystemId = CatalogResolver::lookupPublicId(stdPublicId, d->catalogPath); if (stdSystemId.empty() && systemId) stdSystemId = systemId; Replace::run(stdSystemId, "file:///", "", false); Replace::run(stdSystemId, "%20", " ", false); if (base) { std::string test = PathResolver::run(stdSystemId, base); if (!test.empty()) { stdSystemId = test; } } if (!stdSystemId.empty()) { ReadFile::run(stdSystemId, buffer); } std::string encoding = XmlEncodingHandler::get(buffer); XML_Parser dtdParser = XML_ExternalEntityParserCreate(d->p, context, encoding.c_str());//"UTF-8"); if (!dtdParser) return false; wxString wideName, wideDir; wideName = wxString(stdSystemId.c_str(), wxConvUTF8, stdSystemId.size()); wxFileName fn(wideName); wideDir = fn.GetPath(); XML_SetBase(dtdParser, wideName.mb_str(wxConvUTF8)); return XML_Parse(dtdParser, buffer.c_str(), buffer.size(), true); } void XMLCALL XmlPromptGenerator::entitydeclhandler( void *data, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName) { PromptGeneratorData *d; d = (PromptGeneratorData *)data; // arg is set to user data in c'tor if ( entityName && !is_parameter_entity && !systemId && !publicId && !notationName) { d->entitySet.insert(entityName); } }