Find node parent position using xpath

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

Let's 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 XSLT to convert it to HTML, which looks like this (snippet only):

 <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 on the spot ???? to get the position of the parent cd tag in the document. I tried many expressions but nothing works. Maybe I'm doing it completely wrong.

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

I interpret the second how to select the current parent axis of the node, and then pass the position of the parent of the current node. Why is this not working? What is the right way to do this.

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

Please tell me how to do this.

+7
source share
3 answers
 count(../preceding-sibling::cd) + 1 

You can run it here (note that I deleted the other number that you displayed, just for clarity).

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

 ../*[position()] 

... effectively says: "Find me a parent who has a position." It returns node, not the position itself. A predicate is just a filter.

In any case, errors occur using position() , and it can be used to return the position of the current context of a node only - not another node.

+16
source

Utkanos answer works fine, but my experience is that when an XML document is large, it can lead to performance problems.

In this scenario, you can simply pass the parent position in the parameter.

 <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> 
+3
source
  <xsl:number format="1" select="????" /> 

What should I write on the spot ???? get the position of the cd parent in the document.

First of all, the XSLT statement above is syntactically illegal - the <xsl:number> statement does not (cannot) a select .

Using

  <xsl:number format="1" count="cd" /> 
+1
source

All Articles