c - 在 C 中以流方式读取和处理内存中的 XML 数据

标签 c xml

下面是原始问题,如果有人遇到类似问题,请更新有关解决方案:

对于快速正则表达式,我找到了 http://re2c.org/ ;用于 xml 解析 http://expat.sourceforge.net/


是否有一个 xml 库可以用来在 c 中以流方式从内存(而不是文件)解析 xml?

目前我有:

  • libxml2 ; XMLReader 似乎只能与文件句柄一起使用,而不是在内存中使用
  • rapidxml 是 c++ 并且似乎没有公开 c 接口(interface)

要求:

  • 我需要处理单个 xml 节点,而不需要将整个 xml(400GB 未压缩,“只有”29GB 作为原始 .bz2 文件)存储在内存中(bzip 文件被读入并分段解压,我会传递那些xml 解析器使用的未压缩片段)
  • 不需要非常快,但我更喜欢高效的解决方案
  • 我(很可能)不需要提取节点的路径,所以只要它们被我的回调处理过就丢弃它们就可以了(如果我需要与我想的相反的路径现在,我仍然可以自己追踪它)

这是我试图解决我自己的问题的一部分(不,这不是同一个问题):How to efficiently parse large bz2 xml file in C

理想情况下,我希望能够一次为库提供一定数量的字节,并在节点完成时调用一个函数。

非常感谢


为了更好地理解,这里有一些伪 C 代码(比实际的 C 代码短得多)

// extracted data gets put here
strm.next_out = buffer_ptr;

while( bytes_processed_total < filesize ) {

  // extracts up to amount of data set in strm.avail_in
  BZ2_bzDecompress( strm );

  bytes_processed = strm.next_out - buffer_ptr;
  bytes_processed_total += bytes_processed;

  // here I would like to pass bytes_processed of buffer_ptr to xmlreader

}

关于我要解析的数据:http://wiki.openstreetmap.org/wiki/OSM_XML

目前我只需要某些<node ...>来自此的节点,其中有子节点 <tag k="place" v="country|county|city|town|village"> (“|”在此上下文中至少表示其中一个,在文件中它当然只是“国家”等而没有“|”)

最佳答案

libxml2 中的 xmlReaderForMemory 对我来说似乎是个不错的选择(但还没有用过,我可能错了)

char * 缓冲区需要指向一个有效的 XML 文档(它可以是整个 XML 文件的一部分)。这可以提取成 block 读取您的文件,但获得有效的 XML 片段。

您的 XML 文件的结构是什么?包含后续相似节点的根还是完全成熟的树?

如果我有这样的 XML:

<root>
<node>...</node>
<node>...</node>
<node>...</node>
</root>

我会从开头开始阅读 <node>至收盘</node>然后用 xmlReaderForMemory 函数解析它,做我需要做的,然后继续下一个 <node>节点。

Ofc 如果你的 <node>内容太复杂/太长,你可能需要深入一些层次:

<node>
<subnode>....</subnode>
<subnode>....</subnode>
<subnode>....</subnode>
<subnode>....</subnode>
</node>

然后从文件中读取直到拥有整个 <subnode>节点(但要跟踪您在 <node> 中。

我知道这很丑陋,但却是一种可行的方式。或者您可以尝试使用 sax 解析器(不知道是否存在某些 C 实现)。

Sax 解析会在每个节点开始和节点结束时触发事件,因此在找到您的节点并只处理它们之前,您什么都不做。

另一种可行的方法是使用一些外部工具来过滤整个 XML(XQuery 或 XPath 处理器),以便从整个文件中提取您感兴趣的节点,获得一个较小的文档,然后对其进行处理。

编辑:Zorba 是一个很好的 XQuery 框架,带有命令行预处理器,可能是个不错的地方

EDIT2:好吧,既然你有这个维度,一个替代解决方案可以将文件作为文本文件来管理,所以读取和解压缩 block ,然后匹配类似的东西:

<yourNode>.*</yourNode>

使用正则表达式。

如果您使用的是 Linux/Unix,您应该拥有 POSIX 正则表达式库。检查
this question on S.O.以获得进一步的见解。

关于c - 在 C 中以流方式读取和处理内存中的 XML 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18512207/

相关文章:

javascript - 如何创建包含 CDATA 的 xml 元素

c - WSAStartup 函数如何启动 Winsock DLL 的使用?

C...字符串分割问题

c - OpenCL本地工作本地内存

java - 如何在 java 代码中读取 View 的 android 默认属性

python - : in node causing Keyerror in xmlparsing using ElementTree

c++ - 可以在 C/C++ 中声明但不定义局部变量吗?

c - 将非静态内联函数重新声明为 extern

android - 如何使用多个旋转标签正确形成动画 xml

java - 如何设计正确的 XML 并根据请求名称检索值?