我正在使用Ruby在选定的XML节点周围注入新元素。像这样:
require 'rexml/document'
include REXML
xml = <<EOF
<fmxmlsnippet type="FMObjectList">
<Step name="Variable"/>
<Step name="Comment"/>
<Step name="Variable"/>
</fmxmlsnippet>
EOF
doc = Document.new xml
el = Element.new 'node'
doc.elements.each( "//Step[@name=\"Variable\"]"){ |e|
e.previous_sibling = el
e.next_sibling = el
}
doc.write( $stdout, 2 )
这是我想要的结构:
<fmxmlsnippet type='FMObjectList'>
<node/>
<Step name='Variable'/>
<node/>
<Step name='Comment'/>
<node/>
<Step name='Variable'/>
<node/>
</fmxmlsnippet>'
但这是我用上面的代码得到的:
<fmxmlsnippet type='FMObjectList'>
<Step name='Variable'/>
<Step name='Comment'/>
<Step name='Variable'/>
<node/>
</fmxmlsnippet>'
我做错了什么?
我猜这与我对块的执行方式缺乏了解有关。该路径似乎有效,因为它可以很好地打印所需元素的属性。
我想继续使用REXML,因为它是Ruby发行版的一部分,但我会考虑Nokogiri是否能以这种方式工作。
答案 0 :(得分:2)
这是使用Nokogiri。我更喜欢并推荐它,因为它非常灵活,而且这些天Ruby的事实标准。
xml = <<EOT
<fmxmlsnippet type="FMObjectList">
<Step name="Variable"/>
<Step name="Comment"/>
<Step name="Variable"/>
</fmxmlsnippet>
EOT
require 'nokogiri'
doc = Nokogiri::XML(xml)
doc.search('Step[name="Variable"]').each do |s|
s.add_previous_sibling('<node/>')
s.add_next_sibling('<node/>')
end
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <fmxmlsnippet type="FMObjectList">
# >> <node/><Step name="Variable"/><node/>
# >> <Step name="Comment"/>
# >> <node/><Step name="Variable"/><node/>
# >> </fmxmlsnippet>
使用CSS访问器查找Step
节点name="Variable"
。对于遇到的每一个,它会添加上一个和下一个兄弟<node>
。 Nokogiri也支持XPath,因此'//Step[@name="Variable"]'
也可以正常工作。