XSLT не может удалить разрыв строки до и после значения атрибута - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь преобразовать XML-схему с XSLT 3.0 с Saxon 9.9 HE в JSON. Преобразование работает. Однако, когда я вывожу значение атрибута, оно идет с разрывом строки до и после имени. Фрагмент XSD приведен ниже:

    <group name="imapAttachmentDownloaderGroup">
    <annotation>
        <documentation>
            Configuration block definitions for IMAP attachment downloader delegate. It contains all the configuration
            block definitions that are required to configure the delegate successfully.
        </documentation>
    </annotation>
    <sequence>
        <element name="IMAPConnectorConfig">
            <complexType>
                <attribute name="imapHost" use="required" type="string">
                    <annotation>
                        <documentation>
                            This configuration block deals with the IMAP server name or IP address to where the 
                            connection is to be made to download the attachments.
                            Example: "outlook.office365.com" or "40.100.137.66"
                        </documentation>
                    </annotation>
                </attribute>
                <attribute name="imapPort" use="required" type="int">
                    <annotation>
                        <documentation>
                            The port to use to connect to the server, defaults to 993.
                            Example: "993"
                        </documentation>
                    </annotation>
                </attribute>
....

SXL, как показано ниже:

<?xml version="1.0" encoding="UTF-8"?>
<stylesheet version="3.0" 
            xmlns="http://www.w3.org/1999/XSL/Transform"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema"
            xmlns:tns="http://www.proviseconsulting.com/ProcessConfig"
            xmlns:saxon="http://saxon.sf.net/"
            xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform 
                                https://www.w3.org/2007/schema-for-xslt20.xsd">

<mode on-no-match="shallow-skip"/>
<output method="text" encoding="utf-8" indent="no" media-type="application/json" normalization-form="true"/>
<strip-space elements="*" />
<!-- <template match="text()|@*"/> -->
<param name="delegateGroupName" required="yes"/>

<template match="/child::xsi:schema/child::xsi:group[attribute::name=$delegateGroupName]">
    <variable name="xx" select="attribute::name"/>
    {'groupName':'<value-of select="normalize-space($xx)"/>'
                  <for-each select="child::xsi:sequence/child::xsi:element">
                    ,'<value-of select="attribute::name"/>':{
                        <for-each select="child::xsi:complexType/child::xsi:attribute">
                            <choose>
                                <when test="position()=last()">'name':'<value-of select="attribute::name"/>'</when>
                                <otherwise>'name':'<value-of select="attribute::name"/>',</otherwise>
                            </choose>
                        </for-each>
                        <for-each select="child::xsi:complexType/child::xsi:attributeGroup">
                            <value-of select="attribute::ref"/>
                        </for-each>
                                                            }
                  </for-each>
        }

    <!-- <apply-templates select="attribute::name"/> -->
</template>

Вывод:

    {'groupName':'
imapAttachmentDownloaderGroup
'
,    '
IMAPConnectorConfig
':{
'name':'
imapHost
',
'name':'
imapPort
',
'name':'
sslEnabled
',
'name':'
startTLSEnabled
',
'name':'
imapUser
',
'name':'
imapPassword
',
'name':'
credentialId

Я испробовал все механизмы, которые я мог найти в постах, присваивающих его переменной, normalize-space, normalize-space с string () с data (). Кажется, ничего не работает. Любая помощь будет с благодарностью.

=== Включая полный пример ===

XSL (удалены все комментарии и другие элементы):

<?xml version="1.0" encoding="UTF-8"?>
<stylesheet version="3.0" 
            xmlns="http://www.w3.org/1999/XSL/Transform"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema"
            xmlns:tns="http://www.proviseconsulting.com/ProcessConfig"
            xmlns:saxon="http://saxon.sf.net/"
            xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform 
                                https://www.w3.org/2007/schema-for-xslt20.xsd">

<mode on-no-match="shallow-skip"/>
<output method="text" encoding="utf-8" indent="no" media-type="application/json" normalization-form="true"/>
<strip-space elements="*" />

<param name="delegateGroupName" required="yes"/>

<template match="/child::xsi:schema/child::xsi:group[attribute::name=$delegateGroupName]">
    <text>{"groupName":"</text><value-of select="attribute::name/normalize-space()"/><text>"}</text>
</template>

=== Вывод ===

{"groupName":"
imapAttachmentDownloaderGroup
"}

Вход XSD остается прежним. Код Java выглядит следующим образом:

        String xsdFilePath="file:///D:/workspaces/mtplatform/PlatformManual_V1/PlatformManual/ProcessConfiguration/ProcessConfiguration.xsd";
    String xslFilePath="file:///D:/workspaces/mtplatform/PlatformManual_V1/PlatformManual/ProcessConfiguration/ProcessConfiguration.xsl";

    Processor processor=new Processor(false);
    XdmNode node=processor.newDocumentBuilder().build(new File(new URI(xsdFilePath)));
    XsltCompiler xsltCompiler=processor.newXsltCompiler();
    //xsltCompiler.setParameter(new QName("delegateGroupName"), XdmValue.makeValue("imapAttachmentDownloaderGroup"));

    StreamSource xsdSource=new StreamSource(new FileInputStream(new File(new URI(xsdFilePath))));
    StreamSource xslSource=new StreamSource(new FileInputStream(new File(new URI(xslFilePath))));

    XsltExecutable compiledXSL=xsltCompiler.compile(xslSource);
    Xslt30Transformer xslTransformer=compiledXSL.load30();

    HashMap<QName, XdmValue> parameterMap=new HashMap<>();
    parameterMap.put(new QName("delegateGroupName"), XdmValue.makeValue("imapAttachmentDownloaderGroup"));
    xslTransformer.setStylesheetParameters(parameterMap);
    XdmValue output=xslTransformer.applyTemplates(node);

    System.out.println(output.toString());

1 Ответ

0 голосов
/ 20 ноября 2018

Как правило, для управления выводом текста можно использовать элемент xsl:text https://www.w3.org/TR/xslt-30/#xsl-text в форме

 <for-each select="child::xsi:sequence/child::xsi:element">
                <text>,'</text>
                <value-of select="attribute::name"/>
                <text>':{</text>

Кроме того, если вы используете Xslt30Transformer и хотите получить сериализованный результат в виде текста, например JSON, где формат определяется xsl:output в вашем XSLT, тогда вам следует использовать перегрузку applyTemplates, позволяющую вы должны использовать Serializer в качестве пункта назначения, то есть http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/Xslt30Transformer.html#applyTemplates-net.sf.saxon.s9api.XdmValue-net.sf.saxon.s9api.Destination- с Serializer, созданным Xslt30Transformer (http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/Xslt30Transformer.html#newSerializer-java.io.OutputStream-),, так что в простом случае тестирования результата с System.out вы будет использовать

Serializer serializer =  xslTransformer.newSerializer(System.out);
xslTransformer.applyTemplates(node, serializer);

В вашем случае с Java вы использовали перегрузку для создания XdmValue, обратите внимание, что в его документации http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/Xslt30Transformer.html#applyTemplates-net.sf.saxon.s9api.XdmValue- написано, что он возвращает

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

Как вы обнаружили в соответствии с вашими комментариями, если у вас есть XdmValue и вы хотите его сериализовать контролируемым образом, вам лучше использовать serializeXdmValue метод Serializer, настроенный по необходимости вместо просто позвонив toString на XdmValue.

...