Использование одного и того же узла дважды в потоковом XSLT - PullRequest
1 голос
/ 18 января 2020

Я пытаюсь преобразовать некоторое XML в промежуточное представление JSON, указанное в XSLT 3.0 (для последующего преобразования в JSON через xml-to-json). Мой текущий XSLT хорошо работает как таблица стилей без потоковой передачи, но у меня возникают проблемы при переходе на потоковую передачу. В частности, бывают ситуации, когда мне нужно использовать один и тот же узел дважды, особенно в случае повторяющихся тегов в XML, которые я преобразую в массивы в эквивалентном представлении JSON.

<xsl:if test="boolean(cdf:AdjudicatorName)">
    <array key="AdjudicatorName">
        <xsl:for-each select="cdf:AdjudicatorName">
            <string>
                <xsl:value-of select="."/>
            </string>
        </xsl:for-each>
    </array>
</xsl:if>

логическое значение (cdf: AdjudicatorName) проверяет наличие тега и создает массив, если так.

Этот код завершается ошибкой в ​​Oxygen (Saxon-EE) со следующим сообщением

Template rule is declared streamable but it does not satisfy the streamability rules. * There is more than one consuming operand: {fn:exists(...)} on line {X}, and {<string {(attr{key=...}, ...)}/>} on line {Y}

I Я знаю об обходном пути copy-of, однако многие элементы в исходном файле могут повторяться на самом высоком уровне, поэтому использование этого подхода приведет к минимальной экономии памяти.

1 Ответ

3 голосов
/ 18 января 2020

Это выглядит как идеальный вариант использования для xsl:where-populated:

<xsl:where-populated>
    <array key="AdjudicatorName">
        <xsl:for-each select="cdf:AdjudicatorName">
            <string>
                <xsl:value-of select="."/>
            </string>
        </xsl:for-each>
    </array>
</xsl:where-populated>

Инструкция xsl:where-populated (которая была изобретена именно для этой цели) логически оценивает свои дочерние инструкции, а затем удаляет любые элементы в результирующая последовательность, которая «считается пустой», где элемент считается пустым, если у него нет дочерних элементов. В реализации потоковой передачи начальный тег (<array>) будет «задерживаться» до тех пор, пока не будет сгенерирован его первый дочерний элемент, и когда соответствующий конечный тег (</array>) будет выпущен, пара тегов будет отброшена, если не было выброшенные дети.

...