【问题标题】:Most efficient data structure to store an XML tree in C++在 C++ 中存储 XML 树的最有效数据结构
【发布时间】:2017-08-24 17:10:42
【问题描述】:

我正在使用 C++ 中的 XML 做一些工作,我想知道存储 XML 数据的最佳数据结构是什么。请不要只告诉我你过去听说过什么;我想知道最有效的结构是什么。我希望能够以最小的内存开销和查找时间存储任意 XML 树(假设它是有效的)。

我最初的想法是一个哈希,但我不知道如何处理同一个标签的多个孩子,以及如何处理属性。

Qt 解决方案是可以接受的,但我更关心整体结构而不是特定库。感谢您的意见。

【问题讨论】:

  • 给定一个根节点,我想找到给定标签的所有元素,然后对每个元素执行一些操作。像 Javascript 的 getElementsByTagName 和 getElementById 这样的东西会很理想。
  • 最好是什么意思?建造速度最快?最快访问? (以什么方式?) 最小的?最容易实施?最适合导航?最适合小型文档,最适合大型文档?您需要说明一些要求。

标签: c++ xml qt


【解决方案1】:

最有效的结构是从 DTD 或 Schema 派生的一组类,这些类定义了您要处理的特定 XML 实例。 (您肯定不会处理任意 XML?)标签由类表示。单个孩子可以用字段来表示。具有 min...max arity 的子级可以由包含数组的字段表示。具有不定元数的子代可以由动态分配的数组来表示。属性和子项可以存储为字段,通常具有推断的数据类型(如果属性表示数字,为什么将其存储为字符串?)。使用这种方法,您通常可以使用原生 C++ 访问路径导航到 XML 文档中的特定位置,例如, root->tag1.itemlist[1]->description.

所有这些都可以从 Schema 或 DTD 中自动生成。有工具可以做到这一点。 Altova 提供一些。我没有这方面的具体经验(尽管我为 Java 和 COBOL 构建了类似的工具)。

【讨论】:

  • 这听起来很有趣。有没有办法在运行时动态创建这些对象?你能把我链接到这些工具吗?谢谢。
  • @Zach Ratter:修改答案以提供指向一个供应商的链接。您不能在运行时创建此类对象,因为它们使用编译时生成的类型。您当然可以在运行时模拟此类对象,方法是创建一个将字段名称字符串与值相关联的类,但这可能效率不高。如果您同意将子项存储在数组中,将标签名称与数组插槽相关联,并以最少的次数查找每个标签名称整数,则您可以在此妥协。但由于您的 XML 不太可能是动态的,因此“编译”DTD/Schema 很有意义。
【解决方案2】:

您应该首先确定对效率的要求是什么,具体数字是存储、速度等。在不知道这些信息的情况下,您无法判断您的实现是否满足要求。

而且,如果您有这个要求,您可能会发现 DOM 满足它,并且具有零代码维护的优势。

这对于未来的程序员来说将是一场噩梦,因为他们想知道为什么有人要编写 DOM 的替代实现。

实际上,您所做的几乎所有事情都只是一个 DOM 实现,但可能是不完整的,并且对索引等进行了优化。我个人的感觉是,重新发明轮子应该是您最后考虑的事情。

【讨论】:

  • 我想要的所有功能都由 DOM 提供。你知道 C++ 的任何 DOM 实现吗?
【解决方案3】:

已经建立了一个 C++ XML 库:xerces。 http://xerces.apache.org/xerces-c/install-3.html

\include\boost-1_46_1\boost\intrusive\ 中有一些树结构 有一个红黑和一个avl树,但是好久没看,不知道是不是特别好用,我觉得没有。

XML 是一个树形结构。你不知道结构将是什么,除非它定义了一个 DTD 并将其包含在 a 中(尽管 validrome 的验证器在 !DOCTYPEs 上中断并且它不应该)。

查看http://w3schools.com/xml/xml_tree.asp 获取树示例。

您可能会得到不遵循 DTD 或架构的东西。完全非结构化。像这样:

<?xml version="1.0"?>
<a>
 <b>hello
  <e b="4"/>
  <c a="mailto:jeff@nowhere.com">text</c>
 </b>
 <f>zip</f>
 <z><b /><xy/></z>
 <zook flag="true"/>
 <f><z><e/></z>random</f>
</a>

我知道确实存在可查询的 XML 数据库,但我对它们了解不多,只知道它们可以处理非结构化数据。

PHP 有一个 XML 解析器,它将它粘贴到 PHP 所称的数组中(不太像 C/C++ 数组,因为数组可以有数组),您可以修改它以查看 XML 数据结构的示例应该有。

您基本上想要的是一个非常灵活的树,其中根指针指向一个列表。列表中的每个节点都包含一个可以指向列表的指针。它应该是一个有序列表,所以将其设为 .如果您的目的是能够删除数据,请使用 a 而不是 a - 它是有序的,同时具有易于操作的能力。

警告:.erase(iterator i) 擦除从 i 开始和之后的所有内容。 .erase(iterator i1, iterator i2) 擦除从 i1 到但不包括 i2 的所有内容。 .end() 是一个迭代器,它指向列表末尾之后的 1,基本上什么都没有。 .begin() 是一个指向列表开头的迭代器。

学习使用 for_each(start,end,function) { } 或使用常规 for 语句。

迭代器就像指针。这样对待他们。

#include <iterator>
#include <list>
#include <iostream>
using namespace std;
list<class node> nodelist;
list<class node>::iterator nli;
for (nli=nodelist.begin(); nli!=nodelist.end(); nli++) {
    cout<<nli->getData()<<endl;
}

节点需要有一个可选的属性列表,并注意 DTD 可能包含在 XML 文档中,因此您必须能够读取它来解析文档(或者您可以将其丢弃)。你也可能会遇到 XML Schema,DTD 的继承者。

【讨论】:

    【解决方案4】:

    我认为存储 xml 的最有效的数据结构可能是 vtd-xml,它使用 long 数组而不是许多相互连接的结构/类。主要思想是结构/类基于小型内存分配器,在正常情况下会产生严重的开销。有关详细信息,请参阅本文。

    http://soa.sys-con.com/node/250512

    【讨论】:

      【解决方案5】:

      我不确定最有效的方法是什么,但既然 DOM 已经存在,为什么要重新发明轮子?

      按名称散列所有节点以进行查找可能有意义,但您仍应使用 DOM 作为基本表示。

      【讨论】:

        【解决方案6】:

        我自己一直在探索这个问题。而且,这些是我的想法。

        a) xml 中的每个元素要么是一个节点,要么是一个(键,值)对。 b)将每个元素存储在哈希中。为每个元素分配一个类型,即“节点”、“键、值”。 c) 每个元素都有一个父元素。为它们中的每一个分配一个值。 d) 每个元素可能或可能没有子/引用。将孩子存储在将定义引用的 btree 中。

        任何键的搜索时间都是 O(1)。引用遍历可以有一个元素内所有子元素的列表。

        请查看并提出我错过的内容。

        【讨论】:

          【解决方案7】:

          只需使用 DOM 来存储解析后的 XML 文件。肯定有 C++ DOM 库。 您可以使用 XPath 表达式查询 DOM。

          【讨论】:

          • 那是什么让你认为这是高效的?
          • DOM API 的效率取决于 api 的供应商。还有其他因素,例如 XML 文件的大小,但 Zach 没有提供任何细节。 Zach 也要求“最”高效。你真的认为有一种最有效的方法(其他方法更好)吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-27
          • 1970-01-01
          • 2022-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多