Xpath - Find span, exclude child i attribute - xpath

Given the following object:
<span id="PartComment">
REMAN WATER PUMP
<i>w/2.05" DIAMETER THERMOSTAT OUTLET - SUPPLIED w/PULLEY
</i>
</span>
I'm trying to come up with an xpath that should locate me only the span by id and the text inside it (REMAN WATER PUMP). Unfortunately, the text inside the i is also caught up.
I was thinking of something like:
//span[#id='PartComment'][not(self::i)]
But it keeps selecting the i text too.
Thanks for stopping by!

Try this:
//span[#id='PartComment']/text()

Related

Filling in text box with capybara

I have a text box that I'm trying to fill in with Capybara. I've tried to play around with it and try to figure something's out but my tests don't pass.
Here's
It's for this specific text box:
<span class="ui-grid-header-cell-label ng-binding" ui-grid-one-bind-id-grid="col.uid + '-header-text'" id="14213131-uiGrid-0008-header-text">DOB</span>
<input type="text" class="ui-grid-filter-input ui-grid-filter-input-0 ng-touched" ng-model="colFilter.term" ng-attr-placeholder="{{colFilter.placeholder || ''}}" aria-label="Filter for column" placeholder="" aria-invalid="false" style="">
Here's the code I have.
find('ui-grid-filter-input ui-grid-filter-input-0 ng-touched').set('1414234')
Ideally I'm trying to find this specific text box and type something in.
To fill the <input> using Capybara you can use either of the following locator strategies:
find('[aria-label=Filter for column]').set('1414234')
or
find('input[aria-label=Filter for column]').set('1414234')
As a CSS selector 'ui-grid-filter-input ui-grid-filter-input-0 ng-touched' is looking for a ng-touched element which is a descendant of a ui-grid-filter-input-0 element which is a descendant of a ui-grid-filter-input element - which obviously isn't what you want. Since you're trying to match on classes you need to use the CSS class selector which starts with .
find('.ui-grid-filter-input.ui-grid-filter-input-0.ng-touched')
would be the correct way to do what you were doing, however you probably don't really need all those classes, and the more you specify the more brittle you are making your selectors. It's likely that just
find('.ui-grid-filter-input-0').set('1414234')
would do what you want - or better
find('.ui-grid-filter-input-0').fill_in(with: '1414234')

When adding text() to my XPath, the number of results are duplicated. Why?

The following Xpath executed in Chrome's web inspector returns the expected number, 13, of nodes
//*[#id="day1"]//span[contains(#class, 'day-time-clock')]
However, when I add text() to it:
//*[#id="day1"]//span[contains(#class, 'day-time-clock')]/text()
it returns 26 nodes. However, only every other hit actually points somewhere in the source code, the others are just "numb".
The end node looks like this
<span class="medium bold day-time-clock">
09:00
<div class="tooltip-box first-free-tip ">
<div class="tooltip-box-inner">
<span class="fa fa-clock-o"></span>
Some text
</div>
</div>
</span>
The code sample above doesn't show exactly how it looks in the web inspector, there are a couple of empty rows in the text of this node. Here is a small screenshot of how it really looks.
Why is this happening? And what can I do about it?
Your span elements have multiple text node children. Some of the text node children contain only whitespace. In your example, the outer span element has one text node child containing "....09:00...." where "...." represents whitespace, plus one text node child immediately following the child div element. (Incidentally, my HTML is rusty, but I didn't think that having a div inside a span was allowed.)
Your second (inner) span element contains no text nodes, so /text() on this should select nothing.
Generally, using /text() in XPath is a bad idea unless you have some very good reason and know exactly what you are doing.

Trouble accessing a text with XPath query

I have this html snippet
<div id="overview">
<strong>some text</strong>
<br/>
some other text
<strong>more text</strong>
TEXT I NEED IS HERE
<div id="sub">...</div>
</div>
How can I get the text I am looking for (shown in caps)?
I tried this, I get an error message saying not able to locate the element.
"//div[#id='overview']/strong[position()=2]/following-sibling"
I tried this, I get the div with id=sub, but not the text (correctly so)
"//div[#id='overview']/*[preceding-sibling::strong[position()=2]]"
Is there anyway to get the text, other than doing some string matching or regex with contents of overview div?
Thanks.
following-sibling is the axis, you still need to specify the actual node (in your example the XPath processor is searching for an element named following-sibling). You separate the axis from the node with ::.
Try this:
//div[#id='overview']/strong[position()=2]/following-sibling::text()[1]
This specifies the first text node after the second strong in the div.
If you always want the text immediately preceding the <div id="sub"> then you could try
//div[#id='sub']/preceding-sibling::text()[1]
That would give you everything between the </strong> and the opening <div ..., i.e. the upper case text plus its leading and trailing new lines and whitespace.

XPath expression for element based on containing text

I'm running out of ideas. I have identified for my Selenium test an div based on its text ("security administrator ") contained. Unfortunately, the div contains two other divs. See the example.
<div class="rich-stglpanel-marker">
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_on" style="display: none"></div>
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_off"></div>
security administrator
</div>
<div class="rich-stglpanel-marker">
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_on" style="display: none"></div>
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_off"></div>
technical administrator
</div>
... and so on
I tried that expressions:
//div[text()='security administrator']
//div[text()='security administrator ']
//div[text()='security administrator ']
//div[text()='security administrator${nbsp}'] (this is a special hack from selenium)
Nothing works. Any ideas?
Thanks in advance.
Can you try with this :
//div[contains(.,'security administrator')]
System.out.println(driver.findElementByXPath("//div[contains(.,'security adm')]").getText())
gave me security administrator
try this
//div[#class='rich-stglpanel-marker']
Try this: //div[#class='rich-stglpanel-marker' and text()!='']
EDIT
Finally got it!
Use this: //div[#class='rich-stglpanel-marker' and normalize-space(div[last()]/following-sibling::text())='security administrator']
I believe that in this situation, the text "security administrator" is counted as a node, and not as the sole text value of the first div node, which is why //div/text() will give you multiple return lines followed by the text you're searching for, and also why you cannot apply something like normalize-space(),translate(), or even contains() to div/text() and receive results. But, since the text node doesn't have a name, that makes it a funky XPath to figure out, so navigating to the closest possible sibling node was the only option I could think of.

Xpath getting node without node child contents

hey guys coudln't get around this. I have an html structured as follow:
<div class="review-text">
<div id="reviewerprofile">
<div id="revimg"></div>
<div id="reviewr">marc</div>
<div id="revdate">2011-07-06</div>
</div>
this is an awesome review
</div>
what i am trying to get is just the text "this is an awesome review" but everytyme i query the node i also get the other content in the childs. using something like this now ".//div[#class='review-text']" how to get just that text only? tank you very much
You're almost there! Just add /text() at the end of your XPath to get the text node.
An XPath expression such as //div returns a set of nodes, in this case div elements. These are in effect pointers to the original nodes in the original tree; the nodes are still connected to their parents, children, ancestors, and siblings. If you see the children of the div element and don't want them, that's not the fault of the XPath processor, it's the fault of whatever software is processing the results returned by the XPath expression.
You can get the text that's an immediate child of the div element by using /text() as suggested. However, that assumes that you know exactly what you are expecting to find in the HTML page - if "awesome" were in italics, it would give you something different.

Resources