xml-object 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|