[libxml-devel] [ libxml-Bugs-22415 ] xml_node.attributes.each { |a| a.remove! } # stops after removing the first attribute

noreply at rubyforge.org noreply at rubyforge.org
Sat Nov 15 19:32:53 EST 2008


Bugs item #22415, was opened at 2008-10-15 01:52
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=1971&aid=22415&group_id=494

Category: General
Group: None
>Status: Closed
Resolution: None
Priority: 3
Submitted By: Elia Schito (elia)
>Assigned to: Charlie Savage (cfis)
Summary: xml_node.attributes.each { |a| a.remove! } # stops after removing the first attribute

Initial Comment:
# With the XML below the following won't work (will remove only the first attribute):

xml_object.find_first('ibbas:ncsa/ibbas:mcrange').attributes.each do |xml_attribute|
  xml_attribute.remove! if xml_attribute.name =~ /^(addr|range)\d+$/
end

# The following works:

attributes = []
xml_object.find_first('ibbas:ncsa/ibbas:mcrange').attributes.each{ |a| attributes << a }
attributes.each do |xml_attribute|
  xml_attribute.remove! if xml_attribute.name =~ /^(addr|range)\d+$/
end


__DATA__

<?xml version="1.0"?>
<ibbas:configuration xmlns:ibbas="http://www.gcs-salzburg.at/ibbas/0.3/">
	<ibbas:ncsa active="1" nrchannels="1" autoreg="1" staticcfg="1" tsid="9200" dulmpid="0" timpid="2052" rcstblpid="2055" tbtppid="2056" dvbbase="10.0.0.1">
		<ibbas:mcrange addr1="224.1.1.1" range1="32" addr2="239.0.0.0" range2="8" addr3="224.20.20.1" range3="32"/>
	</ibbas:ncsa>
</ibbas:configuration>



----------------------------------------------------------------------

>Comment By: Charlie Savage (cfis)
Date: 2008-11-15 17:32

Message:
Hi Elia,

I took a look at this.  The issue is when you remove a node (including attributes), libxml sets the next and prev pointers of the node to nil.

The way iteration works for attributes is like this:

  xattr = xnode->properties;

  while (xattr)
  {
     VALUE attr = ruby_xml_attr_wrap(xattr);
     rb_yield(attr);
     xattr = xattr->next;
  }

So what happens is xattr->next is null, and thus only the first node is deleted.

This doesn't seem worth changing to me because its easy to workaround.  Just do this:

attributes = []
node = xml_object.find_first('ibbas:ncsa/ibbas:mcrange')
node.attributes.entries.each{ |a| a.remove!}

Notice the use of entries to first collect all the attributes into an array, then they are deleted.

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=1971&aid=22415&group_id=494


More information about the libxml-devel mailing list