Почему `copy-of ()` не позволяет этому XSL быть потоковым ("пакетный режим")? - PullRequest
0 голосов
/ 06 марта 2020

Я пытаюсь преобразовать множество XSL-преобразований в XSLT 3.0, чтобы я мог воспользоваться преимуществами потоковой передачи, поскольку большая часть XML, с которой я имею дело, довольно велика. У меня проблема с этим относительно простым преобразованием. Мне дано понять, что copy-of() должен разрешать несколько операндов-потребителей, но Саксон по-прежнему жалуется на это.

Когда я пытаюсь применить этот XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.workday/bsvc"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
    <xsl:mode streamable="yes"/>
    <xsl:strip-space elements="*" />

    <!-- Identity template -->
    <xsl:template match="/">
        <ROOT>
            <xsl:apply-templates select="/ROOT/ROW/copy-of(.)" />
        </ROOT>
    </xsl:template>

    <xsl:template match="ROW">
        <xsl:if test="contains(WD_BATCH_ID, 'timeoff_corr')" >
            <xsl:copy-of select="." />
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

... на XML, который выглядит следующим образом:

<ROOT>
    <ROW>
        <INT_ID>229274</INT_ID>
        <WD_BATCH_ID>kns_timeoff20200105_5365_78659138_TEST</WD_BATCH_ID>
        <WD_PAY_INPUT_ID>229174</WD_PAY_INPUT_ID>
        <DATE_WORKED>2019-12-31</DATE_WORKED>
        <EMPLOYEE_ID>103839</EMPLOYEE_ID>
        <WEEK_END_DATE>2020-01-05</WEEK_END_DATE>
        <EFFECTIVE_DATE>2020-01-05</EFFECTIVE_DATE>
        <HOURS>2</HOURS>
        <PAY_COMPONENT>INVALID_TIMEOFF1</PAY_COMPONENT>
        <TK_COMMENTS>kns_timeoff20200105_5365_78659138</TK_COMMENTS>
        <SS_REQUEST_ID>78658686</SS_REQUEST_ID>
        <REQUEST_ID>78659138</REQUEST_ID>
        <PROCESS_DATE>2020-02-10</PROCESS_DATE>
        <PROCESS_STATUS>C</PROCESS_STATUS>
    </ROW>
    <ROW>
    <INT_ID>1008269</INT_ID>
    <WD_BATCH_ID>kns_wd20200105_26285_78659138_TEST</WD_BATCH_ID>
    <WD_PAY_INPUT_ID>WK2.1008269</WD_PAY_INPUT_ID>
    <DATE_WORKED>2020-01-05</DATE_WORKED>
    <EMPLOYEE_ID>101113</EMPLOYEE_ID>
    <WEEK_END_DATE>2020-01-05</WEEK_END_DATE>
    <EFFECTIVE_DATE>2020-01-05</EFFECTIVE_DATE>
    <HOURS>40</HOURS>
    <PAY_COMPONENT>INVALID_CODE1</PAY_COMPONENT>
    <TK_COMMENTS>kns_wd20200105_26285_78659138</TK_COMMENTS>
    <SS_REQUEST_ID>78658686</SS_REQUEST_ID>
    <REQUEST_ID>78659138</REQUEST_ID>
    <PROCESS_DATE>2020-02-10</PROCESS_DATE>
    <PROCESS_STATUS>C</PROCESS_STATUS>
</ROW>
    <ROW>
    <INT_ID>234387</INT_ID>
    <WD_BATCH_ID>kns_timeoff_corr_test_7_78668139</WD_BATCH_ID>
    <WD_PAY_INPUT_ID>234386</WD_PAY_INPUT_ID>
    <DATE_WORKED>2019-12-12</DATE_WORKED>
    <EMPLOYEE_ID>150389</EMPLOYEE_ID>
    <WEEK_END_DATE>2019-12-15</WEEK_END_DATE>
    <EFFECTIVE_DATE>2020-01-05</EFFECTIVE_DATE>
    <HOURS>-9</HOURS>
    <PAY_COMPONENT>Jury Duty</PAY_COMPONENT>
    <TK_COMMENTS>kns_wd20200105_7_78668139</TK_COMMENTS>
    <SS_REQUEST_ID>78668068</SS_REQUEST_ID>
    <REQUEST_ID>78668139</REQUEST_ID>
    <PROCESS_DATE>2020-02-19</PROCESS_DATE>
    <PROCESS_STATUS>C</PROCESS_STATUS>
</ROW>
</ROOT>

... он должен выдавать идентичные XML, но пропустить любые ROW узлы, в которых дочерний элемент WD_BATCH_ID не содержит timeoff_corr. Это работает, как и ожидалось, без объявленной потоковой передачи, но с потоковой передачей, объявленной «да», Саксон жалуется net.sf.saxon.trans.XPathException: Template rule is declared streamable but it does not satisfy the streamability rules. * There is more than one consuming operand: {contains(...)} on line 17, and {xsl:copy-of} on line 18

Конечно, есть contains() 17 и xsl:copy-of 18, но в соответствии с Saxon использование select="/ROOT/ROW/copy-of(.)" должно разрешить «не потоковые» операции с копией этого узла.

Чего мне не хватает, что мешает этому XSL быть потоковым?

1 Ответ

0 голосов
/ 06 марта 2020

Используйте другой режим для этого шаблона, где этот другой режим не требует потоковой передачи, тогда ваш код будет работать.

Анализ потоков для вашего текущего шаблона, если вы объявили режим как поток, не будет охватывать ваш путь к коду и обнаружит, что вы просто хотите использовать шаблон для заземленных узлов, он просто проверяет, является ли только пересылка возможно выполнение одного потребляющего операнда для определенного шаблона.

Я думаю, вы также можете просто использовать <xsl:copy-of select="/ROOT/ROW/copy-of()[contains(WD_BATCH_ID, 'timeoff_corr')]" /> вместо <xsl:apply-templates select="/ROOT/ROW/copy-of(.)" />.

...