【问题标题】:XSLT unable to remove line break before and after attribute valueXSLT 无法删除属性值前后的换行符
【发布时间】:2018-11-19 13:35:06
【问题描述】:

我正在尝试将带有 XSLT 3.0 和 Saxon 9.9 HE 的 XML 模式转换为 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

我已经尝试了所有可以在帖子中找到的机制,将其分配给变量、规范化空间、规范化空间和字符串()和数据()。似乎没有任何工作。任何帮助将不胜感激。

=== 包括完整的例子===

XSL(删除了所有的 cmets 和其他元素):

<?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());

【问题讨论】:

  • 您可以使用&lt;xsl:text&gt;':{&lt;/xsl:text&gt; 来确保您仅显式输出该文本,而不是当前代码还包含的换行符。但是,鉴于您使用 XSLT 3 并且想要 JSON 输出,使用 output method="json" 并让代码创建必要的 XPath 3.1 映射结构似乎更合适。
  • @MartinHonnen,建议尝试 {'groupName':'' 它仍然提供相同的输出将换行...任何帮助将不胜感激,谢谢
  • 考虑发布最少但完整的示例,以便我们重现问题。当我尝试在xsltfiddle.liberty-development.net/gWmuiKm/1 应用我的建议时,我在一行'IMAPConnectorConfig':{'name':'imapHost','name':'imapPort' 上得到属性名称。但是不确定具有相同名称name 的两个属性的 JSON 类型。
  • 至于我建议使用输出方法json 并构建XPath 3.1 映射,请参阅xsltfiddle.liberty-development.net/gWmuiKm。我必须调整结构以使 JSON 有意义,因为如果 JSON 真的是目标格式,那么有几个 "name" : "..." 似乎没有意义。
  • xsl:output 上的属性 normalization-form="true" 真的对你有用吗?如果您发布最少但完整的示例以允许其他人运行示例以轻松重现问题,这将非常有帮助,不明白为什么我们需要完成模式或样式表代码。也尝试先从命令行运行。如果您希望xsl:output 产生任何效果,我不明白您为什么使用applyTemplates 的重载返回原始结果,似乎最好使用发生序列化的目的地。

标签: xml xslt xsd saxon


【解决方案1】:

一般来说,要控制文本输出,可以在表单中使用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,其中格式由 XSLT 中的 xsl:output 定义,那么您应该使用 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-SerializerXslt30Transformer (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- 说它返回

将模板应用于提供的选择值的原始结果, 无需包装在文档节点或序列化结果

根据您的 cmets 发现,如果您有一个 XdmValue 并希望以受控方式对其进行序列化,您最好使用 SerializerserializeXdmValue 方法根据需要设置,而不是只需在XdmValue 上调用toString

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 2020-04-04
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    相关资源
    最近更新 更多