流式传输 xml 到 json
Streaming xml-to-json
我有许多非常大的 XML 文件,我想将它们转换为(同样大的)JSON 文件。为此,我编写了一个 XSLT,将 XML 转换为 XSLT 3.0 规范中指定的插页式 "XML-to-JSON representation"。然后我可以调用 fn:xml-to-json 函数。
但是,我想流式传输此过程,以便内存使用保持稳定。这可能吗?
不幸的是,不可能(根据 W3C 的 XSLT 3.0 规范,或在 Saxon 实现中)在单个样式表中编写 multi-phase 流式转换。通常有两种编写 multi-phase 转换的方法(即由两个单独的转换组成的转换:第一阶段可以作为函数调用,或者第一阶段可以在变量。这些机制都不允许将中间结果(第一阶段的结果)作为流式文档传送。
(我们在设计规范时就意识到了这一限制,但决定将其从要求中删除,因为事情已经变得相当复杂了。)
但我相信它可以在 Saxon 中完成,使用一个 multi-phase 转换,该转换使用链接在一起的两个单独的样式表实现。执行此操作的最简单方法可能是使用 s9api 接口。像这样编写第二个转换 t2.xsl
(它只是调用 xml-to-json):
<xsl:transform version="3.0" expand-text="yes"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode streamable="yes"/>
<xsl:output method="text"/>
<xsl:template match="/">{xml-to-json(.)}</xsl:template>
</xsl:transform>
然后做:
Processor proc = new Processor(true);
Serializer out = proc.newSerializer(new File("out.xml");
XsltCompiler comp = proc.newXsltCompiler();
Xslt30Transformer t2 = comp.compile(new File("t2.xsl")).load30();
Destination phase2 = t2.asDocumentDestination(out);
Xslt30Transformer t1 = comp.compile(new File("t1.xsl").load30();
t1.applyTemplates(source, phase2);
注意事项:虽然输入文档是流式传输并且中间 XML 是流式传输,但输出 JSON 是(我认为)在写出到输出之前完全在内存中构建的文件。这有点不幸,我们应该尝试修复它。
我有许多非常大的 XML 文件,我想将它们转换为(同样大的)JSON 文件。为此,我编写了一个 XSLT,将 XML 转换为 XSLT 3.0 规范中指定的插页式 "XML-to-JSON representation"。然后我可以调用 fn:xml-to-json 函数。
但是,我想流式传输此过程,以便内存使用保持稳定。这可能吗?
不幸的是,不可能(根据 W3C 的 XSLT 3.0 规范,或在 Saxon 实现中)在单个样式表中编写 multi-phase 流式转换。通常有两种编写 multi-phase 转换的方法(即由两个单独的转换组成的转换:第一阶段可以作为函数调用,或者第一阶段可以在变量。这些机制都不允许将中间结果(第一阶段的结果)作为流式文档传送。
(我们在设计规范时就意识到了这一限制,但决定将其从要求中删除,因为事情已经变得相当复杂了。)
但我相信它可以在 Saxon 中完成,使用一个 multi-phase 转换,该转换使用链接在一起的两个单独的样式表实现。执行此操作的最简单方法可能是使用 s9api 接口。像这样编写第二个转换 t2.xsl
(它只是调用 xml-to-json):
<xsl:transform version="3.0" expand-text="yes"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode streamable="yes"/>
<xsl:output method="text"/>
<xsl:template match="/">{xml-to-json(.)}</xsl:template>
</xsl:transform>
然后做:
Processor proc = new Processor(true);
Serializer out = proc.newSerializer(new File("out.xml");
XsltCompiler comp = proc.newXsltCompiler();
Xslt30Transformer t2 = comp.compile(new File("t2.xsl")).load30();
Destination phase2 = t2.asDocumentDestination(out);
Xslt30Transformer t1 = comp.compile(new File("t1.xsl").load30();
t1.applyTemplates(source, phase2);
注意事项:虽然输入文档是流式传输并且中间 XML 是流式传输,但输出 JSON 是(我认为)在写出到输出之前完全在内存中构建的文件。这有点不幸,我们应该尝试修复它。