我正在寻找一个不会重建整个 DOM 文档以查找文档节点的 XPath 评估器:实际上,该对象是使用 SAX 模型管理大量 XML 数据(理想情况下超过 2Gb),这非常有利于内存管理,并提供搜索节点的可能性。
谢谢大家的支持!
对于所有说不可能的人:我最近在问了这个问题后,找到了一个名为“saxpath”的项目(http://www.saxpath.org/),但我找不到任何实施项目。
我正在寻找一个不会重建整个 DOM 文档以查找文档节点的 XPath 评估器:实际上,该对象是使用 SAX 模型管理大量 XML 数据(理想情况下超过 2Gb),这非常有利于内存管理,并提供搜索节点的可能性。
谢谢大家的支持!
对于所有说不可能的人:我最近在问了这个问题后,找到了一个名为“saxpath”的项目(http://www.saxpath.org/),但我找不到任何实施项目。
我当前的列表(根据网络搜索结果和其他答案编译)是:
下一步是使用 XMLDog 的示例并比较所有这些方法的性能。然后,测试用例应该扩展到支持的 XPath 表达式。
我们定期使用 SAX 解析器解析 1GB+ 复杂的 XML 文件,该解析器提取可以使用 XPath 方便地查询的部分 DOM 树。我在这里写了博客:http: //softwareengineeringcorner.blogspot.com/2012/01/conveniently-processing-large-xml-files.html - github上提供了源代码- MIT 许可证。
XPath 确实可以与 SAX 一起使用,并且大多数 XSLT 处理器(尤其是 Saxon 和 Apache Xalan)确实支持在 SAX 流上的 XSLT 内执行 XPath 表达式,而无需构建整个 dom。
他们非常粗略地做到了这一点,如下所示:
他们如何缓冲它也很有趣,因为有些人只是在这里和那里创建 DOM 片段,而另一些人则使用非常优化的表来快速查找并减少内存消耗。
他们设法优化多少很大程度上取决于他们找到的 XPath 查询类型。正如已经发布的撒克逊文档清楚地解释的那样,“向上”移动然后“水平”遍历文档的查询(兄弟姐妹)显然需要整个文档都在那里,但其中大多数只需要保留几个节点RAM 随时可用。
我很确定这一点,因为当我还在每天使用 Cocoon 制作 webapp 时,每次我们在 XSLT 中使用“//something”表达式时都会遇到 XSLT 内存占用问题,而且我们经常不得不重新编写 XPath 表达式允许更好的 SAX 优化。
SAX 是只向前的,而 XPath 查询可以在任何方向上导航文档(考虑、 和parent::
轴ancestor::
)。我不明白这通常是怎么可能的。最好的近似值是某种延迟加载 DOM,但是根据您的查询,这可能会给您带来任何好处,也可能不会给您带来任何好处 - 总是有一个最坏情况的查询,例如.preceding::
preceding-sibling::
//*[. != preceding::*]
抱歉,这里的答案稍微晚了一点——似乎这对于 XPath 的一个子集来说是可能的——一般来说,这是非常困难的,因为 XPath 可以从“当前”点向前和向后匹配。我知道两个使用状态机在一定程度上解决它的项目:http: //spex.sourceforge.net和http://www.cs.umd.edu/projects/xsq。我没有详细查看它们,但它们似乎使用了类似的方法。
我将为我的一个名为 AXS 的新项目插入一个插件。它位于https://code.google.com/p/annotation-xpath-sax/并且想法是您使用(仅向前轴)XPath 语句注释方法,并且当 SAX 解析器位于节点时调用它们匹配它。所以有了一个文件
<doc>
<nodes>
<node name="a">text of node 1</node>
<node name="b">text of node 2</node>
<node otherattr="I have attributes!">text of node 3</node>
</nodes>
</doc>
你可以做类似的事情
@XPath("/nodes/node")
void onNode(String nodeText)
{
// will be called with "text of node [123]"
}
或者
@XPathStart("//node[@name='']")
void onNode3(Attrs node3Attrs) { ... }
或者
@XPathEnd("/nodes/node[2]")
void iDontCareAboutNode3() throws SAXExpression
{
throw new StopParsingExpression();
}
当然,这个库太新了,我什至还没有发布它,但它是 MIT 许可的,所以请随意尝试一下,看看它是否符合您的需要。(我写它是为了用足够低的内存要求进行 HTML 屏幕抓取,我可以在旧的 Android 设备上运行它......)如果你发现错误,请通过在 googlecode 网站上提交它们让我知道!
有基于 SAX/StAX 的 XPath 实现,但它们仅支持一小部分 XPath 表达式/轴,主要是由于 SAX/StAX 的仅向前性质。我知道的最佳替代方案是扩展VTD-XML,它支持完整的 xpath,通过 mem-map 加载部分文档.. 最大文档大小为 256GB,但您需要 64 位 JVM 才能充分利用它
您可以做的是将 XSL 转换器连接到 SAX 输入源。您的处理将是连续的,XSL 预处理器将尝试捕获输入,以便将其调整为您指定的任何结果。您可以使用它从流中提取路径的值。如果您想一次生成一堆不同的 XPATH 结果,这将特别方便。
作为结果,您将(通常)获得一个 XML 文档,但是您可以从例如 a 中提取预期的输出,StreamResult
而不会有太多麻烦。
查看 Saxon-SA XSLT 处理器的流模式。
http://www.saxonica.com/documentation/sourcedocs/serial.html
“确定路径表达式是否可以流式传输的规则是:
通过调用 doc() 或 document 引入的路径表达式必须符合如下定义的 XPath 子集:
如果 XPath 表达式符合 XML Schema 中身份约束中出现的路径表达式的规则,则它是可接受的。这些规则不允许使用谓词;第一步(但仅是第一步)可以用“//”引入;最后一步可以选择使用属性轴;所有其他步骤必须是使用子轴的简单轴步骤。
表达式必须要么只选择元素,要么只选择属性,或者混合使用元素和属性。
还支持简单的过滤器(一个或多个)。每个过滤器都可以应用于最后一步或整个表达式,并且它只能使用从上下文节点(self、child、attribute、descendant、descendant-or-self 或命名空间轴)的向下选择。它不能是位置的(也就是说,它不能引用 position() 或 last(),也不能是数字的:事实上,它必须是 Saxon 可以在编译时确定它不是数字的)。过滤器不能应用于联合或联合分支。任何违反这些条件的行为都会导致在没有流优化的情况下评估表达式。
这些规则在对表达式应用其他优化重写后应用。例如,某些 FLWOR 表达式可能会被重写为满足这些规则的路径表达式。
仅当显式请求时才启用优化,通过使用 saxon:stream() 扩展函数、anXSLT xsl:copy-of 指令上的 saxon:read-once 属性或 XQuery pragma saxon:stream。仅当样式表或查询使用 Saxon-SA 处理时才可用。”
注意:很可能在商业版本中可以使用此工具。我之前已经广泛使用过 Saxon,这是一个不错的作品。
嗯,我不知道我是否真的了解你。据我所知,SAX 模型是面向事件的。这意味着,如果在解析过程中遇到某个节点,你会做一些事情。是的,这对记忆更好,但我不明白您希望如何将 XPath 放入其中。由于 SAX 不建立模型,我认为这是不可能的。
标准的 javax xpath API 在技术上已经适用于流;javax.xml.xpath.XPathExpression
可以针对 a 进行评估InputSource
,而后者又可以用 a 构造Reader
。我不认为它在幕后构造了一个 DOM。
我认为 xpath 不能与 SAX 一起使用,但您可能会看一下 StAX,它是 Java 的扩展流 XML API。
您是否也尝试过 QuiXPath https://code.google.com/p/quixpath/?