eli.rodriguez
eli.rodriguez

Reputation: 490

xpath selection based by nodeName

I have an XML Like the following, and i want select just the elements "b" and "c" childrens of "a" using xpath filtering in xslt

<a>
  <b>data_1</b>
  <c>data_1</c>
  <d>data_1</d>
  <e>data_1</d>
</a>
<a>
  <b>data_2</b>
  <c>data_2</c>
  <d>data_2</d>
  <e>data_2</d>
</a>
<a>
  <b>data_3</b>
  <c>data_3</c>
  <d>data_3</d>
  <e>data_3</d>
</a>

Suggestions?

Upvotes: 2

Views: 953

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

First, do notice that you haven't provided a well-formed XML document. By definition a well-formed XML document must have a single top element.

I assume in this answer, that all a elements are children of this single top element, that isn't shown in the question.


Use:

/*/a/*[self::b or self::c]

This selects any element that is either b or c and that is a child of any aelement that is a child of the top element of the XML document.

Do note that the currently-accepted answer is incorrect:

/a/*[self::a or self::b or self::c]

Not only it supposes that there is a single a top element (and there isn't such), but given a specific XML document, it would select, besides the wanted elements, also any a element that is a child of the top element a.

The XPath expression that I recommend above:

/*/a/*[self::b or self::c]

is more efficient than another, correct XPath expression that is proposed in one of the other answers:

/a/b | /a/c

This requires evaluatiing separately /a/b/ and /a/c and then performing the set-union of the results of the two evaluations.

The XPath expression that I recommend needs only a single scan of the document, requires no union and can be used even in streaming mode over an unlimited in size, huge XML document.

Upvotes: 1

Sean B. Durkin
Sean B. Durkin

Reputation: 12729

In XPATH 2.0+, the simplest expression to select b & c is ...

/a/(b|c)

Note that in XPATH 2.0, if you don't need nodes to be sorted in document order, you could also use ...

/a/(b,c)

In XPATH 1.0, you will need ...

/a/b | /a/c

Upvotes: 0

Related Questions