2012-07-10 125 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