我试图为xml文件中的特定元素设置属性,并且我使用
取得了成功doc.css('Object').attr("Id").value = timestamp
这种情况很好,直到“对象”不存在导致程序中出现异常并退出的情况。为了避免这种情况,我想使用Nodeset,因为它只是空的。
doc.css('Object').each do |element|
element.attr("Id").value = timestamp
end
然而,这返回错误,value =是一个未定义的方法。它可能很简单,但我是Ruby和CSS的新手,所以任何帮助都会很棒。
答案 0 :(得分:2)
这个问题与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>
了解at
,at_css
和at_xpath
之间的区别非常重要,它们会返回第一个匹配的Node和search
,{{3返回NodeSets的{}和css
。 xpath
类似于包含节点的数组。当你知道,你的陈述:
doc.css('Object').attr("Id").value = timestamp
没有多大意义,特别是因为那不是NodeSet方法的定义方式:
attr(key, value = nil, &blk)
您需要使用:
doc.css('Object').attr("Id", value)
将value
分配给文档中每个Id
节点的所有<Object>
属性。
但是,再次,这不是正确的选择,而是应该使用at
或at_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然后插入它来走很长的路线,但是,一般来说,这会产生更丑陋的代码并导致你做更多的工作,这会导致那些跟随你的脚步的人的代码可读性降低保持来源。