Re: [xsl] Inconsistent values from <xsl:variable/>

Subject: Re: [xsl] Inconsistent values from <xsl:variable/>
From: David Carlisle <davidc@xxxxxxxxx>
Date: Wed, 15 Jun 2005 22:41:38 +0100
   The use of an <xsl:if/> seem to result in different values being assigned:

     <xsl:variable name="RTF_GOOD">
	 <xsl:value-of select="//out-form:Subform[@idType = 'RuleContent']"/>
     </xsl:variable>

     <xsl:variable name="RTF_BAD">
       <xsl:if test="2 > 1">
	 <xsl:value-of select="//out-form:Subform[@idType = 'RuleContent']"/>
       </xsl:if>
     </xsl:variable>

   Both have the same select="" expression; it's only the presence of the
   <xsl:if/> that changes things.


The two expressions are equivalent.
Both generate a result tree fragment corresponding to a node set with
one node, a root node, that has a single text node child with string
value the string value the first SubForm element with the specified
attribute.

You probably shouldn't be making an rtf at all but instead just doing
<xsl:variable name="x" select="//out-form:Subform[@idType = 'RuleContent']"/>
which makes a node set of all the Subform elements with that attribute.


    $RTF_GOOD appears to contain the RTF that I expect;

    $RTF_BAD appears to be a string containing the flattened text() from
       within the RTF I expect.

   Any ideas why they differ ? Is this a bug in Xalan ? A bug in my
   understanding of XSL is far more likely :>

value-of always returns the string value of the first node selected, so
both your rtf variables contain no element nodes.


   --- Details ---

   The above is a trivial example; I know about <xsl:variable select="..."/>,
   but I need to do some conditional logic to determine exactly which
   nodeset to place into my variable.)

   (It may also be worth pointing out that I'm repeatedly using XPath on
    node-sets, along the lines of:

     <xsl:variable "foo"  select="//elem1"/>
     <xsl:variable "bar"  select="$foo//elem2"/>
     <xsl:variable "quux" select="$bar/[@attr = 'thing']"/>

    in case that explains anything ...)

   I'm examining the contents using this:

     <xsl:message>GOOD
       <xsl:call-template name="dumpContext">
	 <xsl:with-param name="myNodeSet" select="xalan:nodeset($RTF_GOOD)"/>
       </xsl:call-template>
     </xsl:message>

     <xsl:message>BAD
       <xsl:call-template name="dumpContext">
	 <xsl:with-param name="myNodeSet" select="xalan:nodeset($RTF_BAD)"/>
       </xsl:call-template>
     </xsl:message>

     <xsl:template name="dumpContext">
       <xsl:param name="myNodeSet"/>
       <xsl:for-each select="$myNodeSet">
	 <xsl:value-of select="local-name()"/>
	 <xsl:text>[</xsl:text>
	 <xsl:for-each select="ancestor-or-self::*">
	   <xsl:text>/</xsl:text><xsl:value-of select="local-name()"/>
	 </xsl:for-each>
	 <xsl:text>]</xsl:text>
	 <xsl:text>"</xsl:text>
	 <xsl:value-of select="text()"/>
	 <xsl:text>"</xsl:text>
       </xsl:for-each>
     </xsl:template>

   And seeing output like this:

    Validation ERROR: GOOD
    Subform[/QueryResult/FormSet/Form/Thing/Subform]""]
This is a bug if your variable is declared as you suggest. (it would
have been easier to test given a complete stylesheet.

    Validation ERROR: BAD  []"aaaaacoy3y0co110yy2005-01-012005-01-012005-01-03"]
This is the expected result.

myNodeSet has just a single node (/) so the for-each just iterates over
one node. local-name() on a root node is the empty string.
root nodes have no ancestors so ancestor-or-self::* selects nothing (*
only selects elements so not even the self:* part selcts anything)
so your ineer for-each is not executed. You then select the text node
child (which is the nodes only child, and get the result you show.


David


________________________________________________________________________
This e-mail has been scanned for all viruses by Star. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________

Current Thread