XPath Combining/Multiple - xpath

I'm using XPath to select elements of content and i want to select 2 elements, the problem is I dont know how to combine the 2 selectors into 1 query.
//div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/img[#class=""]
//div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/div/div[#class="quote"]
I thought I could do this by doing;
//div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/img[#class=""] and //div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/div/div[#class="quote"]
or
//div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/img[#class=""] | //div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/div/div[#class="quote"]
But none of these work.

You forget the brackets:
This:
(//div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/img[#class=""]|//div[#id="dle-content"]/div[#class="mcontent_inner"]/div[#class="mcontent_inner_box"]/div[#class="article"]/div/div[#class="quote"])
should work.

Related

xpath query url with one folder depth only

I am using this XPath query succesfully:
//div[(#class="result")]//a[contains(#href,"pinterest.com")]/#href
The URL I am using the XPath query (with simple_html_dom.php) is this one here.
Now, I would like to find results for pinterest.com/one-folder-deep-only and exclude all URLs deeper than one directory, like pinterest.com/one-folder-deep-only/this or pinterest.com/one-folder-deep-only/this/this. I have no idea if there is a way to achieve that. Have googled a lot, but not found anything. Maybe my search terms weren't the best.
Do you have any ideas? Thanks for helping me here.
I am testing the query using the Chrome XPath Helper.
"//" is to evaluate all levels/depths. Instead use only one "/" for the "a" query to only evaluate immediate children
//div[(#id="first-result")]/a[contains(#href,"url.com")]/#href
Note use of / instead of // before the "a" tag.
Try below XPath to select #href from required anchors only:
//a[contains(#href, "url.com") and not(contains(substring-after(./#href, 'url.com/'), "/"))]/#href
Solution for XPath 2.0:
//a[contains(#href, "url.com") and count(tokenize(#href, "/"))=2]/#href
Note that if in real HTML source href starts-with "http://url.com" you should specify =4 instead of =2

Select element and its descendants

I'm trying to select an folder and its descendants from a JCR with XPath. I can select the folder easily enough:
//content/documents/folder-name
I can select its descendants too:
//content/documents/folder-name//*
However, I can't figure out how to get both. I've tried several things. These select nothing:
//content/documents/folder-name | //content/documents/folder-name//*
//content/documents/folder-name(. | *)
//content/documents/folder-name/(. | *)
//content/documents/folder-name/descendant-or-self
//content/documents/folder-name/descendant-or-self::node()
These both throw a javax.jcr.query.InvalidQueryException:
//content/documents/folder-name[. | *]
//content/documents/folder-name/[. | *]
Obviously I'm terrible at XPath. Please help.
Edit: I was using the // prefix because I didn't realize I could use /jcr:root/content instead. I have the same problem with that, however.
You can combine two XPaths using the union operator:
xpath1 | xpath2
However, your first XPath,
//content/documents/folder-name
does select the folder-name element(s), which includes the descendants of the element.
If you want the folder-name elements to be first in a list, followed by their descendants, you could combine as follows:
//content/documents/folder-name | //content/documents/folder-name//*
//content/documents/folder-name/descendant-or-self::node() looks correct to me (without seeing your XML input), though //content/documents/folder-name/descendant-or-self::* is probably better.
Certainly if //content/documents/folder-name selects something then ``//content/documents/folder-name/descendant-or-self::*` should also select something.
In XPath 2.0 you can do //content/documents/folder-name/(.|descendant::*) but although it's shorter, it seems clumsier to me than using the descendant-or-self axis.

Xpath select multiple elements

Is there any ways to make the following lines shorter?
Can i select both /span/strong[2] and /strong[2] in one line without "|"?
//*[#id="content"]/div[2]/div[2]//following-sibling::p[1]/span/strong[2] | //*[#id="content"]/div[2]/div[2]//following-sibling::p[1]/strong[2]
Use p[1]//strong[2]
It means all strong[2] descendants of p[1]
why dont't you just use the second path only
//*[#id="content"]/div[2]/div[2]//following-sibling::p[1]/strong[2]
it contains both directives.

Xpath Multiple Predicates

I am trying to quickly find a specific node using XPath but it seems my multiple predicates are not working. The div I need has a specific class, but there are 3 others that have it. I want to select the fourth one so I did the following:
//div[#class='myCLass' and 4]
However the "4" is being ignored. Any help? I am new to XPath.
Thanks.
If a xpath query returns a node set you can always use the [OFFSET] operator to access a certain element of it.
Use the following query to access the fourth element that matches the #class='myClass' predicate:
//div[#class='myCLass'][4]
#WilliamNarmontas answer might be an alternative to the syntax showed above.
Alternatively,
//div[#class='myCLass' and position()=4]
The accepted answer works correctly only if all of the div elements have the same parent. Otherwise use:
(//div[#class='myCLass'])[4]

WebDriver locate element by combined xpath

Is there any way, how I can to identify two xpath values in one.
I have text located somewhere on web page, on another page it exists in same element, but has different xpath. See below two variants:
Variant1: .//*[#id='quote_1']/div[2]/div[1]/div[1]/div[1]/p[2]
Variant2: .//*[#id='quote_1']/div/div[1]/div[1]/div[1]/div[2]/div[3]/span[2]
I'm looking how I can combine these two xpath's to one like the following:
xpath = Variant1 or Variant2;
Thank you.
The XPath union operator | is probably what you are asking for:
.//*[#id='quote_1']/div[2]/div[1]/div[1]/div[1]/p[2]
|
.//*[#id='quote_1']/div/div[1]/div[1]/div[1]/div[2]/div[3]/span[2]
This XPath expressions selects the union of two nodesets:
All nodes selected by .//*[#id='quote_1']/div[2]/div[1]/div[1]/div[1]/p[2]
All nodes selected by .//*[#id='quote_1']/div/div[1]/div[1]/div[1]/div[2]/div[3]/span[2]

Resources