xml-object 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +70 -57
- data/TODO +7 -0
- data/WHATSNEW +13 -0
- data/lib/xml-object.rb +6 -9
- data/lib/xml-object/adapters.rb +7 -7
- data/lib/xml-object/adapters/hpricot.rb +3 -6
- data/lib/xml-object/adapters/libxml.rb +5 -7
- data/lib/xml-object/adapters/rexml.rb +5 -6
- data/lib/xml-object/array_notation.rb +19 -18
- data/lib/xml-object/collection_proxy.rb +28 -7
- data/lib/xml-object/element.rb +6 -5
- data/lib/xml-object/method_missing_dispatchers.rb +13 -4
- data/xml-object.gemspec +3 -12
- metadata +2 -10
- data/lib/xml-object/adapters/jrexml.rb +0 -10
- data/lib/xml-object/blankish_slate.rb +0 -10
- data/lib/xml-object/core_ext.rb +0 -3
- data/lib/xml-object/core_ext/hash.rb +0 -5
- data/lib/xml-object/core_ext/nil_class.rb +0 -5
- data/lib/xml-object/core_ext/string.rb +0 -19
- data/lib/xml-object/string.rb +0 -24
data/README.rdoc
CHANGED
@@ -3,23 +3,19 @@
|
|
3
3
|
(This is inspired by Python's +xml_objectify+)
|
4
4
|
|
5
5
|
XMLObject attempts to make the accessing of small, well-formed XML structures
|
6
|
-
convenient, by
|
7
|
-
elements whenever possible.
|
8
|
-
|
9
|
-
XML parsing libraries (in general) have interfaces that are useful when one
|
10
|
-
is using XML for its intended purpose, but cumbersome when one always sends
|
11
|
-
the same XML structure, and always process all of it in the same way. This
|
12
|
-
one aims to be a bit different.
|
13
|
-
|
14
|
-
At the moment, I aim for compatibility with Ruby 1.8, 1.9, and JRuby 1.1.
|
6
|
+
convenient, by providing a syntax that fits well in most Ruby programs.
|
15
7
|
|
16
8
|
== Dependencies
|
17
9
|
|
18
10
|
None outside of Ruby, though some optional gems add additional features. See
|
19
|
-
below
|
11
|
+
more below.
|
12
|
+
|
13
|
+
At the moment, I aim for compatibility with Ruby 1.8, 1.9, and JRuby 1.1.
|
20
14
|
|
21
15
|
== Installation instructions
|
22
16
|
|
17
|
+
From Rubyforge's gem server:
|
18
|
+
|
23
19
|
gem install xml-object
|
24
20
|
|
25
21
|
Or from Github's gem server:
|
@@ -32,6 +28,8 @@ Both are the same, and are loaded the same way:
|
|
32
28
|
|
33
29
|
== Example usage
|
34
30
|
|
31
|
+
recipe.xml is as follows:
|
32
|
+
|
35
33
|
<recipe name="bread" prep_time="5 mins" cook_time="3 hours">
|
36
34
|
<title>Basic bread</title>
|
37
35
|
<ingredient amount="8" unit="dL">Flour</ingredient>
|
@@ -50,7 +48,7 @@ Both are the same, and are loaded the same way:
|
|
50
48
|
</recipe>
|
51
49
|
|
52
50
|
require 'xml-object'
|
53
|
-
recipe = XMLObject.new
|
51
|
+
recipe = XMLObject.new(File.open('recipe.xml'))
|
54
52
|
|
55
53
|
recipe.name => "bread"
|
56
54
|
recipe.title => "Basic bread"
|
@@ -74,89 +72,91 @@ the issue of passing a data-structure over the network, and/or between two
|
|
74
72
|
different languages. Tools like +JSON+ or +YAML+ are a much better fit for
|
75
73
|
this kind of job, but one doesn't always have that luxury.
|
76
74
|
|
77
|
-
==
|
75
|
+
== Features & Problems
|
78
76
|
|
79
|
-
|
77
|
+
=== Adapters
|
80
78
|
|
81
|
-
|
79
|
+
XMLObject supports different adapters to do the actual XML parsing. It ships
|
80
|
+
with +REXML+, +Hpricot+, and +LibXML+ adapters. By default, the +REXML+
|
81
|
+
adapter is used.
|
82
|
+
|
83
|
+
To use a different adapter than the +REXML+ default:
|
84
|
+
|
85
|
+
require 'xml-object' # Require XMLObject first
|
86
|
+
require 'xml-object/adapters/hpricot'
|
87
|
+
require 'xml-object/adapters/libxml'
|
88
|
+
|
89
|
+
=== Access to elements and attributes
|
90
|
+
|
91
|
+
XMLObject uses dot notation (foo.bar) for both elements and attributes, with
|
92
|
+
a few rules, and with an array notation fallback for invalid method names
|
93
|
+
or other tricky situations. For example, with the given file:
|
94
|
+
|
95
|
+
<outer object_id="root" name="foo">
|
82
96
|
<name>Outer Element</name>
|
83
97
|
</outer>
|
84
98
|
|
85
99
|
+outer.name+ is the +name+ *element*. Child elements are always looked up
|
86
|
-
first, then attributes. To access the attribute in
|
100
|
+
first, then attributes. To access the attribute in case of ambiguity, use
|
87
101
|
outer[:attr => 'name'].
|
88
102
|
|
89
|
-
+outer.
|
90
|
-
preserved (this is on purpose). To access the attribute
|
91
|
-
outer[:attr => '
|
92
|
-
ambiguity.
|
103
|
+
+outer.object_id+ is really Object#object_id, because all of the object
|
104
|
+
methods are preserved (this is on purpose). To access the attribute
|
105
|
+
+object_id+, use outer[:attr => 'object_id'] (or just outer['object_id'],
|
106
|
+
since there's no element/attribute ambiguity there).
|
93
107
|
|
94
|
-
|
108
|
+
=== Question notation
|
95
109
|
|
96
|
-
|
97
|
-
|
98
|
-
XMLObject supports different adapters to do the actual XML parsing. It ships
|
99
|
-
with +REXML+, +Hpricot+, +JREXML+, and +LibXML+ adapters. By default, the
|
100
|
-
+REXML+ adapter is used.
|
101
|
-
|
102
|
-
To use a different adapter than the +REXML+ default:
|
103
|
-
|
104
|
-
require 'xml-object' # Require XMLObject first
|
105
|
-
require 'xml-object/adapters/hpricot' # (Under MRI or JRuby)
|
106
|
-
require 'xml-object/adapters/libxml' # (Under MRI only)
|
107
|
-
require 'xml-object/adapters/jrexml' # (Under Jruby only)
|
110
|
+
Elements or attributes that look like booleans are "booleanized" if called by
|
111
|
+
their question names (such as +enabled?+)
|
108
112
|
|
109
113
|
=== Collection auto-folding
|
110
114
|
|
111
|
-
|
112
|
-
|
115
|
+
Like XmlSimple, XMLObject folds same-named elements found at the same level,
|
116
|
+
like so:
|
113
117
|
|
114
118
|
<student>
|
115
119
|
<name>Bob</name>
|
116
|
-
<course>Math</course>
|
117
|
-
<course>Biology</course>
|
120
|
+
<course>Math</course> |
|
121
|
+
<course>Biology</course> | => 'course' becomes an Array
|
118
122
|
</student>
|
119
123
|
|
120
124
|
student = XMLObject.new(xml_file)
|
121
125
|
|
122
|
-
student.course.is_a?
|
126
|
+
student.course.is_a?(Array) => true
|
123
127
|
student.course.first == 'Math' => true
|
124
128
|
student.course.last == 'Biology => true
|
125
129
|
|
126
130
|
=== Collection pluralization
|
127
131
|
|
128
|
-
With the same file
|
129
|
-
get this:
|
132
|
+
With the same file as in the example above:
|
130
133
|
|
131
134
|
student.courses.first == student.course.first => true
|
132
135
|
|
133
136
|
Note that the pluralization algorithm is just tacking an 's' at the end of
|
134
137
|
the singular, unless +ActiveSupport+ is installed, in which case you get
|
135
|
-
|
138
|
+
proper plurals, as well as the ability to teach the +Inflector+ about
|
136
139
|
new ones.
|
137
140
|
|
138
141
|
=== Collection proxy
|
139
142
|
|
140
143
|
Sometimes, collections are expressed with a container element in XML:
|
141
144
|
|
142
|
-
<
|
143
|
-
<name>
|
144
|
-
<
|
145
|
-
<
|
146
|
-
<
|
147
|
-
</
|
148
|
-
</
|
145
|
+
<author>
|
146
|
+
<name>John</name>
|
147
|
+
<publications>
|
148
|
+
<book>Math 101</book>
|
149
|
+
<book>Biology 101</book>
|
150
|
+
</publications>
|
151
|
+
</author>
|
149
152
|
|
150
153
|
In this case, since the container element +courses+ has no text element of
|
151
|
-
its own, and it only has elements of one name under it,
|
152
|
-
|
153
|
-
|
154
|
-
student.courses.collect { |c| c.downcase.to_sym } => [:math, :biology]
|
154
|
+
its own (attributes are ok), and it only has elements of one name under it,
|
155
|
+
it delegates all methods to the collection below, so you get:
|
155
156
|
|
156
|
-
|
157
|
+
author.publications == author.publications.books => true
|
157
158
|
|
158
|
-
|
159
|
-
mark names (such as +enabled?+)
|
159
|
+
author.publications.map { |b| b.downcase } => ['math 101', 'biology 101']
|
160
160
|
|
161
161
|
=== Recursive
|
162
162
|
|
@@ -167,9 +167,22 @@ on the TODO list.
|
|
167
167
|
|
168
168
|
=== Incomplete
|
169
169
|
|
170
|
-
It most likely doesn't work with a ton of features of complex XML files
|
171
|
-
always try to accomodate those, as long as they
|
172
|
-
more complex. As usual, patches welcome.
|
170
|
+
It most likely doesn't work with a ton of features of complex XML files (see
|
171
|
+
the caveats section). I'll always try to accomodate those, as long as they
|
172
|
+
don't make the basic usage more complex. As usual, patches welcome.
|
173
|
+
|
174
|
+
== Caveats
|
175
|
+
|
176
|
+
=== Adapter specific
|
177
|
+
|
178
|
+
==== Hpricot adapter
|
179
|
+
|
180
|
+
While XMLObject doesn't yet aim to support namespaces, they seem to, for the
|
181
|
+
most part, work. That is, unless you're using the Hpricot adapter.
|
182
|
+
|
183
|
+
==== LibXML adapter
|
184
|
+
|
185
|
+
The LibXML adapter will not return the 'xmlns' attribute.
|
173
186
|
|
174
187
|
== Legal
|
175
188
|
|
data/TODO
CHANGED
@@ -1 +1,8 @@
|
|
1
1
|
* Refactor so as to not do things recursively
|
2
|
+
* Implement #inspect, #pp
|
3
|
+
* Decide if NameError is indeed better than nil?
|
4
|
+
* Decide if Element text should be stripped
|
5
|
+
* See if namespaces are a possibility.
|
6
|
+
* See if we can sort out Hpricot not folding namespaces.
|
7
|
+
* Figure out a way to fix the 'xmlns' problem in LibXML, remove entry from
|
8
|
+
caveats in README.rdoc
|
data/WHATSNEW
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
* 0.9.8 (2008-10-23):
|
2
|
+
- Much improved test suite. More granular, better coverage, much faster
|
3
|
+
- The collection proxy behaviour is now a lot faster when called in a loop
|
4
|
+
- Collection Proxies are a lot more transparent
|
5
|
+
- Reduced memory footprint of instantiated XMLObject trees
|
6
|
+
- Calling elements, attributes, question methods or pluralized collections
|
7
|
+
(anything, really) that's not there raises NameError instead of just
|
8
|
+
returning nil
|
9
|
+
- Removed #rb (wasn't really all that useful)
|
10
|
+
- The [:sym => 'foo'] notation now only supports :attr and :elem
|
11
|
+
- The question method notation is a bit more strict
|
12
|
+
- JREXML adapter removed. It barely sped up REXML under JRuby
|
13
|
+
|
1
14
|
* 0.9.7 (2008-10-20):
|
2
15
|
- LibXML adapter added
|
3
16
|
- JREXML "adapter" added, as well as JREXML support during tests and
|
data/lib/xml-object.rb
CHANGED
@@ -3,15 +3,12 @@ begin; require 'activesupport'; rescue Exception, StandardError; nil; end
|
|
3
3
|
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__), 'xml-object')
|
5
5
|
|
6
|
-
require 'core_ext'
|
7
6
|
require 'adapters'
|
8
7
|
require 'adapters/rexml'
|
9
8
|
require 'array_notation'
|
10
|
-
require 'blankish_slate'
|
11
9
|
require 'collection_proxy'
|
12
10
|
require 'element'
|
13
11
|
require 'method_missing_dispatchers'
|
14
|
-
require 'string'
|
15
12
|
|
16
13
|
module XMLObject
|
17
14
|
# Returns a String or Array object representing the given XML, decorated
|
@@ -29,16 +26,16 @@ module XMLObject
|
|
29
26
|
# Takes any Element object, and converts it recursively into
|
30
27
|
# the corresponding tree of decorated objects.
|
31
28
|
def self.new_decorated_obj(xml) # :nodoc:
|
32
|
-
obj = if xml.value.
|
33
|
-
|
29
|
+
obj = if ( (xml.value !~ /\S/) && (xml.children.size > 1) &&
|
30
|
+
xml.children.collect { |e| e.name }.uniq.size == 1 )
|
34
31
|
|
35
|
-
CollectionProxy.new
|
32
|
+
CollectionProxy.new xml.children[0].name.to_sym
|
36
33
|
else
|
37
34
|
# Teach our string to behave like and XML Element
|
38
|
-
xml.value.extend
|
35
|
+
xml.value.extend Element
|
39
36
|
end
|
40
37
|
|
41
|
-
obj.instance_variable_set :@
|
38
|
+
obj.instance_variable_set :@__raw_xml, xml.raw
|
42
39
|
|
43
40
|
xml.children.each { |child| add_child(obj, child.name, new(child)) }
|
44
41
|
xml.attributes.each { |name, value| add_attribute(obj, name, value) }
|
@@ -71,7 +68,7 @@ module XMLObject
|
|
71
68
|
def self.add_attribute(obj, name, attr_value) # :nodoc:
|
72
69
|
|
73
70
|
attributes = obj.instance_variable_get :@__attributes
|
74
|
-
attributes[(key = name.to_sym)] = attr_value.
|
71
|
+
attributes[(key = name.to_sym)] = attr_value.strip.gsub(/\s+/, ' ')
|
75
72
|
|
76
73
|
obj.instance_variable_set :@__attributes, attributes
|
77
74
|
attr_value
|
data/lib/xml-object/adapters.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
module XMLObject # :nodoc:
|
2
|
+
|
3
|
+
class << self # :nodoc:
|
4
|
+
attr_accessor :adapter # :nodoc:
|
5
|
+
end
|
6
|
+
|
2
7
|
module Adapters # :nodoc:
|
3
8
|
module Base # :nodoc:
|
4
9
|
class Element # :nodoc:
|
@@ -7,18 +12,13 @@ module XMLObject # :nodoc:
|
|
7
12
|
def initialize(*args)
|
8
13
|
|
9
14
|
@children = @element_nodes.map { |node| self.class.new(node) }
|
10
|
-
|
11
|
-
@value = case
|
12
|
-
when (not text_value.blank?) then text_value
|
13
|
-
when (not cdata_value.blank?) then cdata_value
|
14
|
-
else ''
|
15
|
-
end
|
15
|
+
@value = (not (text_value !~ /\S/)) ? text_value : cdata_value
|
16
16
|
end
|
17
17
|
|
18
18
|
private ###########################################################
|
19
19
|
|
20
20
|
def text_value
|
21
|
-
@text_nodes.reject { |n| n
|
21
|
+
@text_nodes.reject { |n| n !~ /\S/ }.join
|
22
22
|
end
|
23
23
|
|
24
24
|
def cdata_value
|
@@ -8,9 +8,8 @@ module XMLObject::Adapters::Hpricot
|
|
8
8
|
def self.new(duck)
|
9
9
|
case
|
10
10
|
when duck.is_a?(::Hpricot::Elem) then Element.new(duck)
|
11
|
-
when duck.
|
12
|
-
when duck.respond_to?(:
|
13
|
-
when duck.respond_to?(:to_s) then new(duck.to_s)
|
11
|
+
when duck.respond_to?(:read) then new(::Hpricot::XML(duck.read).root)
|
12
|
+
when duck.respond_to?(:to_s) then new(::Hpricot::XML(duck.to_s).root)
|
14
13
|
else raise "Don't know how to deal with '#{duck.class}' object"
|
15
14
|
end
|
16
15
|
end
|
@@ -36,6 +35,4 @@ module XMLObject::Adapters::Hpricot
|
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
XMLObject::Adapters::Hpricot
|
41
|
-
end
|
38
|
+
::XMLObject.adapter = ::XMLObject::Adapters::Hpricot
|
@@ -7,10 +7,10 @@ module XMLObject::Adapters::LibXML
|
|
7
7
|
def self.new(duck)
|
8
8
|
case
|
9
9
|
when duck.is_a?(::LibXML::XML::Node) then Element.new(duck)
|
10
|
-
when duck.
|
11
|
-
then new(::LibXML::XML::Parser.string(duck).parse.root)
|
12
|
-
when duck.respond_to?(:
|
13
|
-
|
10
|
+
when duck.respond_to?(:read)
|
11
|
+
then new(::LibXML::XML::Parser.string(duck.read).parse.root)
|
12
|
+
when duck.respond_to?(:to_s)
|
13
|
+
then new(::LibXML::XML::Parser.string(duck.to_s).parse.root)
|
14
14
|
else raise "Don't know how to deal with '#{duck.class}' object"
|
15
15
|
end
|
16
16
|
end
|
@@ -33,6 +33,4 @@ module XMLObject::Adapters::LibXML
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
XMLObject::Adapters::LibXML
|
38
|
-
end
|
36
|
+
::XMLObject.adapter = ::XMLObject::Adapters::LibXML
|
@@ -7,9 +7,10 @@ module XMLObject::Adapters::REXML
|
|
7
7
|
def self.new(duck)
|
8
8
|
case
|
9
9
|
when duck.is_a?(::REXML::Element) then Element.new(duck)
|
10
|
-
when duck.
|
11
|
-
|
12
|
-
when duck.respond_to?(:to_s)
|
10
|
+
when duck.respond_to?(:read)
|
11
|
+
then new(::REXML::Document.new(duck.read).root)
|
12
|
+
when duck.respond_to?(:to_s)
|
13
|
+
then new(::REXML::Document.new(duck.to_s).root)
|
13
14
|
else raise "Don't know how to deal with '#{duck.class}' object"
|
14
15
|
end
|
15
16
|
end
|
@@ -35,6 +36,4 @@ module XMLObject::Adapters::REXML
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
-
XMLObject::Adapters::REXML
|
40
|
-
end
|
39
|
+
::XMLObject.adapter = ::XMLObject::Adapters::REXML
|
@@ -18,27 +18,28 @@ module XMLObject::ArrayNotation
|
|
18
18
|
# article[:author] => "J. Random Hacker" # <author> element
|
19
19
|
# article[:attr => 'author'] => "j-random" # author attribute
|
20
20
|
#
|
21
|
-
# Valid keys for the hash notation
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
# Valid keys for the hash notation are +:attr+ and +:elem+.
|
22
|
+
def [](duck)
|
23
|
+
if @__target_kid && duck.is_a?(Numeric)
|
24
|
+
@__children[@__target_kid][duck]
|
25
|
+
elsif duck.is_a?(Hash)
|
26
|
+
raise NameError.new('only one key allowed') if duck.keys.size != 1
|
27
|
+
key, name = duck.keys[0].to_sym, duck.values[0].to_sym
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
unless ( (key == :elem) || (:attr == key) )
|
30
|
+
raise NameError.new("Invalid key :#{key.to_s}. Use :elem or :attr")
|
31
|
+
end
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
raise 'one and only one key allowed' if name.size != 1
|
33
|
+
value = (key == :elem) ? @__children[name] : @__attributes[name]
|
34
|
+
value.nil? ? raise(NameError.new(name.to_s)) : value
|
35
|
+
else
|
36
|
+
key = duck.to_s.to_sym
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
else raise %{ Invalid key :#{param.to_s}.
|
41
|
-
Use one of :element, :child, :attr, or :attribute }.squish!
|
38
|
+
case
|
39
|
+
when (not @__children[key].nil?) then @__children[key]
|
40
|
+
when (not @__attributes[key].nil?) then @__attributes[key]
|
41
|
+
else raise NameError.new(key.to_s)
|
42
|
+
end
|
42
43
|
end
|
43
44
|
end
|
44
45
|
end
|
@@ -1,14 +1,35 @@
|
|
1
|
-
class XMLObject::CollectionProxy
|
2
|
-
|
3
|
-
|
1
|
+
class XMLObject::CollectionProxy # :nodoc:
|
2
|
+
|
3
|
+
instance_methods.each do |m|
|
4
|
+
meth_str, meth_sym = m.to_s, m.to_sym # Ruby 1.8 and 1.9 differ, so...
|
5
|
+
|
6
|
+
undef_method meth_sym unless ( (meth_str =~ /^__/) ||
|
7
|
+
(meth_str =~ /^instance_/) ||
|
8
|
+
(meth_sym == :extend) ||
|
9
|
+
(meth_sym == :nil?) ||
|
10
|
+
(meth_sym == :object_id) )
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(target_kid_key) # :nodoc:
|
14
|
+
@__children, @__attributes, @__target_kid = {}, {}, target_kid_key
|
4
15
|
end
|
5
16
|
|
6
17
|
private ##################################################################
|
7
18
|
|
8
19
|
def method_missing(m, *a, &b) # :nodoc:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
20
|
+
dispatched = __question_dispatch(m, *a, &b)
|
21
|
+
dispatched = __dot_notation_dispatch(m, *a, &b) if dispatched.nil?
|
22
|
+
|
23
|
+
if dispatched.nil? && @__children[@__target_kid].respond_to?(m)
|
24
|
+
dispatched = @__children[@__target_kid].__send__(m, *a, &b)
|
25
|
+
|
26
|
+
unless dispatched.nil?
|
27
|
+
# All is fair in Love and War. And 100% coverage.
|
28
|
+
instance_eval \
|
29
|
+
%{ def #{m}(*a, &b); @__children[@__target_kid].#{m}(*a, &b); end }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
dispatched.nil? ? raise(NameError.new(m.to_s)) : dispatched
|
13
34
|
end
|
14
35
|
end
|
data/lib/xml-object/element.rb
CHANGED
@@ -6,16 +6,17 @@ module XMLObject::Element
|
|
6
6
|
end
|
7
7
|
|
8
8
|
# The raw, unadapted XML object. Whatever this is, it really depends on
|
9
|
-
# the
|
9
|
+
# the currently chosen adapter.
|
10
10
|
def raw_xml
|
11
|
-
@
|
11
|
+
@__raw_xml
|
12
12
|
end
|
13
13
|
|
14
14
|
private ##################################################################
|
15
15
|
|
16
16
|
def method_missing(m, *a, &b) # :nodoc:
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
dispatched = __question_dispatch(m, *a, &b)
|
18
|
+
dispatched = __dot_notation_dispatch(m, *a, &b) if dispatched.nil?
|
19
|
+
|
20
|
+
dispatched.nil? ? raise(NameError.new(m.to_s)) : dispatched
|
20
21
|
end
|
21
22
|
end
|
@@ -3,7 +3,7 @@ module XMLObject::MethodMissingDispatchers # :nodoc:
|
|
3
3
|
private ##################################################################
|
4
4
|
|
5
5
|
def __question_dispatch(meth, *args, &block)
|
6
|
-
return unless meth.to_s.match(/\?$/) && args.empty? && block.nil?
|
6
|
+
return nil unless meth.to_s.match(/\?$/) && args.empty? && block.nil?
|
7
7
|
|
8
8
|
method_sans_question = meth.to_s.chomp('?').to_sym
|
9
9
|
|
@@ -14,7 +14,7 @@ module XMLObject::MethodMissingDispatchers # :nodoc:
|
|
14
14
|
else nil
|
15
15
|
end
|
16
16
|
|
17
|
-
unless bool.nil?
|
17
|
+
unless bool.nil?
|
18
18
|
instance_eval %{ def #{meth}; #{bool ? 'true' : 'false'}; end }
|
19
19
|
end
|
20
20
|
|
@@ -23,7 +23,7 @@ module XMLObject::MethodMissingDispatchers # :nodoc:
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def __dot_notation_dispatch(meth, *args, &block)
|
26
|
-
return unless args.empty? && block.nil?
|
26
|
+
return nil unless args.empty? && block.nil?
|
27
27
|
|
28
28
|
if @__children.has_key?(meth)
|
29
29
|
instance_eval %{ def #{meth}; @__children[%s|#{meth}|]; end }
|
@@ -33,11 +33,20 @@ module XMLObject::MethodMissingDispatchers # :nodoc:
|
|
33
33
|
instance_eval %{ def #{meth}; @__attributes[%s|#{meth}|]; end }
|
34
34
|
@__attributes[meth]
|
35
35
|
|
36
|
-
elsif @__children.has_key?(
|
36
|
+
elsif @__children.has_key?(naive_sing = meth.to_s.chomp('s').to_sym) &&
|
37
|
+
@__children[naive_sing].is_a?(Array)
|
38
|
+
|
39
|
+
instance_eval %{ def #{meth}; @__children[%s|#{naive_sing}|]; end }
|
40
|
+
@__children[naive_sing]
|
41
|
+
|
42
|
+
elsif defined?(ActiveSupport::Inflector) &&
|
43
|
+
@__children.has_key?(singular = meth.to_s.singularize.to_sym) &&
|
37
44
|
@__children[singular].is_a?(Array)
|
38
45
|
|
39
46
|
instance_eval %{ def #{meth}; @__children[%s|#{singular}|]; end }
|
40
47
|
@__children[singular]
|
48
|
+
else
|
49
|
+
nil
|
41
50
|
end
|
42
51
|
end
|
43
52
|
end
|
data/xml-object.gemspec
CHANGED
@@ -2,12 +2,11 @@ Gem::Specification.new do |gem|
|
|
2
2
|
gem.rubyforge_project = 'xml-object'
|
3
3
|
|
4
4
|
gem.name = 'xml-object'
|
5
|
-
gem.version = '0.9.7'
|
6
|
-
gem.date = '2008-10-20'
|
7
|
-
gem.author = 'Jordi Bunster'
|
8
|
-
gem.email = 'jordi@bunster.org'
|
9
5
|
gem.homepage = 'http://github.com/jordi/xml-object'
|
10
6
|
|
7
|
+
gem.version, gem.date = '0.9.8', '2008-10-23'
|
8
|
+
gem.author, gem.email = 'Jordi Bunster', 'jordi@bunster.org'
|
9
|
+
|
11
10
|
gem.summary = "The Rubyista's way to do quick XML sit-ups"
|
12
11
|
gem.description = %{ XMLObject is a library for reading (not writing) XML.
|
13
12
|
It is particularly suited for cases where one is dealing with small
|
@@ -24,21 +23,13 @@ Gem::Specification.new do |gem|
|
|
24
23
|
lib/xml-object
|
25
24
|
lib/xml-object/adapters
|
26
25
|
lib/xml-object/adapters/hpricot.rb
|
27
|
-
lib/xml-object/adapters/jrexml.rb
|
28
26
|
lib/xml-object/adapters/libxml.rb
|
29
27
|
lib/xml-object/adapters/rexml.rb
|
30
28
|
lib/xml-object/adapters.rb
|
31
29
|
lib/xml-object/array_notation.rb
|
32
|
-
lib/xml-object/blankish_slate.rb
|
33
30
|
lib/xml-object/collection_proxy.rb
|
34
|
-
lib/xml-object/core_ext
|
35
|
-
lib/xml-object/core_ext/hash.rb
|
36
|
-
lib/xml-object/core_ext/nil_class.rb
|
37
|
-
lib/xml-object/core_ext/string.rb
|
38
|
-
lib/xml-object/core_ext.rb
|
39
31
|
lib/xml-object/element.rb
|
40
32
|
lib/xml-object/method_missing_dispatchers.rb
|
41
|
-
lib/xml-object/string.rb
|
42
33
|
lib/xml-object.rb
|
43
34
|
xml-object.gemspec
|
44
35
|
]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xml-object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordi Bunster
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-10-
|
12
|
+
date: 2008-10-23 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -31,21 +31,13 @@ files:
|
|
31
31
|
- lib/xml-object
|
32
32
|
- lib/xml-object/adapters
|
33
33
|
- lib/xml-object/adapters/hpricot.rb
|
34
|
-
- lib/xml-object/adapters/jrexml.rb
|
35
34
|
- lib/xml-object/adapters/libxml.rb
|
36
35
|
- lib/xml-object/adapters/rexml.rb
|
37
36
|
- lib/xml-object/adapters.rb
|
38
37
|
- lib/xml-object/array_notation.rb
|
39
|
-
- lib/xml-object/blankish_slate.rb
|
40
38
|
- lib/xml-object/collection_proxy.rb
|
41
|
-
- lib/xml-object/core_ext
|
42
|
-
- lib/xml-object/core_ext/hash.rb
|
43
|
-
- lib/xml-object/core_ext/nil_class.rb
|
44
|
-
- lib/xml-object/core_ext/string.rb
|
45
|
-
- lib/xml-object/core_ext.rb
|
46
39
|
- lib/xml-object/element.rb
|
47
40
|
- lib/xml-object/method_missing_dispatchers.rb
|
48
|
-
- lib/xml-object/string.rb
|
49
41
|
- lib/xml-object.rb
|
50
42
|
- xml-object.gemspec
|
51
43
|
has_rdoc: true
|
data/lib/xml-object/core_ext.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
def blank?
|
3
|
-
self !~ /\S/
|
4
|
-
end unless ''.respond_to? :blank?
|
5
|
-
|
6
|
-
def squish
|
7
|
-
dup.squish!
|
8
|
-
end unless ''.respond_to? :squish
|
9
|
-
|
10
|
-
def squish!
|
11
|
-
strip!
|
12
|
-
gsub! /\s+/, ' '
|
13
|
-
self
|
14
|
-
end unless ''.respond_to? :squish!
|
15
|
-
|
16
|
-
def singularize
|
17
|
-
self.chomp 's'
|
18
|
-
end unless ''.respond_to? :singularize
|
19
|
-
end
|
data/lib/xml-object/string.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module XMLObject::String
|
2
|
-
|
3
|
-
# Attempts to detect wether this String is really an integer or float,
|
4
|
-
# and returns accordingly. If not, just returns the string.
|
5
|
-
def rb
|
6
|
-
result = case
|
7
|
-
when (self !~ /\S/) then ''
|
8
|
-
when match(/[a-zA-Z]/) then ::String.new(self)
|
9
|
-
when match(/^[+-]?\d+$/) then self.to_i
|
10
|
-
when match(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/) then self.to_f
|
11
|
-
else ::String.new(self)
|
12
|
-
end
|
13
|
-
|
14
|
-
@__rb ||= result
|
15
|
-
end
|
16
|
-
|
17
|
-
# A decorated String is blank when it has a blank value, no child
|
18
|
-
# elements, and no attributes. For example:
|
19
|
-
#
|
20
|
-
# <blank_element></blank_element>
|
21
|
-
def blank?
|
22
|
-
(self !~ /\S/) && @__children.blank? && @__attributes.blank?
|
23
|
-
end
|
24
|
-
end
|