К сожалению, невозможно (ни в соответствии со спецификацией XSLT 3.0 от W3C, ни в реализации 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 (я думаю) полностью создается в памяти перед записью в выходной файл.Это немного прискорбно, и мы должны попытаться это исправить.