Подход, который я бы выбрал (если я понимаю вашу проблему), заключается в использовании XPath или CSS для поиска вашего элемента "start_here" и родительского элемента, в котором вы хотите искать. Затем рекурсивно обойдите дерево, начиная с родительского, останавливаясь при нажатии на элемент «start_here» и удерживая последний элемент, который соответствует вашему стилю на этом пути.
Что-то вроде:
parent = value.search("//body").first
div = value.search("//div[@id = 'X2']").first
find = FindPriorTo.new(div)
assert_equal('Foo', find.find_from(parent, 'h1').text)
assert_equal('Bar', find.find_from(parent, 'h2').text)
Где FindPriorTo
- простой класс для обработки рекурсии:
class FindPriorTo
def initialize(stop_element)
@stop_element = stop_element
end
def find_from(parent, style)
@should_stop = nil
@last_style = nil
recursive_search(parent, style)
end
def recursive_search(parent, style)
parent.children.each do |ch|
recursive_search(ch, style)
return @last_style if @should_stop
@should_stop = (ch == @stop_element)
@last_style = ch if ch.name == style
end
@last_style
end
end
Если этот подход недостаточно масштабируемый, то вы можете оптимизировать вещи, переписав recursive_search
, чтобы не использовать рекурсию, а также передать оба стиля, которые вы ищете, и отследить последний найденный, так что вам не нужно обходить дерево в дополнительное время.
Я бы также сказал, что попробуйте подключить Node к обезьяне, чтобы зацепить его при разборе документа, но похоже, что все это написано на C. Возможно, вам лучше использовать что-то иное, чем Nokogiri с собственным Ruby SAX-парсер (может быть REXML ), или, если ваша реальная задача - скорость, выполните поиск в C / C ++, используя Xerces или аналогичный. Я не знаю, насколько хорошо они будут работать с парсингом HTML.