Re: what are node set fragments and why are they ruining my life?

Subject: Re: what are node set fragments and why are they ruining my life?
From: Phil Lanch <phil@xxxxxxxxxxxxxxx>
Date: Tue, 14 Dec 1999 10:50:58 +0000
"Mark D. Anderson" wrote:
> 
> see the minimal xsl and xml file below.
> 
> first off, nothing i've read in the spec or the various xsl tutorials
> make any sense in defining what a node set fragment is.
> they talk about things like "not being well-formed", but (a) i'm not
> clear how one is able to produce something that isn't well-formed,
> and (b) that doesn't match experience as this example shows.

See [11.1]: a result-tree fragment is a type which XSLT uses in addition
to the 4 types it takes from XPath (viz. string, number, boolean, &
node-set). The main point of it is that it can be copied into the output
document using xsl:copy-of. Otherwise, you can do similar but fewer
things with it as you can with a node-set: "An operation is permitted on
a result tree fragment only if that operation would be permitted on a
string" [11.1]. In particular, you can't use a tree-frag as the value of
the select attribute on an xsl:for-each element. Hence the reported
error.

The reason you've got a tree-frag in the first place as the value of
$members is that you always do when you initialize a variable by giving
it content (instead of by giving it a select attribute).

The solution is to convert your tree-frag to a node-set, which means
using an extension function, sxf:node-set in saxon or xt:node-set in xt
(using the namespace declarations you've already made). So try one of
these:

<xsl:for-each select="sxf:node-set($members)">

<xsl:for-each select="xt:node-set($members)">

> here i've shown where the mere act of passing a node set (fragment)
> through a call-template is enough to defile it.
> 
> here are the various outputs.
> 
> 1. comment out first for-each, use xt
> output is:
> member 1
> 
> note that there is a result, but no xsl:message instructions are run
> 
> 2. comment out first for-each, use saxon
> output is:
> member local-name=member, id=1
> member local-name=member, id=2
> 
> note that there is no result, but the xsl:message instructions are run

Well, I think they're both wrong: there should be both the result (that
xt gives) and the messages (that saxon gives). These are both
outstanding programs, so it seems very odd to be criticizing them both
in one email, but, hey, the worst that can happen is that I look stupid
...

> 3. leave in first for-each, use xt
> output is:
> cannot convert to node-set
> 
> 4. leave in first for-each, use saxon
> member local-name=member, id=1
> member local-name=member, id=2
> Error during source document processing
> At xsl:for-each on line 32 of file:/d:/mda/projects/xmlhacks/xmlidl/test1.xsl: Cannot convert value [** RESULT TREE FRAGMENT **] to
> a node-set
> 
> Thanks to anyone who can elucide this matter.
> 
> -mda
> 
> test1.xml
> 
> <root>
>   <member id="1">member 1</member>
>   <member id="2">member 2</member>
> </root>
> 
> test1.xsl
> 
> <?xml version="1.0" ?>
> 
> <xsl:stylesheet
>   version="1.0"
>   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>   xmlns:date="http://www.jclark.com/xt/java/java.util.Date";
>   xmlns:xt="http://www.jclark.com/xt";
>   xmlns:sxf="/com.icl.saxon.functions.Extensions"
>   extension-element-prefixes="date xt sxf"
>   exclude-result-prefixes="date sxf xt"
>   >
>   <xsl:output
>      method="html"
>      indent="yes"
>      doctype-public="-//W3C//DTD HTML 4.0 Transitional//EN"
>   />
>   <xsl:strip-space elements="*"/>
> 
>   <xsl:template match="root">
>     <xsl:variable name="members">
>       <xsl:call-template name="get_members"/>
>     </xsl:variable>
>     <!-- why can't i use a variable? something about result tree fragments... -->
> 
>     <!-- comment this for-each out to avoid the runtime error
>     <xsl:for-each select="$members">
>       <xsl:message>member local-name=<xsl:value-of select="local-name(.)"/>, id=<xsl:value-of select="@id"/></xsl:message>
>     </xsl:for-each>
>     -->
>     <xsl:value-of select="$members"/>
>   </xsl:template>
> 
>   <xsl:template name="get_members">
>     <xsl:variable name="result" select="*"/>
>     <xsl:for-each select="$result">
>       <xsl:message>member local-name=<xsl:value-of select="local-name(.)"/>, id=<xsl:value-of select="@id"/></xsl:message>
>     </xsl:for-each>
>     <!-- same thing as: <xsl:value-of select="$result"/> -->
>     <xsl:value-of select="*"/>
>   </xsl:template>
> 
> </xsl:stylesheet>

-- 

cheers

phil

"that monotonous state of the soul halfway between fulfillment
and futility which comes with life in the country" --- Musil


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


Current Thread