Reputation: 1
I got a XML file looks like
<root>
<number>1</number>
<number>
<deleted>0</deleted>
3
</number>
<number>2</number>
</root>
I want to sort the file only by valid value, like the valid value of the second element is 3. I only need the value not contained in any child elements. So the desired output looks like:
<root>
<number>1</number>
<number>2</number>
<number>
<deleted>0</deleted>
3
</number>
</root>
I tried to use except
in sorting but it didn't work. My stylesheet:
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="number">
<xsl:sort select=". except del"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
Thank you!
Add: I changed the XML into
<root>
<number>1</number>
<number>
1
<deleted>0</deleted>
3
</number>
<number>2</number>
</root>
Insert a node before the <deleted>
tag, then the <xsl:sort select="text()">
can't work. An error message says
XTTE1020: A sequence of more than one item is not allowed as the @select attribute of xsl:sort (text("1"), text("3"))
Please help :(
Upvotes: 0
Views: 140
Reputation: 70638
.
matches the current node, which is number
, so doing . except deleted
is not really going to achieve much. You need to sort on the child node that is not deleted
<xsl:sort select="node() except deleted" data-type="number" />
Although, it is really only the text node you want, so you don't really need except
at all
<xsl:sort select="text()" data-type="number" />
However, this will only work if you strip out white-space nodes first with xsl:strip-space
(otherwise you will get an error about the sort selecting a sequence of nodes). Alternatively you could do <xsl:sort select="text()[normalize-space()]" data-type="number" />
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes" />
<xsl:template match="root">
<xsl:copy>
<xsl:for-each select="number">
<xsl:sort select="text()" data-type="number" />
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note, the above stylesheet will work in XSLT 1.0, but if you are using XSLT 2.0, then you can simplify this a bit with xsl:perform-sort
instead...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes" />
<xsl:template match="root">
<xsl:copy>
<xsl:perform-sort select="number">
<xsl:sort select="text()" data-type="number" />
</xsl:perform-sort>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
EDIT: And, if you have multiple child text nodes, then do this to concatenate them...
<xsl:sort select="string-join(text()/normalize-space())" data-type="number" />
Upvotes: 1