I have an XML in which I wish to sort different nodes based on different criteria. I wish to have the output as an XML as well. The issue I run into is when a node-set matching one of the sort
is an ancestor of a node that is captured by a different sort
criterion.
Below is the XSL:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="//*[string]">
<xsl:copy>
<xsl:for-each select="string">
<xsl:sort order="ascending" data-type="text" case-order="upper-first"/>
<xsl:copy-of select="."/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/foo">
<xsl:copy>
<xsl:for-each select="bar">
<xsl:sort order="ascending" data-type="text" case-order="upper-first" select="name"/>
<xsl:copy-of select="."/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is a sample XML that when fed as input for the above XSL, shows the problem:
<root>
<foo>
<bar>
<name>W</name>
<blah>
<string>P</string>
<string>R</string>
<string>Q</string>
<string>S</string>
</blah>
</bar>
<bar>
<name>U</name>
<blah>
<string>N</string>
<string>L</string>
<string>M</string>
<string>O</string>
</blah>
</bar>
<bar>
<name>V</name>
<blah>
<string>Z</string>
<string>X</string>
<string>Y</string>
</blah>
</bar>
</foo>
<some>
<other>
<hierarchy>
<string>D</string>
<string>A</string>
<string>C</string>
<string>B</string>
</hierarchy>
</other>
</some>
<some>
<other>
<hierarchy>
<with />
<no />
<impact />
</hierarchy>
</other>
</some>
</root>
This is the output that I get:
<root>
<foo><bar>
<name>U</name>
<blah>
<string>N</string>
<string>L</string>
<string>M</string>
<string>O</string>
</blah>
</bar>
<bar>
<name>V</name>
<blah>
<string>Z</string>
<string>X</string>
<string>Y</string>
</blah>
</bar>
<bar>
<name>W</name>
<blah>
<string>P</string>
<string>R</string>
<string>Q</string>
<string>S</string>
</blah>
</bar>
</foo>
<some>
<other>
<hierarchy><string>A</string>
<string>B</string>
<string>C</string>
<string>D</string>
</hierarchy>
</other>
</some>
<some>
<other>
<hierarchy>
<with/>
<no/>
<impact/>
</hierarchy>
</other>
</some>
</root>
As one can see, the <name>
nodes as well as the <string>
nodes that appear in the some-other-hierarchy
are sorted. However, the <string>
nodes that are in the foo-bar-blah
hierarchy are unsorted.
I am required to use these versions of the libraries:
While they are old, I do not think/expect that will be an issue for the solution (i.e., the problem stems from my lack of knowledge regarding xsl:sort
and not the technology)
I would appreciate any/all help. Thank you for listening,
Instead of
<xsl:template match="//*[string]">
<xsl:copy>
<xsl:for-each select="string">
<xsl:sort order="ascending" data-type="text" case-order="upper-first"/>
<xsl:copy-of select="."/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/foo">
<xsl:copy>
<xsl:for-each select="bar">
<xsl:sort order="ascending" data-type="text" case-order="upper-first" select="name"/>
<xsl:copy-of select="."/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
try
<xsl:template match="*[string]">
<xsl:copy>
<xsl:apply-templates select="string">
<xsl:sort order="ascending" data-type="text" case-order="upper-first"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/foo">
<xsl:copy>
<xsl:apply-templates select="bar">
<xsl:sort order="ascending" data-type="text" case-order="upper-first" select="name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>