Nokogiri::XML::Node#dup showing unexpected result

Find the below code :

require ‘nokogiri’

xml = <<-eot




firstOrField
supplier.orgProfiles(${orgProfileId}).location.address.countryId


firstFieldValue
1487


eot

doc = Nokogiri::XML(xml)
node = doc.at(‘field’)
new_node = node.dup
new_node.at(‘arg0’)[‘key’] = “Country is Australlia”
new_node.at("//var[2]/var-value").content = 122

puts node





firstOrField
supplier.orgProfiles(${orgProfileId}).loc
yId


firstFieldValue
122

puts new_node





firstOrField
supplier.orgProfiles(${orgProfileId}).location.address.countr
yId


firstFieldValue
1487

How in node, the tag <var-value> got changed to 122 from 1487. It is
not expected. That change should be happened in the new_nodes
<var-value> tag.

What wrong I am doing here?

On Mon, Jan 20, 2014 at 11:19 AM, Arup R. [email protected]
wrote:

doc = Nokogiri::XML(xml)
node = doc.at(‘field’)
new_node = node.dup
new_node.at(‘arg0’)[‘key’] = “Country is Australlia”
new_node.at("//var[2]/var-value").content = 122

What wrong I am doing here?

#dup and #clone create shallow copies, i.e. all the references are
identical. So you copied only one node and not a sub tree.

Cheers

robert

Robert K. wrote in post #1133716:

On Mon, Jan 20, 2014 at 11:19 AM, Arup R. [email protected]
wrote:

doc = Nokogiri::XML(xml)
node = doc.at(‘field’)
=====================================================
I copied the below node in totally






firstOrField
supplier.orgProfiles(${orgProfileId}).location.address.countryId</var
-value>


firstFieldValue
1487

Then I did a #dup. According to
http://nokogiri.org/Nokogiri/XML/Node.html#method-i-dup

Copy this node. An optional depth may be passed in, but it defaults to
a deep copy. 0 is a shallow copy, 1 is a deep copy.

It means new_node = node.dup I did here deep copy.

When I am doing the changes for one part changes happed in the dup
object

new_node.at(‘arg0’)[‘key’] = “Country is Australlia”

But for the other part changes happedned in the original node, which I
expected to be happened in the new_node too.

new_node.at("//var[2]/var-value").content = 122

Why is that?

To make a deep copy, you need to pass 1 as argument.

node2 = node1.dup(1)

Sadjow Leão wrote in post #1133732:

To make a deep copy, you need to pass 1 as argument.

node2 = node1.dup(1)

If you don’t pass any argument, by default deep copy will be
happened.

The below code worked:

require ‘nokogiri’

xml = <<-eot




firstOrField
supplier.orgProfiles(${orgProfileId}).location.address.countryId</var
-value>


firstFieldValue
1487


eot

doc = Nokogiri::XML(xml)
node = doc.at(‘field’)
dump_node = Marshal.load(Marshal.dump(node.to_s))
new_node = Nokogiri::XML(dump_node).at(‘field’)
new_node.at(‘arg0’)[‘key’]=“Country is Autralia”
new_node.at(’//var[2]/var-value’).content = 112
[new_node,node].each do |n|
puts n.to_xml
puts “-”*7
end

>> <field property=“dummyProperty”

depends=“firstFieldEqualSecondFieldRequiredRelationship”>

>>

>>

>>

>> firstOrField

>>

supplier.orgProfiles(${orgProfileId}).location.address.countryId-value>

>>

>>

>> firstFieldValue

>> 112

>>

>>

>> -------

>> <field property=“dummyProperty”

depends=“firstFieldEqualSecondFieldRequiredRelationship”>

>>

>>

>>

>> firstOrField

>>

supplier.orgProfiles(${orgProfileId}).location.address.countryId-value>

>>

>>

>> firstFieldValue

>> 1487

>>

>>

>> -------

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs