我目前必须修复现有应用程序以使用DOM interface libxml2以外的其他内容,因为事实证明它传递的XML文件太大而无法加载到内存中。< / p>
我已经重复了从迭代DOM树到大部分时间使用xmlTextReader的数据加载,而没有太多问题。 (我使用xmlNewTextReaderFilename
打开本地文件。)
然而,事实证明,大数据所在的子树必须不按顺序读取,但我必须先收集一些(少量)数据。 (问题正是这个子树包含大量数据,所以只将这个子树加载到内存中也没有多大意义。)
最简单的方法就是“克隆”/“复制”我当前的读者,提前读取然后返回原始实例继续阅读。 (似乎我not the first one ......在C#方面甚至实现了一些东西:XML Reader with Bookmarks。)
然而,似乎没有办法“复制”xmlTextReader的状态。
如果我无法重新读取文件的部分,我还可以重新阅读整个文件,虽然这很浪费,但在这里可以,但是我还需要记住我之前的位置吗?
是否有一种简单的方法可以记住xmlTextReader在当前文档中的位置,以便稍后在第二次阅读文档/文件时再次找到该位置?
这是一个问题示例:
<root>
<cat1>
<data attrib="x1">
... here goes up to one GB in stuff ...
</data>
<data attrib="y2"> <!-- <<< Want to remember this position without having to re-read the stuff before -->
... even more stuff ...
</data>
<data attrib="z3">
<!-- I need (part of) the data here to meaningfully interpret the data in [y2] that
came before. The best approach would seem to first skip all that data
and then start back there at <data attrib="y2"> ... not having to re-read
the whole [x1] data would be a big plus! -->
</data>
</cat1>
...
</root>
答案 0 :(得分:1)
我想从我learned at the XML mailing list:
中给出一个解决方法的答案没有简单的方法可以在xmlReader上“克隆”状态,但是应该可以做什么,也应该很简单就是计算文档上的读取数。
也就是说,要使用xmlReader读取文档,您必须调用以下内容:
// looping ...
status = ::xmlTextReaderRead(pReader);
如果您以结构化方式执行此操作(例如,我最终编写了一个封装我的xmlReader使用模式的封装类),则添加计数器相对容易:
// looping ...
status = ::xmlTextReaderRead(pReader);
if (1 == status) { // success
++m_ReadCounter;
}
要重新阅读文档(到达某个位置),您只需致电xmlTextReaderRead
多次m_ReadCounter
次,弃置结果,直至到达您想要重新开始的位置。
是的,您必须重新解析整个文档,但这可能足够快。 (实际上可能比缓存文档的大量部分更好/更快。)