xsl-list
[Top] [All Lists]

Re: AW: AW: Using key() from outside the default namespace

2003-08-08 08:48:41
Peter Flynn wrote:
On Wed, 2003-08-06 at 16:07, Markus Abt wrote:
I can see the problem. However, the reason for the root template to
be instantiated more than once is not the global variable $maindoc
that holds the root node of the main document, nor is it the dummy
<xsl:for-each> to switch the context back to the main document.

OK.

The reason is:

(1) In your entry template, you define the variable $content with:
        <xsl:variable name="content">
          <xsl:for-each select="$maindoc">
            <xsl:value-of select="key($keyname,$entryid)"/>
          </xsl:for-each>
        </xsl:variable>
The value of this variable is now a result tree fragment, containing a
root node and a text node with the string from the <xsl:value-of>.

So this for-each applied to my $maindoc actually places a node into the
variable? Yuck.

(??) No, the variable $maindoc remains unchanged. The variable $contents
is set, but not from the for-each, it is set from the result of value-of.

The for-each is looping exactly one time, since $maindoc contains
exactly one node (the root node /).

Oddly, if I declare maindoc to be some empty unused element buried deep
in the document (*anything* which will get me back to the main doc), it
still triggers the root template.

Nothing is "triggered" here. 

Again, the for-each is looping exactly one time, since $maindoc contains
one node (the empty node you chose).

Honest, the "trigger problem" is not here, but in (2) below.

(2) In your format template, you use this variable (via the param of
the same name):
        <xsl:apply-templates select="$content"/>

Right, because $content may contain further subelements which need
matching in templates.

No, it does only contain one root node and one text node, since the
value-of doesn't return the whole tree but only the first text node.

If you use copy-of instead of value-of, then the variable $content will
contain a result tree fragment with all subelements.

This results in applying ("firing" in your words):
-  The root template, and then
-  the default template for text nodes.

So you get the output from the root template more than once.

Thank you very much, this explains what's happening. I really hadn't
expected the for-each to insert anything into the variable.

See above, the for-each does *not* do that.

What I need is a key-with-respect-to-where-I-tell-it($foo,$bar).

One solution would be to replace the <xsl:apply-templates>
with a <xsl:value-of> to output only the text node of this
result tree fragment:
        <xsl:value-of select="$content"/>

Unfortunately not. The possibility of subelements needing processing
within $content precludes this.

If you use copy-of instead of value-of to construct the value of
the variable, as I wrote above, then and only then $content will
contain the subelements.

Then, you can either
-  use <xsl:copy-of select="$content"/> here to copy the result
   tree fragment to the output *without processing*, or
-  use <xsl:apply-templates select="xx:node-set($content)/node()"/>
   to first convert the result tree fragment to a node set, and then
   apply templates to the resulting node-set.
   Note the .../node() here, to avoid "firing" of the root template...

xx:node-set() is an extension function that must be supported by
your xslt processor. Major processors have such an extension
function. Look into the their docu, or start reading at:
http://www.exslt.org/exsl/functions/node-set/index.html

It looks as if it simply isn't possible in XSLT transparently to
revisit a document like this to retrieve a key value. 

No, it is, via a node-set() extension function.

///Peter

Regards,
Markus
__________________________
Markus Abt
Comet Computer GmbH
http://www.comet.de



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