XSLT Templates and applying templates
I am very new to XSLT and I am having a hard time understanding some of its concepts.
I have the following XML file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<Page>
<Page>
<Page />
</Page>
<Page>
<Page />
</Page>
<Page />
<Page />
<Page />
</Page>
And when the following XSL file (test.xsl) is applied:
<?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>
<head>
</head>
<body>
<h2>
<xsl:apply-templates name="PageCount" />
</h2>
</body>
</html>
</xsl:template>
<xsl:template match="Page" name="PageCount">
Page <xsl:value-of select="position()" />
of <xsl:value-of select="count(/Page/Page)" />
</xsl:template>
</xsl:stylesheet>
I get the output:
Page 2 of 5
However if I change the "apply-templates" to "call-template" it changes the output to:
Page 1 of 5
Why does this happen?
Also if I add another template:
<xsl:template match="Page" name="PageCount2">
Page <xsl:value-of select="position()" />
of <xsl:value-of select="count(/Page)" />
</xsl:te开发者_运维技巧mplate>
and use "apply-templates" it seems gives me the output:
Page 2 of 1
This is baffling to me. What is going on?
Thanks in advance.
When you use <xsl:apply-templates/>
, it is really short for <xsl:apply-templates select="node()"/>
and is being invoked inside of a template match on /
, which is the root node of the document and an abstract concept for the top of the file. It's children include the document element (i.e. <Page>
), as well as any top-level comments or processing instructions that may be siblings of the document element.
So, when you are "standing" on the root node, the call to <xsl:apply-templates/>
will apply templates to /Page
, which matches the template that you define. position()
is evaluated from the matched context, which is /Page
, and returns 2
, because it is the second item in the document. The first item is the xml-stylesheet processing instruction. If you were to remove it, then position()
would evaluate to 1
.
When you use <xsl:call-template name="PageCount"/>
, it invokes the same template, but the context does not change when the template is called. You are still "standing" on the root node, so position()
evaluates to 1
.
The count()
always evaluates the same, regardless of the context, because it uses an XPath that starts at the root node. If you were to change it to count(Page/Page)
and evaluate relative from the context node, then you would get different values(2
and 5
respectively).
精彩评论