Tim
Tim

Reputation: 1023

how to express xpath 1.0 count function?

I have a document like the one below and I need the count of each subitem[@role="special"] starting from its parent item.

My problem is that I need to calculate the number for the subitem and the same value for any nested subitems in that subitem. So for all subitems that are descendants of subitem[@role="special"] I should always get the same value. I've labeled what I want in the tree below with (want N)

<root>
    <item role="special">
        <name>One</name>
        <subitem>
            <name>A (want 0)</name>
        </subitem>
    </item>
    <item>
        <name>Two</name>
        <subitem role="special">
            <name>B (want 1)</name>
            <subitem>
                <name>B b (want 1)</name>
            </subitem>
        </subitem>
        <subitem>
            <name> C (want 0)</name>
            <subitem>C c (want 0)</subitem>
        </subitem>

        <subitem role="special">
            <name> D (want 2)</name>
            <subitem>
                <name>D d (want 2)</name>
            </subitem>
        </subitem>
    </item>
</root>

These are the kinds of things I've tried but I'm beginning to wonder if what I want is possible:

    <xsl:template match="subitem">
      <xsl:value-of select="count(ancestor-or-self::subitem[@role='special'])"/>
      <xsl:value-of select="count(preceding-sibling::subitem[@role='special'])"/>
      <xsl:text>
      </xsl:text>
      <xsl:apply-templates/>
  </xsl:template>

that itself returns:

  00
  10
  10
  01
  00
  11
  10

Is there a way to accomplish this?

Upvotes: 0

Views: 234

Answers (1)

Jayvee
Jayvee

Reputation: 10875

If I understood correctly, you have three cases: the current subitem is special itself or is descendant of a special item or is not special. Then we can use a choose condition for it and treat each case as applicable:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 <xsl:template match="subitem">
 <xsl:choose>
    <xsl:when test="@role='special'">
      <xsl:value-of select="count(preceding-sibling::subitem[@role='special'])+1" />
    </xsl:when>
    <xsl:when test="ancestor::subitem[@role='special']">
      <xsl:value-of select="count(preceding::subitem[@role='special'])+1" />
    </xsl:when> 
    <xsl:otherwise>0</xsl:otherwise>
</xsl:choose>      
      <xsl:text>
      </xsl:text>
      <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Related Questions