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 |