tags:

views:

39

answers:

3

How I can find with Xsl all the node that have then name like the value of an other node Like these:

 <root>
    <data1>
      <subdata1>
        ...
        <selectThese></selectThese>
        ...
      </subdata1>

    </data1>
    <nodesetFind>
      <node1>selectThese</node1>
    </nodesetFind>
  </root>

the result: <selectThese></selectThese>

+4  A: 

Use:

/*/data1//*[name() = /*/nodesetFind/*]

Demonstrated in an XSLT transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:template match="/">
  <xsl:copy-of select="/*/data1//*[name() = /*/nodesetFind/*]"/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<root>
    <data1>
      <subdata1>
        ...
        <selectThese></selectThese>
        ...
      </subdata1>

    </data1>
    <nodesetFind>
      <node1>selectThese</node1>
    </nodesetFind>
  </root>

the wanted, correct result is produced:

<selectThese></selectThese>
Dimitre Novatchev
@Dimitre: +1 good answer.
Alejandro
@Alejandro, Thanks! You seem to have forgotten the +1? :)
Dimitre Novatchev
@Dimitre: You are rigth! I must to remember first upvote and then comment... ;)
Alejandro
+1  A: 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:variable name="find" select="//nodesetFind/node1" />
        <root>
            <xsl:for-each select="//*[name()=$find]">
                <xsl:copy-of select="." />
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>
VladV
The for-each is unnecessary... you could do `<xsl:copy-of select="//*[name()=$find]" />`. But +1 because useful and correct.
LarsH
@LarsH, you're right. I used for-each for some debug printout and forgot to remove it.
VladV
+3  A: 

Another way, this stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:key name="kDataByName" match="*[ancestor::data1]" use="name()"/>
    <xsl:template match="/">
        <xsl:copy-of select="key('kDataByName',/root/nodesetFind/node1)"/>
    </xsl:template>
</xsl:stylesheet>

Output:

<selectThese></selectThese>

Note: This is XSLT only solution (Dimitre's answer is general XPath, then XSLT) because the use of fn:key. So, you need to declare the key for ussing this expression to select the nodes you want:

key('kDataByName',/root/nodesetFind/node1)
Alejandro
+1 for the "more advanced" solution :)
Dimitre Novatchev
@Alejandro, When you say "This is XSLT only solution" you mean that this solution cannot work without XSLT, right? At first I thought you meant this solution didn't require XPath. But that didn't make sense.
LarsH
@LarsH: Yes. `fn:key` is in scope only for XSLT.
Alejandro