Updated to libxml-ruby 2.0.5 and fixed code accordingly.
authorMatt Amos <zerebubuth@gmail.com>
Sat, 21 May 2011 14:15:49 +0000 (15:15 +0100)
committerTom Hughes <tom@compton.nu>
Sat, 21 May 2011 16:36:58 +0000 (17:36 +0100)
I've tested this through the unit tests and by hitting it with
bulk_upload.py and neither fail or cause the server to crash or
go into an infinite loop. Both of these things happened randomly
with 1.1.3/4 due to an apparent early deregistration of the
expanded nodes.

config/environment.rb
lib/diff_reader.rb

index 58d9432f5c5d99ccadeccc28a9b36f1b1e37450a..d5cee81e1407ae1b27c519a861099fb0791f0083 100644 (file)
@@ -18,7 +18,7 @@ Rails::Initializer.run do |config|
   unless  STATUS == :database_offline
     config.gem 'composite_primary_keys', :version => '2.2.2'
   end
-  config.gem 'libxml-ruby', :version => '~> 1.1.1', :lib => 'libxml'
+  config.gem 'libxml-ruby', :version => '>= 2.0.5', :lib => 'libxml'
   config.gem 'rmagick', :lib => 'RMagick'
   config.gem 'oauth', :version => '>= 0.4.3'
   config.gem 'oauth-plugin', :version => '0.3.14'
index 0f0492f444f57d781bf9ec21dcf4b90d7ac8ac59..de2da3c6bfd3c55c705918c8e79e2e3b27a3226b 100644 (file)
@@ -20,6 +20,10 @@ class DiffReader
   def initialize(data, changeset)
     @reader = XML::Reader.string(data)
     @changeset = changeset
+    # document that's (re-)used to handle elements expanded out of the
+    # diff processing stream.
+    @doc = XML::Document.new
+    @doc.root = XML::Node.new("osm")
   end
 
   ##
@@ -85,8 +89,21 @@ class DiffReader
       model = MODELS[model_name]
       raise OSM::APIBadUserInput.new("Unexpected element type #{model_name}, " +
                                      "expected node, way or relation.") if model.nil?
-      yield model, @reader.expand
+      # new in libxml-ruby >= 2, expand returns an element not associated 
+      # with a document. this means that there's no encoding parameter,
+      # which means basically nothing works.
+      expanded = @reader.expand
+
+      # create a new, empty document to hold this expanded node
+      new_node = @doc.import(expanded)
+      @doc.root << new_node
+
+      yield model, new_node
       @reader.next
+
+      # remove element from doc - it will be garbage collected and the
+      # rest of the document is re-used in the next iteration.
+      @doc.root.child.remove!
     end
   end