SAX模型是否有任何XPath处理器?

我正在寻找一个XPath评估器,它不重build整个DOM文档来查找文档的节点:实际上,对象是用SAX模型pipe理大量的XML数据(理想情况下超过2Gb)有利于内存pipe理,并可以search节点。

谢谢大家的支持!

对于所有那些说不可能的人:我最近在问了这个问题之后,find了一个名为“saxpath”的项目( http://www.saxpath.org/ ),但是我找不到任何的实施项目。

我目前的列表(从networkingsearch结果和其他答案编译)是:

下一步是使用XMLDog的例子,并比较所有这些方法的性能。 然后,testing用例应该扩展到支持的XPathexpression式。

我们通过使用SAXparsing器定期parsing1GB +复杂的XML文件,该parsing器可以提取部分DOM树,可以使用XPath方便地查询。 我在这里博客: http : //softwareengineeringcorner.blogspot.com/2012/01/conveniently-processing-large-xml-files.html – 源代码在github上可用 – MIT许可证。

XPath可以和SAX一起工作,而且大多数XSLT处理器(特别是Saxon和Apache Xalan)都支持在SAXstream的XSLT中执行XPathexpression式,而不需要构build整个dom。

他们设法做到这一点,非常粗略,如下所示:

  1. 检查他们需要匹配的XPathexpression式
  2. 接收SAX事件并testing该XPathexpression式是否需要或将需要该节点。
  3. 如果对XPathexpression式没有用处,则忽略SAX事件。
  4. 缓冲它,如果需要的话

他们如何缓冲它也是非常有趣的,因为一些简单的创buildDOM碎片,其他人使用非常优化的表来快速查找和减less内存消耗。

他们设法优化多less主要取决于他们find的XPath查询的种类。 正如已经发布的Saxon文档清楚地解释的那样,向上移动然后“横向”(兄弟姐妹)移动文档的查询显然需要整个文档在那里,但是大多数只需要将几个节点保存到RAM在任何时刻。

我非常肯定这一点,因为当我每天都在使用Cocoon制作Web应用程序时,每当我们在XSLT中使用“// something”expression式时,都会遇到XSLT内存占用问题,通常我们不得不重写XPathexpression式以实现更好的SAX优化。

SAX是仅向前的,而XPath查询可以在任何方向上浏览文档(考虑parent::ancestor::preceding::preceding-sibling:: axis)。 我不明白这是如何可能的一般。 最好的近似是某种延迟加载的DOM,但根据您的查询,这可能会或可能不会给您带来任何好处 – 总会有最差情况的查询,例如//*[. != preceding::*] //*[. != preceding::*]

对不起,这里稍微迟一点的答案 – 似乎这对于XPath的一个子集是可能的 – 总的来说这很困难,因为XPath可以从“当前”点向前和向后匹配。 我知道有两个项目使用状态机在一定程度上解决了这个问题: http : //spex.sourceforge.net&http : //www.cs.umd.edu/projects/xsq 。 我没有详细看过他们,但他们似乎使用了类似的方法。

我会为了一个叫做AXS的新项目而投入一个插件。 它位于https://code.google.com/p/annotation-xpath-sax/ ,其思想是您使用(仅向前轴)XPath语句注释方法,并在SAXparsing器处于节点时被调用匹配它。 所以用一个文件

 <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(); } 

当然,图书馆是如此的新,我甚至还没有发布它,但它是麻省理工学院许可的,所以随时试一试,看看它是否符合你的需要。 (我写它做HTML屏幕刮擦足够低的内存要求,我可以在旧的Android设备上运行…)如果你发现错误,请让我知道在Googlecode网站上提交他们!

对不起,迟来的答案,但我没有实现SAXparsing器的简单的XPathexpression式path。 它只支持标签,具有可选值的属性,以及由于SAX的前向性而产生的索引。 当Handler实现ExpressionFilter时,我做了一个委托处理程序来评估给定的expression式。 虽然这些类embedded到项目中,但不应该难以提取。

更多信息

示例 – 使用HandlerHtml前缀查看类

有基于SAX / StAX的XPath实现,但是它们只支持XPathexpression式/轴的一个小子集,很大程度上是由于SAX / StAX的仅向前性质。我知道的最好的select是扩展的VTD-XML ,它支持完整的xpath,通过mem-map加载部分文档,最大文档大小为256GB,但是您需要64位JVM才能充分利用它

嗯,我不知道我是否真的了解你。 据我所知,SAX模型是面向事件的。 这意味着,如果在parsing过程中遇到某个节点,则会执行某些操作。 是的,这对内存来说更好,但是我不明白你想如何获得XPath。 由于SAX不构build模型,我不认为这是可能的。

你可以做的是将一个XSL转换器挂接到一个SAXinput源。 你的处理将是连续的,XSL预处理器会尝试捕捉input,以便将它转换为你指定的结果。 你可以使用这个从stream中拉出path的值。 如果您想要一次生成一堆不同的XPATH结果,这将特别方便。

您将(通常)得到一个XML文档,但是您可以从StreamResult获得预期的输出,而不会太麻烦。

看看Saxon-SA XSLT处理器的stream模式。

http://www.saxonica.com/documentation/sourcedocs/serial.html

“确定pathexpression式是否可以stream式处理的规则是:

  • 要进行stream式处理的expression式首先调用document()或doc()函数。
  • doc()或文档上的调用引入的pathexpression式必须符合XPath的子集,定义如下:

  • 如果任何XPathexpression式符合出现在XML模式中的标识约束中的pathexpression式的规则,则该expression式是可接受的。 这些规则不允许谓词; 第一步(但只有第一步)可以用“//”来引入; 最后一步可以select使用属性轴; 所有其他步骤必须是简单的轴步骤使用子轴。

  • 另外,Saxon允许expression式包含一个联合,例如doc()/(* / ABC | / XYZ)。 联盟也可以用缩写forms表示,例如上面可以写成doc()/ /(ABC | XYZ)。
  • 该expression式必须仅select元素,或仅select属性,或者select元素和属性的混合。

  • 简单的filter(一个或多个)也被支持。 每个filter可以应用到最后一步或整个expression式,并且只能从上下文节点(自我,孩子,属性,后代,后代或自我或名称空间轴)向下select。 它不能是位置的(也就是说,它不能引用position()或last(),也不能是numeric:实际上,它必须是Saxon在编译时可以确定它不会是数字的)。 filter不能应用于工会或工会的分支。 任何违反这些条件的情况都会导致在没有stream式优化的情况下评估expression式。

  • 这些规则适用于其他优化重写已应用到expression式之后。 例如,一些FLWORexpression式可以被重写为满足这些规则的pathexpression式。

  • 只有通过使用saxon:stream()扩展函数或者在XSLT xsl:copy-of指令或者XQuery pragma saxon:stream中使用saxon:read-once属性,才能显式请求优化。 只有使用Saxon-SA处理样式表或查询时才可用。“

注意:这个工具最有可能在商业版本中可用。 我之前广泛使用过撒克逊,这是一件很好的工作。

我不认为xpath可以与SAX协同工作,但是您可以看看StAX,这是一个扩展的用于Java的stream式XML API。

http://en.wikipedia.org/wiki/StAX

标准的javax xpath API在技术上已经可以在stream中使用; javax.xml.xpath.XPathExpression可以用一个InputSource来评估,而InputSource又可以用Reader来构build。 我不认为它构build了一个DOM下的封面。

你有没有尝试过QuiXPath https://code.google.com/p/quixpath/