Эффективное логическое значение не определено - XSLT - PullRequest
0 голосов
/ 04 мая 2020

Я получаю эту ошибку (т. Е. Эффективное логическое значение не определено) при применении преобразования к XML файлам. Здесь есть странная загвоздка:

* Мое приложение считывает от 500 до 800 XML файлов (XML размер файла в диапазоне от нескольких КБ до 10 МБ) из местоположения файла, а затем выполняет преобразование для каждого из них , Изначально все идет гладко, но после некоторых выполнений выдает ошибку ниже:

Ошибка в строке 651 productsFromLOC_v3.xsl:
FORG0006: Действительное логическое значение не определено
в xsl: имя шаблона вызова = "AssetStream" (файл: / C: / app / comp / nfs / services / transformer / productsFromLOC_v3.xsl # 378) в xsl: call-template name = "Products" (файл: / C: / app /comp/nfs/services/transformer/productsFromLOC_v3.xsl#53)

Строка № 651: xsl: if test = "fn: длина строки (fn: copy-of ($ vStruct)) )! = 0 "

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

Если я выберу эти файлы с ошибкой XML, и обрабатывать затем индивидуально, тогда нет никаких проблем вообще. Похоже, что массовое преобразование XML вызывает только эту проблему.

Может ли кто-нибудь помочь мне в этом сценарии?

Saxon EE версия - 9.8.0.7J и XSLT версия - 3.0

Java код:

private byte[] transformFromSource(String urlParams, String xslFullPath, final String uriXSLT,
    final String outputXSLTFilePath, String transformParams, final Object xmlSource,
    final String outputEncoding)
    throws SaxonApiException, MalformedURLException, SystemException, UnsupportedEncodingException {

final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
List<XsltExecutable> xsltExecutables = xsltTemplateManager.getTemplates(windowsOS ? xslFullPath.split("\\\\")[xslFullPath.split("\\\\").length - 1].trim() : xslFullPath.trim());
Processor processor = null;
XdmNode xdmNode = null;
XdmDestination xdmDestination1 = new XdmDestination();
XdmDestination xdmDestination2 = new XdmDestination();
for (XsltExecutable xsltExecutable : xsltExecutables) {
    int i = 0;
    final Xslt30Transformer transformer = xsltExecutable.load30();
    final Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
    if (StringUtils.isNotBlank(uriXSLT)) {
        params.put(new QName("xslt.location.uriXSLTPath"), new XdmAtomicValue(uriXSLT));
    }
    if (StringUtils.isNotBlank(outputXSLTFilePath)) {
        params.put(new QName("xslt.location.outputXSLTPath"), new XdmAtomicValue(outputXSLTFilePath));
    }
    if (StringUtils.isNotBlank(transformParams)) {
        params.put(new QName("xslt.transform.params"), new XdmAtomicValue(transformParams));
    }
    if (StringUtils.isNotBlank(urlParams)) {
        params.put(new QName("http.query.params"), new XdmAtomicValue(urlParams));
    }
    transformer.setStylesheetParameters(params);
    if (xsltExecutables.size() == 1) {
        processor = xsltExecutable.getProcessor();
        if (xmlSource instanceof File) {
            if (((File) xmlSource).isFile()) {
                String inFile = "<file>" + ((File) xmlSource).getAbsolutePath() + "</file>";
                xdmNode = processor.newDocumentBuilder().build(new StreamSource(new ByteArrayInputStream(inFile.getBytes(outputEncoding))));
            }
        } else {
            xdmNode = processor.newDocumentBuilder().build((StreamSource) xmlSource);
        }
        final Serializer serializer = processor.newSerializer(outputStream);
        /* serializer.setOutputProperty(Serializer.Property.METHOD, "xml"); */
        serializer.setOutputProperty(Serializer.Property.INDENT, "yes");
        serializer.setOutputProperty(Serializer.Property.ENCODING, outputEncoding);
        transformer.applyTemplates(xdmNode, serializer);
    } else if (xsltExecutables.size() > 1 && i == 0) {
        processor = xsltExecutable.getProcessor();
        if (xmlSource instanceof File) {
            xdmNode = processor.newDocumentBuilder().build((File) xmlSource);
        } else {
            xdmNode = processor.newDocumentBuilder().build((StreamSource) xmlSource);
        }
        transformer.applyTemplates(xdmNode, xdmDestination1);
    } else if (xsltExecutables.size() > 1 && i == xsltExecutables.size()) {
        final Serializer serializer = processor.newSerializer(outputStream);
        serializer.setOutputProperty(Serializer.Property.INDENT, "yes");
        serializer.setOutputProperty(Serializer.Property.ENCODING, outputEncoding);
        transformer.applyTemplates(xdmNode, serializer);
        transformer.applyTemplates(xdmDestination2.getXdmNode(), serializer);
    } else if (xsltExecutables.size() > 1 && i > 0) {
        transformer.applyTemplates(xdmDestination1.getXdmNode(), xdmDestination2);
        xdmDestination1 = xdmDestination2;
    }
}
processor = null;
xdmNode = null;
xsltExecutables = null;
return outputStream.toByteArray(); }

Раздел XSLT, который приводит к ошибке:

<xsl:iterate select="$STEP/STEP-ProductInformation/Assets/Asset[@UserTypeID='PDF' or @UserTypeID='PNG']">
<xsl:param name="vCount" select="1" as="xs:integer"/>
<xsl:param name="vFileCount" select="1" as="xs:integer"/>
<xsl:param name="vStruct" select="'' " as="xs:string"/>
<xsl:on-completion>
    <xsl:variable name="vFileName" select="concat($outputXSLTFilePath,'/Asset-',$vTimestamp,'-',$vFileCount,$vJMSID,'.xml')"/>
    <xsl:variable name="vResult">
        <map xmlns="http://www.w3.org/2005/xpath-functions">
            <array key="assets">
                <xsl:copy-of select="$vStruct"/>
            </array>
            <string key="locale">
                <xsl:value-of select="$vContextID"/>
            </string>
            <string key="exportTime">
                <xsl:value-of select="$vExportTime"/>
            </string>
        </map>
    </xsl:variable>
    <xsl:if test="fn:string-length( fn:copy-of($vStruct)) ne 0">
        <Payload>
            <ControlData>
                <FeedType>Assets</FeedType>
                <FullImport>
                    <xsl:value-of select="$fullUpload"/>
                </FullImport>
                <Resequencing>true</Resequencing>
                <JMSXGroupID>
                    <xsl:value-of select="$vJMSID"/>
                </JMSXGroupID>
                <JMSXGroupSeq>
                    <xsl:value-of select="$vFileCount"/>
                </JMSXGroupSeq>
                <GroupSize>
                    <xsl:value-of select="$vTotalMessages"/>
                </GroupSize>
                <OutboundQueueName>feeds/out/1.0/products</OutboundQueueName>
            </ControlData>
            <Message id="{$vFileCount}">
                <xsl:value-of select="odfn:JsonBS(xml-to-json($vResult,map{ 'indent':true() }))"/>
            </Message>
        </Payload>
    </xsl:if>
</xsl:on-completion>
<xsl:variable name="vX">
    <map xmlns="http://www.w3.org/2005/xpath-functions">
        <string key="id">
            <xsl:value-of select="@ID"/>
        </string>
        <string key="typeId">
            <xsl:value-of select="@UserTypeID"/>
        </string>
        <string key="filename">
            <xsl:value-of select="./Values/Value[@AttributeID='asset.filename']"/>
        </string>
    </map>
</xsl:variable>
<xsl:variable name="vXS">
    <xsl:copy-of select="$vStruct"/>
    <xsl:copy-of select="$vX"/>
</xsl:variable>
<xsl:choose>
    <xsl:when test="$vCount &lt; 50">
        <xsl:next-iteration>
            <xsl:with-param name="vCount" select="$vCount+1"/>
            <xsl:with-param name="vFileCount" select="$vFileCount"/>
            <xsl:with-param name="vStruct">
                <xsl:copy-of select="$vXS"/>
            </xsl:with-param>
        </xsl:next-iteration>
    </xsl:when>
    <xsl:otherwise>
        <xsl:variable name="vFileName" select="concat($outputXSLTFilePath,'/Asset-',$vTimestamp,'-',$vFileCount,$vJMSID,'.xml')"/>
        <xsl:variable name="vResult">
            <map xmlns="http://www.w3.org/2005/xpath-functions">
                <array key="assets">
                    <xsl:copy-of select="$vXS"/>
                </array>
                <string key="locale">
                    <xsl:value-of select="$vContextID"/>
                </string>
                <string key="exportTime">
                    <xsl:value-of select="$vExportTime"/>
                </string>
            </map>
        </xsl:variable>
        <Payload>
            <ControlData>
                <FeedType>Assets</FeedType>
                <FullImport>
                    <xsl:value-of select="$fullUpload"/>
                </FullImport>
                <Resequencing>true</Resequencing>
                <JMSXGroupID>
                    <xsl:value-of select="$vJMSID"/>
                </JMSXGroupID>
                <JMSXGroupSeq>
                    <xsl:value-of select="$vFileCount"/>
                </JMSXGroupSeq>
                <GroupSize>
                    <xsl:value-of select="$vTotalMessages"/>
                </GroupSize>
                <OutboundQueueName>feeds/out/1.0/products</OutboundQueueName>
            </ControlData>
            <Message id="{$vFileCount}">
                <xsl:value-of select="odfn:JsonBS(xml-to-json($vResult,map{ 'indent':true() }))"/>
            </Message>
        </Payload>
        <xsl:next-iteration>
            <xsl:with-param name="vCount" select="1"/>
            <xsl:with-param name="vFileCount" select="$vFileCount+1"/>
            <xsl:with-param name="vStruct" select="''"/>
            <!-- blank -->
        </xsl:next-iteration>
    </xsl:otherwise>
</xsl:choose>

1 Ответ

0 голосов
/ 04 мая 2020

В качестве эксперимента отключите генерацию байт-кода. (FeatureKeys.GENERATE_BYTE_CODE)

Генерация байт-кода запускается, когда конструкция была выполнена определенное количество раз, что согласуется с вашим наблюдением, что сбой происходит только после выполнения определенного числа преобразований, и что это не не произойдет, если вы запустите эти преобразования по отдельности.

Я думаю, что есть очень большая вероятность, что проблема вызвана неправильной генерацией байт-кода. Если это подтвердится, мы, очевидно, хотели бы, чтобы вы помогли нам найти реальную ошибку (а не просто обойти ее): для этого попробуйте запустить с более низким порогом для генерации байт-кода, чтобы он срабатывал раньше (FeatureKeys.THESHOLD_FOR_HOTSPOT_BYTECODE ).

Я бы также посоветовал вам попробовать его на Saxon 10.0. Вполне возможно, что это ошибка, которая была исправлена.

...