我对Nokogiri和Ruby很陌生,正在寻求一点帮助。
我正在使用class MyDoc < Nokogiri::XML::SAX::Document
解析一个非常大的XML文件。现在我想遍历块的内部。
这是我的XML文件的格式:
<Content id="83087">
<Title></Title>
<PublisherEntity id="1067">eBooksLib</PublisherEntity>
<Publisher>eBooksLib</Publisher>
......
</Content>
我已经可以判断是否找到了"内容"标签,现在我想知道如何在其中遍历。这是我缩短的代码:
class MyDoc < Nokogiri::XML::SAX::Document
#check the start element. set flag for each element
def start_element name, attrs = []
if(name == 'Content')
#get the <Title>
#get the <PublisherEntity>
#get the Publisher
end
end
def cdata_block(string)
characters(string)
end
def characters(str)
puts str
end
end
纯粹主义者可能不同意我的观点,但我一直这样做的方法是使用 Nokogiri 遍历大文件,然后使用 XmlSimple 来处理文件中较小的对象。这是我的代码片段:
require 'nokogiri'
require 'xmlsimple'
def isend(node)
return (node.node_type == Nokogiri::XML::Reader::TYPE_END_ELEMENT)
end
reader = Nokogiri::XML::Reader(File.open('database.xml', 'r'))
# traverse the file looking for tag "content"
reader.each do |node|
next if node.name != 'content' || isend(node)
# if we get here, then we found start of node 'content',
# so read it into an array and work with the array:
content = XmlSimple.xml_in(node.outer_xml())
title = content['title'][0]
# ...etc.
end
这对我来说效果很好。有些人可能反对在同一代码中混合使用 SAX 和非 SAX(nokogiri 和 XmlSimple),但就我而言,它以最小的麻烦完成工作。
使用 SAX 比较棘手。我认为解决方案需要看起来像这样:
class MyDoc < Nokogiri::XML::SAX::Document
def start_element name, attrs = []
@inside_content = true if name == 'Content'
@current_element = name
end
def end_element name
@inside_content = false if name == 'Content'
@current_element = nil
end
def characters str
puts "#{@current_element} - #{str}" if @inside_content && %w{Title PublisherEntity Publisher}.include?(@current_element)
end
end