tags:

views:

26

answers:

1

I have XML like this:

<exam>
    <section name="SampleSection1">
        <attributes>
            <variable_name data_type="String" value="SCORE"/>
        </attributes>
        <item name="SampleItem1-1"/>
        <item name="SampleItem1-2"/>
        <item name="SampleItem1-3"/>
    </section>
    <section name="SampleSection2">
        <attributes>
            <variable_name data_type="String" value="NO-SCORE"/>
        </attributes>
        <item name="SampleItem2-1"/>
        <item name="SampleItem2-2"/>
    </section>
</exam>

I want to count the number of items that are in a section that has a variable_name of "SCORE".

I thought that this would do the job:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

  <xsl:output method="text"/>

    <xsl:template match="section">
        <xsl:variable name="scoredItems"
                  select="./item/../attributes/variable_name[@value='SCORE']"/>
        <xsl:variable name="scoredItemsCount" select="count($scoredItems)"/>
        <xsl:value-of select="$scoredItemsCount"/>
    </xsl:template>
</xsl:stylesheet>

However, this outputs:

1
0

not

3
0

which is what I would expect (and want).

What am I doing wrong here?

+2  A: 
    <xsl:variable name="scoredItems" 
              select="./item/../attributes/variable_name[@value='SCORE']"/>

This selects all variable-name elements such that their value attribute has value of 'SCORE'. And this is just one node.

You want:

self::section[attributes/variable_name/@value='SCORE']/item

This selects all item elements in case the context node (section) has an element attributes that has an element variable_name whose value attribute is `'SCORE'.

In case the context node doesn't have that property, then the above XPath expression selects nothing.

Now the corrected transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

  <xsl:output method="text"/>

    <xsl:template match="section">
        <xsl:variable name="scoredItems"
                  select="self::section[attributes/variable_name/@value='SCORE']/item"/>
        <xsl:variable name="scoredItemsCount" select="count($scoredItems)"/>
        <xsl:value-of select="$scoredItemsCount"/>
    </xsl:template>
</xsl:stylesheet>

produces the wanted result:

3
0
Dimitre Novatchev