aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
authorWillem van Bergen <willem@vanbergen.org>2010-01-01 12:08:48 +0100
committerJeremy Kemper <jeremy@bitsweat.net>2010-01-01 13:17:45 -0800
commitd7f9b9fd244228d3503d7d37ac2f07365d54df3c (patch)
tree1c4a59e7ff70b4beb0af199ea79febf0d056a21b /activesupport/lib/active_support
parent34b03cebf9c9f2ce2a53511a4b2160485e270f12 (diff)
downloadrails-d7f9b9fd244228d3503d7d37ac2f07365d54df3c.tar.gz
rails-d7f9b9fd244228d3503d7d37ac2f07365d54df3c.tar.bz2
rails-d7f9b9fd244228d3503d7d37ac2f07365d54df3c.zip
Added SAX-based parser for XmlMini, using Nokogiri.
Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogirisax.rb82
1 files changed, 82 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/xml_mini/nokogirisax.rb b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
new file mode 100644
index 0000000000..42a44897ba
--- /dev/null
+++ b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
@@ -0,0 +1,82 @@
+require 'nokogiri'
+
+# = XmlMini Nokogiri implementation using a SAX-based parser
+module ActiveSupport
+ module XmlMini_NokogiriSAX
+ extend self
+
+ # Class that will build the hash while the XML document
+ # is being parsed using SAX events.
+ class HashBuilder < Nokogiri::XML::SAX::Document
+
+ CONTENT_KEY = '__content__'.freeze
+ HASH_SIZE_KEY = '__hash_size__'.freeze
+
+ attr_reader :hash
+
+ def current_hash
+ @hash_stack.last
+ end
+
+ def start_document
+ @hash = {}
+ @hash_stack = [@hash]
+ end
+
+ def end_document
+ raise "Parse stack not empty!" if @hash_stack.size > 1
+ end
+
+ def error(error_message)
+ raise Nokogiri::XML::SyntaxError, error_message
+ end
+
+ def start_element(name, attrs = [])
+ new_hash = { CONTENT_KEY => '' }
+ new_hash[attrs.shift] = attrs.shift while attrs.length > 0
+ new_hash[HASH_SIZE_KEY] = new_hash.size + 1
+
+ case current_hash[name]
+ when Array then current_hash[name] << new_hash
+ when Hash then current_hash[name] = [current_hash[name], new_hash]
+ when nil then current_hash[name] = new_hash
+ end
+
+ @hash_stack.push(new_hash)
+ end
+
+ def end_element(name)
+ if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ''
+ current_hash.delete(CONTENT_KEY)
+ end
+ @hash_stack.pop
+ end
+
+ def characters(string)
+ current_hash[CONTENT_KEY] << string
+ end
+
+ alias_method :cdata_block, :characters
+ end
+
+ attr_accessor :document_class
+ self.document_class = HashBuilder
+
+ def parse(data)
+ if !data.respond_to?(:read)
+ data = StringIO.new(data || '')
+ end
+
+ char = data.getc
+ if char.nil?
+ {}
+ else
+ data.ungetc(char)
+ document = self.document_class.new
+ parser = Nokogiri::XML::SAX::Parser.new(document)
+ parser.parse(data)
+ document.hash
+ end
+ end
+ end
+end \ No newline at end of file