Потоковое xml-to-json - PullRequest
       24

Потоковое xml-to-json

0 голосов
/ 22 мая 2019

У меня есть несколько очень больших файлов XML, которые я хотел бы преобразовать в (одинаково большие) файлы JSON.Для этого я написал XSLT, который преобразует XML в промежуточное «представление XML-JSON», указанное в спецификации XSLT 3.0.Затем я могу вызвать функцию fn: xml-to-json.

Однако я бы хотел, чтобы этот процесс был потоковым, чтобы использование памяти оставалось стабильным.Это возможно?

1 Ответ

1 голос
/ 23 мая 2019

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

...