XPATH - grab content from DIV with nestled a text - xpath

Can anyone help me with this? I cannot grab the 'Blue Shoes' text from this div no matter what I try! Been over an hour now and still cannot work it out. Tried:
//div[#class='breadcrumbs']/text(
//div[#class='breadcrumbs']
//div[#class='breadcrumbs']/div
Nothing seems to work. Any help MUCH appreciated.
<div class="breadcrumbs">Home/Blue Shoes</div>
</div>

//div[#class='breadcrumbs']/text()
should give you what you need in this case - it will select the set of all text nodes that lie directly under the breadcrumbs div. if you want to specifically target the one at the end (e.g. if there's more than two levels of breadcrumb and there's another text node for, say, a slash between two a elements) then the slightly more specific
//div[#class='breadcrumbs']/text()[last()]
may work better.
If this doesn't work then there are two other possibilities I can think of. Firstly, the HTML DOM uses upper case for element names, and since XPath is case-sensitive you may find you need //DIV instead of //div. Or maybe there's a namespace issue - if your document has an xmlns="..." on the root element then that puts your div elements in a namespace, and unprefixed names in xpath refer to nodes in no namespace. To select namespaced nodes you have to bind a prefix to the corresponding namespace URI and then use the prefix in your expressions (//xhtml:div). Exactly how you go about mapping prefixes depends on what library/tool/language you're using to execute the xpath queries.

Related

What is the difference between Relative XPath and Minimal XPath?

Is there any difference between relative XPaths and minimal XPaths or both are same?
In Firebug there are two types of XPath mentioned in the options: 'XPath' and 'Minimal XPath'.
The difference between the two options is described within the documentation to the HTML panel.
The option Copy Minimal XPath is meant to make the XPath, which relates to one element, as short as possible. So the word 'minimal' actually refers to the length of the resulting XPath.
It is currently (Firebug 2.x) only available for elements, which have an ID. And for those elements it copies the XPath in the form of
//*[#id="elementID"]
where elementID represents the ID given within the id attribute of the element. So the words 'minimal' and 'relative' actually mean the same at the moment. Though future versions of Firebug may extend the feature to produce minimal XPaths for elements without ID. And those minimal paths don't necessarily have to be relative.
The option Copy XPath is available for all elements and copies an absolute XPath to an element, which e.g. looks like this:
/html/body/div/div[1]/div/div/table[4]/tbody/tr[17]/td[2]/a

Get element name by containing text

I'm looking through HTML documents for the text: "Required". What I need to find is the element that holds the text. For example:
<p>... Required<p>
I would get to element name = p
However, it might not be in a <p> tag. It could be in any kind of tag, which is where this question differs from some of the other search text Stack Overflow questions.
Right now I'm using:
page.at(':contains("Required")')
but this only get me the full HTML element
The problem you have is the :contains pseudo class matches any element that has the searched for text anywhere in its descendants. You need to find the innermost element that contains such text. Since html is the ancestor of all elements, if the page contains the text anywhere then html will contain, and so that will be the first matching element.
I’m not sure you can achieve this with CSS, but you can use XPath like this:
page.at_xpath('//*[text()[contains(., "Required")]]')
This finds the first element node that has a text() node as a child that contains Required. When you have that node (if it exists) you can then call name on it to give the name of the element.
For CSS you can do:
page.at('[text()*="Required"]')
It's not real CSS though, or even a jQuery extra.
You should use CSS selectors:
page.css('p').text

Would like to use wildcard within an xpath

I have two links on a page that have the text 'London'. I want to choose the second one on the page, but I want to define the xpath in a way that it chooses by the parent div, but I want to use wildcard in case the link is moved.
So, the two xpaths are
//div[#id="first-id"]/div/div[2]/a[text()="London"]
//div[#id="second-id"]/div[2]/div[3]/div/a[text()="London"]
I want to use a wildcard and define the xpath within the parent div:
i.e. //div[#id="second-id"]/*/a[text="London"]
I already understand I can just use the full xpath and not have any wildcards, but I want to know if there's a way to do what I am proposing using xpath. I thought maybe contains() in some way would work but am not familiar enough with it.
To find the a element wherever it may appear within the div element, the descendant path is represented simply by //:
//div[#id="second-id"]//a[text="London"]

xpath: find a node whose content has a provided string

I have some HTML like this:
<div> Make </div>
And I want to match it based on the fact that the content of the node contains the text "Make".
Put another way "Make" is a substring of the div node's content and I want to make such a match on this node using XPath.
The obvious solution would be
//div[contains(., 'Make')]
but this will find all divs that contain the string "Make" anywhere within their content, so not only will it find the example you've given in the question but also any ancestor div of that one, or any divs where that substring is buried deep in a descendant element.
If you only want cases where that string is directly inside the div with no other intervening elements then you'd have to use the slightly more complex
//div[text()[contains(., 'Make')]]
This is subtly different from
//div[contains(text(), 'Make')]
which would look only in the first text node child of the div, so it would find <div>Make<br/>Break</div> but not <div>Break<br/>Make</div>
If you want to allow for intervening elements other than div, then try
//div[contains(., 'Make')][not(.//div[contains(., 'Make'])]
Seems like this is what you are looking for: //div[contains(text(),'Make')]
If this will not work you can try: //div[contains(.,'Make')]. This will find all divs, which contain 'Make' in any attribute.
To find that node anywhere in the document, you would need this:
//div[contains(text(), "Make")]

How to use Selenium using Xpath to determine the classes of an element?

I am trying to use xpath within selenium to select a div element that is within a td.
What I am really trying to do is determine the class of the div and if it is either classed LOGO1, LOGO2, LOGO3 and so on. Originally I was going to just snag the image:url to determine with logo.jpg was used but whoever made the target website used one image for each logo type and used css to determine which portion of the image will be displayed. So Imagine 4 images on one sprite image. This is the reason why I have to determine the class of the div instead of digging through the css paths.
In selenium I am using storeElementPresent | /html/body/form/center/table/tbody/tr/td[2]/div[3]/div[2]/fieldset/table/tbody/tr[2]/td/div/table/tbody/tr[${i}]/td[8]/div//class | cardLogo .
The div has multiple classes so I am thinking that this is the issue, but any help is appreciated. Below is the target source. This is source from within the table in the tbody. Selenium has no problems identifying all the way up to td[8] but then fails to gather the div. Please help!
<td class="togglehidefields" style="width:80px;">
<div class="cardlogo LOGO1" style="background-image:url(https://www.somesite.com/merchants/images/image.jpg)"></div>
<span id="ContentPlaceHolder1_grdCCChargebackDetail_lblCardNumber_0">7777</span>
</td>
I was fiddling with selenium.getAttribute() but it kept erroring out, any ideas there?
This <div/> element has one class attribute with one value, but this one is tokenized when parsed as HTML.
As selenium only supports XPath 1.0, you will need to check for classes like this:
//div[contains(#class, "LOGO1") or contains(#class, "LOGO2")]
Extend that pattern as needed and embed it in your expression.
With XPath 2.0 and better, you could tokenize and use the = operator which works on a set-based semantics:
//div[tokenize(#class, ' ') = ("LOGO1", "LOGO2")]
Old post but I'll put the solution I used up just in case it can help anyone.
xpath=//div[contains(#class,'carouselNavNext ')]/.[contains(#class, 'disabled')]
Fire of your contains, and then follow with /. to check children AND the current element.

Resources