【问题标题】:What is the Most Efficient Java-Based streaming XSLT Processor? [closed]什么是最高效的基于 Java 的流式 XSLT 处理器? [关闭]
【发布时间】:2010-10-02 10:22:52
【问题描述】:

我有一个非常大的 XML 文件,我需要将它转换成另一个 XML 文件,我想用 XSLT 来做这件事。我更感兴趣的是内存优化,而不是速度优化(不过,速度也不错!)。

对于这项任务,您会推荐哪种基于 Java 的 XSLT 处理器?

您是否会推荐任何其他方式(非 XSLT?、非 Java?),如果是,为什么?

问题中的 XML 文件非常大,但不是很深 - 有数百万行(元素),但只有大约 3 级深。

【问题讨论】:

    标签: java xslt processor


    【解决方案1】:

    目前已知只有三个XSLT 2.0 处理器,其中Saxon 9.x 在速度和内存利用率方面可能是最有效的(至少根据我的经验)。 Saxon-SA(Saxon 的模式感知版本,不像 B(基本)版本那样免费)具有流处理的特殊扩展。

    从现有的各种 XSLT 1.0处理器来看,.NET XslCompiledTransform(基于 C#,而不是 Java!)似乎是冠军。

    在基于 Java 的 XSLT 1.0 处理器世界中 Saxon 6.x 又是相当不错的。

    更新

    现在,从最初回答这个问题之日起 3 年多,没有任何证据表明提到的 XSLT 处理器之间的效率差异已经改变。

    关于流媒体

    1. 即使没有任何流式处理,也可以很好地处理具有“数百万个节点”的 XML 文档。我进行了一个实验,其中 Saxom 9.1.07 处理了一个 XML 文档,该文档包含大约一百万个具有整数值的 3 级元素。转换只是计算它们的总和。在我的电脑上转换的总时间不到 1.5 秒。使用的内存是 500MB——这在 10 年前的 PC 上也有,

    以下是 Saxon 的信息性消息,其中显示了有关转换的详细信息:

    Saxon 9.1.0.7J from Saxonica
    Java version 1.6.0_17
    Stylesheet compilation time: 190 milliseconds
    Processing file:/C:\temp\delete\MRowst.xml
    Building tree for file:/C:\temp\delete\MRowst.xml using class net.sf.saxon.tinytree.TinyBuilder
    Tree built in 1053 milliseconds
    Tree size: 3075004 nodes, 1800000 characters, 0 attributes
    Loading net.sf.saxon.event.MessageEmitter
    Execution time: 1448 milliseconds
    Memory used: 506661648
    NamePool contents: 14 entries in 14 chains. 6 prefixes, 6 URIs
    
    1. Saxon 9.4有一个saxon:stream() extension function,可用于处理巨大的 XML 文档。

    这是文档的摘录

    在 Saxon 中进行流式传输基本上有两种方式:

    突发模式流式传输:通过这种方法, 大文件被分解成一系列小的转换 文件的片段。依次从输入中读取每一块,转动 到内存中的一棵小树,转换并写入输出 文件。

    这种方法适用于结构相当扁平的文件, 例如一个包含数百万条日志记录的日志文件,其中 每个日志记录的处理独立于那些去的 之前。

    此技术的一个变体使用新的 XSLT 3.0 xsl:iterate 用于迭代记录的指令,代替 xsl:for-each。 这允许在记录时维护工作数据 已处理:这使得例如可以输出总计或 运行结束时的平均值,或进行一个处理 记录取决于文件中之前的内容。 xsl:迭代 指令还允许提前退出循环,这使得它 转换可以从一个开始处理数据 大文件而不实际读取整个文件。

    突发模式流在 XSLT 和 XQuery 中都可用,但在 在 XQuery 中不等同于 xsl:iterate 构造。

    流模板:这种方法遵循传统的 XSLT 执行输入 XML 的递归下降的处理模式 通过将模板规则与每个级别的节点匹配来实现层次结构,但是 一次只处理一个元素,无需在内存中构建树。

    每个模板都属于一个模式(可能是默认的、未命名的模式), 并且流是可以使用指定的模式的属性 新的 xsl:mode 声明。如果模式被声明为 流式传输,则该模式下的每个模板规则都必须遵守 流式处理的规则。

    流处理中允许的内容的规则是相当的 复杂,但基本原则是模板规则 给定节点只能读取该节点的后代一次,在 命令。当前的限制还有其他规则 Saxon 实现:例如,虽然使用 理论上是一致的 使用流式实现,目前尚未在 撒克逊人。

    1. XSLT 3.0 将具有标准 streaming feature。然而,W3C 文档仍处于“工作草案”状态,流式规范在后续草案版本中可能会发生变化。因此,不存在当前草案(流式传输)规范的实现。

    2. 警告:并非所有转换都可以在流模式下执行 - 无论 XSLT 处理器如何。无法在流模式(RAM 数量有限)下对大型文档执行转换的一个示例是对它们的元素进行排序(比如通过一个公共属性)。

    【讨论】:

    • 一年过去了,Dimitre 的评论仍然有效。事实上,撒克逊人变得更快了。
    • XSLT 3 流式传输绝对是要走的路。感谢您及时更新此答案,Dimitre。
    【解决方案2】:

    你可以考虑STX,它的Java实现是Joost。由于它类似于 XSLT,但作为流处理器,它能够使用非常少的 RAM 处理大量文件。

    Joost 可以用作标准的 javax.xml.transform.TransformerFactory

    【讨论】:

    • 这个项目似乎已经死了。我尝试了他们最新的(2009 年)版本。我的 452GB XML 文件效果不佳,而且它缺乏 UTF-8 支持
    • 约斯特死了。我正在做一个使用 Joost 的项目。它工作正常,只是当我们尝试升级 Joost 依赖项(XML 解析)时,它会中断。这引起了严重的头痛。不要使用 Joost。
    【解决方案3】:

    查看 Saxon 对流模式的支持。 http://www.saxonica.com/html/documentation/sourcedocs/streaming/

    如果这种流模式不适合你,你可以尝试使用 Saxon 的tiny tree mode,它针对更小的内存使用进行了优化。 (反正都是默认的)

    【讨论】:

      猜你喜欢
      • 2010-10-12
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2013-05-29
      相关资源
      最近更新 更多