tags:

views:

197

answers:

3

Hi,
I am trying to implement a text filter that adds a parent node to each text node.

<xsl:template match="text()">
   <aNewTag><xsl:value-of select="."/></aNewTag>
</xsl:template>

This works fine until when I call it indirectly by:

<xsl:apply-templates/>

But if I call the template directly using

<xsl:apply-templates select="text()"/>

the new tag disappears.

Can anyone explain me why?

Cheers
Jan

A: 

If you use the xal:apply-templates element without a select attribute, the value of select is implicitly set to node() i.e. all the child nodes and hence your text() template is matched.

fpmurphy
+1  A: 

I was a bit confused by my own code. The complete example looks like this:

<xsl:template match="/">
    <xsl:call-template name="a">
     <xsl:with-param name="b">
      <xsl:apply-templates select="text()"/>
     </xsl:with-param>
    </xsl:call-template>
</xsl:template>

<xsl:template name="a">
    <xsl:param name="b"/>
    <xsl:value-of select="$b"/> <!-- here is my error -->
</xsl:template>

<xsl:template match="text()">
    <aNewTag>
     <xsl:value-of select="."/>
    </aNewTag>
</xsl:template>

My error was, that I have not seen the value-of in the calling template. If I change the value-of to a apply-templates, everything works fine.

Thanks
Jan

A: 

I think the issue is that in template "a" that the parameter "b" is a node set. To access this, you may have to use an "node-set" extension function in the XSL. It is not part of standard XSLT, so you need to specify an extension.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="urn:schemas-microsoft-com:xslt">
    <xsl:template match="/">
     <xsl:call-template name="a">
      <xsl:with-param name="b">
       <xsl:apply-templates select="text()"/>
      </xsl:with-param>
     </xsl:call-template>
    </xsl:template>
    <xsl:template name="a">
     <xsl:param name="b"/>
     <xsl:for-each select="ext:node-set($b)">
      <xsl:copy-of select="."/>
     </xsl:for-each>
    </xsl:template>
    <xsl:template match="text()">
     <aNewTag>
      <xsl:value-of select="."/>
     </aNewTag>
    </xsl:template>
</xsl:stylesheet>

This one only works for Microsoft's XML parser (MSXML) only. For other XML processors, such as xsltproc, the namespace "http://exslt.org/common" should be used.

This then allows you to access the node, or nodes, that make up the "b" parameter, although in my example above I have used to iterate over them.

Here is an article which explains about the node-set

XML.Com Article

Tim C