XSLT xsl:for-each conditional selection
I have a piece of xml 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 get transform it so that I get subtags 2 and 3 from each tag2 node, but only the tag2 nodes where subtag1 is apple. I also need a sequence 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 would be fine, except that I need the for-each only to return the tag2 which are apples (i.e. subtag1 = apple). I can't use an xsl:if or an xsl:when because then the sequence number would be inaccurate for the second apple.
Any ideas?
Thanks, Rik
To stay with your 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>
As per the comments below, as suggested, it's better avoid //
. You should be able when in the correct 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>
Apllied on your input, produces the same result. Or still better, avoid the xsl:for-each
as well:
<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>
精彩评论