1

I have a radio button with value as HTML as follows:

<div class='result'>
<span>
<input type='radio'/>
option1
</span>
<span>
<input type='radio'/>
option2
</span>
<span>
<input type='radio'/>
option3
</span>
</div>

I tried the following XPath, but this isn't working:

//span[contains(text(),'option1')]/input[@type='radio']

Please help me write XPath for this.

Bill Bell
  • 21,021
  • 5
  • 43
  • 58
Vijay Asok
  • 17
  • 1
  • 7

4 Answers4

1

There are actually two text nodes in target span: the first one is just an empty string before <input> and the second- after <input> (the one that contains "option1")

And your XPath //span[contains(text(),'option1')] means return span that contains "option1" in first text node.

You can use one of below expressions to match required input:

  1. //span[normalize-space()="option1"]/input[@type="radio"]
  2. //span[contains(text()[2],'option1')]/input[@type='radio']
Andersson
  • 51,635
  • 17
  • 77
  • 129
0

I guess you can't use text() here. Because this function returns a sequence of child text nodes of current span element. There are 2 text nodes in your example:

<span>
<input type='radio'/>
option1
</span>

1st text node is between <span> and <input type='radio'/> containing just a newline.

2nd text node is between <input type='radio'/> and </span> containing option1 text plus 2 newlines (at the begining and at the ending).

contains function expects a string argument instead of a sequence. I think it will take only first text node from the sequence, which contains just a newline.

If you need to select input followed by some text node you can use the following expression:

//input[@type='radio'][contains(following-sibling::text(), 'option1')]

If you need to select span containing text option1 and input with @type='radio', you can try the following expression:

//span[contains(., 'option1') and input/@type='radio']

If you need to select input instead of span then use the following expression:

//span[contains(., 'option1')]/input[@type='radio']

I can suggest you the following resources to gain some information about XPath. W3C recomendations contains a full description of XPath. If you use XPath 2.0 then you can look at:

For XPath 3.0 look at:

These recomendations are big enough and hard to read. But you can find in these documents a list of all available axes including following-sibling::, a description of text(), a description of contains(), etc.

Also there are a lot of brief XPath tutorials. For example you can look at this one.

Denis
  • 1,167
  • 1
  • 10
  • 30
0

There are two text elements per span. One precedes the input element, and one follows it, but the first one is essentially empty.

In this code I find the input elements, then their parents, then the second text elements of those span parents.

>>> from scrapy.selector import Selector
>>> selector = Selector(text=open('temp.html').read())
>>> for item in selector.xpath('.//input[@type="radio"]/../text()[2]'):
...     item.extract()
...     
'\noption1\n'
'\noption2\n'
'\noption3\n'
Bill Bell
  • 21,021
  • 5
  • 43
  • 58
0

try this to select option 1

//input[@type='radio']/preceding::span[1][contains(.,'option1')]
iamsankalp89
  • 4,607
  • 2
  • 15
  • 36