【发布时间】:2014-04-19 02:55:18
【问题描述】:
我正在尝试使用 xerces-c 来解析从 StarUML 生成的相当庞大的 XML 文档以更改某些内容,但我遇到了让 xpath 查询工作的问题,因为它一直在崩溃。
为了简化操作,我将文件的一部分拆分为一个较小的 XML 文件进行测试,如下所示:
<?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>
对于这个例子,我要做的就是找到所有的XPD:OBJ 元素,其中只有一个。问题似乎源于尝试使用命名空间进行查询。当我传递一个非常简单的XPD:OBJ xpath 查询时,它会崩溃,但如果我只传递OBJ,它不会崩溃,但它不会找到XPD:OBJ 元素。
我假设在初始化期间我缺少一些重要的属性或设置,我需要设置但我不知道它可能是什么。我查找了与命名空间有关的解析器的所有属性,并启用了我可以使用的属性,但它根本没有帮助,所以我完全被卡住了。初始化代码看起来像这样,显然删除了很多东西:
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 查询,以防出现明显错误:
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);
对evaluate() 的调用是它在xerces 深处的某个地方崩溃的地方,我看不清楚,但据我所知,有很多东西看起来已删除或未初始化,所以我不确定是什么正是导致崩溃。
那么这里有什么看起来明显错误或缺失的东西是使 xerces 与 XML 命名空间一起工作所必需的吗?
【问题讨论】:
标签: c++ xml xpath namespaces xerces