Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select on multiple criteria with XPath

Tags:

xpath

I have an XML document which looks something like this:

<meadinkent>  <record>   <comp_div>MENSWEAR</comp_div>    <sty_ret_type>ACCESSORIES</sty_ret_type>    <sty_pdt_type>BELTS</sty_pdt_type>    <pdt_category>AWESOME_BELTS</pdt_category>    </record> <medinkent> 

I want to useXPath to select nodes which match all four elements and I'm having trouble getting the boolean syntax right. I'm trying this to match the first two just as a test:

"/meadinkent/record/comp_div[.='" & comp_div & "'] and /meadinkent/record/sty_ret_type[.='" & sty_ret_type & "']" 

Which is failing, saying no nodes are returned. Obviously I'm being very stupid - what am I doing wrong?

Cheers, mAtt

like image 902
Bob Tway Avatar asked Apr 08 '10 10:04

Bob Tway


People also ask

How write multiple contains in XPath?

$xml->xpath("(//person)[firstname[contains(., 'Kerr')]]"); then it works fine.

How do I apply and condition in XPath?

XPath multiple conditions are used to select multiple attributes, by using XPath in multiple conditions we can select any category with the attribute by specifying child node. We can define the condition in the path when we have to forward the message to more than one interface or more than one receiver.

How do you write two XPath?

The syntax for locating elements through XPath- Multiple Attribute can be written as: //<HTML tag>[@attribute_name1='attribute_value1'][@attribute_name2='attribute_value2]

How do you combine two XPath expressions?

selects the union of all nodes selected by expr1 and all nodes selected by expr2. The | character denotes the XPath union operator. You can use the union operator in any case when you want the union of the nodes selected by several XPath expressions to be returned.


1 Answers

Union
In order to get both nodes you need to use union operator - |

For example, the next query will return both type of nodes - comp_div and sty_ret_type:

/meadinkent/record/comp_div | /meadinkent/record/sty_ret_type 

Filter by sub-nodes values
In order to filter node based on its sub-nodes values you need to place all conditions in same brackets [nodeA='value1' and nodeB='value2']

For example, the next query will return record nodes whose sub nodes match the filter:

/meadinkent/record[comp_div='MENSWEAR' and sty_ret_type='ACCESSORIES'] 

A C# union example:

[Test] public void UnionExample() {     string xml =         @"<meadinkent>             <record>                 <comp_div>MENSWEAR</comp_div>                  <sty_ret_type>ACCESSORIES</sty_ret_type>                  <sty_pdt_type>BELTS</sty_pdt_type>                  <pdt_category>AWESOME_BELTS</pdt_category>             </record>           </meadinkent>";      XDocument xDocument = XDocument.Parse(xml);     IEnumerable<XElement> selectedElements =         xDocument.XPathSelectElements(                 "/meadinkent/record/comp_div | /meadinkent/record/sty_ret_type");      Assert.That(selectedElements.Count(), Is.EqualTo(2)); } 

A C# filter by sub-nodes example:

[Test] public void FilterExample() {     string xml =         @"<meadinkent>             <record>                 <comp_div>MENSWEAR</comp_div>                  <sty_ret_type>ACCESSORIES</sty_ret_type>                  <sty_pdt_type>BELTS</sty_pdt_type>                  <pdt_category>AWESOME_BELTS</pdt_category>             </record>           </meadinkent>";      XDocument xDocument = XDocument.Parse(xml);     IEnumerable<XElement> selectedElements =         xDocument.XPathSelectElements(        "/meadinkent/record[comp_div='MENSWEAR' and sty_ret_type='ACCESSORIES']");      Assert.That(selectedElements.Count(), Is.EqualTo(1));     Assert.That(selectedElements.First().Name.LocalName, Is.EqualTo("record")); } 
like image 128
Elisha Avatar answered Oct 16 '22 11:10

Elisha