开发者

Unable to iterate over elements in REXML

开发者 https://www.devze.com 2023-03-14 12:22 出处:网络
I\'m using Ruby to inject new elements around selected XML nodes. Like this: require \'rexml/document\'

I'm using Ruby to inject new elements around selected XML nodes. Like this:

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 )

This is the structure that I want:

<fmxmlsnippet type='FMObjectList'>
    <node/>
    <Step name='Variable'/>
    <node/>
    <Step name='Comment'/>
    <node/>
    <Step name='Variable'/>
    <node/>
</fmxmlsnippet>' 

But this is what I'm getting with the code above:

<fmxmlsnippet type='FMObjectList'>
    <Step name='Variable'/>
    <Step name='Comment'/>
    开发者_StackOverflow中文版<Step name='Variable'/>
    <node/>
</fmxmlsnippet>' 

What am I doing wrong?

I'm guessing it has to do with my lack of understanding of how the block is getting executed. The path seems to work because it can print the desired elements' attributes just fine.

I'd like to stay with REXML because it's part of the Ruby distribution, but I'd consider Nokogiri if I can get it working that way.


This is using Nokogiri. I prefer and recommend it because it's very flexible and the defacto standard for Ruby these days.

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>

It's using CSS accessors to find the Step nodes with name="Variable". For each one encountered it adds a previous and next sibling <node>. Nokogiri supports XPath also so '//Step[@name="Variable"]' would work just as well.

0

精彩评论

暂无评论...
验证码 换一张
取 消