Reputation: 10780
I rarely use XLST and get confusing results when I try to count child nodes in a parent node.
Edit:
The XML is structured as follows:
<?xml version="1.0"?>
<Response>
<result>
<name>Someone</name>
**<rating>4.5</rating>**
<review>
<text>Some review.</text>
</review>
<review>
<text>Another review.</text>
</review>
</result>
<result>
<name>Another one</name>
**<rating>2</rating>**
<review>
<text>Blah, grieve, blah.</text>
</review>
<review>
<text>Blah, grrrrr, blah.</text>
</review>
<review>
<text>Blah, good grrrrr, blah.</text>
</review>
</result>
...
...
</Response>
The template (simplified) is as follows:
**<body>
<xsl:apply-templates/>
</body>**
<xsl:template match="Response/result">
<div class="item">
<div class="name">
<xsl:value-of select="name"/>
</div>
<xsl:if test="rating">
<span class="review-count">
**(<xsl:value-of select="count(review)"/>)**
</span>
</xsl:if>
</div>
</xsl:template>
I do not get the correct child node count from this approach. In addition to the count(review)
, I tried count(descendant::review)
and several xPath variations. I know I'm missing something simple - but what?
Upvotes: 12
Views: 53511
Reputation: 243579
<xsl:if test="rating"> <span class="review-count"> **(<xsl:value-of select="count(review)"/>)** </span> </xsl:if>
This will never generate even a single character, because there is no rating
element in the provided XML document. In case you remove the above conditional instruction, then the result contains the wanted count values.
If you indeed have rating
child for at least some review
elements (but failed to show this to us), then you probably also didn't show other important parts of the XML document -- such as a default namespace.
Update:
The OP has provided a more precise XML document, that contains rating
elements.
I can't repro the problem.
This XSLT transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="Response/result">
<div class="item">
<div class="name">
<xsl:value-of select="name"/>
</div>
<xsl:if test="rating">
<span class="review-count">
**(<xsl:value-of select="count(review)"/>)**
</span>
</xsl:if>
</div>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<Response>
<result>
<name>Someone</name>
<rating>4.5</rating>
<review>
<text>Some review.</text>
</review>
<review>
<text>Another review.</text>
</review>
</result>
<result>
<name>Another one</name>
<rating>2</rating>
<review>
<text>Blah, grieve, blah.</text>
</review>
<review>
<text>Blah, grrrrr, blah.</text>
</review>
<review>
<text>Blah, good grrrrr, blah.</text>
</review>
</result>
...
...
</Response>
produces the wanted, correct result:
<div class="item">
<div class="name">Someone</div>
<span class="review-count">
**(2)**
</span>
</div>
<div class="item">
<div class="name">Another one</div>
<span class="review-count">
**(3)**
</span>
</div>
...
...
Upvotes: 16