xpath help can't get the text? - html

I am unable to get the text from this website: http://mp3bear.com...so now I just want to get the title of the song that is displayed on it.. here is what i wrote as the code:
//table/tr[2]/td[2]
so now I want to get second row from second column... it doesn't display anything.... is there any thing special when

I can't find any table element on this site, the tables are constructed with divs.
Therefore the expression for the second row of the second column of the table is.
//div[#id='listwrap']/div[3]/div[2]
There are some xpath implementations that don't allow indexing of child elements in this manner. In this case you could use
//div[#id='listwrap']/div[position()='3']/div[position()='2']
Edit:
In that case you need this expression:
//div[#id='listwrap']/div[3]/div[2]/a/text()
as the title is contained in a 'a' element and you use the xpath function text() to get the text value of the 'a' element
tested in firepath.

Related

XPath - get text from whole document except text from specified elements

I'm trying to figure out how to get text using XPath and exclude some tags.
Let's say (for illustration) I want to get all text from this page's body tag (so all visible text), but I don't want my text to contain text from tags with class="comment-copy" i.e. I don't want text to include comments.
I tried this but it doesn't work. It returns text including comments.
//body//text()[not(*[contains(#class,"comment-copy")])]
Do you have any idea?
EDIT:
Probably figured it out but maybe there are better or faster approaches so I won't delete the question.
//body//text()[not(ancestor-or-self::*[contains(#class,"comment-copy")])]
You were very close.
Just change
//body//text()[not(*[contains(#class,"comment-copy")])]
to
//body//text()[not(contains(../#class,"comment-copy"))]
Note that this will only exclude immediate children text() nodes of comment-copy marked elements. Your follow-up XPath will exclude all descendant text() nodes beneath comment-copy marked elements.
Note: You might want to beef up the robustness of the #class test; see Xpath: Find element with class that contains spaces.

writing xpath for getting a row in a table

If I write the XPath for a row in a table which is expandable, like each row is expandable on the table. it has a dropdown. if I click on the dropdown of the row, I get to see some stuff inside it.
if I want to write XPath for the body inside the dropdown. ex: for the second row, I get it by writing the XPath:
//div[#class=‘react-bs-container-body’]//tbody/tr[2]
If i write the following xpath :
//div[#class=‘react-bs-container-body’]//tbody/tr[td[#tabindex="7"]]
where I am trying to access the same thing by giving the attribute of the column which is unique. Xpath should give me the body inside the dropdown.
but this is not happening. The second case won't work. Can anyone tell me why?
You can try this xpath with single quotations,
//div[#class=‘react-bs-container-body’]//tbody/tr[td[#tabindex='7']]
Also, you can try with the below xpath as well
//div[#class=‘react-bs-container-body’]//tbody/tr[td[7]]

XPath select second element of many unless only one exists

I have a webpage with three <input> elements that all have the same name attribute. Ideally, I would like to select the second of these elements except sometimes there is only one element on the page and I want to instead select that element.
Ideally I would like something like (pseudo-code since max doesn't exist)
(//input[#name='myname'])[max(1, last()-1)]
I thought that maybe I could do something like the following except it yields all three elements
(//input[#name='myname'])[last()-1 or 1]
What is the best way to accomplish this using XPath?
Maybe grab both and then only the last one.
If there's two or more, it gets the second. If there's only one, it grabs that one.
((//input[#name='myname'])[position()=1 or position()=2])[last()]

Finding xpath of element

In the following snippet
I want to get xpath of the element containing the text 'This is what I should get'. I use the xpath expression html/body/div[5]/div[3]/div/div/div/div[2]/div/table/tbody/tr[2]/td/span, but I am getting the element with text 'This is what I am getting'. Please help me to modify element locator to get desired text
There must be a better XPath expression than that verbose one, but without more information I can only suggest based on the existing XPath. So, the desired text node can be identified either as text node that follows the previously selected span element :
..../table/tbody/tr[2]/td/span/following-sibling::text()[1]
or as direct child text node from the parent td element :
..../table/tbody/tr[2]/td/text()[normalize-space()]
If you want to get the text node, the xpath would be:
html/body/div[5]/div[3]/div/div/div/div[2]/div/table/tbody/tr[2]/td/text()[2]
Although xPath expression should probably less verbose.

How to select a child node by conditionally excluding a parents previous sibling

I have a question regarding using (what is to me) some complex XPath queries in Selenium IDE (thought they do apply to XPath in general).
Firstly, here is my scenario.
I'm writing some automated tests for a feature of a website I am working on that only certain items for sale on the website have. I'm trying to engineer the test in such a way that changes in data will not break it. Here is an abstraction of what I'm testing:
Given a set of search results, certain products within the results will have a feature (let's call the feature attributes), I want to click on the first result (which may change in the future) that has a single price and attributes.
I am using Selenium IDE 2.5.0 / FF 28.
Here is a JsFiddle I created that simulates the markup / DOM structure I have to work with (the markup cannot be changed): http://jsfiddle.net/xDaevax/3qUHB/6/
Here is my XPath query:
//div[contains(#class, 'primary')]//div[contains(#class, 'results')]//div[#class='price-range']/span[not(contains(#class, 'seperate'))]/../../..//a[#class='detail-link']
Essentially, the problem is this: All three have the same wrapping markup and css class information, but they differ in the price-range class due to the second element (the one I'm after) does not have "separate" or "minimum" CSS class elements.
I have made it this far with the XPath selector, but am stuck. I assume that when I traverse back up the DOM with the "/../..", I am losing the conditional XPath clause I previously used.
I apologize for the vagueness of the details, but due to contractual restrictions, I'm being as generic as possible.
Any suggestions on how to achieve the selection I want would be greatly appreciated. Please let me know if I need to clarify any of the requirements or steps I have tried.
Edit:
Here is a succinct description of the desired outcome.
In the markup example given, I want to select and click the link in the middle result element only. This is because the middle element has the desired "attributes" that once the link is clicked, it will take you to the product page which has additional things needing tested. That being said, the data could change: today it is the second element in the list, but maybe tomorrow it is the 7th element of 16 total elements.
My current logic for the XPath (though my solution does not work) is as follows: The element I am interested in is distinguishable from the other results because of two things: 1), it has a detail hyperlink (that will later be clicked) and 2) it does not have a range of prices (unlike the first result). Because the first result also has a hyperlink, the only difference between the two is that the first result has a minimum and separator markup element, while the second does not (my target link will always have a single price and not a range). Based on this information, I tried to write XPath that will select the first hyperlink that is not contained within an element that has a price range.
This expression will select all three div elements:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
If I understood your requirements correctly, the price-range div must have a sibling that is an <a href> element, so we can filter out the last div by adding that restriction in a predicate: [../a[#href]]. So this expression selects only the first two divs:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
[../a[#href]]
Now you can add one more predicate to remove the items that don't have a single price. You chose the separate class as the criterion, so we can change that last predicate and add another restriction to it: [../a[#href] and not(span[contains(#class,'separate')])]. Now your expression selects the div that you want:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
[../a[#href] and not(span[contains(#class,'separate')])]
This is a location path, which creates a context. From this context, you can navigate anywhere you want. You can get the sibling <a href> adding a new step with its relative path: ../a. So, finally, this expression selects the link at the same level as your div:
//div[contains(#class, 'primary')]
//div[contains(#class, 'results')]
//div[#class='price-range']
[../a[#href] and not(span[contains(#class,'separate')])]
/../a
Or in one line:
//div[contains(#class, 'primary')]//div[contains(#class, 'results')]//div[#class='price-range'][../a[#href] and not(span[contains(#class,'separate')])]/../a