Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select all nodes with the same name for different parent nodes?

Tags:

xml

xslt

xpath

Let's say I have the following xml:

<root>
  <person>
    <name>John</name>
  </person>
  <children>
    <person>
      <name>Jack</name>
    </person>
  </children>
</root>

Is it possible to select both persons at once? Assuming that I don't know that the other person is in the children tag, they could easily be in the spouse tag or something completely different and possibly in an other child. I do know all persons I need are in the root tag (not necessarily the document root).

like image 366
Thijs Wouters Avatar asked Oct 20 '11 08:10

Thijs Wouters


3 Answers

You can use

//person

or

//*[local-name()='person']

to find any person elements in the document, but be careful - certain xsl processors (like Microsoft's), the performance of double slash can be poor on large xml documents because all nodes in the document need to be evaluated.

Edit :
If you know there are only 2 paths to 'person' then you can avoid the // altogether:

<xsl:for-each select="/root/person | /root/children/person">
    <outputPerson>
        <xsl:value-of select="name/text()" />
    </outputPerson>
</xsl:for-each>

OR namespace agnostic:

<xsl:for-each select="/*[local-name()='root']/*[local-name()='person'] 
  | /*[local-name()='root']/*[local-name()='children']/*[local-name()='person']">
like image 83
StuartLC Avatar answered Sep 23 '22 17:09

StuartLC


In Petar Ivanov's answer the definition of // is wrong.

Here is the correct definition from the XPath 1.0 W3C Specification:

// is short for /descendant-or-self::node()/

like image 25
Dimitre Novatchev Avatar answered Sep 23 '22 17:09

Dimitre Novatchev


//name

will match both, no matter where they are in the xml tree.

// Selects nodes in the document from the current node that match the selection no matter where they are (link)

like image 38
Petar Ivanov Avatar answered Sep 23 '22 17:09

Petar Ivanov