【发布时间】:2010-10-02 10:22:52
【问题描述】:
我有一个非常大的 XML 文件,我需要将它转换成另一个 XML 文件,我想用 XSLT 来做这件事。我更感兴趣的是内存优化,而不是速度优化(不过,速度也不错!)。
对于这项任务,您会推荐哪种基于 Java 的 XSLT 处理器?
您是否会推荐任何其他方式(非 XSLT?、非 Java?),如果是,为什么?
问题中的 XML 文件非常大,但不是很深 - 有数百万行(元素),但只有大约 3 级深。
【问题讨论】:
我有一个非常大的 XML 文件,我需要将它转换成另一个 XML 文件,我想用 XSLT 来做这件事。我更感兴趣的是内存优化,而不是速度优化(不过,速度也不错!)。
对于这项任务,您会推荐哪种基于 Java 的 XSLT 处理器?
您是否会推荐任何其他方式(非 XSLT?、非 Java?),如果是,为什么?
问题中的 XML 文件非常大,但不是很深 - 有数百万行(元素),但只有大约 3 级深。
【问题讨论】:
目前已知只有三个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 处理器之间的效率差异已经改变。
关于流媒体:
以下是 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
这是文档的摘录:
在 Saxon 中进行流式传输基本上有两种方式:
突发模式流式传输:通过这种方法, 大文件被分解成一系列小的转换 文件的片段。依次从输入中读取每一块,转动 到内存中的一棵小树,转换并写入输出 文件。
这种方法适用于结构相当扁平的文件, 例如一个包含数百万条日志记录的日志文件,其中 每个日志记录的处理独立于那些去的 之前。
此技术的一个变体使用新的 XSLT 3.0 xsl:iterate 用于迭代记录的指令,代替 xsl:for-each。 这允许在记录时维护工作数据 已处理:这使得例如可以输出总计或 运行结束时的平均值,或进行一个处理 记录取决于文件中之前的内容。 xsl:迭代 指令还允许提前退出循环,这使得它 转换可以从一个开始处理数据 大文件而不实际读取整个文件。
突发模式流在 XSLT 和 XQuery 中都可用,但在 在 XQuery 中不等同于 xsl:iterate 构造。
流模板:这种方法遵循传统的 XSLT 执行输入 XML 的递归下降的处理模式 通过将模板规则与每个级别的节点匹配来实现层次结构,但是 一次只处理一个元素,无需在内存中构建树。
每个模板都属于一个模式(可能是默认的、未命名的模式), 并且流是可以使用指定的模式的属性 新的 xsl:mode 声明。如果模式被声明为 流式传输,则该模式下的每个模板规则都必须遵守 流式处理的规则。
流处理中允许的内容的规则是相当的 复杂,但基本原则是模板规则 给定节点只能读取该节点的后代一次,在 命令。当前的限制还有其他规则 Saxon 实现:例如,虽然使用 理论上是一致的 使用流式实现,目前尚未在 撒克逊人。
XSLT 3.0 将具有标准 streaming feature。然而,W3C 文档仍处于“工作草案”状态,流式规范在后续草案版本中可能会发生变化。因此,不存在当前草案(流式传输)规范的实现。
警告:并非所有转换都可以在流模式下执行 - 无论 XSLT 处理器如何。无法在流模式(RAM 数量有限)下对大型文档执行转换的一个示例是对它们的元素进行排序(比如通过一个公共属性)。
【讨论】:
查看 Saxon 对流模式的支持。 http://www.saxonica.com/html/documentation/sourcedocs/streaming/
如果这种流模式不适合你,你可以尝试使用 Saxon 的tiny tree mode,它针对更小的内存使用进行了优化。 (反正都是默认的)
【讨论】: