Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何在Nokogiri中使用SAX遍历内部节点?_Ruby_Nokogiri_Sax - Fatal编程技术网

Ruby 如何在Nokogiri中使用SAX遍历内部节点?

Ruby 如何在Nokogiri中使用SAX遍历内部节点?,ruby,nokogiri,sax,Ruby,Nokogiri,Sax,我对Nokogiri和Ruby还很陌生,正在寻求一些帮助 我正在使用classmydoc

我对Nokogiri和Ruby还很陌生,正在寻求一些帮助

我正在使用
classmydoc
解析一个非常大的XML文件。现在我想遍历块的内部

以下是我的XML文件的格式:

<Content id="83087">
    <Title></Title>
    <PublisherEntity id="1067">eBooksLib</PublisherEntity>
    <Publisher>eBooksLib</Publisher>
    ......
</Content>

电子书
电子书
......
我已经知道是否找到了“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
classmydoc
使用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
classmydoc
纯粹主义者可能不同意我的观点,但我的做法是使用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?您很有可能正在寻找Nokogiri.XML。XML文件至少为1GIG,因此我希望它具有内存效率。+1是的,这实际上是使用SAX的一个很好的理由