流式 XPath 评估

Posted

技术标签:

【中文标题】流式 XPath 评估【英文标题】:Streaming XPath evaluation 【发布时间】:2010-11-03 00:35:33 【问题描述】:

是否有任何生产就绪库可用于针对提供的 xml 文档进行流式 XPath 表达式评估?我的调查表明,大多数现有解决方案在评估 xpath 表达式之前会将整个 DOM 树加载到内存中。

【问题讨论】:

非常感谢,我以前看过你的项目。看起来很有希望 有一些关于这个主题的新信息——见我的回答。 【参考方案1】:

我想我会选择自定义代码。如果只想读取 xml 文档的一些路径,.NET 库让我们非常接近目标。

由于到目前为止我看到的所有解决方案都只考虑 XPath 子集,所以这也是这种解决方案。虽然子集真的很小。 :)

此 C# 代码读取 xml 文件并计算给定显式路径的节点。您还可以使用xr["attrName"] 语法轻松地对属性进行操作。

  int c = 0;
  var r = new System.IO.StreamReader(asArgs[1]);
  var se = new System.Xml.XmlReaderSettings();
  var xr = System.Xml.XmlReader.Create(r, se);
  var lstPath = new System.Collections.Generic.List<String>();
  var sbPath = new System.Text.StringBuilder();
  while (xr.Read()) 
    //Console.WriteLine("type " + xr.NodeType);
    if (xr.NodeType == System.Xml.XmlNodeType.Element) 
      lstPath.Add(xr.Name);
    

    // It takes some time. If 1 unit is time needed for parsing the file,
    // then this takes about 1.0.
    sbPath.Clear();
    foreach(object n in lstPath) 
      sbPath.Append('/');
      sbPath.Append(n);
    
    // This takes about 0.6 time units.
    string sPath = sbPath.ToString();

    if (xr.NodeType == System.Xml.XmlNodeType.EndElement
        || xr.IsEmptyElement) 
      if (xr.Name == "someElement" && lstPath[0] == "main")
        c++;
      // And test simple XPath explicitly:
      // if (sPath == "/main/someElement")
    

    if (xr.NodeType == System.Xml.XmlNodeType.EndElement
        || xr.IsEmptyElement) 
      lstPath.RemoveAt(lstPath.Count - 1);
    
  
  xr.Close();

【讨论】:

【参考方案2】:

虽然我没有实践经验,但我认为值得一提的是 QuiXProc (http://code.google.com/p/quixproc/)。它是 XProc 的一种流式处理方法,并使用为 XPath 等提供流式传输支持的库。

【讨论】:

【参考方案3】:

XSLT 3.0 提供streaming mode of processing,随着 XSLT 3.0 W3C 规范成为 W3C 推荐标准,这将成为一个标准。

在撰写此答案时(2011 年 5 月),Saxon 提供了一些 support for XSLT 3.0 streaming

【讨论】:

【参考方案4】:

FWIW,我对非常大 (>3GB) 的文件使用了 Nux 流式过滤器 xpath 查询,它既可以完美运行,也可以使用很少的内存。我的用例略有不同(不是以验证为中心),但我强烈建议您尝试使用 Nux。

【讨论】:

【参考方案5】:

有几种选择:

DataDirect Technologies sells an XQuery implementation 在可能的情况下采用投影和流式传输。它可以处理数千兆字节范围内的文件 - 例如大于可用内存。它是一个线程安全的库,因此很容易集成。仅限 Java。

Saxon 是一个开源版本,有一个价格适中的更昂贵的表亲,它可以在某些情况下进行流式传输。 Java,但也有一个 .net 端口。

MarkLogic 和 eXist 是 XML 数据库,如果将您的 XML 加载到其中,它们将以相当智能的方式处理 XPath。

【讨论】:

【参考方案6】:

试试Joost。

【讨论】:

【参考方案7】:

这对于完整的 XPath 实现是否实用,因为 XPath 语法允许:

/AAA/XXX/following::*

/AAA/BBB/following-sibling::*

这意味着前瞻性要求?即,无论如何您都必须从特定节点加载文档的其余部分。

Nux 库(特别是 StreamingPathFilter)的文档说明了这一点,并引用了一些依赖于 XPath 子集的实现。 Nux 声称可以执行一些流式查询功能,但鉴于上述情况,在 XPath 实现方面会有一些限制。

【讨论】:

实际上我需要执行简单的 xpath 查询来检查给定 xml 文档中的多个节点以进行验证。 XML 文档代表一个实体,它的一些节点存储其他实体的外键。因此,应该对这些特殊节点应用某种完整性验证。整个文档非常大,在内存中存储如此大量的数据以执行几个简单的 xpath 查询将是低效的。 看起来 Nux 库很可能在这种情况下为您提供帮助。或者,您是否可以使用 Stax 库并将 XPath 应用于从某个节点提取的本地 XML 文档? 其实我不能采用第二种方法,因为xml文档的结构比较简单,撕掉文档的某个节点并对其应用evaluate xpath表达式是没有意义的。 我想我现在会尝试 XOM。 @Brian 谢谢你的建议,我很感激。

以上是关于流式 XPath 评估的主要内容,如果未能解决你的问题,请参考以下文章

xslt 中的 xpath 产生与直接评估 xpath 不同的结果

XSL 动态 XPath 评估

XPath 是不是对逻辑表达式进行短路评估?

xpath 文档评估包含此 OR

在python中评估Xpath2.0

在 node.js 中评估 xpath2.0