ManUO
ManUO

Reputation: 347

XSLT sort by attribute value

I have a question about how to sort based on attribute value.

I have the following source document and I would like to sort the track items by the value of the title class value.

Hopefully someone can help with this.

input.xml:

<trackList>

    <track>
        <location>http://localhost/vmydoc</location>
        <title class="STD">Data Two</title>
    </track>
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="SH">Data Three</title>

    </track>
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="STD">Data Four</title>

    </track>
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="SH">Data Five</title>

    </track>
</trackList>

The final output should look like this:

output.xml:

<trackList>
        
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="SH">Data Three</title>
            
    </track>
        
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="SH">Data Five</title>
            
    </track>
        
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="STD">Data Four</title>
            
    </track>
    <track>
        <location>http://localhost/vmydoc</location>
        <title class="STD">Data Two</title>
    </track>
</trackList>

I have tried the following but it does not work.

my-stylesheet.xsl:

<xsl:for-each-group select="title" group-by="@class">
                        
    <xsl:for-each select="current-group()">
        <xsl:value-of select="@class"/>
    </xsl:for-each>
                        
</xsl:for-each-group>

Thanks.

Upvotes: 11

Views: 24216

Answers (1)

JLRishe
JLRishe

Reputation: 101652

You can do this as follows:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

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

  <xsl:template match="trackList">
    <xsl:copy>
      <xsl:apply-templates select="track">
        <xsl:sort select="title/@class"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

When run on your sample input, the result is:

<trackList>
  <track>
    <location>http://localhost/vmydoc</location>
    <title class="SH">Data Three</title>

  </track>
  <track>
    <location>http://localhost/vmydoc</location>
    <title class="SH">Data Five</title>

  </track>
  <track>
    <location>http://localhost/vmydoc</location>
    <title class="STD">Data Two</title>
  </track>
  <track>
    <location>http://localhost/vmydoc</location>
    <title class="STD">Data Four</title>

  </track>
</trackList>

Upvotes: 19

Related Questions