Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

understanding position() function in XSLT

Tags:

xml

xslt

I have a similar problem as this guy:

using position() function in xslt

But I dont need the numbering, I just want to understand the way it works:

<?xml version="1.0" encoding="UTF-8"?>
<test>
<a>blah</a>
<a>blah</a>
<a>blah</a>
<a>blah</a>
</test>

for this input, the following stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

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

<xsl:template match="a">
<xsl:value-of select="position()"/><br/>
<xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

outputs:

<html><body>
2<br>blah
4<br>blah
6<br>blah
8<br>blah
</body></html>

Why does it skip the uneven numbers?

like image 995
user3629892 Avatar asked Feb 25 '15 09:02

user3629892


People also ask

What is position function XSLT?

position() Function — Returns a number equal to the context position from the current context.

What is position in XML?

The position() function gives you the position of the current node within the "current node list", which is whatever was select -ed by the nearest apply-templates or for-each (XSLT 2.0 refers to "items" and "sequences" rather than nodes and node lists but the principle is the same).

What is number () in XSLT?

Specifies the format pattern. Here are some of the characters used in the formatting pattern: 0 (Digit)

What is text () in XSLT?

XSLT <xsl:text> The <xsl:text> element is used to write literal text to the output. Tip: This element may contain literal text, entity references, and #PCDATA.


2 Answers

The position() function gives you the position of the current node within the "current node list", which is whatever was select-ed by the nearest apply-templates or for-each (XSLT 2.0 refers to "items" and "sequences" rather than nodes and node lists but the principle is the same).

In your example the root template applies templates to its two child nodes (the text node containing the line break after the xml declaration, and the test element). There's no explicit rule matching test so the default rule applies, which for elements means <xsl:apply-templates/>.

Thus when the a template fires its "current node list" is the set of all 9 child nodes of test. This list consists of alternating text nodes (the line breaks) and element nodes (the a elements), with the text nodes at the odd positions and the element nodes at the even positions.

If you added an explicit template for test like this:

<xsl:template match="test">
  <xsl:apply-templates select="*"/>
</xsl:template>

Then this would select only the 4 a element nodes as the current node list, so position() would give you 1, 2, 3 and 4.

like image 82
Ian Roberts Avatar answered Oct 26 '22 16:10

Ian Roberts


Why does it skip the uneven numbers?

Because while you were at the / level, you said:

<xsl:apply-templates/>

which applies templates to all nodes children of the root node, and (due to the built-in template rules) to all of their descendants - including the text nodes that separate the <a> elements.

You will get a different result with an input of:

<?xml version="1.0" encoding="UTF-8"?>
<test><a>blah</a><a>blah</a><a>blah</a><a>blah</a></test>

or if you add an instruction to your stylesheet to:

<xsl:strip-space elements="*"/>

or if you apply templates selectively, e.g.

<xsl:apply-templates select="//a"/>
like image 20
michael.hor257k Avatar answered Oct 26 '22 17:10

michael.hor257k