XSLT xsl: for each conditional selection
I have an xml part that looks like this:
<root> <tag1>tractor</tag1> <tag2> <subtag1 att="apple" /> <subtag2> <subsubtag1>red</subsubtag1> <subsubtag2>lunch</subsubtag2> </subtag2> </tag2> <tag1>forklift</tag1> <tag2> <subtag1 att="pear" /> <subtag2> <subsubtag1>green</subsubtag1> <subsubtag2>breakfast</subsubtag2> </subtag2> </tag2> <tag2> <subtag1 att="apple" /> <subtag2> <subsubtag1>green</subsubtag1> <subsubtag2>dinner</subsubtag2> </subtag2> </tag2> <tag1>combine harvester</tag1> </root> What I need to convert it so that I get subtags 2 and 3 from each tag2 node, but only tag2 nodes, where subtag1 is an apple. I also need a serial number for each.
My current code looks something like this:
<xsl:for-each select="//tag2"> <apple> <seq_num><xsl:value-of select="position()" /></seq_num> <colour><xsl:value_of select="subtag2" /></colour> <meal><xsl:value_of select="subtag3" /></meal> </apple> </xsl:for-each> This will be fine, except that I need for-each only to return tag2, which are apples (i.e. subtag1 = apple). I can not use xsl: if or xsl: when because the serial number will be inaccurate for the second apple.
Any ideas?
Thanks Rik
Stay with the code should be as simple as:
<xsl:for-each select="//tag2[subtag1/@att='apple']"> <apple> <seq_num><xsl:value-of select="position()" /></seq_num> <colour><xsl:value-of select="subtag2/subsubtag1" /></colour> <meal><xsl:value-of select="subtag2/subsubtag2" /></meal> </apple> </xsl:for-each> According to the comments below, as suggested, it is better to avoid // . You must be able to when in the right context. For instance:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/root"> <xsl:for-each select="tag2[subtag1/@att='apple']"> <apple> <seq_num><xsl:value-of select="position()" /></seq_num> <colour><xsl:value-of select="subtag2/subsubtag1" /></colour> <meal><xsl:value-of select="subtag2/subsubtag2" /></meal> </apple> </xsl:for-each> </xsl:template> </xsl:stylesheet> Signed at your entrance gives the same result. Or better yet, avoid xsl:for-each :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="/root"> <xsl:apply-templates select="tag2[subtag1/@att='apple']"/> </xsl:template> <xsl:template match="tag2"> <apple> <seq_num><xsl:value-of select="position()" /></seq_num> <colour><xsl:value-of select="subtag2/subsubtag1" /></colour> <meal><xsl:value-of select="subtag2/subsubtag2" /></meal> </apple> </xsl:template> </xsl:stylesheet>