xml - double sort in xslt on two different fields -
i sort xml file on 2 fieds: identifier , impact. order elements identifier, except elements have xx product must appear last.
my xml file
<evolutionlist> <date> <object> <identifier>id5</identifier> <impact> <product>aa</produit> </impact> </objet> <object> <identifier>id2</identifier> <impact> <product>xx</produit> </impact> </objet> <object> <identifier>id4</identifier> <impact> <product>bb</produit> </impact> </objet> <object> <identifier>id3</identifier> <impact> <product>xx</produit> </impact> </objet> <object> <identifier>id1</identifier> <impact> <product>cc</produit> </impact> </objet> </date> </evolutionlist>
the expceted result be:
<evolutionlist> <date> <object> <identifier>id1</identifier> <impact> <product>cc</produit> </impact> </objet> <object> <identifier>id4</identifier> <impact> <product>bb</produit> </impact> </objet> <object> <identifier>id5</identifier> <impact> <product>aa</produit> </impact> </objet> <object> <identifier>id2</identifier> <impact> <product>xx</produit> </impact> </objet> <object> <identifier>id3</identifier> <impact> <product>xx</produit> </impact> </objet> </date> </evolutionlist>
my xslt code (does not work though)
<xsl:for-each select="//date"> <tr> <td> <xsl:value-of select="./@id"/> </td> </tr> <xsl:for-each select="./object"> <xsl:choose> <xsl:when test="impact/produit = 'xx'"> <xsl:sort select="impact/produit" order="descending"/> </xsl:when> <xsl:otherwise> <xsl:sort select="identifiant"/> </xsl:otherwise> </xsl:choose> ... </xsl:for-each>
you can place <xsl:sort>
in origin of <xsl:for-each>
or <xsl:apply-templates/>
, not in <choose>
block.
you using sort order xx
, i assume that's ok in scenario (e.g.: don't have product named zz
, placed after xx
). if that's not case, shouldn't utilize sort
rule, template matches xx
contents , places them @ end.
this stylesheet produces results expect using sort
rules have in original stylesheet (ordering id , product strings). moved selection rules xpath predicate, , used templates instead of nested for-each
nodes.
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:template match="date"> <xsl:apply-templates select="object"> <xsl:sort select="impact/product[. = 'xx']" order="ascending"/> <xsl:sort select="identifier"/> </xsl:apply-templates> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
you can seek out in xslt fiddle
update in case don't want order xx
products, place them @ end, always, can filter elements , apply templates after processing other elements. other stylesheet that:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:template match="date"> <xsl:apply-templates select="object[not(impact[product = 'xx'])]"> <xsl:sort select="identifier"/> </xsl:apply-templates> <xsl:apply-templates select="object[impact[product = 'xx']]"/> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
here's xslt fiddle example.
xml xslt
No comments:
Post a Comment