什么是最高效的基于 Java 的流式 XSLT 处理器?[已关闭]

2022-09-01 13:02:21

我有一个非常大的XML文件,我需要将其转换为另一个XML文件,我想用XSLT来执行此操作。我更感兴趣的是内存优化,而不是速度优化(虽然速度也会很好!

您将建议哪种基于 Java 的 XSLT 处理器来完成此任务?

你会推荐任何其他方法来做到这一点(非XSLT?,非Java?),如果是这样,为什么?

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


答案 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文档,其中包含大约一百万个具有整数值的3rd级元素。转换只是计算它们的总和。在我的计算机上进行转换的总时间小于 1.5 秒。使用的内存是500MB - 这是PC在10年前可能拥有的,

以下是 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() 扩展函数,可用于处理大型 XML 文档。

以下是文档摘录

在撒克逊语中,基本上有两种进行流式传输的方法:

突发模式流式处理:使用此方法,大文件的转换被分解为文件小片段的一系列转换。每个部分依次从输入中读取,变成内存中的小树,转换并写入输出文件。

此方法适用于结构相当平坦的文件,例如包含数百万条日志记录的日志文件,其中每个日志记录的处理与之前的日志记录无关。

此技术的变体使用新的 XSLT 3.0 xsl:迭代指令来循环访问记录,以代替 xsl:for-each。这允许在处理记录时维护工作数据:例如,这样就可以在运行结束时输出总计或平均值,或者使一条记录的处理依赖于文件中之前的内容。xsl:迭代指令还允许早期退出循环,这使得转换可以从大文件的开头处理数据,而无需实际读取整个文件。

突发模式流式处理在 XSLT 和 XQuery 中都可用,但在 XQuery 中没有与 xsl:迭代构造等效的构造。

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

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

流处理中允许的规则非常复杂,但基本原则是给定节点的模板规则只能按顺序读取该节点的后代一次。在当前的 Saxon 实现中,还有一些限制所施加的进一步规则:例如,尽管分组使用在理论上与流实现一致,但目前在 Saxon 中尚未实现。

  1. XSLT 3.0 将具有标准的流式处理功能。但是,W3C 文档仍处于“工作草稿”状态,流式处理规范可能会在后续草稿版本中更改。因此,不存在当前草稿(流式处理)规范的实现。

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


答案 2

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

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


推荐