Подтвердить что ты не робот

Выражение xpath для регулярного сравнения?

Я хочу найти div id в html-документе с определенным шаблоном. Я хочу сопоставить этот шаблон в регулярном выражении:

foo_([[:digit:]]{1.8})

используя xpath. Каков эквивалент xpath для вышеуказанного шаблона?

Я застрял с //div[@id="foo_, и что тогда? Если кто-то может продолжить юридическое выражение для него.

ИЗМЕНИТЬ

Извините, я думаю, что мне нужно уточнить больше. На самом деле это не foo_, it post_message_

Btw, я использую mechanize/nokogiri (ruby)

Здесь фрагмент:

html_doc = Nokogiri::HTML(open(myfile))
message_div =  html_doc.xpath('//div[substring(@id,13) = "post_message_" and substring-after(@id, "post_message_") => 0 and substring-after(@id, "post_message_") <= 99999999]') 

Все еще не удалось. Сообщение об ошибке:

Не удалось оценить выражение '//div[substring(@id,13) = "post_message_" and substring-after(@id, "post_message_") => 0 and substring-after(@id, "post_message_") <= 99999999]' (Nokogiri:: XML:: XPath:: SyntaxError)

4b9b3361

Ответ 1

Как насчет этого (обновленного):

XPath 1.0:

"//div[substring-before(@id, '_') = 'foo' 
       and substring-after(@id, '_') >= 0 
       and substring-after(@id, '_') <= 99999999]"

Изменить № 2: ОП внес изменения в вопрос. Для меня работает следующее, еще более сжатое выражение XPath 1.0:

"//div[substring(@id, 1, 13) = 'post_message_' 
       and substring(@id, 14) >= 0 
       and substring(@id, 14) <= 99999999]"

XPath 2.0 имеет удобную функцию matches():

"//div[matches(@id, '^foo_\d{1,8}$')]"

Помимо лучшей переносимости, я ожидал бы, что числовое выражение (стиль XPath 1.0) будет работать лучше, чем тест регулярного выражения, хотя это станет заметным только при обработке больших наборов данных.


Оригинальная версия ответа:

"//div[substring-before(@id, '_') = 'foo' 
       and number(substring-after(@id, '_')) = substring-after(@id, '_') 
       and number(substring-after(@id, '_')) &gt;= 0 
       and number(substring-after(@id, '_')) &lt;= 99999999]"

Использование функции number() не требуется, потому что операторы математического сопоставления неявно принуждают свои аргументы к номерам, любые не-номера станут NaN, и тесты, превышающие/меньше, будут терпеть неудачу.

Я также удалил кодировку угловых скобок, поскольку это требование XML, а не требование XPath.

Ответ 2

Как уже указывалось, в XPath 2.0 было бы полезно использовать стандартные возможности регулярного выражения с помощью как функция matches().

Один возможный XPath 1.0 решение:

//div[starts-with(@id, 'post_message_')
    and
      string-length(@id) = 21
    and
      translate(substring-after(@id, 'post_message_'), 
                '0123456789', 
                ''
                )
     =
      ''
      ] 

Обратите внимание на следующее:

  • Использование стандартной функции XPath starts-with().

  • Использование стандартной функции XPath string-length().

  • Использование стандартной функции XPath substring-after().

  • Использование стандартной функции XPath translate().

Ответ 3

Или используйте соответствия функции xpath (строка, шаблон).

  <xsl:if test="matches(name(.),'foo_')">

К сожалению, это не регулярное выражение, но этого может быть достаточно, если у вас нет других тэгов foo_, которые вам не нужны, тогда я думаю, вы можете добавить еще несколько "если", чтобы отбросить их.

Ответ 4

Nikkou делает это очень простым и понятным:

doc.search('div').attr_matches('id', /post_message_\d{1,8}/)