How to find the element who's xpath change dynamically? - xpath

We have element which doesn't have id or name to find while automation testing.
Below is the html code for it.
<div _ngcontent-c1="" class="col-md-4">
<div _ngcontent-c1="" class="form-group"> Account Name: </div>
</div>
<div _ngcontent-c1="" class="form-group">
<span _ngcontent-c1="" class="ng-tns-c1-0">1234567890</span>
</div>
We found element by using xpath. we can click the element in one case. Here the xpath was,
/html/body/app-root/app-root/div/div[4]/div[2]/form/div/div[5]/div[2]/div/span
But in the second case we are unable to find the element ,because new element will in the page. Now the above xpath will change to ,
/html/body/app-root/app-root/div/div[4]/div[2]/form/div/div[1]/div[5]/div[2]/div/span
Now the question how to find the above element?.

Venkatesh from the comment section I understood you want to find the Account Name value from the page
You can write xpath with visible text.
//*[contains(text()," Account Name: ")]/ancestor::div/following-sibling::div[contains(#class,"form-group")]/span
You can find the Preceding div with visible text Account Name: and later find the following sibling which will hold the Account Name: value in it.
Similarly you can find each element by changing the visible text alone.

Related

Adding aria-label to label or paragraph

I am working on fixing a bug for a frontend built using Fluent UI. I have a ChoiceGroup in which I have rendered two div tags each having text. I want the screen reader to read both the texts when the first div is chosen. The only way I can narrate both text is by having them inside the same div but then I cannot style them the way I want to style them.
Similar question but related to Bootstrap: Adding aria-label to text elements
So you have something like this?
<div>
text1
</div>
<div>
text2
</div>
What do you mean by "chosen" in "when the first div is chosen"? Is it an interactive element?
In my previous answer that you alluded to, all the elements to be read were contained in a parent container. It was a <button> in that case.
Normally, if you want all the text to be read, then the focus needs to move to the parent element so that all the child elements will be read, so you'd need a parent <div> and the focus would have to move to it.
<div>
<div>
text1
</div>
<div>
text2
</div>
</div>
Alternatively, for interactive elements, you can have aria-labelledby (or aria-describedby, depending on the nature of the second <div>) to have an element's text announced with another element. Something like this:
<div id="new1" aria-labelledby="new1 new2">
text1
</div>
<div id="new2">
text2
</div>
However, using aria-labelledby directly on a <div> without a subsequent role is not really supported.
And when I said the "nature" of your second <div>, if the second div acts like an extension of the first text, then aria-labelledby (with two IDs) seems appropriate. But if the second text is more of a "further description" of the first element, then aria-described might be more appropriate.
<div aria-describedby="new2">
text1
</div>
<div id="new2">
text2
</div>
Without further details of your code, a more specific answer can't be given.

Xpath extraction between two nodes

