xsl-list
[Top] [All Lists]

Re: [xsl] xsl:key on part of a document in XSLT2.0?

2006-10-31 02:55:24
On 10/31/06, len feremans <lenferemans(_at_)hotmail(_dot_)com> wrote:
Hi,

I am writing XSLT 1.0 stylesheets over a year now and was wondering if the
following is possible in XSLT 2.0: Applying a key to only part of a
document.

For example:
Let's say I do a for-each on each child of a node "$node1" and then check if
a "$node2" has any child with the same id...

<xsl:template name="compare">
                <xsl:param name="node1"/>
                <xsl:param name="node2"/>
                <xsl:for-each select="$node1/e">
                        <xsl:variable name="id1" select="@id"/>
                        <xsl:variable name="n2" select="$node2/e[(_at_)id = 
$id1]"/> //can be slow
                        //do something with node2
                </xsl:for-each>
</xsl:template>

Now this code can be quite slow if there are thousands of nodes under $node2
or $node1.
The complexity would be O(N*K) where N = number of children of $node1 and K
= number of children of $node2. If I could use a key then complexity could
be O(N*log(K)). xsl:key would be also very usefull if it could be created
dynamically inside a template... The code could look something like this:
<xsl:template name="compare">
                <xsl:param name="node1"/>
                <xsl:param name="node2"/>
                <xsl:key name="nodes" match="$node2/e" use="@id"/>
                <xsl:for-each select="$node1/e">
                        <xsl:variable name="id1" select="@id"/>
                        <xsl:variable name="n2" select="key('nodes',$id1)"/> 
//fast
                        //do something with node2
                </xsl:for-each>
</xsl:template>

You could just do a set compare:

<xsl:apply-templates select="$node2/e[(_at_)id = $node1/e/@id]"/>

which you could optimize by storing $node1 ids in a variable:

<xsl:variables name="node1IDs" select="$node1/e/@id" as="xs:string+"/>
<xsl:apply-templates select="$node2/e[(_at_)id = $node1IDs]"/>

Or key it:

<xsl:key name="e-by-id" match="e" use="@id"/>
<xsl:apply-templates select="$node2/e[key('e-by-id', @id, $node1)]"/>

Either way should be faster than the for-each.

cheers
andrew

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>