xsl-list
[Top] [All Lists]

RE: 'apply-templates' on parameter of 'call-template'

2004-04-09 10:53:51
No, this will definitely will not work.  But its not because the actual
code itself is not valid but instead the data that is being sent with
the "body" with-param is considered to be a string to the processor even
though to you and I it looks just like valid XML.  The function of
xsl:apply-templates is not to match the value of an element but instead,
the element name itself.  Actually, you could use the value of an
element or attribute to match an element to the proper template but the
syntax requires to first match the element or attribute name accompanied
by the desired value following the "=" sign (e.g. match="matchable[(_at_)id =
'123'] is valid match="123" is not.  In your particular case you're the
param that you are passing ("body") is being interpreted by the
processor as a string as opposed to a node-set or Result Tree Fragment
and as such you are technically trying to match a string with the value
of "<p>This is my body</p><matchable id="123"/>" to a template.  As you
pointed out various processors handled this differently as there are no
rules as to how a processor HAS TO handle errors in your XSLT.
Frustrating, I know... but theres not a whole lot that can be done about
that.  There are a handful of XSLT validators out there that do a good
job of parsing your XSLT and validating it, throwing human
understandable reasons as to why something will not work.  If necessary
post another message to the list asking advice on a good human
understandable XSLT validator and im sure you'll get more than a handful
of good responses.

In the mean time here are several ways to fix this.  The first would be
to pass a valid Result Tree Fragment to the template using valid XPath
in the select statement attribute of xsl:with-param.  The second would
be to use the node-set function specific to your processor. This was not
part of the original specification for XSLT 1.0 although it should have
been.  As such all major XSLT processors have some sort of variation of
the node-set function.  You will need to declare the correct namespace
specific to the processor you are using and then use a combination of
that namespace and the proper node-set function name for that namespace
e.g. xalan:nodeset($body) or msxsl:node-set($body).  The easiest way to
implement this second format would be to create a variable with the
desired xml as its value(at this point its actually still a string to
the eyes of the processor but to you it would look like valid xml.)  If
the name of the variable you created was "body" then you would use:
<xsl:with-param name="body" select="xalan:nodeset($body)"/> or the
namespace and proper node-set name for the processor you want to use.
Note: using the same name for the variable and with-param tends to be
the easiest as far as managing your code is concerned.  However, its
definitely not mandatory.

I hope this helps!

Best regards,

<M:D/>

-----Original Message-----
From: Angus McIntyre [mailto:angus(_at_)pobox(_dot_)com] 
Sent: Friday, April 09, 2004 11:08 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] 'apply-templates' on parameter of 'call-template'

Is it legitimate to invoke 'xsl:apply-templates' on a parameter 
passed to 'xsl:call-template'? In other words, should the following 
fragment be expected to work:

        <xsl:template match="/">
           <xsl:call-template name="test">
              <xsl:with-param name="body">
                 <p>This is my body</p>
                 <matchable id="123"/>
              </xsl:with-param>
           </xsl:call-template>
        </xsl:template>

        <xsl:template name="test">
           <xsl:param name="body">no body</xsl:param>
           <xsl:apply-templates select="$body"/>
        </xsl:template>

        <xsl:template name="matchable">
           <p>The value is <xsl:value-of select="@id"/></p>
        </xsl:template>

On the test platform I'm using (TestXSLT from Marc Liyanage), the 
different stylesheet processors all choke on this in different ways. 
Xalan throws an error, LibXSLT ignores it, Saxon and Sablotron blow 
up.

Replacing the 'xsl:apply-templates' in the named template 'test' by 
'xsl:copy-of' works fine - except that, of course, the "matchable" 
template is never invoked.

The Xalan error ("can not convert #RTREEFRAG to a nodelist") hints 
that I'm trying to do something basically contrary to the spirit of 
XSL, or at least XSL 1.0. What I'd like to do can be described as 
follows: use 'call-template' to 'surround' an arbitrary block of XML, 
_contained in the XSL stylesheet_, by additional XML content - and 
have templates applied to the contained block in the usual way.

As to why I want to do this particularly horrible thing, put it down 
to someone else's questionable design decisions. If the nodes that I 
want to 'surround' were in the XML rather than the XSL, this would be 
trivial.

Thanks in advance for any suggestions,

Angus
-- 
Business:   http://www.nomadcode.com/
Personal:   http://www.raingod.com/angus/
Political:  http://www.gollum2004.com/

--+------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--+--