I have several web pages that have the following structure
<div id="w_33086" class = "eight columns">
<h2 id="about">About<span itemprop="name">Name of Place</span></h2>
<p style="margin-top: 0px;">
.
.
.
<p class="contactAdvisor"><a href="http://www.example.com/contact">
The text and markup between the two paragraphs is quite variable as it is created through individual users. In some cases it includes markup and in some cases it does not. When it does include markup, the mark up can be quite variable.
I'm trying to select all of the text and markup between these two <p> but have not been successful.
The best result I've achieved comes from //div[id='w_33086']/node()
However, that is dropping the <p> tags when those are present. It also picks up the <h2> tag and the <p class="contactAdvisor"> that I would rather exclude.
I'm using Google Sheets (and or Screaming Frog) to apply the xpath
If the two <p> elements are siblings of each other, then you could try
//div[id='w_33086']/p[#style="margin-top: 0px;"]/
following-sibling::node()[following-sibling::p[#class="contactAdvisor"]]
This is assuming that there is only one <p> under <div id="w_33086"> that has the style or class attribute value (respectively) that we're using to identify them.
Please note that XPath does not select any "markup". It selects nodes such as text nodes, elements (which have descendants attached), and attributes. Those nodes can be serialized as markup, but that's not XPath's business.

How to get value from a placeholder using xpath

All of the elements are dynamic. I can see only Placeholder which is unique from the following html:-
<input
id="ext-gen1617"
type="text"
size="20"
class="x-form-field x-form-text x-form-focus"
autocomplete="off"
aria-invalid="false"
placeholder="Gender"
data-errorqtip=""
role="textbox"
aria-describedby="combobox-1166-errorEl"
aria-required="true"
style="width: 78px;"
/>
I need to get the value displayed in
placeholder="Gender".
I tried using
//input[#placeholder='Gender']
But my webdriver script failed to identify it.
Can anyone please help me out with possible solution to it?
String s=driver.findElement(By.xpath("//input[#placeholder='Gender']")).getAttribute("placeholder");
System.out.println(s);
To get an attribute for a filed, you can use the .getAttribute() method.
I assume you are dealing with (front end)script generated web elements, then you must need to embrace lean way of thinking. Don't try to pull out a web element by it's property alone. If you are not getting them try to build a xpath from its parent or siblings.
say, the HTML goes like this,
<div id="somestatic id">
<div id="xyz">
<input name="dynamic one"/>
</div>
</div>
Then you can build a xpath as ,
//*[#id='staticID']/div/input
for the HTML,
<div id="staticID"></div>
<input name="dynamic one"/>
the xpath is ,
//*[#id='staticID']/following-sibling::input
similarly there are n number of option available. Give them a try
Try
driver.findElement(
By.cssSelector("input[id*='ext-gen']")
).getAttribute("placeholder")
Let me know is the above statement is working or not.
The best way is to find the element with CSS selector in this case -
input[placeholder='Gender'], which can easily find the element.

xpath accessing information in nodes

i need to scrap information form a website contain the property details.
<div class="inner">
<div class="col">
<h2>House in Digana </h2>
<div class="meta">
<div class="date"></div>
<span class="category">Houses</span>,
<span class="location">Kandy</span>
</div>
</div>
<div class="attr polar">
<span class="data">Rs. 3,600,000</span>
</div>
what is the xpath notation for "Kandy" and "Rs. 3,600,000" ?
It is not wise to address text nodes directly using text() because of nuances in an XML document.
Rather, addressing an element node directly returns the concatenation of all descendant text nodes as the element value, which is what people usually want (and think they are getting when they address text nodes).
The canonical example I use in the classroom is this example of OCR'ed content as XML:
<cost>39<!--that 9 may be an 8-->.22</cost>
The value of the element using the XPath address cost is "39.22", but in XSLT 1.0 the value of the XPath address cost/text() is "39" which is not complete. In XSLT 2.0 (which is how the question is tagged), you get two text nodes "39" and ".22", which if you concatenate them it looks correct. But, if you pass them to a function requiring a singleton argument, you will get a run-time error. When you address an element, the text returned is concatenated into a single string, which is suitable for a singleton argument.
I tell students that in all of my professional work there are only very (very!) few times that I ever have to use text() in my stylesheets.
So //span[#class='location' or #class='data'] would find the two fields if those were the only such elements in the entire document. You may need to use ".//span" from a location inside of the document tree.

Finding an element by XPath in Selenium

I am trying to use Selenium to navigate a webpage. There is a button I am trying to get to via its xpath. For other buttons on the site, it works fine. But for this particular one, I keep getting the error that the element can't be located. Firebug is just giving me the xpath in this format: //*[#id="continueButton"].
I notice that the button has wrappers around it. They are structured like
<div class = "cButtonWrapper">
<div class = "cButtonHolder">
<input type="image" id="continueButton" name="Continue" alt="Continue" src="/store/images/btn_continue.gif" value="Continue">
</div>
</div>
Could the wrappers around the button have anything to do with not being able to locate it?
Maybe the <input> element cannot be properly located by XPath because you are using invalid HTML. Try using <input id="continueButton"/> or <input id="continueButton"></input> in your page source.

Resources