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*
|
*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)*
|
*2.3.1 [RC2] (March 5, 2009)*
|
||||||
|
@ -8,6 +8,10 @@ module XmlMini
|
|||||||
extend self
|
extend self
|
||||||
delegate :parse, :to => :@backend
|
delegate :parse, :to => :@backend
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_reader :backend
|
||||||
|
end
|
||||||
|
|
||||||
def backend=(name)
|
def backend=(name)
|
||||||
require "active_support/xml_mini/#{name.to_s.downcase}.rb"
|
require "active_support/xml_mini/#{name.to_s.downcase}.rb"
|
||||||
@backend = ActiveSupport.const_get("XmlMini_#{name}")
|
@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