Find position of parent node using xpath

15,627

Solution 1

count(../preceding-sibling::cd) + 1

You can run it here (note I removed the other number you were outputting, just for clarity).

You were on the right lines, but remember that predicates are used only to filter nodes, not to return information. So:

../*[position()]

...effectively says "find me the parent that has a position". It returns the node, not the position itself. The predicate is just a filter.

In any case there are pitfalls with using position(), and it can be used to return the position of the current, context node only - not another node.

Solution 2

Utkanos's answer works fine but my experience is that, when the xml document is large, this could lead to performance issues.

In this scenario you could simply pass the position of the parent in a param.

<xsl:template match="/">
<html>
  <body>  
  <xsl:apply-templates/>  
  </body>
  </html>
</xsl:template>

<xsl:template match="cd">
  <p>
    <xsl:number format="1. "/><br/>
    <xsl:apply-templates select="title">  
        <xsl:with-param name="parent_position" select="position()"/> <!-- Send here -->
    </xsl:apply-templates>
    <xsl:apply-templates select="artist"/>
  </p>
</xsl:template>

<xsl:template match="title">
  <xsl:param name="parent_position"/> <!-- Receive here -->
  <xsl:number format="1" select="$parent_position"/><br/>
  Title: <span style="color:#ff0000">
  <xsl:value-of select="."/></span>
  <br />
</xsl:template>

result:

<html xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><body>
  <p>1. <br>1<br>
  Title: <span style="color:#ff0000">Empire Burlesque</span><br>Bob Dylan</p>
  <p>2. <br>1<br>
  Title: <span style="color:#ff0000">Hide your heart</span><br>Bonnie Tyler</p>
</body></html>

Solution 3

  <xsl:number format="1" select="????" /> 

What should I write at the place of ???? to get position of the parent cd tag in the document.

First of all, the above XSLT instruction is syntactically illegal -- the <xsl:number> instruction doesn't (cannot) have a select attribute.

Use:

   <xsl:number format="1" count="cd" /> 
Share:
15,627
Harshdeep
Author by

Harshdeep

A Software Engg by profession. Coding excites me and I wanna know it all :) SOreadytohelp

Updated on June 05, 2022

Comments

  • Harshdeep
    Harshdeep almost 2 years

    How to get the position of parent node in the complete document using xpath?

    say I have the following xml:

    <catalog>
      <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
      </cd>
      <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
      </cd>
    </catalog>
    

    and I have a XSLT to convert it into HTML, which is as follows (only snippet):

    <xsl:template match="/">
    <html>
      <body>  
      <xsl:apply-templates/>  
      </body>
      </html>
    </xsl:template>
    
    <xsl:template match="cd">
      <p>
        <xsl:number format="1. "/><br/>
        <xsl:apply-templates select="title"/>  
        <xsl:apply-templates select="artist"/>
      </p>
    </xsl:template>
    
    <xsl:template match="title">
      <xsl:number format="1" select="????" /><br/>
      Title: <span style="color:#ff0000">
      <xsl:value-of select="."/></span>
      <br />
    </xsl:template>
    

    What should I write at the place of ???? to get position of the parent cd tag in the document. I have tried many expressions but nothing seems to be working. May be I am doing it altogether wrong.

    1. <xsl:number format="1" select="catalog/cd/preceding-sibling::..[position()]" />
    2. <xsl:number format="1" select="./parent::..[position()]" /><br/>
    3. <xsl:value-of select="count(cd/preceding-sibling::*)+1" /><br/>

    I am interpreting 2nd as select current node's parent axis and then tell the position of parent of the current node. Why is it not working? What is the correct way to do this.

    FYI: I expect the code to print the position of parent cd tag of the current title tag uder processing.

    Please can someone tell me how to do this.