2013-12-05 4 views
1

У меня возникает странная проблема с nokogiri и xpath. Я хочу проанализировать HTML-документ и получить все ссылки по значению href и содержащемуся в них якорем.xpath with содержит ошибку throw, если строка начинается с числа

Вот мой XPath до сих пор:

xpath = "//a[contains(text(), #{link['anchor_text']}) and @href='#{link['target_url']}']" 
    a = doc.search(xpath) 

Это прекрасно работает до сих пор, пока связь [ «anchor_text»] является строка без цифр.

Если я пытаюсь получить ссылку с якорным текстом «11example» он выдает следующее сообщение об ошибке:

Invalid expression: //a[contains(text(), 11example) and @href='http://www.example.com/'] 

Может быть, это просто глупая ошибка, но я не вижу, почему возникает эта ошибка , Если я помещаю некоторые цитаты вокруг ссылки # {link ['anchor_text']} в xpath, ничего не работает.

Edit: Вот пример HTML:

<!DOCTYPE html> 
<head> 
    <title>Example.com</title> 
</head> 
<body> 
<p> 
<strong>Here is some text</strong><br /> 
<a href="example.com" target="_blank">11example</a>Some text here and there 
</p> 
<p> 
<strong>Another text</strong><br /> 
<a href="example.com/test" target="_blank">example.com</a>Some text here and there 
</p> 
</body> 

Edit2: Если я запускаю эти запросы вручную в IRB консоли все работает, как ожидалось, но только если я надену текст в кавычках.

Заранее благодарен!

С наилучшими пожеланиями, madhippie

+1

Дайте нам HTML-код также. –

+0

О, извините, я добавил HTML. – madhippie

ответ

5

Простой ответ заключается в том, что вам не хватает в кавычки #{link['anchor_text']}, как у вас есть вокруг #{link['target_url']}. Полный XPath должен быть

xpath = "//a[contains(text(), '#{link['anchor_text']}') and @href='#{link['target_url']}']" 

Причина, по-видимому, работает (по крайней мере, не приводит к ошибке), когда вы не начать с номером, что строка интерпретируется как запрос узла. Например, Nokogiri ищет тег с именем <example.com> внутри тега <a>, а затем преобразовывает его в строку и видит, содержат ли текстовые узлы тега эту строку. Если тега нет (как в этом случае), то результат contains всегда верен.

В качестве демонстрации с HTML:

<a href="example.com"><q>foo</q>example</a> 
<a href="example.com"><q>foo</q>foo</a> 
<a href="example.com">foo</a> 

Тогда запрос

doc.search("//a[contains(text(), q)]") 

не соответствует первой <a> тег, но совпадает с вторым и третьим.

Когда строка начинается с числа, она не может быть проанализирована в запросе узла, поскольку имена, начинающиеся с цифр, являются недопустимыми именами элементов XML (или HTML), поэтому вы получаете ошибку.

+0

Действительно ли '' # {link ['anchor_text']} '' действительно будет работать? Как XPath знает, что '' 'before' anchor' не сигнализирует о конце строки' # {link ['? – LarsH

+1

@LarsH Содержимое '# {...}' сначала интерполируется Ruby, а затем переходит к Nokogiri. Поэтому, если 'link ['anchor_text']' оценивается как '11example' (в Ruby), то строка, которую видит Nokogiri, будет' '11example'' (с внешними кавычками). Ruby обрабатывает кавычки, вложенные внутри '# {...}', как это прекрасно. – matt

+0

А, глупо меня. Спасибо за подробный ответ и объяснение! – madhippie

Смежные вопросы