Нокогири и поиск элемента по имени - PullRequest
4 голосов
/ 29 апреля 2011

Я анализирую XML-файл, используя Nokogiri со следующим фрагментом:

doc.xpath('//root').each do |root|
  puts "# ROOT found"
  root.xpath('//page').each do |page|
    puts "## PAGE found / #{page['id']} / #{page['name']} / #{page['width']} / #{page['height']}"
    page.children.each do |content|
      ...
    end
  end
end

Как я могу разобрать все элементы в элементе страницы? Есть три разных элемента: изображение, текст и видео. Как я могу сделать заявление для каждого элемента?

Ответы [ 2 ]

10 голосов
/ 29 апреля 2011

Честно, ты выглядишь довольно близко от меня ..

doc.xpath('//root').each do |root|
  puts "# ROOT found"
  root.xpath('//page').each do |page|
    puts "## PAGE found / #{page['id']} / #{page['name']} / #{page['width']} / #{page['height']}"
    page.children.each do |child|
      case child.name
       when 'image'  
          do_image_stuff
       when 'text'
          do_text_stuff
       when 'video'
          do_video_stuff
       end
    end
  end
end
5 голосов
/ 01 мая 2011

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

require 'nokogiri'

doc = Nokogiri::XML('
  <xml>
  <body>
  <image>image</image>
  <text>text</text>
  <video>video</video>
  <other>other</other>
  <image>image</image>
  <text>text</text>
  <video>video</video>
  <other>other</other>
  </body>
  </xml>')

Это поиск с использованием CSS:

doc.search('image, text, video').each do |node|
  case node.name
  when 'image'
    puts node.text
  when 'text'
    puts node.text
  when 'video'
    puts node.text
  else
    puts 'should never get here'
  end
end

# >> image
# >> image
# >> text
# >> text
# >> video
# >> video

Обратите внимание, что он возвращает теги в том порядке, в котором CSSаксессор указывает это.Если вам нужен порядок тегов в документе, вы можете использовать XPath:

doc.search('//image | //text | //video').each do |node|
  puts node.text
end

# >> image
# >> text
# >> video
# >> image
# >> text
# >> video

В любом случае программа должна работать быстрее, потому что весь поиск происходит в libXML, возвращая только те узлы, которые вам нужныОбработка Руби.

Если вам нужно ограничить поиск с помощью тега <page>, вы можете выполнить поиск заранее, чтобы найти узел page, а затем выполнить поиск под ним:

doc.at('page').search('image, text, video').each do |node|
  ...
end

или

doc.at('//page').search('//image | //text | //video').each do |node|
  ...
end
...