In libxml, I try to select the first element to verify a condition using xpath. If I understood correctly, "//div[contains(#id,'art')][1]" in xpath would give just one element, though I get more than one of them. I use the function getnodeset in the libxml tutorial (see here). Here is the code :
xmlXPathObjectPtr result=getnodeset(def,(xmlChar*) "//div[contains(#id,'art')][1]"); // where def is a htmlDocPtr
xmlNodeSetPtr nodeset;
if(result)
{
nodeset=result->nodesetval;
if(nodeset->nodeNr>1)
fprintf(stderr,"%i first div with id attribute *art* : %s\n",nodeset->nodeNr,nomDef);
}
Instead of
"//div[contains(#id,'art')][1]"
you want
"(//div[contains(#id,'art')])[1]"
The reason has to do with binding precedence. As you probably know, [1] is shorthand for [position() = 1]. In the variant that you were trying to use, this means "when the current node (the div element) is the first child of its parent". Clearly, there could be many such divs that are each the first child of their respective parent.
When you put parentheses around the expression //div[predicate] and append [1] to that, then you're asking the question you intended to ask: what is the first node in the nodeset selected by //div[predicate]?
Related
I am trying to write a locator where the next text descendant is returned. I wont know the text. The following xpath works:
//*[#id='myChart']//label[contains(text(),"Show:")]/following::div[4]
but I dont like the div[4] as this could easily change. The element is the first div type descendant under show that contains text. Any suggestions?
A
Considering the following clauses:
the next text descendant
I wont know the text
div[4] as this could easily change
element is the first div type descendant
To locate the element a couple of effective approaches are as follows:
Using xpath:
//*[#id='myChart']//label[contains(., "Show")]//div[text()]
Using xpath with descendant:
//*[#id='myChart']//label[contains(., "Show")]//descendant::div[text()]
Using xpath with following:
//*[#id='myChart']//label[contains(., "Show")]//following::div[text()]
I think this will work for you:
//*[#id='myChart']//label[contains(text(),"Show:")]//div[text()]
To give more confident answer we need to see the actual page / XML.
In case the desired div is a direct child of the label containing the "Show:" the above expression can be presided to
//*[#id='myChart']//label[contains(text(),"Show:")]/div[text()]
How can I use xpath instead of id to find the element in DOM. I know that for id I can use: $("#id")[0].
I use $("#id")[0] inside Developer mode in browser in order to get the element by id to see what methods (like .getText(), innerHTML or others) am I able to use for the element. I want to know how to do this by XPATH
Thanks in advance
On Firefox console you can find (and explore) the element like this:
$x("//button[#id='myButton']")
But if you want to call a function on the element, you have to call it like this:
$x("//button[#id='myButton']")[0].click()
because there is always an array of elements returned (provided that the element is present and the first one in the array).
Thanks for the comments. I found out the answer. It can be done with:
$x("xpath")
Usually in protractor you can select singular element with:
element(protractor.By.css('#fdfdf'));
Occasionally you get something like this:
element(protractor.By.css('.dfdf'));
which potentially has more than one element. What's the correct way to select an index from a locator that locates multiple elements, and still contain the protractor's methods for sending Keys?
You can get an indexed element from an array returned with
// Get the 5th element matching the .dfdf css selector
element.all(by.css('.dfdf')).get(4).sendKeys('foo');
If you want to get the first element then
element.all(by.css('.dfdf')).first();
element.all(by.css('.dfdf')).get(0);
Try this one. It will work:
element.all(by.css('.dfdf')).get(4).getText();
I don't know why xpath is so much underestimated but you can solve thousands of problems with it, including this one
let elem = element(by.xpath('(//div//a)[3]'))
You can specify the number of element to use. Keep in mind the numbers start from 1, not 0 as usually in js
Using selenium for the first time here, I was wondering why:
final WebElement justAnId = findElement(By.cssSelector("#someId"));
final WebElement whatIWant = justAnId.findElement(
By.cssSelector(".aClass.andAnother input[type=text]")
);
works, but not:
final WebElement whatIWant = findElement(By.cssSelector(
"div#someId.aClass.andAnother input[type=text]"
));
Although they seem equivalent to me I get:
org.openqa.selenium.NoSuchElementException: Unable to locate element:
{"method":"css selector","selector":"div#someId.aClass.andAnother input[type=text]"}
Is this intended behaviour or a bug in Selenium? I had a quick look in the bug tracker in Selenium but I didn't see anything about that. I wanted to ask here before raising an issue that doesn't need to be. Also as far as I understand it doesn't work in IE6 but who cares. I was using firefox for this run.
Actually the two are quite different selectors.
Here is your cssSelector:
div#someId.aClass.andAnother input[type=text]
But what you really wanted to write was:
div#someId .aClass.andAnother input[type=text]
notice the space between ID and class. you need that.
findElement() finds an element in the current context, which means your first snippet of code is really finding an element that matches .aClass.andAnother input[type=text], which is contained within #someId. The element with that ID may or may not contain the two classes; WebDriver doesn't assume you're referring to the same element; it just finds the input as long as its ancestors are #someId and .aClass.andAnother.
This is completely different from div#someId.aClass.andAnother input[type=text], which finds any input[type=text] within div#someId.aClass.andAnother only (i.e. it's a div that contains both the ID and the classes).
I'm trying to check whether a certain node exists beneath a branch of an ExtJS tree. Knowing the ID of the parent node, is there a library function to check whether a node exists beneath the parent (by its ID)?
I've checked the API numerous times over, and can only seem to accomplish this by iterating through the entire branch of the tree.
Is there a library function which allows me to check if a child exists (by its ID) if the parent node ID is known?
Thanks!
PS, to find the parent ID, I'm using the following:
tree.getNodeById('myID');
Ext.tree.TreeNode "contains" function does exactly what you want:
var parent = tree.getNodeById('myID');
parent.contains(tree.getNodeById('childId'));
Have you looked at DomQuery? The API defines the method jsSelect: selects a group of elements.
jsSelect( String selector, [Node/String root] ) : Array
Parameters:
selector : String
The selector/xpath query (can be a comma separated list of selectors)
root : Node/String
(optional) The start of the query (defaults to document).
Returns an Array of DOM elements which match the selector. If there are no matches, and empty Array is returned.