Выражение xPath для атрибутов, у которых нет предков с таким же атрибутом - PullRequest
0 голосов
/ 27 февраля 2011

Я пытаюсь извлечь элементы с атрибутом, а не извлекать потомков по отдельности, которые имеют тот же атрибут.

Используя следующий HTML-код:

<html><body>
  <div box>
    some text
    <div box>
      some more text
    </div>
  </div>
  <div box>
    this needs to be included as well
  </div>
</body></html>

Я хочу бытьЯ могу извлечь два внешних <div box> и его потомков, включая внутренний <div box>, но не хочу, чтобы внутренний <div box> извлекался отдельно.

Я пытался использовать все виды различных выражений, ноЯ думаю, что мне не хватает чего-то совершенно фундаментального.Основное выражение, которое я пробовал: //[@box and not(ancestor::@box), но оно по-прежнему возвращает два элемента.

Я пытаюсь сделать это, используя гем Hpricot (0.8.3) в Ruby 1.9.2, следующим образом:

# Assuming html is set to the html above
doc = Hpricot(html)
elements = doc.search('//[@box and not(ancestor::@box)]')

# The following is returning 3 instead of 2
elements.size

Любая помощь в этом была бы полезна.

Ответы [ 2 ]

2 голосов
/ 27 февраля 2011

Ваш XPATH недействителен. Вы должны обратиться к чему-то, чтобы использовать фильтр предикатов (например, []). Иначе нечего фильтровать.

Этот XPATH работает:

//div[@box and not(ancestor::div/@box)]

Если не все элементы гарантированно равны <div>, вы можете использовать более общее соответствие для элементов:

//*[@box and not(ancestor::*/@box)]
0 голосов
/ 27 февраля 2011

Использование elements = doc.search('//[@box and not(ancestor::@box)]') неверно.

Используйте elements = doc.at('//div[@box]'), который найдет первое вхождение.

Я бы рекомендовал использовать Nokogiri вместо Hpricot. Nokogiri хорошо поддерживается, очень гибкий и надежный.


РЕДАКТИРОВАТЬ: Добавлено, потому что оригинальный вопрос изменился:

Спасибо, что сработало отлично, за исключением того, что я забыл упомянуть, что хочу вернуть несколько внешних элементов. Извините, я обновил вопрос. Я рассмотрю Nokogiri дальше, я не выбрал его изначально, потому что Hpricot казался более доступным.

Помните, что XPath действует как доступ к файлу в каталоге в его самой простой форме, поэтому вы можете развернуть его и искать в "подкаталогах". Если вам нужны только внешние теги <div>, то загляните внутрь уровня <body> и не дальше:

doc.search('/html/body/div')

или, если у вас есть целые div метки вместе с целями:

doc.search('/html/body/div[@box]')

Относительно Hpricot, кажущегося более доступным:

Nokogiri реализует расширенный набор аксессоров Hpricot, что позволяет вам использовать его в большинстве случаев. Он поддерживает XPath и CSS-аксессоры, предоставляя более интуитивно понятные способы получения данных, если вы живете в CSS и HTML и не пользуетесь XPath. Кроме того, есть много способов найти желаемую цель:

doc.search('body > div[box]')
(doc / 'body > div[box]')
doc.css('body > div[box]')

Nokogiri также поддерживает синоним at и %, найденный в Hpricot, наряду с css_at, если вы хотите только первое появление чего-либо.

Я начал использовать Nokogiri после того, как столкнулся с некоторыми ситуациями, когда Hpricot взорвался, потому что он не мог обрабатывать неправильно сформированные новостные ленты в дикой природе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...