While trying to create shallow copies of nodes I have run into some oddities.
Firstly I have been unable to access each attribute of a node except
through Xpath (as coded in each_attribute, below). This is frustrating
and seems to contradict the documentation for Node.properties and
Node.each_attr
More strangely, my each_attribute method only works for nodes returned
from a scan of the document, and not from the original nodes as added to
the document. The following snippet should illustrate this:
node1 = XML::Node.new('node1')
node1['x'] = 'y'
node1['z'] = 'a'
doc.root << node1
node1.each_attribute do |name, val|
# Will never reach this point!
end
doc.each do |node|
if node.name == 'node1'
node.each_attribute do |name, val|
# Reaches this point for each attribute
end
end
end
There is no obvious difference between the 'node1' object, and the
'node' object yielded by doc.each. They both print the same and both
yield similar looking doc objects, yet they have puzzlingly different
semantics.
I write in the hope that someone can explain, document and/or correct
this, and if not, to ensure that this strange behaviour is at least
described in this list.
Here is a simple test case to illustrate the issue.
require 'xml/libxml'
def each_attribute(node)
begin
attrs = node.find('./@*')
rescue TypeError
# Do nothing. This error is mistakenly? raised when no matching
# elements can be found
return
end
attrs.each do |elem|
yield elem.name, elem.value
end
end
def shallowcopy(old)
node = XML::Node.new(old.name)
each_attribute(old) do |name, value|
node[name] = value
end
node
end
doc = XML::Document.new
root = XML::Node.new('root')
node1 = XML::Node.new('node1')
node2 = XML::Node.new('node2')
node1['type'] = 'x'
node2['type'] = 'y'
node1['value'] = 'xval'
node2['value'] = 'yval'
doc.root = root
root << node1
root << node2
puts "NODE1 : #{node1} :NODE1"
puts "COPY OF NODE1: #{shallowcopy(node1)} :COPY OF NODE1"
doc.root.each_child do |node|
if node.name == 'node1'
puts "NODE1 : #{node1} :NODE1"
puts "COPY OF NODE1: #{shallowcopy(node)} :COPY OF NODE1"
end
end
And this is the output generated. Note that the first copy of node1 has
no attributes, while the second does.
NODE1 : <node1 type="x" value="xval"/> :NODE1
COPY OF NODE1: <node1/> :COPY OF NODE1
NODE1 : <node1 type="x" value="xval"/> :NODE1
COPY OF NODE1: <node1 type="x" value="xval"/> :COPY OF NODE1
__
Marc
signature.asc
Description: This is a digitally signed message part
_______________________________________________ libxml-devel mailing list [email protected] http://rubyforge.org/mailman/listinfo/libxml-devel
