RE: [xsl] Passing tree fragment as a tunneled param to be accessed by key

Subject: RE: [xsl] Passing tree fragment as a tunneled param to be accessed by key
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Mon, 15 May 2006 00:06:50 +0100
The variable

  <xsl:param name="objects"/>

is unrelated to the variable

 <xsl:with-param name="objects" select="$objects" tunnel="yes"/>

because one is a tunnel parameter and the other isn't. So the non-tunnel
parameter gets it's default value, which is "".

To correct this, specify 

<xsl:param name="objects" tunnel="yes"/>

To prevent it happening again (or to get better diagnostics next time you
make the mistake), some good practices are:

(a) On a parameter, specify required="yes" if you expect a value to be
supplied

(b) Declare the expected types of your parameters. Thus:

<xsl:param name="objects" required="yes" tunnel="yes" as="document-node()"/>

Michael Kay
http://www.saxonica.com/

> -----Original Message-----
> From: Tim Lebo [mailto:timleboxslt@xxxxxxxxx] 
> Sent: 14 May 2006 23:33
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Passing tree fragment as a tunneled param to 
> be accessed by key
> 
> All,
> 
> The input and output formats that I am working with both use IDs.
> Unfortunately, the mapping between the IDs is rather complex.
> Fortunately, I can dymanically determine the mapping. This is 
> done by creating elements within the transform (and in its 
> own namespace) that pair the ids. All of these pairings sit 
> in a variable in the / template.
> 
> My problem: While I'm processing the input structure with 
> apply-templates, when the input refers to an id, I need to 
> dip into my pairings variable to look up the appropriate 
> output id. I use a key for this and use the pairings variable 
> to define the tree fragment scope for the key. It appears 
> that when I pass the pairing variable into the 
> apply-templates, it becomes a string and is not recognized as 
> a tree fragment.
> 
> Hopefully any ambiguity of my description will be absolved 
> with the following domain-independent code. The Input, 
> current xsl, and desired output follow.The xsl includes 
> comments describing current problem in code.
> 
> Kindest thanks and highest regards,
> Tim
> 
> current xsl throws two errors:
> 
> Error on line 34 of file:/Users/tml/Desktop/question/attempt.xsl:
>   XPTY0019: Required item type of first operand of '/' is 
> node(); supplied value has item
>   type xs:string
> Transformation failed: Run-time errors were reported
> 
> Error on line 37 of file:/Users/tml/Desktop/question/attempt.xsl:
>   XPTY0019: Required item type of first operand of '/' is 
> node(); supplied value has item
>   type xs:string
> Transformation failed: Run-time errors were reported
> 
> 
> ======== input ==========
> <in-objects>
>   <in-object ref="AAA"/>
>   <in-object ref="BBB"/>
>   <in-object ref="CCC"/>
> </in-objects>
> 
> 
> ======== desired output =========
> 3
> <out-object>
>    <refers-to>input @ref: AAA count($objects/*): 3 get 
> @out-id: 111</refers-to> </out-object>
> 
> 
> ========= current xsl ==========
> <xsl:transform version="2.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>   xmlns:xfm="intermediate nodes created during transform not 
> in input and not for final output"
>   exclude-result-prefixes="xfm">
> 
> <xsl:output method="xml" indent="yes"/>
> <xsl:key name="objects" match="xfm:object" use="@in-id"/>
> 
> <xsl:template match="/">
>   <xsl:variable name="objects">
>     <!-- This would be generated with an apply-templates, but 
> is hard coded for example -->
>     <xfm:object in-id="AAA" out-id="111">text a 1</xfm:object>
>     <xfm:object in-id="BBB" out-id="222">text b 2</xfm:object>
>     <xfm:object in-id="CCC" out-id="333">text c 3</xfm:object>
>   </xsl:variable>
>   <xsl:value-of select="count($objects/*)"/>
>   <xsl:apply-templates select="in-objects">
>     <xsl:with-param name="objects" select="$objects" tunnel="yes"/>
>   </xsl:apply-templates>
> </xsl:template>
> 
> <xsl:template match="in-objects">
>   <xsl:apply-templates select="in-object[1]"/> </xsl:template>
> 
> <xsl:template match="in-object">
>   <xsl:param name="objects"/>
>   <out-object>
>     <refers-to>
> 
>       <xsl:value-of select="concat('input @ref: ',@ref,' ')"/>
> 
>       <!-- LINE 34: I expect $objects to be a tree fragment 
> of 3 xfm:object here, but it is a string. -->
>       <xsl:value-of select="concat('count($objects/*):
> ',count($objects/*),' ')"/>
> 
>       <!-- LINE 37: After $objects is a tree fragment here, 
> this does not select '111' -->
>       <xsl:value-of select="concat('get @out-id:
> ',$objects/key('objects',@ref)/@out-id)"/>
> 
>     </refers-to>
>   </out-object>
> </xsl:template>
> 
> <xsl:variable name="NL">
> <xsl:text>
> </xsl:text>
> </xsl:variable>
> 
> </xsl:transform>

Current Thread