7

1)I am doing a tutorial to show how findElements By xpath works. I would like to know why it returns all the texts that following the <div> element with attribute id=container.

code for xpath: By.xpath("//div[@id='container']

2) how should I modify the code so it just return first or first few nodes that follow the parent note e.g. first node like 'Home', first few node like, Home, Manual Testing and Automation Testing.

Thanks for your advise and help!

Here is the code fragment for this tutorial:

import java.util.List;

import org.junit.Test;
import org.junit.Before;
import org.junit.After;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class WD_findElements 
{
    @Test
    public void test_byxpath(){

        WebDriver driver = new FirefoxDriver();

        try{
            driver.get("http://www.hexbytes.com");

        List<WebElement> elements = driver.findElements(By.xpath("//div[@id='container']"));    
            System.out.println("Test7 number of elements: " + elements.size());

            for(WebElement ele : elements){
                //ele.sendKeys("hexbyes");
                System.out.println(ele.getText());
                //System.out.println(ele.getAttribute("id"));
                //System.out.println(ele.getTagName());
            } 
        }
        finally {
            driver.close();
        }

    }//end of test_byxpath

 public void xpathDemo2() {
           WebDriver driver = new FirefoxDriver();
           try{
               driver.get("http://www.hexbytes.com");
               WebElement webelement = driver.findElement(By.id("container"));
               //matching single element with attribute value=container
               System.out.println("The id value is: " + webelement.getAttribute("id"));
               System.out.println("The tag name is: " + webelement.getTagName());
           }
           finally {
               driver.close();
           }
       }//end of xpathDemo2 

public void xpathDemo3() {
       WebDriver driver = new FirefoxDriver();
       try{
           driver.get("http://www.hexbytes.com");
          //find first child node of div element with attribute=container
          List<WebElement> elements = driver.findElements(By.xpath("//div[@id='container']/*[1]"));
          System.out.println("Test1 number of elements: " + elements.size()); 

          for(WebElement ele : elements){
              System.out.println(ele.getTagName());
              System.out.println(ele.getAttribute("id"));
              System.out.println("");
              System.out.println("");
          }
   }
   finally {
       driver.close();
   }
 }//end of xpathDemo3
 }
Gijs
  • 144
  • 1
  • 1
  • 11
user2061466
  • 485
  • 9
  • 17
  • 27

3 Answers3

6

Your questions:

Q 1.) I would like to know why it returns all the texts that following the div?
It should not and I think in will not. It returns all div with 'id' attribute value equal 'containter' (and all children of this). But you are printing the results with ele.getText() Where getText will return all text content of all children of your result.

Get the visible (i.e. not hidden by CSS) innerText of this element, including sub-elements, without any leading or trailing whitespace.
Returns:
The innerText of this element.

Q 2.) how should I modify the code so it just return first or first few nodes that follow the parent note
This is not really clear what you are looking for. Example:

<p1> <div/> </p1 <p2/> 

The following to parent of the div is p2. This would be:

 //div[@id='container'][1]/parent::*/following-sibling::* 

or shorter

 //div[@id='container'][1]/../following-sibling::* 

If you are only looking for the first one extent the expression with an "predicate" (e.g [1] - for the first one. or [position() &lt; 4]for the first three)

If your are looking for the first child of the first div:

//div[@id='container'][1]/*[1]

If there is only one div with id an you are looking for the first child:

   //div[@id='container']/*[1]

and so on.

hr_117
  • 9,589
  • 1
  • 18
  • 23
  • thanks for the reply. I am not quiet sure about the node concept. From view html source page, `
    ` I think the first child of the div tag is `
    – user2061466 May 04 '13 at 16:30
  • Your xpath `"//div[@id='container'][1]"` returns the first div with id container. If there is only one this is the same as `"//div[@id='container']"` all children would be `/*` and the first child `/*[1]`. Therefor try: `"//div[@id='container']/*[1]` – hr_117 May 04 '13 at 17:12
  • Thank you so much for the clarification. I have a better understanding on the xpath subject. More practice needed to enhance my knowledge. – user2061466 May 04 '13 at 21:45
  • Glad I could help. Please consider to select the answer as valid if it was what you arr looking for. – hr_117 May 05 '13 at 05:50
  • @user2061466 the div tag doesnt have any children in that case. the div is a node with an attribute 'id' which has value 'header' – JonnyRaa Feb 06 '14 at 10:46
3

The XPath turns into this:

Get me all of the div elements that have an id equal to container.

As for getting the first etc, you have two options.

Turn it into a .findElement() - this will just return the first one for you anyway.

or

To explicitly do this in XPath, you'd be looking at:

(//div[@id='container'])[1]

for the first one, for the second etc:

(//div[@id='container'])[2]

Then XPath has a special indexer, called last, which would (you guessed it) get you the last element found:

(//div[@id='container'])[last()]

Worth mentioning that XPath indexers will start from 1 not 0 like they do in most programming languages.

As for getting the parent 'node', well, you can use parent:

//div[@id='container']/parent::*

That would get the div's direct parent.

You could then go further and say I want the first *div* with an id of container, and I want his parent:

(//div[@id='container'])[1]/parent::*

Hope that helps!

Arran
  • 24,648
  • 6
  • 68
  • 78
  • thanks for the reply. I understood that .findElement method only return a single matching element, but .findElements returns multiple matching elements. I tried to match the first node or the child of the div element with attribute=container, it returned the id value as container. To me the first child should be the div element with id=header `driver.findElements(By.xpath("//div[@id='container'][1]"))` `System.out.println(ele.getAttribute("id"));` it retuned *container* instead of *header*. Am I doing this correctly? Please give me some feedback. – user2061466 May 04 '13 at 16:14
  • You are looking for `//div[@id='container']/div[id@='header']`. – Arran May 05 '13 at 19:01
0

Instead of

css=#container

use

css=div.container:nth-of-type(1),css=div.container:nth-of-type(2)
Random Dev
  • 51,810
  • 9
  • 92
  • 119
user3487861
  • 340
  • 2
  • 2