Nokogiri backend for XmlMini
[#2190 state:committed] Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
This commit is contained in:
parent
d4091d3bc7
commit
694998ee4f
@ -1,6 +1,7 @@
|
||||
*Edge*
|
||||
|
||||
* XmlMini supports libxml if available. #2084 [Bart ten Brinke]
|
||||
* XmlMini supports LibXML and Nokogiri backends. #2084, #2190 [Bart ten Brinke, Aaron Patterson]
|
||||
Example: XmlMini.backend = 'Nokogiri'
|
||||
|
||||
|
||||
*2.3.1 [RC2] (March 5, 2009)*
|
||||
|
@ -8,6 +8,10 @@ module XmlMini
|
||||
extend self
|
||||
delegate :parse, :to => :@backend
|
||||
|
||||
class << self
|
||||
attr_reader :backend
|
||||
end
|
||||
|
||||
def backend=(name)
|
||||
require "active_support/xml_mini/#{name.to_s.downcase}.rb"
|
||||
@backend = ActiveSupport.const_get("XmlMini_#{name}")
|
||||
|
67
activesupport/lib/active_support/xml_mini/nokogiri.rb
Normal file
67
activesupport/lib/active_support/xml_mini/nokogiri.rb
Normal file
@ -0,0 +1,67 @@
|
||||
# = XML Mini Nokogiri implementation
|
||||
module ActiveSupport
|
||||
module XmlMini_Nokogiri #:nodoc:
|
||||
extend self
|
||||
|
||||
# Parse an XML Document string into a simple hash using libxml / nokogiri.
|
||||
# string::
|
||||
# XML Document string to parse
|
||||
def parse(string)
|
||||
return {} if string.blank?
|
||||
doc = Nokogiri::XML(string).to_hash
|
||||
end
|
||||
|
||||
module Conversions
|
||||
module Document
|
||||
def to_hash
|
||||
root.to_hash
|
||||
end
|
||||
end
|
||||
|
||||
module Node
|
||||
CONTENT_ROOT = '__content__'
|
||||
|
||||
# Convert XML document to hash
|
||||
#
|
||||
# hash::
|
||||
# Hash to merge the converted element into.
|
||||
def to_hash(hash = {})
|
||||
hash[name] ||= attributes_as_hash
|
||||
|
||||
walker = lambda { |child, memo, callback|
|
||||
next if child.blank?
|
||||
|
||||
if child.text?
|
||||
(memo[CONTENT_ROOT] ||= '') << child.content
|
||||
next
|
||||
end
|
||||
|
||||
name = child.name
|
||||
|
||||
if memo[name]
|
||||
memo[name] = [memo[name]].flatten
|
||||
memo[name] << child.attributes_as_hash
|
||||
else
|
||||
memo[name] = child.attributes_as_hash
|
||||
end
|
||||
|
||||
# Recusively walk children
|
||||
child.children.each { |c| callback.call(c, memo[name], callback) }
|
||||
}
|
||||
|
||||
children.each { |c| walker.call(c, hash[name], walker) }
|
||||
hash
|
||||
end
|
||||
|
||||
def attributes_as_hash
|
||||
Hash[*(attribute_nodes.map { |node|
|
||||
[node.node_name, node.value]
|
||||
}.flatten)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Nokogiri::XML::Document.send(:include, Conversions::Document)
|
||||
Nokogiri::XML::Node.send(:include, Conversions::Node)
|
||||
end
|
||||
end
|
112
activesupport/test/xml_mini/nokogiri_engine_test.rb
Normal file
112
activesupport/test/xml_mini/nokogiri_engine_test.rb
Normal file
@ -0,0 +1,112 @@
|
||||
require 'abstract_unit'
|
||||
require 'active_support/xml_mini'
|
||||
|
||||
|
||||
begin
|
||||
|
||||
require 'nokogiri'
|
||||
|
||||
class NokogiriEngineTest < Test::Unit::TestCase
|
||||
include ActiveSupport
|
||||
|
||||
def setup
|
||||
@default_backend = XmlMini.backend.to_s.split('_').last
|
||||
XmlMini.backend = 'Nokogiri'
|
||||
end
|
||||
|
||||
def teardown
|
||||
XmlMini.backend = @default_backend
|
||||
end
|
||||
|
||||
def test_setting_nokogiri_as_backend
|
||||
XmlMini.backend = 'Nokogiri'
|
||||
assert_equal XmlMini_Nokogiri, XmlMini.backend
|
||||
end
|
||||
|
||||
def test_blank_returns_empty_hash
|
||||
assert_equal({}, XmlMini.parse(nil))
|
||||
assert_equal({}, XmlMini.parse(''))
|
||||
end
|
||||
|
||||
def test_one_node_document_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products/>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_one_node_with_attributes_document_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products foo="bar"/>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_products_node_with_book_node_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products>
|
||||
<book name="awesome" id="12345" />
|
||||
</products>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_products_node_with_two_book_nodes_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products>
|
||||
<book name="awesome" id="12345" />
|
||||
<book name="america" id="67890" />
|
||||
</products>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_single_node_with_content_as_hash
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<products>
|
||||
hello world
|
||||
</products>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_children
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
<book name="america" id="67890" />
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_text
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
<products>
|
||||
hello everyone
|
||||
</products>
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
def test_children_with_non_adjacent_text
|
||||
assert_equal_rexml(<<-eoxml)
|
||||
<root>
|
||||
good
|
||||
<products>
|
||||
hello everyone
|
||||
</products>
|
||||
morning
|
||||
</root>
|
||||
eoxml
|
||||
end
|
||||
|
||||
private
|
||||
def assert_equal_rexml(xml)
|
||||
XmlMini.backend = 'REXML'
|
||||
hash = XmlMini.parse(xml)
|
||||
|
||||
XmlMini.backend = 'Nokogiri'
|
||||
|
||||
assert_equal(hash, XmlMini.parse(xml))
|
||||
end
|
||||
end
|
||||
rescue LoadError
|
||||
# Yay, no errors
|
||||
end
|
15
activesupport/test/xml_mini/rexml_engine_test.rb
Normal file
15
activesupport/test/xml_mini/rexml_engine_test.rb
Normal file
@ -0,0 +1,15 @@
|
||||
require 'abstract_unit'
|
||||
require 'active_support/xml_mini'
|
||||
|
||||
class REXMLEngineTest < Test::Unit::TestCase
|
||||
include ActiveSupport
|
||||
|
||||
def test_default_is_rexml
|
||||
assert_equal XmlMini_REXML, XmlMini.backend
|
||||
end
|
||||
|
||||
def test_set_rexml_as_backend
|
||||
XmlMini.backend = 'REXML'
|
||||
assert_equal XmlMini_REXML, XmlMini.backend
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user