2014-01-29 60 views
0

我試圖設置特定元素的屬性在XML文件中,我有使用設置在引入nokogiri :: XML ::節點集的屬性與CSS

doc.css('Object').attr("Id").value = timestamp 

成功這是罰款,直至「對象」不存在導致程序中出現異常並退出的情況。爲了避免這種情況,我想使用Nodeset,因爲它只是空的。

doc.css('Object').each do |element| 
    element.attr("Id").value = timestamp 
end 

但是,這返回錯誤值=是一個未定義的方法。這可能很簡單,但我是Ruby和CSS的新手,所以任何幫助都會很棒。

回答

1

該問題與CSS無關,因爲Nokogiri使用CSS選擇器作爲使用XPath選擇器的替代方法,並且兩者僅用於提供節點或節點的路徑。

它看起來像你正在反思這一點,並使它比需要更難。這裏就是我想要做的:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<xml> 
    <foo> 
    <Object>bar</Object> 
    </foo> 
</xml> 
EOT 

doc.at('Object')["Id"] = Time.now.to_s 

看着doc在這一點上顯示:

puts doc.to_xml 
# >> <?xml version="1.0"?> 
# >> <xml> 
# >> <foo> 
# >>  <Object Id="2014-01-28 19:13:32 -0700">bar</Object> 
# >> </foo> 
# >> </xml> 

瞭解atat_cssat_xpath之間的區別是非常重要的,它會返回第一個匹配的Node,和search,cssxpath,其返回NodeSets。 A NodeSet類似於包含節點的數組。當你知道,你的發言:

doc.css('Object').attr("Id").value = timestamp 

將沒有多大意義,尤其是因爲這不是如何attr方法定義:

attr(key, value = nil, &blk) 

你需要使用:

doc.css('Object').attr("Id", value) 

它將爲文檔中的每個<Object>節點的所有Id屬性分配value屬性。

但是,這不是正確的選擇,而應該使用atat_css來返回單個節點。

這是罰款,直至情況下如果沒有<Object>節點存在「對象」不存在

,那麼它變得更有趣,你要確定該怎麼做。你可以插入它,或者,你可以簡單地移動,不做任何事情。

要查看某個節點存在簡單:

object_node = doc.at('Object') 
if object_node 
    object_node['Id'] = Time.now.to_s 
else 
    # ... insert it 
end 

要插入一個節點包括定位要插入的地方,然後將其添加:

doc.at('foo').add_child("<Object Id='#{ Time.now }'>baz</Object>") 
puts doc.to_xml 
# >> <?xml version="1.0"?> 
# >> <xml> 
# >> <foo> 
# >>  <Object>bar</Object> 
# >> <Object Id="2014-01-28 19:39:38 -0700">baz</Object></foo> 
# >> </xml> 

我沒有嘗試爲了使XML輸出更漂亮,這在XML中不重要,它只需要在語法上是正確的。

另請注意,可以通過將節點或節點定義爲XML字符串來插入節點。 Nokogiri會將其解析爲適當的XML並將其移植到您所說的地方。你也可以通過定義一個NodeSet或者Node,然後插入它來走長路,但是,一般來說,這會產生更醜陋的代碼,並導致你做更多的工作,這會導致那些跟隨你腳步的人的可讀代碼變少維護來源。

+0

感謝您的詳細回覆!這肯定有幫助。我一直在思考,並讓我的程序工作,我想要它! – Jud202

+0

很高興幫助。在Perl中使用XML解析器之後,我來到了Ruby和Nokogiri,並且以困難的方式做了很多事情。 Ruby和Nokogiri,使它變得更容易。 –