Re: [xsl] (Possible) pitfall: XSLT 2, 9.4 Creating implicit document nodes

Subject: Re: [xsl] (Possible) pitfall: XSLT 2, 9.4 Creating implicit document nodes
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 09 May 2012 11:18:08 -0400
At 2012-05-09 17:02 +0200, Christian Roth wrote:
this is a heads-up for a pitfall (that at least I have fallen into several times now...) with respect to XSLT 2, 9.4 "Creating implicit document nodes":


With the source document:


and this transformation
<xsl:variable name="v1"><xsl:sequence select="a"/></xsl:variable>
<xsl:variable name="v2" select="a"/>
However, I've spent considerable time debugging stylesheets where accessing a tunnel variable with $var/elem sometimes yielded nothing (see v2 in my example above) until I found that in some places, the variable was defined using <xsl:sequence> (because some complex content construction takes place which is either not doable or hardly readable using a single XPath expression), and using a select attribute at other places.

Fine. But the declaration you use is so very important. You've declared $v1 to be a tree and $v2 to be an element. So you've declared two very different animals and you cannot use the same syntax to address them.

$v1/a and $v2/a are both addressing the <a> child of the variable. Only $v1 has an <a> child variable. And worrisomely if the <a> in $v2 had an <a> child you would be addressing the child rather than what you want.

Is there a technique or pattern I could employ (maybe utilizing the @as attribute somehow?) to unify the access to variable contents where I know that the sequences are node sequences, regardless of their content construction using @select or <xsl:sequence>?

If you had:

  <xsl:variable name="v1" as="element()">
    <xsl:sequence select="a"/>
  <xsl:variable name="v2" select="a"/>

... then in both $v1 and $v2 *are* <a> (i.e. you wouldn't need to say $v/a to get at <a>). See the working example below.

Does that help? It isn't a document tree, but of course <a> can have descendants. If you want multiple elements in a sequence then use element()+.

. . . . . . . . . . . Ken

T:\ftemp>type christian.xml
<?xml version="1.0" encoding="UTF-8"?>

T:\ftemp>xslt2 christian.xml christian.xsl
<?xml version="1.0" encoding="UTF-8"?>v1: ab
v2: ab
T:\ftemp>type christian.xsl
<xsl:stylesheet xmlns:xsl="";

  <xsl:template match="/">
    <xsl:variable name="v1" as="element()">
      <xsl:sequence select="a"/>
    <xsl:variable name="v2" select="a"/>

<xsl:text>v1: </xsl:text> <xsl:apply-templates select="$v1" mode="out"/> <xsl:text>&#xa;</xsl:text>

    <xsl:text>v2: </xsl:text>
    <xsl:apply-templates select="$v2" mode="out"/>

<xsl:template match="*" mode="out"> <xsl:value-of select="name()"/> <xsl:apply-templates mode="#current"/> </xsl:template>

<xsl:template match="text()" mode="#all"/> </xsl:stylesheet> T:\ftemp>

Public XSLT, XSL-FO, UBL and code list classes in Europe -- Oct 2012
Contact us for world-wide XML consulting and instructor-led training
Free 5-hour lecture:
Crane Softwrights Ltd.  
G. Ken Holman                   mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Google+ profile:
Legal business disclaimers:

Current Thread