Narnach-libxml_rails 0.0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +40 -0
- data/Rakefile +28 -0
- data/init.rb +1 -0
- data/lib/bitbckt/core_ext/hash/conversions.rb +91 -0
- data/lib/libxml_rails.rb +6 -0
- data/lib/libxml_rails/active_resource.rb +2 -0
- data/lib/narnach/core_ext/array/conversions.rb +64 -0
- data/lib/narnach/core_ext/hash/conversions.rb +91 -0
- data/lib/narnach/rails_ext/active_resource.rb +64 -0
- data/libxml_rails.gemspec +34 -0
- data/spec/from_xml_spec.rb +328 -0
- data/spec/narnach/core_ext/array/conversions_spec.rb +73 -0
- data/spec/narnach/core_ext/hash/conversions_spec.rb +154 -0
- data/spec/narnach/rails_ext/active_resource_spec.rb +16 -0
- data/spec/spec_helper.rb +4 -0
- metadata +94 -0
data/CHANGELOG
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Brandon Mitchell
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
= libxml_rails
|
2
|
+
|
3
|
+
libxml_rails is a gem/rails plugin by Brandon Mitchell. It is designed to replace the default XML processor in Rails (XmlSimple) with the C-based libxml. It requires the libxml-ruby gem.
|
4
|
+
|
5
|
+
This fork is maintained by Wes 'Narnach' Oldenbeuving.
|
6
|
+
|
7
|
+
Changes from the Brandon's version are:
|
8
|
+
* Don't rely on echoe to build the gem.
|
9
|
+
* Added Hash#to_xml_with_libxml and Array#to_xml_with_libxml
|
10
|
+
* ActiveResource::Base#to_xml uses libxml.
|
11
|
+
* ActiveResource::Formats::XmlFormat#encode uses libxml
|
12
|
+
|
13
|
+
=== Installation
|
14
|
+
|
15
|
+
libxml_rails can be installed as a rails plugin or as a stand-alone gem.
|
16
|
+
|
17
|
+
=== Gem Installation
|
18
|
+
|
19
|
+
From PROJECT_ROOT:
|
20
|
+
|
21
|
+
gem install libxml-ruby
|
22
|
+
rake install
|
23
|
+
|
24
|
+
=== Plugin Installation
|
25
|
+
|
26
|
+
From RAILS_ROOT:
|
27
|
+
|
28
|
+
script/plugin install git://github.com/Narnach/libxml_rails.git
|
29
|
+
|
30
|
+
Add the following to the configuration block in config/environment.rb:
|
31
|
+
|
32
|
+
config.gem 'libxml-ruby'
|
33
|
+
|
34
|
+
=== Gem Installation
|
35
|
+
|
36
|
+
Add the following to the configuration block in config/environment.rb:
|
37
|
+
|
38
|
+
config.gem 'Narnach-libxml_rails', :source => 'http://gems.github.com'
|
39
|
+
|
40
|
+
Copyright (c) 2008 Brandon Mitchell, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
################################################################################
|
7
|
+
### Gem
|
8
|
+
################################################################################
|
9
|
+
|
10
|
+
begin
|
11
|
+
# Parse gemspec using the github safety level.
|
12
|
+
file = Dir['*.gemspec'].first
|
13
|
+
data = File.read(file)
|
14
|
+
spec = nil
|
15
|
+
Thread.new { spec = eval("$SAFE = 3\n%s" % data)}.join
|
16
|
+
|
17
|
+
# Create the gem tasks
|
18
|
+
Rake::GemPackageTask.new(spec) do |package|
|
19
|
+
package.gem_spec = spec
|
20
|
+
end
|
21
|
+
rescue Exception => e
|
22
|
+
printf "WARNING: Error caught (%s): %s\n%s", e.class.name, e.message, e.backtrace[0...5].map {|l| ' %s' % l}.join("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'Package and install the gem for the current version'
|
26
|
+
task :install => :gem do
|
27
|
+
system "sudo gem install -l pkg/%s-%s.gem" % [spec.name, spec.version]
|
28
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'libxml_rails'))
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Bitbckt #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Hash #:nodoc:
|
4
|
+
module Conversions
|
5
|
+
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def from_xml(xml)
|
12
|
+
result = LibXML::XML::Parser.string(xml).parse
|
13
|
+
if result.root.attributes['type'] == 'array'
|
14
|
+
{ result.root.name.to_s.gsub(/-/,'_') => array_from_node(result.root) }
|
15
|
+
else
|
16
|
+
{ result.root.name.to_s.gsub(/-/,'_') => xml_node_to_hash(result.root) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def xml_node_to_hash(node)
|
22
|
+
# If we are at an XML::Node, build the Hash
|
23
|
+
if node.element?
|
24
|
+
result_hash = {}
|
25
|
+
if node.children?
|
26
|
+
|
27
|
+
node.each_child do |child|
|
28
|
+
next if child.empty?
|
29
|
+
|
30
|
+
if child.attributes['type'] == 'array'
|
31
|
+
result = array_from_node(child)
|
32
|
+
elsif child.attributes['type'] == 'string' and child.children.empty?
|
33
|
+
# NOTE: Odd issue with libxml - XML::Node#empty? returns false and
|
34
|
+
# XML::Node#children? returns true when the Node contains just
|
35
|
+
# an empty string (#children == []), but has attributes.
|
36
|
+
result = ''
|
37
|
+
elsif child.attributes['type'] == 'file'
|
38
|
+
result = Object::Hash::XML_PARSING['file'].call(child.content.to_s, child.attributes)
|
39
|
+
elsif Object::Hash::XML_PARSING.include? child.attributes['type'] and not child.content.to_s.chomp.blank?
|
40
|
+
result = Object::Hash::XML_PARSING[child.attributes['type']].call(child.content.to_s)
|
41
|
+
else
|
42
|
+
result = xml_node_to_hash(child)
|
43
|
+
result['type'] = child.attributes['type'] if child.attributes['type'] and result
|
44
|
+
end
|
45
|
+
|
46
|
+
return result if child.name == 'text'
|
47
|
+
|
48
|
+
key = child.name.gsub(/-/, '_')
|
49
|
+
if result_hash[key]
|
50
|
+
if result_hash[key].is_a?(Object::Array)
|
51
|
+
result_hash[key] << result
|
52
|
+
else
|
53
|
+
result_hash[key] = [result_hash[key]] << result
|
54
|
+
end
|
55
|
+
else
|
56
|
+
result_hash[key] = result
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
else
|
61
|
+
if node.attributes['type'] || node.attributes.length == 0 || node.attributes['nil'] == 'true'
|
62
|
+
result_hash = nil
|
63
|
+
else
|
64
|
+
node.each_attr do |attribute|
|
65
|
+
result_hash[attribute.name] = attribute.value.to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
return result_hash
|
71
|
+
else
|
72
|
+
return node.content.to_s
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def array_from_node(node)
|
77
|
+
returning([]) do |collection|
|
78
|
+
node.each_child do |child|
|
79
|
+
next if child.empty?
|
80
|
+
collection << xml_node_to_hash(child)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Hash.class_eval { include Bitbckt::CoreExtensions::Hash::Conversions }
|
data/lib/libxml_rails.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Narnach #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Array #:nodoc:
|
4
|
+
module Conversions
|
5
|
+
# Version of #to_xml copy-adjusted from ActiveSupport to work with libxml.
|
6
|
+
#
|
7
|
+
# Options not supported:
|
8
|
+
# - :indent
|
9
|
+
def to_xml_with_libxml(options = {})
|
10
|
+
raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml_with_libxml }
|
11
|
+
options.reverse_merge!({:to_string => true, :skip_instruct => false })
|
12
|
+
dasherize = !options.has_key?(:dasherize) || options[:dasherize]
|
13
|
+
options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
|
14
|
+
options[:root] = options[:root].to_s.dasherize if dasherize
|
15
|
+
options[:children] ||= options[:root].singularize
|
16
|
+
to_string = options.delete(:to_string)
|
17
|
+
skip_instruct = options.delete(:skip_instruct)
|
18
|
+
root = options.delete(:root).to_s
|
19
|
+
doc = nil
|
20
|
+
if skip_instruct
|
21
|
+
node = LibXML::XML::Node.new(root)
|
22
|
+
doc = node
|
23
|
+
case options[:builder]
|
24
|
+
when LibXML::XML::Document
|
25
|
+
options[:builder].root << node
|
26
|
+
when nil
|
27
|
+
options[:builder] = node
|
28
|
+
else
|
29
|
+
options[:builder] << node
|
30
|
+
end
|
31
|
+
else
|
32
|
+
options[:builder] = LibXML::XML::Document.new
|
33
|
+
options[:builder].encoding = 'UTF-8'
|
34
|
+
options[:builder].root = LibXML::XML::Node.new(root)
|
35
|
+
doc = options[:builder].root
|
36
|
+
end
|
37
|
+
doc['type'] = 'array' unless options[:skip_types]
|
38
|
+
|
39
|
+
|
40
|
+
children = options.delete(:children)
|
41
|
+
opts = options.merge({ :root => children })
|
42
|
+
|
43
|
+
unless empty?
|
44
|
+
yield doc if block_given?
|
45
|
+
each do |e|
|
46
|
+
e.to_xml_with_libxml(opts.merge!({ :skip_instruct => true, :to_string => false, :builder => doc }))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
if to_string
|
50
|
+
string = options[:builder].to_s
|
51
|
+
string << "\n" if skip_instruct # Emulate Builder behaviour
|
52
|
+
return string
|
53
|
+
else
|
54
|
+
return options[:builder]
|
55
|
+
end
|
56
|
+
end # to_xml_with_libxml
|
57
|
+
end # module Conversions
|
58
|
+
end # module Hash
|
59
|
+
end # module CoreExtensions
|
60
|
+
end # module Narnach
|
61
|
+
|
62
|
+
class Array
|
63
|
+
include Narnach::CoreExtensions::Array::Conversions
|
64
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Narnach #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Hash #:nodoc:
|
4
|
+
module Conversions
|
5
|
+
XML_TYPE_NAMES = ActiveSupport::CoreExtensions::Hash::Conversions::XML_TYPE_NAMES unless defined?(XML_TYPE_NAMES)
|
6
|
+
XML_FORMATTING = ActiveSupport::CoreExtensions::Hash::Conversions::XML_FORMATTING unless defined?(XML_FORMATTING)
|
7
|
+
|
8
|
+
# Version of #to_xml copy-adjusted from ActiveSupport to work with libxml.
|
9
|
+
#
|
10
|
+
# Options supported in XMLBuilder that are/will be supported here:
|
11
|
+
# - :root, name of root node. Default to hash
|
12
|
+
# - :children, name of child nodes. Default to singular of root.
|
13
|
+
# - :skip_types
|
14
|
+
#
|
15
|
+
# Options supported in a different way:
|
16
|
+
# - :builder. Holds the active LibXML::XML::Document or LibXML::XML::Node.
|
17
|
+
# - :skip_instruct. Determine if the document encoding needs to be set. When false, a new Document is created and used as :builder. When true a new Node is created when no :builder is specified.
|
18
|
+
# - :dasherize, dasherize the node names or keep them as-is.
|
19
|
+
#
|
20
|
+
# Options known but not (yet) supported:
|
21
|
+
# - :indent, default to level 2
|
22
|
+
#
|
23
|
+
# Uses Builder's String#to_xs for escaping
|
24
|
+
def to_xml_with_libxml(options = {})
|
25
|
+
options.reverse_merge!({:root => "hash", :to_string => true })
|
26
|
+
dasherize = !options.has_key?(:dasherize) || options[:dasherize]
|
27
|
+
root = dasherize ? options[:root].to_s.dasherize : options[:root].to_s
|
28
|
+
to_string = options.delete(:to_string)
|
29
|
+
skip_instruct = options.delete(:skip_instruct)
|
30
|
+
doc = nil
|
31
|
+
if skip_instruct
|
32
|
+
node = LibXML::XML::Node.new(root)
|
33
|
+
doc = node
|
34
|
+
case options[:builder]
|
35
|
+
when LibXML::XML::Document
|
36
|
+
options[:builder].root << node
|
37
|
+
when nil
|
38
|
+
options[:builder] = node
|
39
|
+
else
|
40
|
+
options[:builder] << node
|
41
|
+
end
|
42
|
+
else
|
43
|
+
options[:builder] = LibXML::XML::Document.new
|
44
|
+
options[:builder].encoding = 'UTF-8'
|
45
|
+
options[:builder].root = LibXML::XML::Node.new(root)
|
46
|
+
doc = options[:builder].root
|
47
|
+
end
|
48
|
+
self.each do |key, value|
|
49
|
+
case value
|
50
|
+
when ::Hash
|
51
|
+
value.to_xml_with_libxml(options.merge({ :root => key, :skip_instruct => true, :to_string => false, :builder => doc }))
|
52
|
+
when ::Array
|
53
|
+
value.to_xml_with_libxml(options.merge({ :root => key, :children => key.to_s.singularize, :skip_instruct => true, :to_string => false, :builder => doc}))
|
54
|
+
# when ::Method, ::Proc
|
55
|
+
else
|
56
|
+
if value.respond_to?(:to_xml_with_libxml)
|
57
|
+
value.to_xml_with_libxml(options.merge({ :root => key, :skip_instruct => true, :to_string => false, :builder => doc }))
|
58
|
+
else
|
59
|
+
type_name = XML_TYPE_NAMES[value.class.name]
|
60
|
+
key = dasherize ? key.to_s.dasherize : key.to_s
|
61
|
+
attributes = options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name }
|
62
|
+
if value.nil?
|
63
|
+
attributes[:nil] = true
|
64
|
+
end
|
65
|
+
|
66
|
+
content = XML_FORMATTING[type_name] ? XML_FORMATTING[type_name].call(value) : value
|
67
|
+
child = LibXML::XML::Node.new(key, content.to_s.to_xs)
|
68
|
+
attributes.stringify_keys.each do |akey, avalue|
|
69
|
+
child[akey] = String(avalue).to_s.to_xs
|
70
|
+
end
|
71
|
+
doc << child
|
72
|
+
end # if
|
73
|
+
end # case
|
74
|
+
end # each
|
75
|
+
yield options[:builder] if block_given?
|
76
|
+
if to_string
|
77
|
+
string = options[:builder].to_s
|
78
|
+
string << "\n" if skip_instruct # Emulate Builder behaviour
|
79
|
+
return string
|
80
|
+
else
|
81
|
+
return options[:builder]
|
82
|
+
end
|
83
|
+
end # to_xml_with_libxml
|
84
|
+
end # module Conversions
|
85
|
+
end # module Hash
|
86
|
+
end # module CoreExtensions
|
87
|
+
end # module Narnach
|
88
|
+
|
89
|
+
class Hash
|
90
|
+
include Narnach::CoreExtensions::Hash::Conversions
|
91
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
gem 'activeresource'
|
2
|
+
require 'active_resource'
|
3
|
+
require 'active_resource/formats/xml_format'
|
4
|
+
|
5
|
+
module Narnach
|
6
|
+
module RailsExt
|
7
|
+
module ActiveResource
|
8
|
+
module Base
|
9
|
+
# A method to convert the the resource to an XML string.
|
10
|
+
#
|
11
|
+
# This is a copy-adjusted version of ActiveResource's #to_xml, but
|
12
|
+
# it uses libxml for serialization instead of builder.
|
13
|
+
#
|
14
|
+
# ==== Options
|
15
|
+
# The +options+ parameter is handed off to the +to_xml_with_libxml+ method on each
|
16
|
+
# attribute, so it has the same options as the +to_xml_with_libxml+ methods in
|
17
|
+
# Active Support.
|
18
|
+
#
|
19
|
+
# * <tt>:dasherize</tt> - Boolean option to determine whether or not element names should
|
20
|
+
# replace underscores with dashes (default is <tt>false</tt>).
|
21
|
+
# * <tt>:skip_instruct</tt> - Toggle skipping the +instruct!+ call on the XML builder
|
22
|
+
# that generates the XML declaration (default is <tt>false</tt>).
|
23
|
+
#
|
24
|
+
# ==== Examples
|
25
|
+
# my_group = SubsidiaryGroup.find(:first)
|
26
|
+
# my_group.to_xml
|
27
|
+
# # => <?xml version="1.0" encoding="UTF-8"?>
|
28
|
+
# # <subsidiary_group> [...] </subsidiary_group>
|
29
|
+
#
|
30
|
+
# my_group.to_xml(:dasherize => true)
|
31
|
+
# # => <?xml version="1.0" encoding="UTF-8"?>
|
32
|
+
# # <subsidiary-group> [...] </subsidiary-group>
|
33
|
+
#
|
34
|
+
# my_group.to_xml(:skip_instruct => true)
|
35
|
+
# # => <subsidiary_group> [...] </subsidiary_group>
|
36
|
+
def to_xml(options={})
|
37
|
+
attributes.to_xml_with_libxml({:root => self.class.element_name}.merge(options))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module Formats
|
42
|
+
module XmlFormat
|
43
|
+
def encode(hash, options={})
|
44
|
+
hash.to_xml_with_libxml(options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module ActiveResource
|
53
|
+
module Formats
|
54
|
+
XmlFormat.class_eval do
|
55
|
+
remove_method :encode
|
56
|
+
include Narnach::RailsExt::ActiveResource::Formats::XmlFormat
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
Base.class_eval do
|
61
|
+
remove_method :to_xml
|
62
|
+
include Narnach::RailsExt::ActiveResource::Base
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
# Project
|
3
|
+
s.name = 'libxml_rails'
|
4
|
+
s.description = "Libxml_rails replaces ActiveSupport's XmlSimple XML parsing with libxml-ruby. Original gem by Brandon Mitchell, this fork is by Wes 'Narnach' Oldenbeuving."
|
5
|
+
s.summary = s.description
|
6
|
+
s.version = '0.0.2.5'
|
7
|
+
s.date = '2009-01-06'
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Brandon Mitchell", "Wes Oldenbeuving"]
|
10
|
+
s.email = "narnach@gmail.com"
|
11
|
+
s.homepage = "http://www.github.com/Narnach/libxml_rails"
|
12
|
+
|
13
|
+
# Files
|
14
|
+
root_files = %w[CHANGELOG init.rb libxml_rails.gemspec MIT-LICENSE Rakefile README.rdoc]
|
15
|
+
lib_files = %w[bitbckt/core_ext/hash/conversions narnach/core_ext/hash/conversions narnach/core_ext/array/conversions narnach/rails_ext/active_resource libxml_rails libxml_rails/active_resource]
|
16
|
+
spec_files = %w[from_xml] + lib_files.select{|f| f[0...7] == 'narnach'}
|
17
|
+
other_files = %w[spec/spec_helper.rb]
|
18
|
+
s.require_path = "lib"
|
19
|
+
s.executables = []
|
20
|
+
s.test_files = spec_files.map {|f| 'spec/%s_spec.rb' % f}
|
21
|
+
s.files = root_files + s.test_files + other_files + lib_files.map {|f| 'lib/%s.rb' % f}
|
22
|
+
|
23
|
+
# rdoc
|
24
|
+
s.has_rdoc = true
|
25
|
+
s.extra_rdoc_files = %w[ README.rdoc MIT-LICENSE]
|
26
|
+
s.rdoc_options << '--inline-source' << '--line-numbers' << '--main' << 'README.rdoc'
|
27
|
+
|
28
|
+
# Dependencies
|
29
|
+
s.add_dependency 'activesupport', '>= 2.1.0'
|
30
|
+
s.add_dependency 'libxml-ruby', '>= 0.8.3'
|
31
|
+
|
32
|
+
# Requirements
|
33
|
+
s.required_ruby_version = ">= 1.8.0"
|
34
|
+
end
|
@@ -0,0 +1,328 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Hash, '.from_xml' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@xml_options = { :root => :person, :skip_instruct => true, :indent => 0 }
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'parses a single record' do
|
10
|
+
topic_xml = <<-EOT
|
11
|
+
<topic>
|
12
|
+
<title>The First Topic</title>
|
13
|
+
<author-name>David</author-name>
|
14
|
+
<id type="integer">1</id>
|
15
|
+
<approved type="boolean"> true </approved>
|
16
|
+
<replies-count type="integer">0</replies-count>
|
17
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
18
|
+
<written-on type="date">2003-07-16</written-on>
|
19
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
20
|
+
<content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</content>
|
21
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
22
|
+
<parent-id></parent-id>
|
23
|
+
<ad-revenue type="decimal">1.5</ad-revenue>
|
24
|
+
<optimum-viewing-angle type="float">135</optimum-viewing-angle>
|
25
|
+
<resident type="symbol">yes</resident>
|
26
|
+
</topic>
|
27
|
+
EOT
|
28
|
+
|
29
|
+
expected_topic_hash = {
|
30
|
+
:title => "The First Topic",
|
31
|
+
:author_name => "David",
|
32
|
+
:id => 1,
|
33
|
+
:approved => true,
|
34
|
+
:replies_count => 0,
|
35
|
+
:replies_close_in => 2592000000,
|
36
|
+
:written_on => Date.new(2003, 7, 16),
|
37
|
+
:viewed_at => Time.utc(2003, 7, 16, 9, 28),
|
38
|
+
:content => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
|
39
|
+
:author_email_address => "david@loudthinking.com",
|
40
|
+
:parent_id => nil,
|
41
|
+
:ad_revenue => BigDecimal("1.50"),
|
42
|
+
:optimum_viewing_angle => 135.0,
|
43
|
+
:resident => :yes
|
44
|
+
}.stringify_keys
|
45
|
+
|
46
|
+
Hash.from_xml(topic_xml)["topic"].should == expected_topic_hash
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'parses a single record with nil values' do
|
50
|
+
topic_xml = <<-EOT
|
51
|
+
<topic>
|
52
|
+
<title></title>
|
53
|
+
<id type="integer"></id>
|
54
|
+
<approved type="boolean"></approved>
|
55
|
+
<written-on type="date"></written-on>
|
56
|
+
<viewed-at type="datetime"></viewed-at>
|
57
|
+
<content type="yaml"></content>
|
58
|
+
<parent-id></parent-id>
|
59
|
+
</topic>
|
60
|
+
EOT
|
61
|
+
|
62
|
+
expected_topic_hash = {
|
63
|
+
:title => nil,
|
64
|
+
:id => nil,
|
65
|
+
:approved => nil,
|
66
|
+
:written_on => nil,
|
67
|
+
:viewed_at => nil,
|
68
|
+
:content => nil,
|
69
|
+
:parent_id => nil
|
70
|
+
}.stringify_keys
|
71
|
+
|
72
|
+
Hash.from_xml(topic_xml)["topic"].should == expected_topic_hash
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'parses multiple records' do
|
76
|
+
topics_xml = <<-EOT
|
77
|
+
<topics type="array">
|
78
|
+
<topic>
|
79
|
+
<title>The First Topic</title>
|
80
|
+
<author-name>David</author-name>
|
81
|
+
<id type="integer">1</id>
|
82
|
+
<approved type="boolean">false</approved>
|
83
|
+
<replies-count type="integer">0</replies-count>
|
84
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
85
|
+
<written-on type="date">2003-07-16</written-on>
|
86
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
87
|
+
<content>Have a nice day</content>
|
88
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
89
|
+
<parent-id nil="true"></parent-id>
|
90
|
+
</topic>
|
91
|
+
<topic>
|
92
|
+
<title>The Second Topic</title>
|
93
|
+
<author-name>Jason</author-name>
|
94
|
+
<id type="integer">1</id>
|
95
|
+
<approved type="boolean">false</approved>
|
96
|
+
<replies-count type="integer">0</replies-count>
|
97
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
98
|
+
<written-on type="date">2003-07-16</written-on>
|
99
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
100
|
+
<content>Have a nice day</content>
|
101
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
102
|
+
<parent-id></parent-id>
|
103
|
+
</topic>
|
104
|
+
</topics>
|
105
|
+
EOT
|
106
|
+
|
107
|
+
expected_topic_hash = {
|
108
|
+
:title => "The First Topic",
|
109
|
+
:author_name => "David",
|
110
|
+
:id => 1,
|
111
|
+
:approved => false,
|
112
|
+
:replies_count => 0,
|
113
|
+
:replies_close_in => 2592000000,
|
114
|
+
:written_on => Date.new(2003, 7, 16),
|
115
|
+
:viewed_at => Time.utc(2003, 7, 16, 9, 28),
|
116
|
+
:content => "Have a nice day",
|
117
|
+
:author_email_address => "david@loudthinking.com",
|
118
|
+
:parent_id => nil
|
119
|
+
}.stringify_keys
|
120
|
+
|
121
|
+
Hash.from_xml(topics_xml)["topics"].first.should == expected_topic_hash
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'parses a single record with attributes *other* than "type"' do
|
125
|
+
topic_xml = <<-EOT
|
126
|
+
<rsp stat="ok">
|
127
|
+
<photos page="1" pages="1" perpage="100" total="16">
|
128
|
+
<photo id="175756086" owner="55569174@N00" secret="0279bf37a1" server="76" title="Colored Pencil PhotoBooth Fun" ispublic="1" isfriend="0" isfamily="0"/>
|
129
|
+
</photos>
|
130
|
+
</rsp>
|
131
|
+
EOT
|
132
|
+
|
133
|
+
expected_topic_hash = {
|
134
|
+
:id => "175756086",
|
135
|
+
:owner => "55569174@N00",
|
136
|
+
:secret => "0279bf37a1",
|
137
|
+
:server => "76",
|
138
|
+
:title => "Colored Pencil PhotoBooth Fun",
|
139
|
+
:ispublic => "1",
|
140
|
+
:isfriend => "0",
|
141
|
+
:isfamily => "0",
|
142
|
+
}.stringify_keys
|
143
|
+
|
144
|
+
Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"].should == expected_topic_hash
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'parses an empty array' do
|
148
|
+
blog_xml = <<-XML
|
149
|
+
<blog>
|
150
|
+
<posts type="array"></posts>
|
151
|
+
</blog>
|
152
|
+
XML
|
153
|
+
expected_blog_hash = {"blog" => {"posts" => []}}
|
154
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'parses an empty array with whitespace' do
|
158
|
+
blog_xml = <<-XML
|
159
|
+
<blog>
|
160
|
+
<posts type="array">
|
161
|
+
</posts>
|
162
|
+
</blog>
|
163
|
+
XML
|
164
|
+
expected_blog_hash = {"blog" => {"posts" => []}}
|
165
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'parses an array with one entry' do
|
169
|
+
blog_xml = <<-XML
|
170
|
+
<blog>
|
171
|
+
<posts type="array">
|
172
|
+
<post>a post</post>
|
173
|
+
</posts>
|
174
|
+
</blog>
|
175
|
+
XML
|
176
|
+
expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
|
177
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'parses an array with multiple entries' do
|
181
|
+
blog_xml = <<-XML
|
182
|
+
<blog>
|
183
|
+
<posts type="array">
|
184
|
+
<post>a post</post>
|
185
|
+
<post>another post</post>
|
186
|
+
</posts>
|
187
|
+
</blog>
|
188
|
+
XML
|
189
|
+
expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
|
190
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'parses a file' do
|
194
|
+
blog_xml = <<-XML
|
195
|
+
<blog>
|
196
|
+
<logo type="file" name="logo.png" content_type="image/png">
|
197
|
+
</logo>
|
198
|
+
</blog>
|
199
|
+
XML
|
200
|
+
hash = Hash.from_xml(blog_xml)
|
201
|
+
hash.has_key?('blog').should be_true
|
202
|
+
hash['blog'].has_key?('logo').should be_true
|
203
|
+
|
204
|
+
file = hash['blog']['logo']
|
205
|
+
file.original_filename.should == 'logo.png'
|
206
|
+
file.content_type.should == 'image/png'
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'parses a file with defaults' do
|
210
|
+
blog_xml = <<-XML
|
211
|
+
<blog>
|
212
|
+
<logo type="file">
|
213
|
+
</logo>
|
214
|
+
</blog>
|
215
|
+
XML
|
216
|
+
file = Hash.from_xml(blog_xml)['blog']['logo']
|
217
|
+
file.original_filename.should == 'untitled'
|
218
|
+
file.content_type.should == 'application/octet-stream'
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'parses XSD-like types' do
|
222
|
+
bacon_xml = <<-EOT
|
223
|
+
<bacon>
|
224
|
+
<weight type="double">0.5</weight>
|
225
|
+
<price type="decimal">12.50</price>
|
226
|
+
<chunky type="boolean"> 1 </chunky>
|
227
|
+
<expires-at type="dateTime">2007-12-25T12:34:56+0000</expires-at>
|
228
|
+
<notes type="string"></notes>
|
229
|
+
<illustration type="base64Binary">YmFiZS5wbmc=</illustration>
|
230
|
+
</bacon>
|
231
|
+
EOT
|
232
|
+
|
233
|
+
expected_bacon_hash = {
|
234
|
+
:weight => 0.5,
|
235
|
+
:chunky => true,
|
236
|
+
:price => BigDecimal("12.50"),
|
237
|
+
:expires_at => Time.utc(2007,12,25,12,34,56),
|
238
|
+
:notes => "",
|
239
|
+
:illustration => "babe.png"
|
240
|
+
}.stringify_keys
|
241
|
+
|
242
|
+
Hash.from_xml(bacon_xml)["bacon"].should == expected_bacon_hash
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'trickles the "type" attribute through, when unknown' do
|
246
|
+
product_xml = <<-EOT
|
247
|
+
<product>
|
248
|
+
<weight type="double">0.5</weight>
|
249
|
+
<image type="ProductImage"><filename>image.gif</filename></image>
|
250
|
+
|
251
|
+
</product>
|
252
|
+
EOT
|
253
|
+
|
254
|
+
expected_product_hash = {
|
255
|
+
:weight => 0.5,
|
256
|
+
:image => {'type' => 'ProductImage', 'filename' => 'image.gif' },
|
257
|
+
}.stringify_keys
|
258
|
+
|
259
|
+
Hash.from_xml(product_xml)["product"].should == expected_product_hash
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'unescapes text nodes' do
|
263
|
+
xml_string = '<person><bare-string>First & Last Name</bare-string><pre-escaped-string>First &amp; Last Name</pre-escaped-string></person>'
|
264
|
+
expected_hash = {
|
265
|
+
:bare_string => 'First & Last Name',
|
266
|
+
:pre_escaped_string => 'First & Last Name'
|
267
|
+
}.stringify_keys
|
268
|
+
Hash.from_xml(xml_string)['person'].should == expected_hash
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'parses Hash.to_xml output' do
|
272
|
+
hash = {
|
273
|
+
:bare_string => 'First & Last Name',
|
274
|
+
:pre_escaped_string => 'First & Last Name'
|
275
|
+
}.stringify_keys
|
276
|
+
|
277
|
+
Hash.from_xml(hash.to_xml(@xml_options))['person'].should == hash
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'parses a datetime with UTC time' do
|
281
|
+
alert_xml = <<-XML
|
282
|
+
<alert>
|
283
|
+
<alert_at type="datetime">2008-02-10T15:30:45Z</alert_at>
|
284
|
+
</alert>
|
285
|
+
XML
|
286
|
+
alert_at = Hash.from_xml(alert_xml)['alert']['alert_at']
|
287
|
+
alert_at.utc?.should be_true
|
288
|
+
alert_at.should == Time.utc(2008, 2, 10, 15, 30, 45)
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'parses a datetime with non-UTC time' do
|
292
|
+
alert_xml = <<-XML
|
293
|
+
<alert>
|
294
|
+
<alert_at type="datetime">2008-02-10T10:30:45-05:00</alert_at>
|
295
|
+
</alert>
|
296
|
+
XML
|
297
|
+
alert_at = Hash.from_xml(alert_xml)['alert']['alert_at']
|
298
|
+
alert_at.utc?.should be_true
|
299
|
+
alert_at.should == Time.utc(2008, 2, 10, 15, 30, 45)
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'parses a datetime with a far-future date' do
|
303
|
+
alert_xml = <<-XML
|
304
|
+
<alert>
|
305
|
+
<alert_at type="datetime">2050-02-10T15:30:45Z</alert_at>
|
306
|
+
</alert>
|
307
|
+
XML
|
308
|
+
alert_at = Hash.from_xml(alert_xml)['alert']['alert_at']
|
309
|
+
alert_at.utc?.should be_true
|
310
|
+
alert_at.year.should == 2050
|
311
|
+
alert_at.month.should == 2
|
312
|
+
alert_at.day.should == 10
|
313
|
+
alert_at.hour.should == 15
|
314
|
+
alert_at.min.should == 30
|
315
|
+
alert_at.sec.should == 45
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'undasherizes the root node name' do
|
319
|
+
xml = <<-EOT
|
320
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
321
|
+
<with-dash>
|
322
|
+
<another-dash>text</another-dash>
|
323
|
+
</with-dash>
|
324
|
+
EOT
|
325
|
+
expected_hash = { "with_dash" => {"another_dash"=>"text"} }
|
326
|
+
Hash.from_xml(xml).should == expected_hash
|
327
|
+
end
|
328
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require 'narnach/core_ext/array/conversions'
|
3
|
+
|
4
|
+
describe Array, '#to_xml' do
|
5
|
+
describe 'ActiveSupport tests' do
|
6
|
+
before(:each) do
|
7
|
+
@builder_xml_options = {:skip_instruct => true }
|
8
|
+
@libxml_options = {:skip_instruct => true }
|
9
|
+
end
|
10
|
+
|
11
|
+
def compare_with_rails_for(hash, options = {})
|
12
|
+
builder_xml = hash.to_xml(@builder_xml_options.merge(options))
|
13
|
+
libxml_xml = hash.to_xml_with_libxml(@libxml_options.merge(options))
|
14
|
+
libxml_xml.should == builder_xml
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should pass test_to_xml' do
|
18
|
+
compare_with_rails_for([
|
19
|
+
{ :name => "David", :age => 26, :age_in_millis => 820497600000 },
|
20
|
+
{ :name => "Jason", :age => 31, :age_in_millis => BigDecimal.new('1.0') }
|
21
|
+
])
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should pass test_to_xml_with_dedicated_name' do
|
25
|
+
compare_with_rails_for([
|
26
|
+
{ :name => "David", :age => 26, :age_in_millis => 820497600000 }, { :name => "Jason", :age => 31 }
|
27
|
+
],{:root => "people"})
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should pass test_to_xml_with_options' do
|
31
|
+
compare_with_rails_for([
|
32
|
+
{ :name => "David", :street_address => "Paulina" }, { :name => "Jason", :street_address => "Evergreen" }
|
33
|
+
], {:skip_types => true})
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should pass test_to_xml_with_dasherize_false' do
|
37
|
+
compare_with_rails_for([
|
38
|
+
{ :name => "David", :street_address => "Paulina" }, { :name => "Jason", :street_address => "Evergreen" }
|
39
|
+
], {:skip_types => true, :dasherize => false})
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should pass test_to_xml_with_dasherize_true' do
|
43
|
+
compare_with_rails_for([
|
44
|
+
{ :name => "David", :street_address => "Paulina" }, { :name => "Jason", :street_address => "Evergreen" }
|
45
|
+
], {:skip_types => true, :dasherize => true})
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should pass test_to_with_instruct' do
|
49
|
+
compare_with_rails_for([
|
50
|
+
{ :name => "David", :age => 26, :age_in_millis => 820497600000 },
|
51
|
+
{ :name => "Jason", :age => 31, :age_in_millis => BigDecimal.new('1.0') }
|
52
|
+
], {:skip_instruct => false})
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should pass test_to_xml_with_block' do
|
56
|
+
ary = [
|
57
|
+
{ :name => "David", :age => 26, :age_in_millis => 820497600000 },
|
58
|
+
{ :name => "Jason", :age => 31, :age_in_millis => BigDecimal.new('1.0') }
|
59
|
+
]
|
60
|
+
builder_xml = ary.to_xml(@builder_xml_options) do |builder|
|
61
|
+
builder.count 2
|
62
|
+
end
|
63
|
+
libxml_xml = ary.to_xml_with_libxml(@libxml_options) do |libxml|
|
64
|
+
libxml << LibXML::XML::Node.new('count', 2)
|
65
|
+
end
|
66
|
+
libxml_xml.should == builder_xml
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should pass test_to_xml_with_empty' do
|
70
|
+
compare_with_rails_for([])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
|
3
|
+
describe Hash, '#from_xml' do
|
4
|
+
it "should undasherize the Hash keys" do
|
5
|
+
xml = <<-XML
|
6
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
7
|
+
<post>
|
8
|
+
<post-id type="integer">1</post-id>
|
9
|
+
</post>
|
10
|
+
XML
|
11
|
+
Hash.from_xml(xml).should == {'post' => {'post_id' => 1}}
|
12
|
+
end
|
13
|
+
|
14
|
+
# # libxml will not break, but it takes about 140MB and 60 seconds on a 2.4GHz Core2 Duo Macbook to succeed.
|
15
|
+
# # It would be nice if entity expansion could be disabled if you don't plan to use it.
|
16
|
+
# it 'should pass test_expansion_count_is_limited' do
|
17
|
+
# attack_xml = <<-EOT
|
18
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
19
|
+
# <!DOCTYPE member [
|
20
|
+
# <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
|
21
|
+
# <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
|
22
|
+
# <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
|
23
|
+
# <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
|
24
|
+
# <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
|
25
|
+
# <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
|
26
|
+
# <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
|
27
|
+
# ]>
|
28
|
+
# <member>
|
29
|
+
# &a;
|
30
|
+
# </member>
|
31
|
+
# EOT
|
32
|
+
# lambda {
|
33
|
+
# Hash.from_xml(attack_xml)
|
34
|
+
# }.should_not raise_error
|
35
|
+
# end
|
36
|
+
end
|
37
|
+
|
38
|
+
class IWriteMyOwnXML
|
39
|
+
def to_xml(options = {})
|
40
|
+
options[:indent] ||= 2
|
41
|
+
xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
42
|
+
xml.instruct! unless options[:skip_instruct]
|
43
|
+
xml.level_one do
|
44
|
+
xml.tag!(:second_level, 'content')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_xml_with_libxml(options = {})
|
49
|
+
{:second_level => 'content'}.to_xml_with_libxml(options.merge(:root => 'level_one', :dasherize => false))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe Hash, "#to_xml_with_libxml" do
|
54
|
+
it "should convert a Hash with one element" do
|
55
|
+
hsh = {:one => 1}
|
56
|
+
libxml_xml = hsh.to_xml_with_libxml.to_s
|
57
|
+
builder_xml = hsh.to_xml
|
58
|
+
libxml_xml.should == builder_xml
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should convert a Hash with nested Hash" do
|
62
|
+
hsh = {:one => 1, 'two' => { :three => 3}}
|
63
|
+
libxml_xml = hsh.to_xml_with_libxml.to_s
|
64
|
+
builder_xml = hsh.to_xml
|
65
|
+
libxml_xml.should == builder_xml
|
66
|
+
end
|
67
|
+
|
68
|
+
# These tests are adapted from the Rails ActiveSupport tests, so test to_xml_with_libxml in the same situations as to_xml
|
69
|
+
describe 'ActiveSupport tests' do
|
70
|
+
before(:each) do
|
71
|
+
@builder_xml_options = { :root => :person, :skip_instruct => true }
|
72
|
+
@libxml_options = { :root => :person, :skip_instruct => true }
|
73
|
+
end
|
74
|
+
|
75
|
+
def compare_with_rails_for(hash, custom_builder_options={}, custom_libxml_options={})
|
76
|
+
builder_xml = hash.to_xml(@builder_xml_options.merge(custom_builder_options))
|
77
|
+
libxml_xml = hash.to_xml_with_libxml(@libxml_options.merge(custom_libxml_options))
|
78
|
+
libxml_xml.should == builder_xml
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should pass test_one_level' do
|
82
|
+
compare_with_rails_for({ :name => "David", :street => "Paulina" })
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should pass test_one_level_dasherize_false' do
|
86
|
+
compare_with_rails_for({ :name => "David", :street_name => "Paulina" }, {:dasherize => false}, {:dasherize => false})
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should pass test_one_level_dasherize_true' do
|
90
|
+
compare_with_rails_for({ :name => "David", :street_name => "Paulina" }, {:dasherize => true}, {:dasherize => true})
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should pass test_one_level_with_types' do
|
94
|
+
compare_with_rails_for({ :name => "David", :street => "Paulina", :age => 26, :age_in_millis => 820497600000, :moved_on => Date.new(2005, 11, 15), :resident => :yes })
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should pass test_one_level_with_nils' do
|
98
|
+
compare_with_rails_for({ :name => "David", :street => "Paulina", :age => nil })
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should pass test_one_level_with_skipping_types' do
|
102
|
+
compare_with_rails_for({ :name => "David", :street => "Paulina", :age => nil }, {:skip_types => true}, {:skip_types => true})
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should pass test_one_level_with_yielding' do
|
106
|
+
hash = { :name => "David", :street => "Paulina" }
|
107
|
+
builder_xml = hash.to_xml(@builder_xml_options) do |x|
|
108
|
+
x.creator("Rails")
|
109
|
+
end
|
110
|
+
libxml_xml = hash.to_xml_with_libxml(@libxml_options) do |x|
|
111
|
+
x << LibXML::XML::Node.new('creator', 'Rails')
|
112
|
+
end
|
113
|
+
libxml_xml.should == builder_xml
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should pass test_two_levels' do
|
117
|
+
compare_with_rails_for({ :name => "David", :address => { :street => "Paulina" } })
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should pass test_two_levels_with_second_level_overriding_to_xml' do
|
121
|
+
compare_with_rails_for({ :name => "David", :address => { :street => "Paulina" }, :child => IWriteMyOwnXML.new })
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should pass test_two_levels_with_array' do
|
125
|
+
compare_with_rails_for({ :name => "David", :addresses => [{ :street => "Paulina" }, { :street => "Evergreen" }] })
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should test_three_levels_with_array' do
|
129
|
+
compare_with_rails_for({ :name => "David", :addresses => [{ :streets => [ { :name => "Paulina" }, { :name => "Paulina" } ] } ] })
|
130
|
+
end
|
131
|
+
|
132
|
+
# The XML builder seems to fail miserably when trying to tag something
|
133
|
+
# with the same name as a Kernel method (throw, test, loop, select ...)
|
134
|
+
it 'should pass test_kernel_method_names_to_xml' do
|
135
|
+
compare_with_rails_for({ :throw => { :ball => 'red' } })
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should pass test_escaping_to_xml' do
|
139
|
+
compare_with_rails_for({
|
140
|
+
:bare_string => 'First & Last Name',
|
141
|
+
:pre_escaped_string => 'First & Last Name'
|
142
|
+
}.stringify_keys)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should pass test_roundtrip_to_xml_from_xml' do
|
146
|
+
hash = {
|
147
|
+
:bare_string => 'First & Last Name',
|
148
|
+
:pre_escaped_string => 'First & Last Name'
|
149
|
+
}.stringify_keys
|
150
|
+
|
151
|
+
Hash.from_xml(hash.to_xml_with_libxml(@libxml_options))['person'].should == hash
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
require 'libxml_rails/active_resource'
|
3
|
+
|
4
|
+
class SomePerson < ActiveResource::Base
|
5
|
+
self.site = 'http://example.org'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ActiveResource, '#to_xml' do
|
9
|
+
before(:each) do
|
10
|
+
@sp = SomePerson.new(:name => 'Wes', :last_name => 'Oldenbeuving', :age => 22)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the resource as XML" do
|
14
|
+
@sp.to_xml(:libxml=>false).should == @sp.to_xml(:libxml=>true)
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Narnach-libxml_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brandon Mitchell
|
8
|
+
- Wes Oldenbeuving
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-01-06 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activesupport
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.1.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: libxml-ruby
|
27
|
+
version_requirement:
|
28
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.3
|
33
|
+
version:
|
34
|
+
description: Libxml_rails replaces ActiveSupport's XmlSimple XML parsing with libxml-ruby. Original gem by Brandon Mitchell, this fork is by Wes 'Narnach' Oldenbeuving.
|
35
|
+
email: narnach@gmail.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README.rdoc
|
42
|
+
- MIT-LICENSE
|
43
|
+
files:
|
44
|
+
- CHANGELOG
|
45
|
+
- init.rb
|
46
|
+
- libxml_rails.gemspec
|
47
|
+
- MIT-LICENSE
|
48
|
+
- Rakefile
|
49
|
+
- README.rdoc
|
50
|
+
- spec/from_xml_spec.rb
|
51
|
+
- spec/narnach/core_ext/hash/conversions_spec.rb
|
52
|
+
- spec/narnach/core_ext/array/conversions_spec.rb
|
53
|
+
- spec/narnach/rails_ext/active_resource_spec.rb
|
54
|
+
- spec/spec_helper.rb
|
55
|
+
- lib/bitbckt/core_ext/hash/conversions.rb
|
56
|
+
- lib/narnach/core_ext/hash/conversions.rb
|
57
|
+
- lib/narnach/core_ext/array/conversions.rb
|
58
|
+
- lib/narnach/rails_ext/active_resource.rb
|
59
|
+
- lib/libxml_rails.rb
|
60
|
+
- lib/libxml_rails/active_resource.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://www.github.com/Narnach/libxml_rails
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --inline-source
|
66
|
+
- --line-numbers
|
67
|
+
- --main
|
68
|
+
- README.rdoc
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.8.0
|
76
|
+
version:
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
version:
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.2.0
|
87
|
+
signing_key:
|
88
|
+
specification_version: 2
|
89
|
+
summary: Libxml_rails replaces ActiveSupport's XmlSimple XML parsing with libxml-ruby. Original gem by Brandon Mitchell, this fork is by Wes 'Narnach' Oldenbeuving.
|
90
|
+
test_files:
|
91
|
+
- spec/from_xml_spec.rb
|
92
|
+
- spec/narnach/core_ext/hash/conversions_spec.rb
|
93
|
+
- spec/narnach/core_ext/array/conversions_spec.rb
|
94
|
+
- spec/narnach/rails_ext/active_resource_spec.rb
|