Search code examples
xslt-2.0xsl-fo

Find The Count Of An Element Where Element Is Getting Identified By The Content Text Of Tag In The XML


I am trying Find The Position Or Count of a parent element ; when we can identify its child element with the help of it containing text; below is the xml:

<start>
<Item>
<ItemName>x</ItemName>
<ItemValue>x val</ItemValue>
</Item>
<Item>
<ItemName>y</ItemName>
<ItemValue>y val</ItemValue>
</Item>
<Item>
<ItemName>z</ItemName>
<ItemValue>z val</ItemValue>
</Item>
<Item>
<ItemName>y</ItemName>
<ItemValue>y val</ItemValue>
</Item>
<Item>
<ItemName>Head</ItemName>
<ItemValue>Head val</ItemValue>
</Item>
<Item>
<ItemName>Head1</ItemName>
<ItemValue>Head1 Val</ItemValue>
</Item>
<Item>
<ItemName>Head2</ItemName>
<ItemValue>Head2 Val</ItemValue>
</Item>
</start>

Now as soon as I will find /start/Item[ItemName='Head'] this, I want to find out what is it's position or how many '/start/Item' precedes before this ItemName='Head' so that I can use that count/value/position and fetch further Heads Head1, Head2 etc... ; ItemName Head will be static but Head1, Head2 will be dynamic.

I checked using below I am able to travers to ItemName Head

<xsl:if test="/start/Item[ItemName='Head'] "/> 

So how I can achieve the goal after this ?

Update

I tried below code :

Just trying to print the count in the body but it is not working

<fo:block>
  <xsl:template match="start/Item[ItemName='Head']">
    Count <xsl:value-of select="count(preceding-sibling::Item)"/> 
  </xsl:template>
</fo:block>

Am I missing some thing here? I am new to this so my apology If I am doing very basic mistake here

---------Update--------

Sorry for being inconvenient that I added the code in comment and updated the same in the question. So as it was suggested I tried that and yes it is working ; below is the working code:

</xsl:template>
 <xsl:variable name="var">
    <xsl:apply-templates select="start/Item[ItemName='Head']"/>
</xsl:variable>

 <fo:block  margin-top="9.50mm">
  <xsl:value-of 
  select="start/Item[number($var)+1]/ItemValue"/>
 </fo:block>
</xsl:template>

<xsl:template match="start/ItemItemName='Head']">
  <xsl:value-of select="count(preceding-sibling::Item)"/>
</xsl:template>

Do we have any other short approach for retrieving the index of the xml element ; just wanted to know am I writing unnecessary code for just to get the index ?


Solution

  • In the context of e.g. <xsl:template match="start/Item[ItemName = 'Head']"> you can select e.g. count(preceding-sibling::Item) to find out how many Item elements precede the currently matched Item as siblings.

    Of course depending on your needs and/or context you might want e.g. count(/start/Item[ItemName = 'Head']/preceding-sibling::Item) or (XPath 2 and later) /start/Item[ItemName = 'Head']/count(preceding-sibling::Item).