无法迭代REXML中的元素

时间:2011-06-21 04:52:15

标签: ruby xml-parsing rexml

我正在使用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是否能以这种方式工作。

1 个答案:

答案 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"]'也可以正常工作。