tags:

views:

106

answers:

3

I want to be able to count "end points" in an XML file using XSL. By endpoint I mean tag's with no children that contain data.

i.e.

<xmlsnippet> 
    <tag1>NOTENOUGHDAYS</tag1> 
    <tag2>INVALIDINPUTS</tag2> 
    <tag3> 
        <tag4> 
            <tag5>2</tag5> 
            <tag6>1</tag6> 
        </tag4> 
    </tag3> 
</xmlsnippet> 

This XML should return 4 as there are 4 "end points"

+3  A: 

*[not(*)] is used for elements that has no children elements.

edit: for counting them just use count(elements)

o15a3d4l11s2
How do I do this recursively?
Chris
+2  A: 

Try:-

 <xsl:variable name="numOfLeafNodes" select="count(//*[not(*)])" />

this will tell you how many leaf nodes are found in the whole xml being transformed. Use:-

 <xsl:variable name="numOfLeafNodes" select="count(.//*[not(*)])" />

to find the count of leaf nodes that are descendents of the current context node.

AnthonyWJones
If I do this `<xsl:variable name="numOfLeafNodes" select="count(ParentTag/xmlsnippet/*[not(*)])" />` then it returns 2 not 4.
Chris
@Chris: Indeed, but this would return 4: `count(ParentTag/xmlsnippet//*[not(*)])` note the `//` to which is a short-cut for `descendents::` axis. Also noticed I had missed out the actual count function itself.
AnthonyWJones
+6  A: 
<xsl:template match="/>
  <xsl:value-of select="count(//*[not(*) and normalize-space() != ''])" />
</xsl:template>

This recurses the entire XML tree via the descendant axis (//), looks at all element nodes (*) that have no child element nodes (not(*)) and contain data other than whitespace (normalize-space() != '').

The resulting node-set is counted (and returns 4 in your case).

Tomalak
This looks good but the XML I posted is just a snippet so I need to call something like `select="count(//ParentTag/xmlsnippet/*[not(*) and normalize-space() != ''])"` - this returns 2 not 4. What am I doing wrong?
Chris
Aha, I used this and it worked `select="count(ParentTag/xmlsnippet//*[not(*) and normalize-space() != ''])"`
Chris