2012-07-10 114 views
0

假设我有以下XML文档。我使用Ruby 1.9.3,Rails 3.2.6和Nokogiri 1.5.5将XML解析到数据库中。我希望能够遍历XML标签并按正确的顺序挑选元素。使用Ruby循环解析XML文档

<?xml version="1.0"?> 
<RandomTag> 
    <library name='Favorite Books'> 
     <book ISBN="11342343"> 
      <title>TKAM</title> 
      <description>Desc1</description> 
      <author>H Lee</author> 
     </book> 
     <book ISBN="989894781234"> 
      <title>Catcher in the Rye</title> 
      <description>Desc2</description> 
      <author>JD S</author> 
     </book> 
    </library> 
    <library name='Other Books'> 
     <book ISBN="123456789"> 
      <title>Murphy\'s Gambit</title> 
      <description>Desc3</description> 
      <author>Syne M</author> 
     </book> 
    </library> 
</RandomTag> 

我使用类似于下面来遍历一个循环:

f = File.open(args[:file]) 
doc = Nokogiri::XML(f) 
f.close 

doc.css('library').each do |node| 
    children = node.children 
    lib = {"name" => node['name']} 
    Library.create(lib) 

    doc.css('book').each do |n| 
    churn = n.children 
    book = {#book elements} 
    Book.create(book) 
    end 
end 

所以我基本上是寻找一个库,然后一旦我找到了,我在寻找该图书馆内的所有书籍。我目前的代码的问题是.css()方法搜索,直到EOF。因此,无论图书馆驻留在哪一个图书馆中,内部的“图书”循环都会触发。另外,一旦我打开了第二个图书馆,“图书”循环又从文档开始处开始,继续阅读每本书。最终的结果是我得到正确数量的正确名称的图书馆,但每个图书馆都有每本书。当我点击一个新的“图书馆”标签时,我需要一种方法来停止搜索书籍(从内部循环中断开)。

是否有不同的方法比.css()会做到这一点?有什么方法可以在循环中写入break语句来退出特定情况?

回答

2

你发现所有的书,因为你打电话

doc.css('book') 

其定义搜索任何一本书在文档中。如果你只是想找到某个元素内的书籍,然后调用该.css

doc.css('library').each do |library_node| 
    library_node.css('book').each do |book_node| 
    #only iterates on the books inside that library 
    end 
end 
+0

当然。大概本该想出一个我自己哈哈......谢谢! – 2012-07-11 16:20:57

1

你在这里看到的是一个迭代器。该方法遍历它找到的所有属性。

如果引入nokogiri支持枚举模块,还有,你可以使用多种其他的方法:

http://apidock.com/ruby/Enumerable

你的情况,你可以使用发现只使用第一个匹配的元素。

+0

好了,所以我用.find搜索的第一个库。现在我拥有了。现在我需要遍历(枚举?)所有书籍,直到我点击下一个图书馆标签。我再次使用.find来获得第一本书。我把这个.find方法放在一个循环中去查找所有的书。如何停止查找书籍并继续查找图书馆? – 2012-07-10 21:47:24