2

我正在使用 R 中的 xml2 包解析一些非常大的 xml 文件。 read_xml() 成功加载了大文件,但是当我尝试使用 xml_find_all() 时,我得到“错误:内存分配失败:不断增长的节点集命中限制”。我假设这个限制是在 libxml2 中设置的,也许在 XPATH_MAX_NODESET_LENGTH 变量中?所以也许这不是 xml2 包本身的问题。但是在 xml2 中是否有可能的解决方案?我尝试删除节点并释放内存,但没有运气。谢谢。

4

1 回答 1

5

是的,您达到了libxml2 XPath 引擎的硬编码节点集限制。来自xpath.c:

/*
 * XPATH_MAX_NODESET_LENGTH:
 * when evaluating an XPath expression nodesets are created and we
 * arbitrary limit the maximum length of those node set. 10000000 is
 * an insanely large value which should never be reached under normal
 * circumstances, one would first need to construct an in memory tree
 * with more than 10 millions nodes.
 */
#define XPATH_MAX_NODESET_LENGTH 10000000

一种选择是使用不同的值重新编译libxml2 。或者您可以更改您的 XPath 表达式,以便它们永远不会遇到大于 10M 节点的节点集。请注意,此限制也适用于在计算表达式期间创建的中间节点集。所以,不幸的是,用谓词分割节点集是行不通的:

//element[position() < 5000000]
//element[position() >= 5000000 and position() < 10000000]
//element[position() >= 10000000 and position() < 15000000]

本质上,您必须确保每个NodeTest返回的节点数不超过 10M。如果你不能做到这一点,那么可悲的是,你运气不好。

您也可以在libxml2邮件列表中提出这个问题。我猜想引入这个限制是为了防止可能导致拒绝服务攻击的恶意 XPath 表达式。但在我看来,表达式永远不会返回比输入文档中更多的节点。因此,用于节点集的最大内存量无论如何都会受到输入文档大小的限制。

于 2016-10-21T12:12:49.117 回答