К сожалению, невозможно (ни в соответствии со спецификацией XSLT 3.0 от W3C, ни в реализации Saxon) написать многофазное преобразование потоковой передачи в одной таблице стилей. Обычно существует два способа записать многофазное преобразование (то есть преобразование, которое представляет собой композицию двух отдельных преобразований: либо первая фаза может быть вызвана как функция, либо первая фаза может предоставлять свои результаты в переменной. Ни один из этих механизмов не позволяет предоставлять промежуточные результаты (результаты первого этапа) в виде потокового документа.
(Мы знали об этом ограничении при разработке спецификации, но решили исключить его из требований, поскольку все уже становилось достаточно сложным.)
Но я считаю, что это можно сделать в Saxon, используя многофазное преобразование, реализованное с использованием двух отдельных таблиц стилей, связанных вместе. Самый простой способ сделать это, вероятно, - использовать интерфейс 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 (я думаю) полностью создается в памяти перед записью в выходной файл. Это немного прискорбно, и мы должны попытаться исправить это.
person
Michael Kay
schedule
22.05.2019