Xerces, xpaths, and XML namespaces
我正在尝试使用xerces-c来解析从StarUML生成的相当大的XML文档以更改某些内容,但是我遇到了使xpath查询正常工作的问题,因为它一直崩溃。
为简化起见,我将文件的一部分分成一个较小的XML文件进行测试,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <XPD:UNIT xmlns:XPD="http://www.staruml.com" version="1"> <XPD:HEADER> <XPD:SUBUNITS> </XPD:SUBUNITS> </XPD:HEADER> <XPD:BODY> <XPD:OBJ name="Attributes[3]" type="UMLAttribute" guid="onMjrHQ0rUaSkyFAWtLzKwAA"> <XPD:ATTR name="StereotypeName" type="string">ConditionInteraction</XPD:ATTR> </XPD:OBJ> </XPD:BODY> </XPD:UNIT> |
在此示例中,我要做的就是查找所有
我认为我需要设置一些重要的属性或设置,但我不知道它可能是什么。我查找了与名称空间有关的解析器的所有属性,并启用了那些我可以使用的属性,但是它根本没有帮助,所以我完全陷入了困境。初始化代码看起来像这样,明显地删除了很多东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | const tXercesXMLCh tXMLManager::kDOMImplementationFeatures[] = { static_cast<tXercesXMLCh>('L'), static_cast<tXercesXMLCh>('S'), static_cast<tXercesXMLCh>('\\0') }; // Instantiate the DOM parser. fImplementation = static_cast<tXercesDOMImplementationLS *>(tXercesDOMImplementationRegistry::getDOMImplementation(kDOMImplementationFeatures)); if (fImplementation != nullptr) { fParser = fImplementation->createLSParser(tXercesDOMImplementationLS::MODE_SYNCHRONOUS, nullptr); fConfig = fParser->getDomConfig(); // Let the validation process do its datatype normalization that is defined in the used schema language. //fConfig->setParameter(tXercesXMLUni::fgDOMDatatypeNormalization, true); // Ignore comments and whitespace so we don't get extra nodes to process that just waste time. fConfig->setParameter(tXercesXMLUni::fgDOMComments, false); fConfig->setParameter(tXercesXMLUni::fgDOMElementContentWhitespace, false); // Setup some properties that look like they might be required to get namespaces to work but doesn't seem to help at all. fConfig->setParameter(tXercesXMLUni::fgXercesUseCachedGrammarInParse, true); fConfig->setParameter(tXercesXMLUni::fgDOMNamespaces, true); fConfig->setParameter(tXercesXMLUni::fgDOMNamespaceDeclarations, true); // Install our custom error handler. fConfig->setParameter(tXercesXMLUni::fgDOMErrorHandler, &fErrorHandler); } |
然后稍后我解析文档,找到根节点,然后运行xpath查询以找到所需的节点。我将忽略其中的大部分内容,仅向您显示我在哪里运行xpath查询,以防万一那里有明显的错误:
1 2 3 4 5 | tXercesDOMDocument * doc; // Comes from parsing the file. tXercesDOMNode * contextNode; // This is the root node retrieved from the document. tXercesDOMXPathResult * xPathResult; doc->evaluate("XPD:OBJ", contextNode, nullptr, tXercesDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE), xPathResult); |
那么在这里是否存在使xerces与XML名称空间一起使用所需的任何明显错误或遗漏的东西?
解决方案一直都在我的面前。问题是您需要创建一个解析器并将其传递给
因此,为了解决该问题,我将调用稍微更改为
1 2 3 4 5 6 7 8 9 10 11 12 | tXercesDOMDocument * doc; // Comes from parsing the file. tXercesDOMNode * contextNode; // This is the root node retrieved from the document. tXercesDOMXPathResult * xPathResult; // Create the resolver with the root node, which contains the namespace definition. tXercesDOMXPathNSResolver * resolver(doc->createNSResolver(contextNode)); doc->evaluate("XPD:OBJ", contextNode, resolver, tXercesDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE), xPathResult); // Make sure to release the resolver since anything created from a `create___()` // function has to be manually released. resolver->release(); |