user1659862
user1659862

Reputation:

Xpath finding nodes that match two expressions

I'm using xpath on the following xml, I need to extract only nodes that match two expressions, maybe I'm doing it wrong because no nodes are returned.

<item>
    <title>a product</title>
    <link>http://www.aproduct.com</link>
    <description>cool product</description>
    <author>[email protected]</author>
    <id_product><![CDATA[ 6]]></id_product>
    <section><![CDATA[ industry]]></section>
</item>
<item>
    <title>another product</title>
    <link>http://www.anotherproduct.com</link>
    <description>awesome product</description>
    <author>[email protected]</author>
    <id_product><![CDATA[ 8]]></id_product>
    <section><![CDATA[ diy]]></section>
</item>

What I'm using now is

//item/section[text() = "industry"] | //item/id_product[ text() ="6"]

but I also tried

//item/section[ . = "industry"] | //item/id_product[ . ="8"]

Could anyone help me?

Upvotes: 2

Views: 1114

Answers (3)

LarsH
LarsH

Reputation: 28004

It looks like the text in the nodes you're trying to match starts with a space:

" industry"

" 8"

which is why section[text() = "industry"] doesn't select anything.

You could use

//item/section[normalize-space(.) = "industry"] | ...

P.S. Based on your later comment, it appears that what you want to select is quite different. You want to select the item, not its children, and you only want item elements for which both conditions hold true, not those for which either condition holds true. So:

//item[section[normalize-space(.) = "industry"] and 
       id_product[normalize-space(.) = "6"]]

Upvotes: 1

Ian Roberts
Ian Roberts

Reputation: 122394

I'm trying to select all item elements with section child equal to "industry" AND id_product child equal to "6"

Given that your example XML has leading spaces in the element values, you will need to use normalize-space when comparing:

//item[normalize-space(section) = "industry"][normalize-space(id_product) = "6"]

Multiple predicate expressions in sequence are effectively ANDed together, you can read the expression as

  1. select all item elements in the document
  2. filter this set of nodes to include only those that have a section child whose space-normalized value is industry
  3. then filter that set to include only those that have an id_product child whose space-normalized value is 6

Expressions like //item/section[....] would select the section element, not its parent item.

Upvotes: 1

Jayy
Jayy

Reputation: 2436

You could use fn:normalize-space(string) xpath 1.0 function.

The Xpath would look like

//item/section[normalize-space(.) = "industry"] 
| 
//item/id_product[ normalize-space(.) ="6"]

Update: Based on the OP comment, i understand all the item nodes to be selected based on the values held by its child. So this expression will do

//item[normalize-space(section) = "industry" or normalize-space(id_product) ="6"]

Upvotes: 1

Related Questions