简体   繁体   中英

XSLT Copy and Sort Multiple Nodes

I want to take the following XML and sort:

  1. The <person> elements by the value of the <name> element
  2. The <code> elements by their value

XML

 <test>
    <person>
        <name>Tom</name>
        <codes>
            <code>BS</code>
            <code>BA</code>
            <code>BM</code>
        </codes>
    </person>
    <person>
        <name>Dick</name>
    </person>
    <person>
        <name>Harry</name>
        <codes>
            <code>AB</code>
            <code>FG</code>
            <code>C</code>
        </codes>
    </person>
</test>

XSLT

Using the following XSLT, I am able to achieve outcome 1 but outcome 2 eludes me:

 <xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="utf-8" indent="yes" version="1.0" />

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

    <xsl:template match="test">

        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates select="person">
                <xsl:sort select="name" />
            </xsl:apply-templates>
        </xsl:copy>

    </xsl:template>
</xsl:stylesheet>

Current Output

The current output is

<test>
    <person>
        <name>Dick</name>
    </person>
    <person>
        <name>Harry</name>
        <codes>
            <code>AB</code>
            <code>FG</code>
            <code>C</code>
        </codes>
    </person>
    <person>
        <name>Tom</name>
        <codes>
            <code>BS</code>
            <code>BA</code>
            <code>BM</code>
        </codes>
    </person>
</test>

Desired Output

That is a step in the right direction, but I need:

  <test>
        <person>
            <name>Dick</name>
        </person>
        <person>
            <name>Harry</name>
            <codes>
                <code>AB</code>
                <code>C</code>
                <code>FG</code>
            </codes>
        </person>
        <person>
            <name>Tom</name>
            <codes>               
                <code>BA</code>
                <code>BM</code>
                <code>BS</code>
            </codes>
        </person>
    </test>

I have tried a few ways but none work.

How about:

XSLT 1.0

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

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

<xsl:template match="/test">
    <xsl:copy>
        <xsl:apply-templates select="person">
            <xsl:sort select="name" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="codes">
    <xsl:copy>
        <xsl:apply-templates select="code">
            <xsl:sort/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM