Reputation: 9578
I have been through many similar questions and XSLT tutorials but still I am unable to figure out how XSLT works.
Below is the XML that I want sort :-
<?xml version="1.0" encoding="UTF-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
<file product="mxn" source-language="en">
<body>
<!-- Menu -->
<msg-unit id="Menu.PerformTask">
<msg>Perform Task</msg>
<note>When selected performs a task.</note>
</msg-unit>
<msg-unit id="Menu.Add">
<msg>Add New</msg>
<note>When selected Adds a new row.</note>
</msg-unit>
</body>
</file>
</xliff>
Expected output is:-
<?xml version="1.0" encoding="UTF-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.1" version="1.1">
<file product="mxn" source-language="en">
<body>
<!-- Menu -->
<msg-unit id="Menu.Add">
<msg>Add New</msg>
<note>When selected Adds a new row.</note>
</msg-unit>
<msg-unit id="Menu.PerformTask">
<msg>Perform Task</msg>
<note>When selected performs a task.</note>
</msg-unit>
</body>
</file>
</xliff>
The <msg-unit>
tags needs to be sorted based on the value of their id
attributes. Other tags (like the comments) should be where-ever they were.
I tried so many combinations but I have no clue about XSLT. Below is what was my last attempt.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:copy-of select="*">
<xsl:apply-templates>
<xsl:sort select="attribute(id)" />
</xsl:apply-templates>
</xsl:copy-of>
</xsl:template>
</xsl:stylesheet>
This one simply spits out whatever XML it got, without any sorting.
Upvotes: 1
Views: 4210
Reputation: 107367
Edit Updated - this template will sort only msg-unit
elements by @id
without interfering with the rest of the xml.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:choose>
<xsl:when test="*[local-name()='msg-unit']">
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@id" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@* | node()" />
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1