Nokogiri并按名称查找元素

Tro*_*nic 4 ruby xml nokogiri xml-parsing

我正在使用Nokogiri解析XML文件,其中包含以下代码段:

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
Run Code Online (Sandbox Code Playgroud)

如何解析页面元素中的所有元素?有三个不同的元素:图像,文本和视频.如何为每个元素创建一个case语句?

nol*_*oli 10

老实说,你看起来非常接近我..

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
Run Code Online (Sandbox Code Playgroud)


the*_*Man 5

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>')
Run Code Online (Sandbox Code Playgroud)

这是一个使用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
Run Code Online (Sandbox Code Playgroud)

请注意,它按CSS访问者指定的顺序返回标记.如果您需要文档中的标记顺序,则可以使用XPath:

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

# >> image
# >> text
# >> video
# >> image
# >> text
# >> video
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,程序都应该运行得更快,因为所有搜索都发生在libXML中,只返回Ruby处理所需的节点.

如果您需要将搜索限制在<page>标记内,您可以预先搜索以查找page节点,然后在其下搜索:

doc.at('page').search('image, text, video').each do |node|
  ...
end
Run Code Online (Sandbox Code Playgroud)

要么

doc.at('//page').search('//image | //text | //video').each do |node|
  ...
end
Run Code Online (Sandbox Code Playgroud)