Reputation: 2243
Can I send a node to an XSLT function? For example:
<books>
<book>
<author>a1</author>
<price>10</price>
<year>2009</year>
</book>
<!-- ... -->
</books>
Can I send the <book>
element to a function - within that function I want to process the nodes under book (<author>
, <price>
or <year>
)
Can I create a xsl:function as below ?
<xsl:function name="util:checkNode" as="xs:boolean">
<!-- I would like to know xml schema data type for the param -->
<xsl:param name="nodeP" as="****"/>
</xsl:function
If yes, what xsl schema type to the param ?
It looks like i created lot of confusion to every one by saying function instead of xsl:function ---- :(
Upvotes: 7
Views: 8814
Reputation: 66781
I think the answer to your question is, yes. You can send a node to an XSLT function.
If you are wondering what to use for the value of the as="" attribute, you have several choices. If you want to be very lax and accept just about anything, use as="item()*".
item()* .. sort of nodeset? W3C
Yes, I agree it looks pretty meaningless doesn't it. However. As of CR, its pretty essential, especially if you want to use types. And want to generate, say, a nodeset.. sorry sequence, in a variable.
<xsl:variable name="a"
select="(//h3)[position() < 3]"
as="item()*"/>
This creates a variable you can hack into using xpath quite readily. I.e. remember item()*.
types ... a few examples. W3C
From an explanatory email from Mike Kay, thanks Mike. Examples:
<xsl:param name="x" as="item()"/>
the parameter value can be any item (i.e. a node or atomic value). But it must be a single item.
<xsl:param name="x" as="item()?"/>
the parameter can be a single item or an empty sequence
<xsl:param name="x" as="item()+"/>
the parameter must be a sequence of one or more items - an empty sequence is not allowed
<xsl:param name="x" as="item()*"/>
the parameter can be any sequence of zero or more items - this places no constraints on its value.
<xsl:param name="x" as="node()*"/>
the parameter can be any sequence of zero or more nodes
<xsl:param name="x" as="xs:atomicValue*"/>
the parameter can be any sequence of zero or more atomic values (e.g. integers, strings, or booleans).
item()* is the most general type possible, it matches everything, like "Object" in Java. For that reason, it can usually be omitted. But not always, for example the default type in xsl:variable is not item()* but document-node(), to ensure that
<xsl:variable name="rtf"><a>thing</a> </xsl:variable>
continues to behave like XSLT 1.0
Use these to specify parameters, variable types etc.
Upvotes: 8
Reputation: 96860
There are plenty of XSLT functions that accept nodes as parameters. For instance, all of the arguments of concat
can be nodes, e.g.:
concat(myelement, myelement/@myattribute)
While this answers precisely the question you asked, I would bet folding money that it's not the question you wanted answered. But heck, you asked it four times, so here you go.
Edit
Actually, attributes aren't nodes; only elements, text, comments, processing instructions, and CDATA sections are nodes. But the above example still answers the question correctly.
Upvotes: 1
Reputation: 78282
XSL does not care what the parameter is. It really treats everything as XML. If text is passed in it is treated as a text node.
Here is an example with a link for further reference.
<xsl:call-template name="TemplateName">
<xsl:with-param name="ParamName" select="MyNode/MyNode" />
</xsl:call-template>
<xsl:template name="TemplateName">
<xsl:param name="ParamName" />
</xsl:template>
Upvotes: 0
Reputation: 5348
To add to the ChaosPandion answer you may need to add a node test to your XPath query:
<xsl:call-template name="TemplateName">
<xsl:with-param name="ParamName" select="MyNode/MyNode/node()" />
</xsl:call-template>
<xsl:template name="TemplateName">
<xsl:param name="ParamName" />
</xsl:template>
Officially, node()
is not a function it is a test but can returns a value that is like the XmlNode.InnerXml
property.
Upvotes: -1
Reputation: 4663
In your question:
Can I send the <book> element to a function - within that function I want to process the nodes under book (<author>, <price> or <year>)
and later comment:
can i have a function which accepts the node as a parameter?
...you're asking for a function, but what i think you want is a template
for the book
element.
Of course, you could do this several ways--in a for-each
loop, actually sending the book
node into a template using with-param
, etc.--but a simple template
should accomplish what you need. Whatever the template matches is the "parameter".
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="books">
<xsl:apply-templates select="book"/>
</xsl:template>
<xsl:template match="book">
author: <xsl:value-of select="author" />
price: <xsl:value-of select="price" />
year: <xsl:value-of select="year" />
</xsl:template>
</xsl:stylesheet>
If you want to do some further processing on the sub-elements (author, price, and year), you could look into creating templates for them too. Keep in mind that matching "year" will match all year elements, even for those you might have in date of births etc. (In these cases you would probably want to restrict the XPath in the match or just keep the book/year
processing within the book template.) Say you want to do something extra with year
. Your book processing might evolve into something like this (where you're now passing each year
node as parameters into the year template):
<xsl:template match="book">
author: <xsl:value-of select="author" />
price: <xsl:value-of select="price" />
<xsl:apply-templates select="year" />
</xsl:template>
<xsl:template match="year">
<xsl:choose>
<xsl:when test="year < '2000'">
from a prior century: <xsl:value-of select="." />
</xsl:when>
<xsl:otherwise>
from this century: <xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Upvotes: -1