RE: [xsl] Using "except" with node sequences

Subject: RE: [xsl] Using "except" with node sequences
From: "James Sulak" <jsulak@xxxxxxxxxxxxxxxx>
Date: Mon, 4 Aug 2008 13:30:08 -0500
Hi Ken and Michael,

It turns out the declaration was the problem.  The variable
$normalized_data was produced by a function that was typed as "node()*"
instead of "element()+".  Once I changed that, everything worked
perfectly.  Thanks for suggesting that.

Also, thanks Michael for your suggestion.  The code I posted was a
simplified form of my actual code, in which I'm combining two sequences
produced by two different functions, both of which are a bit complex for
a single predicate:

	select="$active_data except $new_data"

Both of these variables are constructed by functions executed on the
original $normalized_data variable.  Both use <xsl:sequence /> to return
a sequence of elements.  My impression was that by using <xsl:sequence
/>, I am returning references to the existing nodes in $normalized_data,
and not actually creating copies of those nodes in memory.  Is this in
fact the case?

An alternate method I considered was to create Boolean functions that
would allow me to construct a predicate like you suggested:

	select="$normalized_data[fn:active(.) and not(fn:new(.)]

But since I use $active_data and $new_data elsewhere in my stylesheet, I
decided against it, trying to avoid evaluating those Boolean functions
more than necessary.

In general, which approach is better practice?

Thanks,

-James



-----Original Message-----
From: G. Ken Holman [mailto:gkholman@xxxxxxxxxxxxxxxxxxxx]
Sent: Monday, August 04, 2008 12:55 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Using "except" with node sequences

At 2008-08-04 12:38 -0500, James Sulak wrote:
>I have a sequence of nodes stored in a variable,

Perhaps you only have a tree and not a sequence of nodes.

>and I am attempting to filter it using an XPath expression that
>includes the "except" operator.  However, it's not working like I
expect it to.
>...
>I am attempting to filter it using this logic:
>
><olddata>
>    <xsl:sequence
> select="$normalized_data[not(info/@action='delete')] except
> $normalized_data[info/@action='insert' or info/@action='modify']" />
></olddata>
>
>I expect the returned sequence to include all of the nodes in
>$normalized_data that match the first condition and don't match the
>second condition (node 3).  What I am actually getting is all of the
>nodes in $normalized data.  Is there something about the "except"
>operator that I'm not understanding?

Nope!  Just a declaration issue I think.

You don't show your declaration of $normalized_data, so I'm going to
assume you just made it a temporary tree and you didn't make it a
variable of "data" elements.

My students of XSLT 2 who know XSLT 1 have had a problem with this
when jumping on the temporary tree bandwagon, thinking they are
getting variables of nodes, until I tell them about the use of the
as= to direct the processor in the expected use of the variable.

I hope the example below helps illustrate the difference ... please
let me know if this is not the source of your problem.  You can see
the only difference is how I declared the nodes stored in the variable.

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


T:\ftemp>type james.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                 version="2.0">

<xsl:output indent="yes"/>

<xsl:variable name="normalized_data">
<data id="1">
    <info action="delete" />
    <info action="insert" />
    <stuff />
</data>
<data id="2">
    <info action="insert" />
    <stuff />
</data>
<data id="3">
    <stuff />
</data>
</xsl:variable>

<xsl:variable name="normalized_data_ken" as="element(data)+">
<data id="1">
    <info action="delete" />
    <info action="insert" />
    <stuff />
</data>
<data id="2">
    <info action="insert" />
    <stuff />
</data>
<data id="3">
    <stuff />
</data>
</xsl:variable>

<xsl:template match="/">
   <results>
     <james>
       <olddata>
         <xsl:sequence
select="$normalized_data[not(info/@action='delete')] except
$normalized_data[info/@action='insert' or info/@action='modify']" />
       </olddata>
     </james>
     <ken>
         <xsl:sequence
select="$normalized_data_ken[not(info/@action='delete')] except
$normalized_data_ken[info/@action='insert' or info/@action='modify']" />
     </ken>
   </results>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>call xslt2 james.xsl james.xsl james.xml

T:\ftemp>type james.xml
<?xml version="1.0" encoding="UTF-8"?>
<results>
    <james>
       <olddata>
          <data id="1">
             <info action="delete"/>
             <info action="insert"/>
             <stuff/>
          </data>
          <data id="2">
             <info action="insert"/>
             <stuff/>
          </data>
          <data id="3">
             <stuff/>
          </data>
       </olddata>
    </james>
    <ken>
       <data id="3">
          <stuff/>
       </data>
    </ken>
</results>
T:\ftemp>rem Done!


--
Upcoming XSLT/XSL-FO hands-on courses:      Wellington, NZ 2009-01
World-wide corporate, govt. & user group XML, XSL and UBL training
RSS feeds:     publicly-available developer resources and training
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0    +1(613)489-0999 (F:-0995)
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread