如何更新节点集

How to update a NodeSet

我正在尝试在以下 XML 中再添加一个 <EventRouter> 元素:

<EventRouters>
        <EventRouter id="Important Events to Log File" class="com.cyclonecommerce.events2.router.LogFileRouter" active="true">
            <Parameters file="../logs/%nodeName%_events.log"
                        rollOnStart="false" autoFlush="true"
                        maxFileSize="2M" maxBackupFiles="5"/>
            <MetadataProcessorListRef ref="Messaging"/>
            <EventFilterRef ref="Important"/>
        </EventRouter>
        <EventRouter id="Message Detail to Log File"   class="com.cyclonecommerce.events2.router.LogFileRouter" active="false">
            <Parameters file="../logs/%nodeName%_message_detail.log"
                        rollOnStart="true" autoFlush="true"
                        maxFileSize="2M" maxBackupFiles="5"/>
            <MetadataProcessorListRef ref="Messaging"/>
            <EventFilterRef ref="Message Detail"/>
        </EventRouter>

</EventRouters>

我可以将节点附加到节点集,但是在保存后 XML 我没有得到更新的 XML 我想要:

require 'nokogiri'

if File.exist?('a.xml')
  data = File.read("a.xml")

end
doc = Nokogiri::XML.parse data
doc2=doc.xpath("//EventRouters/EventRouter")

event_router = Nokogiri::XML::Node.new("EventRouter",doc)
event_router['id'] = "some"
param_node = Nokogiri::XML::Node.new("Parameters",doc)
param_node.content = "some content"
event_router << param_node
doc2<<  event_router

File.open('test.xml', 'w') do |file|
  file.print doc.to_xml
end

改变

doc2=doc.xpath("//EventRouters/EventRouter")

doc2 = doc.at_xpath("//EventRouters")

xpath returns 一个数组。您可以使用 at_xpath 获取第一个元素。还要去掉 /EventRouter,因为我猜你想将另一个 'EventRouter' 项附加到 EventRouters

添加新节点很简单。基本思路类似于解析 XML 或 HTML:

  1. 找到要添加新内容的节点。
  2. 使用适当的方法附加内容,可以在节点的子节点的开头,也可以作为包裹节点的兄弟节点或父节点。这些方法在 the Node documentation.
  3. 大功告成。

Nokogiri 使用字符串轻松添加节点,它将解析并转换为节点:

require 'nokogiri'
doc = Nokogiri::XML('<xml><node/></xml>')

node = doc.at('node')
node.add_child('<foo>bar</foo>')
doc.to_xml # => "<?xml version=\"1.0\"?>\n<xml>\n  <node>\n    <foo>bar</foo>\n  </node>\n</xml>\n"

您可以走更长的路来创建新节点,但我发现构建字符串更容易。

以您的代码为基础,我会这样写:

require 'nokogiri'

data = DATA.read

doc = Nokogiri::XML.parse data
doc.xpath("//EventRouters/EventRouter").each do |event_router|
  event_router.add_next_sibling("<EventRouter id='some'><Parameters>some content</Parameters></EventRouter>")
end

puts doc.to_xml

__END__
<EventRouters>
  <EventRouter>original1</EventRouter>
  <EventRouter>original2</EventRouter>
</EventRouters>

运行 结果:

<?xml version="1.0"?>
<EventRouters>
  <EventRouter>original1</EventRouter><EventRouter id="some"><Parameters>some content</Parameters></EventRouter>
  <EventRouter>original2</EventRouter><EventRouter id="some"><Parameters>some content</Parameters></EventRouter>
</EventRouters>

您正在尝试使用 << 附加到 NodeSet,这不会按照您的预期进行:

doc = Nokogiri::XML.parse data
ers = doc.search('EventRouter') 
ers << Nokogiri::XML::Node.new('<foo/>', doc)

追加到 ers,这是一个节点集,不会将新节点应用于集合中的所有元素:

doc.to_xml # => "<?xml version=\"1.0\"?>\n<EventRouters>\n  <EventRouter>original1</EventRouter>\n  <EventRouter>original2</EventRouter>\n</EventRouters>\n"

而是将其附加到集合的末尾:

ers.to_xml # => "<EventRouter>original1</EventRouter><EventRouter>original2</EventRouter><<foo/>/>"