RE: [xsl] top level params and xsl:attribute magic?

Subject: RE: [xsl] top level params and xsl:attribute magic?
From: "Roger Glover" <glover_roger@xxxxxxxxx>
Date: Sat, 18 Jan 2003 01:38:52 -0600
S Woodside wrote:

> I'm beginning to think that XSLT is a bit like magic.

Welcome to the wonderful world of functional languages!


> If you think the
> right way,

Yes.


> and use the right magic incantation,

Not magic, intuition and skill.


> it works like a charm.
> If you don't, no cigar.

Once you have the right mind set the intuition will kick in.  And once you
have been through a few more successes and failures your skills will be in
place.


> I have this top-level param to grab a param from http:
>    <xsl:param name="StartPointStr">.</xsl:param>

So far, so good.


> The param StartPointStr is an Xpath string. Next I have this (which
> works) (1)
>    <xsl:param name="StartNode" select="dyn:evaluate($StartPointStr)"/>

Yep.


> Compare to this (which doesn't work): (2)
>    <xsl:param name="StartNode">
>          <xsl:attribute name="select">
>            <xsl:value-of select="dyn:evaluate($StartPointStr)"/>
>          </xsl:attribute>
>    </xsl:param>
>
> (1) works and (2) doesn't work. With two, I get nothing, empty node
> set. They should be equivalent!

There are actually two differences between (1) and (2) here.  One difference
which you discovered reading the spec, and one which you did not.


> OK, wait, I see in the spec "The xsl:attribute element can be used to
> add attributes to result elements"

Right.  You were misinterpreting the action of the <xsl:attribute> element.
You were expecting it to apply to the top level of abstraction, the XSLT
<xsl:param> element, when in reality it applies to the next level of
abstraction down, the XML result tree (conceptually an XML output document)
that the XSLT is creating.  In short, you were looking at a picture of a
pipe (2) and calling it a pipe (1) (apologies to Rene Magritte).

Anticipating this sort of problem comes with the right mindset; once you can
tease apart the parts of XSLT syntax that apply to manipulation of XML
source and output from the parts that apply to manipulation of the flow of
XSLT logic, then you will be in much better shape.

> ... so this must be an illegal use
> of xsl:attribute.

No, it is not.  In XSLT 1.0, a parameter whose value is given by a non-empty
<xsl:param> element body contains a value of type "result tree fragment".
An attribute created with <xsl:attribute> is a perfectly good example of a
"result tree fragment".  There is no syntax error here.

Now there is, sure enough, a big difference between (1) and (2).

With (1) the parameter "StartNode" has as its value:
    - the return value of the extension function call
      "dyn:evaluate($StartPointStr)".

With (2) the parameter "StartNode" has as its value:
    - a result tree fragment containing
      -- an XML attribute node named "select" whose attribute value is
         --- the string conversion of
             ---- the return value of the extension function call
                  "dyn:evaluate($StartPointStr)".

Of course, we still have a problem here.  The parameter evaluates to an
*empty* node set.  An attribute *is* a node so there should be *something*
there, right?

Now we get to the really hairy part.  You see, in XSLT 1.0, a "result tree
fragment" is a bit like a "node set", but not exactly.  Result tree
fragments are conceptually tied to output, while node sets are conceptually
tied to input.  Practically, this means that a "result tree fragment" cannot
be used in many contexts where a "node set" is expected.  Hence it is much
more than likely that in the context where you are using "$StartNode" (2),
the "result tree fragment" it contains evaluates as an empty "node set".

Seeing this problem is the sort of skill that only comes from slogging
through the trenches a few times.  Even experienced XSLT developers
occasionally make this kind of mistake.


> But LibXSLT doesn't complain ...

This is because no syntax or runtime error occured, only a logic error by
the programmer who confused two different layers of abstraction.


> maybe this is just a
> case of inadequate error detection and reporting the in the
> implementation (I used to see that very often in C++ compilers...)

Actually the only legitimate variety of detection and reporting here falls
into the category of "info" messages.  For example, some mature C++
compilers have options that will cause the compiler to flag *legal*
constructs that are most often logical errors on the part of the programmer,
such as "if( i = 0 )" (assignment) instead of "if(i == 0)" (equality).

Of course, there is no guarantee of a "compile" stage in an interpreted
language like XSLT.  So we would need an optional verbose mode of execution
that would log an "INFO" level message somethig like this:
    "result set fragment given where a node set was expected".

Even so, I would not expect the XSLT engine developers to ever add something
like that in this case.  The whole "result set fragement" vs. "node set"
thing is really becoming a moot point; "result set fragments" are going the
way of the dodo in XSLT 1.1 (and good riddance in my humble opinion).  In
1.1, whether some collection of XML nodes represents "input document" nodes,
or "output document" nodes, or even nodes in an intermediate stage of
transformation, that collection is considered a "node set".

So in XSLT 1.1, Your parameter (2) is still *far* different from your
parameter (1), but at least (2) does not counter-intuitively evaluate to an
empty node set.

I hope this helps!

-- Roger Glover
   glover_roger@xxxxxxxxx



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread