Re: [xsl] Frustrated with xxx:node-set

Subject: Re: [xsl] Frustrated with xxx:node-set
From: Karl Stubsjoen <kstubs@xxxxxxxxx>
Date: Wed, 1 Jun 2005 12:20:46 -0700
All right, I did my best to create a "foobar" example.  Here it is...
but first, let me explain the results produced:  You'll find 2 sets of
<foobar_summary> elements; this corresponds to the number <A> elements
in your source.  Within this element there is a <summary_for_foo> and
<summary_for_bar> element.  In the 2nd set of <foobar_summary> the
<summary_for_foo> is empty and this is the point of failure.
See below:
<summary_for_foo></summary_for_foo><!-- POINT OF FAILURE -->
There is no reason that this set is emtpy, this is a quirk in the
parser.  Notice that the next set <summary_for_bar> correctly
summarizes the colors; it's as if the parser loses touch with reality
and then rediscovers it.
If you take away an A element so you just have one, the summary
appears to work fine.  If you add multiple A elements you'll continue
to see the "miss-behaviour"...
Included, source xml; stylesheet; results (as produced parsing with MSXML4):

SOURCE XML:
<?xml version="1.0"?>
<FOOBAR>
<A>
<B code="FOO">red</B>
<B code="BAR">green</B>
<B code="FOO">blue</B>
<B code="BAR">red</B>
<B code="FOO">blue</B>
<B code="BAR">green</B>
<B code="BAR">green</B>
<B code="FOO">green</B>
<B code="BAR">blue</B>
</A>
<A>
<B code="FOO">green</B>
<B code="BAR">green</B>
<B code="FOO">blue</B>
<B code="BAR">green</B>
<B code="FOO">red</B>
<B code="BAR">green</B>
<B code="FOO">green</B>
<B code="FOO">green</B>
<B code="BAR">blue</B>
<B code="FOO">green</B>
<B code="FOO">green</B>
<B code="BAR">blue</B>
</A>
</FOOBAR>

STYLESHEET ==============
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:fx="urn:schemas-microsoft-com:xslt">

<xsl:key name="foobar" match="B" use="."/>

<xsl:template match="/">
<result>
<xsl:apply-templates select="FOOBAR/A"/>
</result>
</xsl:template>

<xsl:template match="A">
<xsl:variable name="foo">
<foo>
<xsl:apply-templates select="B[@code='FOO']" mode="indentity_copy"/>
</foo>
</xsl:variable>

<xsl:variable name="bar">
<bar>
<xsl:apply-templates select="B[@code='BAR']" mode="indentity_copy"/>
</bar>
</xsl:variable>

<!-- what we are working on -->
<xsl:copy-of select="fx:node-set($foo)"/>
<xsl:copy-of select="fx:node-set($bar)"/>

<!-- summary results foo -->
<foobar_summary>
<summary_for_foo>
<xsl:apply-templates select="fx:node-set($foo)" mode="summary"/>
</summary_for_foo>

<!-- summary results bar -->
<summary_for_bar>
<xsl:apply-templates select="fx:node-set($bar)" mode="summary"/>
</summary_for_bar>
</foobar_summary>
</xsl:template>

<xsl:template match="B" mode="indentity_copy">
<xsl:copy-of select="."/>
</xsl:template>

<!-- summary -->
<xsl:template match="foo | bar" mode="summary">
<xsl:apply-templates select="B[generate-id(.) =
generate-id(key('foobar',.)[1])]" mode="summary"/>
</xsl:template>

<xsl:template match="B" mode="summary">
<xsl:variable name="color" select="."/>
<summary>
<xsl:attribute name="code"><xsl:value-of select="@code"/></xsl:attribute>
<xsl:attribute name="color"><xsl:value-of select="$color"/></xsl:attribute>
<xsl:value-of select="count(../B[.=$color])"/>
</summary>
</xsl:template>


</xsl:stylesheet>

RESULT =================
<?xml version="1.0" encoding="UTF-16" ?>
<result xmlns:fx="urn:schemas-microsoft-com:xslt">
<foo>
<B code="FOO">red</B>
<B code="FOO">blue</B>
<B code="FOO">blue</B>
<B code="FOO">green</B>
</foo>
<bar>
<B code="BAR">green</B>
<B code="BAR">red</B>
<B code="BAR">green</B>
<B code="BAR">green</B>
<B code="BAR">blue</B>
</bar>
<foobar_summary>
<summary_for_foo>
<summary code="FOO" color="red">1</summary>
<summary code="FOO" color="blue">2</summary>
<summary code="FOO" color="green">1</summary>
</summary_for_foo>
<summary_for_bar>
<summary code="BAR" color="green">3</summary>
<summary code="BAR" color="red">1</summary>
<summary code="BAR" color="blue">1</summary>
</summary_for_bar>
</foobar_summary>
<foo>
<B code="FOO">green</B>
<B code="FOO">blue</B>
<B code="FOO">red</B>
<B code="FOO">green</B>
<B code="FOO">green</B>
<B code="FOO">green</B>
<B code="FOO">green</B>
</foo>
<bar>
<B code="BAR">green</B>
<B code="BAR">green</B>
<B code="BAR">green</B>
<B code="BAR">blue</B>
<B code="BAR">blue</B>
</bar>
<foobar_summary>
<summary_for_foo></summary_for_foo><!-- POINT OF FAILURE -->
<summary_for_bar>
<summary code="BAR" color="green">3</summary>
<summary code="BAR" color="blue">2</summary>
</summary_for_bar>
</foobar_summary>
</result>

On 6/1/05, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> >
> > I want to strike up conversation/thread about the xxx:node-set, if
> > anyone interested.  I am very frustrated with the lack of consistent
> > performance I have witnessed using the xxx:node-set function with
> > MSXML4 Parser.
> >
>
> You haven't shown us any code or any performance measurements, so it's
> difficult to make any comments. If you provided sample code and measurement
> data then people could see how other products compared, or tell you how to
> improve your code.
>
> There are at least two possible implementation strategies for result tree
> fragments and xx:node-set() in XSLT 1.0: one is to build the RTF as a
> regular tree, in which case xx:node-set() essentially costs nothing; the
> other is to use some other internal structure for an RTF, in which case
> xx:node-set() might be quite expensive. I've no idea which strategy MSXML
> uses, but your measurements might help to shed some light, if they are
> carefully made.
>
> Intrinsically, building trees with any product is likely to be an expensive
> operation. That's one reason that XSLT 2.0 sequences are so useful, because
> they involve less overhead.
>
> Michael Kay
> http://www.saxonica.com/

Current Thread