繁体   English   中英

XML解析使用libxml2生成重复项

[英]XML Parsing results in Duplicates using libxml2

我正在使用libxml2解析以下XML字符串:

<?xml version=\"1.0\"?>
<note>
    <to>
        <name>Tove</name>
        <name>Tovi</name>
    </to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
</note>

格式化为C风格的字符串:

"<?xml version=\"1.0\"?><note><to><name>Tove</name><name>Tovi</name></to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"

这是基于W3C网站上有关XML的示例。 我只在“到”字段中添加了嵌套名称。

我在C ++中具有以下递归代码,将其解析为对象树:

RBCXMLNode * RBCXMLDoc::recursiveProcess(xmlNodePtr node) {
    RBCXMLNode *rNode = new RBCXMLNode();
    xmlNodePtr childIterator = node->xmlChildrenNode;

    const char *chars = (const char *)(node->name);
    string name(chars);
    const char *content = (const char *)xmlNodeGetContent(node);
    rNode->setName(name);
    rNode->setUTF8Data(content);
    cout << "Just parsed " << rNode->name() << ": " << rNode->stringData() << endl;
    while (childIterator != NULL) {
        RBCXMLNode *rNode2 = recursiveProcess(childIterator);
        rNode->addChild(rNode2);
        childIterator = childIterator->next;
    }
    return rNode;
}

因此,它为每个节点创建匹配的对象,设置其名称和内容,然后为其子代递归。 请注意,每个节点仅处理一次。 但是,我得到以下(至少对我来说是荒谬的)输出:

只是分析了笔记:ToveToviJaniReminder这个周末别忘了我!
刚刚解析为:ToveTovi
刚解析的名称:Tove
刚解析的文字:托夫
刚刚解析过的名字:Tovi
刚刚解析的文本:Tovi
刚刚从解析:Jani
刚刚解析的文本:Jani
刚解析标题:提醒
刚解析的文字:提醒
只是剖析了身体:这个周末别忘了我!
刚解析的文字:本周末不要忘记我!

请注意,每个项目都要被解析两次; 一旦将名称命名为“文本”,并将其命名为“应该是什么”。 同样,“ note”根节点也正在解析其数据。 这是不可取的。 另请注意,此根节点不会像其他节点一样被解析两次。

所以我有两个问题:

  1. 如何避免解析根节点的数据,而只知道其名称而不是其内容? 据推测,这也将在更深层嵌套的节点上发生。
  2. 如何避免在其他节点上进行重复解析? 显然,我希望保留正确命名的版本,同时保持(实际上)将节点实际命名为“文本”的可能性。 同样,可能存在所需的重复节点,因此仅检查是否已解析该节点不是一种选择。

提前致谢。

我在你的代码中看到的主要问题是你正在调用xmlNodeGetContent() 这将返回标签内部的整个文本及其结尾对应部分。

使用libxml2解析时,您会得到一些内容复杂的节点,因此您不能依赖xmlNodeGetContent()来检索内容。 您必须以不同方式执行递归功能。 例如,对您的函数而言,最快的解决方案是仅打印非文本节点的节点名称(使用xmlNodeIsText()测试),并仅为文本节点编写xmlNodeGetContent() 这会给你一个类似的输出:

Just parsed note
Just parsed to
Just parsed name
Just parsed text: Tove
Just parsed name
Just parsed text: Tovi
...

请注意,现在您只打印元素, 并且只有文本元素类型时才显示文本。

从概念上讲,这也是有意义的,因为非文本节点(非文本)的内容是如此复杂,以至于您如何打印它? 您只能打印其标签(名称)。 但是,文本节点非常简单,您可以打印其内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM