如何在XSLT 2.0的输出中不复制属性

时间:2019-07-15 07:51:54

标签: xml xslt xslt-1.0 xslt-2.0 xslt-grouping

我想将一种XML消息转换为另一种。我的输入消息当前包含一些属性为@ nil = ture的空元素。我想要的是应该将这些元素创建为空,但没有nill属性。请在下面查看我目前的进展情况:

输入XML:

<?xml version="1.0" encoding="UTF-8"?>
    <collection>
        <row>
            <nr>A00</nr>
            <type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
        </row>
        <row>
            <nr>A01</nr>
            <type>mash</type>
        </row>
    </collection>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:template match="//*[local-name()='collection']">
        <jsonArray>
            <xsl:text disable-output-escaping="yes">&lt;?xml-multiple?&gt;</xsl:text>
            <xsl:for-each select="//*[local-name()='row']">
                <jsonObject>
                     <xsl:copy-of select="node() except @nil" />
                </jsonObject>
            </xsl:for-each>
        </jsonArray>
    </xsl:template>
</xsl:stylesheet>

当前输出:

<?xml version="1.0" encoding="UTF-8"?>
<jsonArray>
   <?xml-multiple?>
   <jsonObject>
      <nr>A00</nr>
      <type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
   </jsonObject>
   <jsonObject>
      <nr>A01</nr>
      <type>mash</type>
   </jsonObject>
</jsonArray>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<jsonArray>
   <?xml-multiple?>
   <jsonObject>
      <nr>A00</nr>
      <type/>
   </jsonObject>
   <jsonObject>
      <nr>A01</nr>
      <type>mash</type>
   </jsonObject>
</jsonArray>

1 个答案:

答案 0 :(得分:2)

当您执行<xsl:copy-of select="node() except @nil" />时,您正在复制当前row的子元素,这些子元素将被复制而无需更改。 except @nil不会执行您期望的操作,因为它将在当前@nil元素上寻找名为row的属性(无论如何,您寻找的属性是@xsi:nil

相反,将xsl:copy-of替换为xsl:apply-templates,并将身份模板添加到您的XSLT(稍作调整即可删除名称空间声明)。

<xsl:template match="@*|node()">
    <xsl:copy copy-namespaces="no">
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

然后,您只需要一个模板即可忽略xsl:type

    <xsl:template match="@xsi:nil" />

尝试使用此XSLT

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="xsi">

    <xsl:template match="@*|node()">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@xsi:nil" />

    <xsl:template match="//*[local-name()='collection']">
        <jsonArray>
            <xsl:processing-instruction name="xml-multiple" />
            <xsl:for-each select="//*[local-name()='row']">
                <jsonObject>
                     <xsl:apply-templates select="@*|node()" />
                </jsonObject>
            </xsl:for-each>
        </jsonArray>
    </xsl:template>
</xsl:stylesheet>

(请注意,您确实应该使用xsl:processing-instruction来创建处理说明)。