Reputation: 7718
I'm doing this:
targets = @xml.xpath("./target")
if targets.empty?
targets << Nokogiri::XML::Node.new('target', @xml)
end
However the @xml
is still without my target. What can I do in order to update the original @xml
?
Upvotes: 0
Views: 245
Reputation: 7718
I end doing this, works fine.
targets = @xml.xpath("./target")
if targets.empty?
targets << Nokogiri::XML::Node.new('target', @xml)
@xml.add_child(targets.first)
end
Upvotes: 0
Reputation: 160551
It's a lot easier than that:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<root>
<node>
</node>
</root>
EOT
doc.at('node').children = '<child>foo</child>'
doc.to_xml
# => "<?xml version=\"1.0\"?>\n<root>\n <node><child>foo</child></node>\n</root>\n"
children=
is smart enough to see what you're passing in and will do the dirty work for you. So just use a string to define the new node(s) and tell Nokogiri where to insert it.
doc.at('node').class # => Nokogiri::XML::Element
doc.at('//node').class # => Nokogiri::XML::Element
doc.search('node').first # => #<Nokogiri::XML::Element:0x3fd1a88c5c08 name="node" children=[#<Nokogiri::XML::Text:0x3fd1a88eda3c "\n ">]>
doc.search('//node').first # => #<Nokogiri::XML::Element:0x3fd1a88c5c08 name="node" children=[#<Nokogiri::XML::Text:0x3fd1a88eda3c "\n ">]>
search
is the generic "find a node" method that will take either CSS or XPath selectors. at
is equivalent to search('some selector').first
. at_css
and at_xpath
are the specific equivalents of at
, just as css
and xpath
are to search
. Use the specific versions if you want, but in general I use the generic versions.
You can't use:
targets = @xml.xpath("./target")
if targets.empty?
targets << Nokogiri::XML::Node.new('target', @xml)
end
targets
would be []
(actually an empty NodeSet) if ./target
doesn't exist in the DOM. You can't append a node to []
, because NodeSet doesn't have an idea of what you're talking about, resulting in a undefined method 'children=' for nil:NilClass (NoMethodError)
exception.
Instead you MUST find the specific location where you want to insert the node. at
is good for that since it finds just the first location. Of course, if you want to look for multiple places to modify something use search
then iterate over the returned NodeSet and modify based on the individual nodes returned.
Upvotes: 1