0

I am trying to sort an XML file using XSLT transformation, but it doesn't do what I want. I want to sort the XML lexicographically by the loc element.

This is my original XML:

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>url3</loc>
    </url>
    <url>
        <loc>url2</loc>
    </url>
    <url>
        <loc>url1</loc>
    </url>
</urlset>

This is the xslt:

<?xml version="1.0" encoding="UTF-8"?>
<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="urlset">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates select="url">
                <xsl:sort select="loc" data-type="text" order="ascending" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

And I'd like to see this output:

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>url1</loc>
    </url>
    <url>
        <loc>url2</loc>
    </url>
    <url>
        <loc>url3</loc>
    </url>
</urlset>

I tried to follow this question, but I can't get it working.

How to sort a subelement

The XSLT above just copies the original xml without any sorting and that's it. Can somebody help me? How can I sort the loc tags?

Community
  • 1
  • 1
Alma Alma
  • 1,641
  • 2
  • 16
  • 19

1 Answers1

0

The problem here is not sorting, but selecting/matching nodes that are in their own namespace. This template:

<xsl:template match="urlset">

does not do anything, because the urlset element and all its descendants are in the "http://www.sitemaps.org/schemas/sitemap/0.9" namespace. You need to declare this namespace in your stylesheet, assign it a prefix and use that prefix when addressing the nodes:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sm="http://www.sitemaps.org/schemas/sitemap/0.9">

<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="sm:urlset">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates select="sm:url">
            <xsl:sort select="sm:loc" data-type="text" order="ascending" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Thank you so much. I've been struggling with this for a while. And yes, the problem was the missing namespace! Worked perfectly. – Alma Alma Jun 30 '14 at 06:20