|
Subject: Re: [xsl] concatenated key From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 23 Apr 2003 12:41:21 +0100 |
DaveP wrote:
>> Given a node, I'm trying to identify/pull out those nodes in the
>> document having the same set of identically named child nodes. For
>> example, given the node Alpha in the following, I'd like to pull
>> out the "Alpha2" node.
>>
>> <node name="Alpha">
>> <node name="a"/>
>> <node name="b"/>
>> </node>
>> <node name="roman">
>> <node name="i"/>
>> <node name="ii"/>
>> </node>
>> <node name="Alpha2">
>> <node name="a"/>
>> <node name="b"/>
>> </node>
>
> Beating Jeni to it for once :-)
> In xslt 2 this is
>
> <xsl:template match="node">
> <xsl:variable name="theseChildren" select="node/@name"/>
> <xsl:if test="some $x in ../node/node/@name satisfies ($x =
> $theseChildren)">
> <xsl:variable name="this" select="generate-id()"/>
> (I am <xsl:value-of select="@name"/>)
> <xsl:for-each select="../node">
> <xsl:if test="(node/@name = $theseChildren ) and not(generate-id() =
> $this)">
> Match at <xsl:value-of select="position()"/> <br />
> </xsl:if>
> </xsl:for-each>
> </xsl:if>
> </xsl:template>
I don't think that works. The test "node/@name = $theseChildren" tests
whether *any* of the name attributes within the current node is the
same as *any* of the name attributes in $theseChildren (just as it
does in XSLT 1.0). So if you had:
<node name="Alpha">
<node name="a" />
...
<node name="i" />
</node>
<node name="roman">
<node name="i" />
<node name="ii" />
</node>
then the above code would say that "roman" was the same as "Alpha"
because they both contain <node name="i" />.
Also note that you don't need to test generate-id() with XPath 2.0 --
you can use the 'is' and 'isnot' operators. Plus you can use "except"
to create a sequence of nodes that doesn't include a node you know.
I think that the best way to approach this problem in XSLT 2.0 would
be to use the string-join() function to concatenate the values of the
name attributes together and then use a key:
<xsl:key name="nodes" match="node[node]"
use="string-join(node/@name, ' ')" />
<xsl:template match="node">
<xsl:variable name="others"
select="key('nodes', string-join(node/@name, ' ')) except ." />
<xsl:if test="$others">
<xsl:value-of select="@name" /> matches...
<xsl:for-each select="$others">
...<xsl:value-of select="@name" />
</xsl:for-each>
</xsl:if>
</xsl:template>
I would be tempted to turn the "string-join(node/@name, ' ')"
expression into a function to prevent myself from making a mistake by
using a different separator or something in the two places where it's
used.
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| RE: [xsl] concatenated key, David . Pawson | Thread | RE: [xsl] concatenated key, David . Pawson |
| RE: [xsl] concatenated key, David . Pawson | Date | RE: [xsl] concatenated key, I-Lin Kuo |
| Month |