Метод "контейнера" ​​в стиле Hpricot для Nokogiri? Выберите только определенные node_types - PullRequest
1 голос
/ 19 апреля 2011

Я перемещаюсь по документу, используя CSS-селекторы с Ruby, но я нашел несколько ошибок css-селектора в Hpricot, которые исправлены в Nokogiri и хотят переключиться.

Единственная проблема, с которой я столкнулся, это выяснить, как получить массив всех дочерних элементов, которые являются «контейнерами» (то есть не текстовыми узлами). Hpricot предоставляет эту функциональность сразу после установки методом контейнеров.

Так что в Hpricot я мог бы сделать:

children = doc.select('*')[0].containers

Но с Nokogiri кажется, что ту же самую функциональность можно получить только с помощью следующего (и я не уверен, работает ли он точно так же):

children = doc.css('*')[0].children.to_a.keep_if {|x| x.type != Nokogiri::XML::Node::TEXT_NODE }

Есть ли лучший способ сделать это?

1 Ответ

0 голосов
/ 22 апреля 2011

Чтобы уточнить, вы хотите только дочерние элементы, но не дочерние текстовые узлы? Если это так, вот три метода:

require 'nokogiri'
doc = Nokogiri::XML "<r>no<a1><b1/></a1><a2>no<b2>hi</b2>mom</a2>no</r>"

# If the element is uniquely selectable via CSS
kids1 = doc.css('r > *')

# ...or if we assume you found an element and want only its children
some_node = doc.at('r')

# One way to do it
kids2 = some_node.children.grep(Nokogiri::XML::Element)

# A geekier-but-shorter-way
kids3 = some_node.xpath('*')

# Confirm that they're the same (converting the NodeSets to arrays)
p [ kids1.to_a == kids2, kids2 == kids3.to_a ]
#=> [true, true]

p kids1.map(&:name), kids2.map(&:name), kids3.map(&:name)
#=> ["a1", "a2"]
#=> ["a1", "a2"]
#=> ["a1", "a2"]
...