将两个XSLT合并为一个以处理相同的节点,原因有两个

时间:2017-11-16 16:31:38

标签: xml xslt xml-parsing xslt-1.0

我想删除所有名称空间(包括属性中的所有xmlns和xsi),然后想要对输出进行排序。

示例XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="https://www.w3schools.com/furniture" xmlns='http://ns.xyz.org/2004-08-02'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:ns1='http://ns.xyz.org/2004-08-02'
xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:type='ns1:table'>

    <h:table>
        <h:tr>
            <!-- <TestComment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/> -->
            <h:td att2="2" att1="1">Bananas</h:td>
            <h:td xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true">Apples</h:td>
        </h:tr>
    </h:table>

    <f:table>
        <f:name class="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true">African Coffee Table</f:name>
        <f:width>80</f:width>
        <f:length>120</f:length>
    </f:table>
</root>

现在我正在用两个不同的xsls转换xml。

删除名称空间(包括xmlns&amp; xsi)的XSL是

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="@xsi:*" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<xsl:template match="comment()|processing-instruction()"/>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

这给了我以下输出

<root>
    <table>
        <tr>
            <td att2="2" att1="1">Bananas</td>
            <td>Apples</td>
        </tr>
    </table>
    <table>
        <name class="1">African Coffee Table</name>
        <width>80</width>
        <length>120</length>
    </table>
</root>

然后我使用下面的xsl对xml进行排序

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="utf-8" method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*">
                <xsl:sort select="local-name()"/>
            </xsl:apply-templates>
            <xsl:apply-templates select="node()">
                <xsl:sort select="local-name()"/>
                <xsl:sort select="."/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这给了我最终的输出

<root>
    <table>
        <length>120</length>
        <name class="1">African Coffee Table</name>
        <width>80</width>
    </table>
    <table>
        <tr>
            <td>Apples</td>
            <td att1="1" att2="2">Bananas</td>
        </tr>
    </table>
</root>

现在,如何将这两个处理合并到一个xsl文件中,这样我就不必再进行两次转换了?

1 个答案:

答案 0 :(得分:2)

将两个xsl:sort移动到命名空间中删除模板:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="@xsi:*" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<xsl:template match="comment()|processing-instruction()"/>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@*">
            <xsl:sort select="local-name()"/>
        </xsl:apply-templates>
        <xsl:apply-templates>
          <xsl:sort select="local-name()"/>
          <xsl:sort select="."/>
        </xsl:apply-templates>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

http://xsltransform.hikmatu.com/jyyiVhg

或者使用两种模式分离处理步骤并执行变量的第一步,然后使用exsl:node-set以第二步/模式处理它。