Как регулярное выражение соответствует значению последнего появившегося определенного атрибута в ruby - PullRequest
0 голосов
/ 12 февраля 2011

В проекте Ruby я работаю с плохо сформированным xml-файлом, полученным из внешнего источника.Я хочу только одно значение;атрибут скорости узла последней записи.XML выглядит следующим образом (я сократил его для удобства чтения)

<?xml version="1.0" encoding="utf-16"?>
<diagram>
  <refresh value="30" />
  <margin top="30" bottom="30" left="30" right="30" />
  <rates>
    <rate value="0" />
    <rate value="100" />
    <rate value="200" />
  </rates>
  <data>
    <record rate="121" label="" />
    <record rate="124" label="" />
    <record rate="141" label="" />
    <record rate="141" label="" />
    <record rate="148" label="" />
    <record rate="269" label="6:00" />
    <record rate="701" label="" />
    <record rate="755" label="" />
    <record rate="795" label="" />
    <record rate="850" label="7:00" />
    <record rate="935" label="" />
    <record rate="977" label="" />
  </data>
</diagram>

Теперь все, что мне нужно, это значение скорости в последнем узле записи.Я не очень хорош в регулярных выражениях, но я играл в Rubular, и у меня появилось такое выражение:

<record\b(?:(?=(\s+(?:rate="([^"]*)")|[^\s>]+|\s+))\1)*>

Что казалось более или менее достаточным;он возвращает значение и лишнюю «/», от которой я не могу избавиться, но если я сам выполню это регулярное выражение в моем коде, я столкнусь с проблемой;Кажется, я не получаю одинаковых результатов.У меня был этот код:

regex = Regexp.new('<record\b(?:(?=(\s+(?:rate="([^"]*)")|[^\s>]+|\s+))\1)*>')
matchdata = regex.match(s)
puts matchdata[0]

Я даю весь источник XML для этой функции в аргументе "s".Но это только возвращает пустые строки.Может ли кто-нибудь помочь мне здесь?

Ответы [ 2 ]

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

Просто для записи, вот как это сделать двумя разными способами с парсером, использующим тот же XML и String # scan:

require 'nokogiri'
doc = Nokogiri::XML(xml)

# using XPath
doc.at('//record[last()]')['rate'] # => "977"

# using CSS
doc.css('record').last['rate'] # => "977"

# using a bit of simple Regex
xml.scan(/<record.+$/).last[/rate="(\d+)"/, 1] # => "977"
2 голосов
/ 12 февраля 2011

Это соответствует одной записи: /<record\s+rate="(\d+?)"\s+label="(.*?)"\s+\/>/. Чтобы получить только последний, используйте:

regex = /(?:<record\s+rate="\d+?"\s+label=".*?"\s+\/>[\s\n\r]*)*<record\s+rate="(\d+?)"\s+label="(.*?)"\s+\/>/
s.scan(regex) do |rate, label|
  ...
end

Если вы хотите только скорость , используйте (?:<record\s+rate="\d+?".*>[\s\n\r]*)*<record\s+rate="(\d+?)".*>.

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