tags:

views:

242

answers:

5

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 ---- :(

A: 

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.

http://www.w3schools.com/xsl/

<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>
ChaosPandion
I am looking for a XSLT function, which accepts a node (basically any node it may be) as a param to the XSLT function ? If yes can i have the syntax for the XSLT function ?
Laxmikanth Samudrala
You are looking at it.
ChaosPandion
A: 

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.

rasx
Not sure what this is supposed to mean, but your XPath is semantically different from the one ChaosPandion's answer.
Pavel Minaev
Looks I am not clear in my question, can i have a function which accepts the node as a parameter ? If yes, can i have a sample code syntax ?
Laxmikanth Samudrala
Pavel, I am aware that .InnerXml is different from .OuterXml---and that /MyNode/node() is different from /MyNode.
rasx
I am looking for a XSLT function, which accepts a node (basically any node it may be) as a param to the XSLT function ? If yes can i have the syntax for the XSLT function ?
Laxmikanth Samudrala
A: 

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"&gt;

<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 &lt; '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>
bill weaver
I am looking for a XSLT function, which accepts a node (basically any node it may be) as a param to the XSLT function ? If yes can i have the syntax for the XSLT function ?
Laxmikanth Samudrala
A: 

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.

Robert Rossney
+1  A: 

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()*".

From David Pawson's site:

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.

Mads Hansen