jordi-xml-object 0.9.5 → 0.9.6
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 +63 -51
- data/TODO +1 -2
- data/WHATSNEW +28 -0
- data/lib/jordi-xml-object.rb +1 -1
- data/lib/xml-object/adapters/hpricot.rb +30 -26
- data/lib/xml-object/adapters/rexml.rb +16 -15
- data/lib/xml-object/adapters.rb +9 -0
- data/lib/xml-object/array_notation.rb +5 -5
- data/lib/xml-object/blankish_slate.rb +4 -3
- data/lib/xml-object/core_ext/hash.rb +5 -0
- data/lib/xml-object/core_ext/nil_class.rb +5 -0
- data/lib/xml-object/core_ext/string.rb +19 -0
- data/lib/xml-object/core_ext.rb +3 -0
- data/lib/xml-object/element.rb +21 -0
- data/lib/xml-object/method_missing_dispatchers.rb +10 -10
- data/lib/xml-object/string.rb +7 -18
- data/lib/xml-object.rb +23 -27
- data/xml-object.gemspec +11 -6
- metadata +12 -14
- data/lib/xml-object/default_adapter.rb +0 -15
data/README.rdoc
CHANGED
@@ -6,10 +6,22 @@ XMLObject attempts to make the accessing of small, well-formed XML structures
|
|
6
6
|
convenient, by using dot notation to represent both attributes and child
|
7
7
|
elements whenever possible.
|
8
8
|
|
9
|
-
XML parsing libraries (in general) have interfaces that are useful when
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
+
== Installation instructions
|
15
|
+
|
16
|
+
gem install xml-object
|
17
|
+
|
18
|
+
Or from Github's gem server:
|
19
|
+
|
20
|
+
gem install jordi-xml-object --source http://gems.github.com
|
21
|
+
|
22
|
+
Both are the same, and are loaded the same way:
|
23
|
+
|
24
|
+
require 'xml-object'
|
13
25
|
|
14
26
|
== Example usage
|
15
27
|
|
@@ -44,15 +56,11 @@ way. This one aims to be a bit different.
|
|
44
56
|
recipe.instructions.first.upcase => "MIX ALL INGREDIENTS TOGETHER."
|
45
57
|
recipe.instructions.steps.size => 7
|
46
58
|
|
47
|
-
== Installation instructions
|
48
|
-
|
49
|
-
sudo gem install jordi-xml-object --source http://gems.github.com
|
50
|
-
|
51
59
|
== Motivation
|
52
60
|
|
53
|
-
XML is an *extensible* markup language. It is extensible because it is
|
54
|
-
|
55
|
-
|
61
|
+
XML is an *extensible* markup language. It is extensible because it is meant
|
62
|
+
to define markup languages for *any* type of document, so new tags are needed
|
63
|
+
depending on the problem domain.
|
56
64
|
|
57
65
|
Sometimes, however, XML ends up being used to solve a much simpler problem:
|
58
66
|
the issue of passing a data-structure over the network, and/or between two
|
@@ -68,8 +76,8 @@ The dot notation is used as follows. For the given file:
|
|
68
76
|
</outer>
|
69
77
|
|
70
78
|
+outer.name+ is the +name+ *element*. Child elements are always looked up
|
71
|
-
first, then attributes. To access the attribute in the case of ambiguity,
|
72
|
-
|
79
|
+
first, then attributes. To access the attribute in the case of ambiguity, use
|
80
|
+
outer[:attr => 'name'].
|
73
81
|
|
74
82
|
+outer.id+ is really Object#id, because all of the object methods are
|
75
83
|
preserved (this is on purpose). To access the attribute +id+, use
|
@@ -80,73 +88,77 @@ ambiguity.
|
|
80
88
|
|
81
89
|
=== Collection auto-folding
|
82
90
|
|
83
|
-
Similar to XmlSimple, XMLObject folds same named elements at the same
|
84
|
-
|
91
|
+
Similar to XmlSimple, XMLObject folds same named elements at the same level.
|
92
|
+
For example:
|
85
93
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
94
|
+
<student>
|
95
|
+
<name>Bob</name>
|
96
|
+
<course>Math</course>
|
97
|
+
<course>Biology</course>
|
98
|
+
</student>
|
91
99
|
|
92
|
-
|
100
|
+
student = XMLObject.new(xml_file)
|
93
101
|
|
94
|
-
|
95
|
-
|
96
|
-
|
102
|
+
student.course.is_a? Array => true
|
103
|
+
student.course.first == 'Math' => true
|
104
|
+
student.course.last == 'Biology => true
|
97
105
|
|
98
106
|
=== Collection pluralization
|
99
107
|
|
100
|
-
With the same file from the +Collection auto-folding+ section above, you
|
101
|
-
|
108
|
+
With the same file from the +Collection auto-folding+ section above, you also
|
109
|
+
get this:
|
102
110
|
|
103
|
-
|
111
|
+
student.courses.first == student.course.first => true
|
112
|
+
|
113
|
+
Note that the pluralization algorithm is just tacking an 's' at the end of
|
114
|
+
the singular, unless +ActiveSupport+ is installed, in which case you get
|
115
|
+
irregular plurals, as well as the ability to teach the +Inflector+ about
|
116
|
+
new ones.
|
104
117
|
|
105
118
|
=== Collection proxy
|
106
119
|
|
107
|
-
|
120
|
+
Sometimes, collections are expressed with a container element in XML:
|
108
121
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
122
|
+
<student>
|
123
|
+
<name>Bob</name>
|
124
|
+
<courses>
|
125
|
+
<course>Math</course>
|
126
|
+
<course>Biology</course>
|
127
|
+
</courses>
|
128
|
+
</student>
|
116
129
|
|
117
|
-
In this case, since the container element +courses+ has no text element
|
118
|
-
|
119
|
-
|
130
|
+
In this case, since the container element +courses+ has no text element of
|
131
|
+
its own, and it only has elements of one name under it, it delegates all
|
132
|
+
methods it doesn't contain to the collection below, so you get:
|
120
133
|
|
121
|
-
|
134
|
+
student.courses.collect { |c| c.downcase.to_sym } => [:math, :biology]
|
122
135
|
|
123
136
|
=== Question mark notation
|
124
137
|
|
125
|
-
Strings that look like booleans are "booleanized" if called by their
|
126
|
-
|
138
|
+
Strings that look like booleans are "booleanized" if called by their question
|
139
|
+
mark names (such as +enabled?+)
|
127
140
|
|
128
141
|
=== Adapters
|
129
142
|
|
130
143
|
XMLObject supports different adapters to do the actual XML parsing. It ships
|
131
|
-
with +REXML+ and +Hpricot+ adapters.
|
132
|
-
|
144
|
+
with +REXML+ and +Hpricot+ adapters. By default, the +REXML+ adapter is used.
|
145
|
+
To use the +Hpricot+ adapter:
|
146
|
+
|
147
|
+
require 'xml-object/adapters/hpricot'
|
133
148
|
|
134
149
|
=== Recursive
|
135
150
|
|
136
151
|
The design of the adapters assumes parsing of the objects recursively. Deep
|
137
152
|
files are bound to throw +SystemStackError+, but for the kinds of files I
|
138
|
-
need to read, things are working fine so far. In any case, stream parsing
|
139
|
-
|
153
|
+
need to read, things are working fine so far. In any case, stream parsing is
|
154
|
+
on the TODO list.
|
140
155
|
|
141
156
|
=== Incomplete
|
142
157
|
|
143
|
-
It most likely doesn't work with a ton of features of complex XML files. I
|
144
|
-
|
145
|
-
|
158
|
+
It most likely doesn't work with a ton of features of complex XML files. I'll
|
159
|
+
always try to accomodate those, as long as they don't make the basic usage
|
160
|
+
more complex. As usual, patches welcome.
|
146
161
|
|
147
162
|
== Legal
|
148
163
|
|
149
164
|
Copyright (c) 2008 Jordi Bunster, released under the MIT license
|
150
|
-
|
151
|
-
|
152
|
-
|
data/TODO
CHANGED
data/WHATSNEW
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
* 0.9.6 (2008-10-??):
|
2
|
+
- Ruby 1.9 compatibility
|
3
|
+
- XMLObject no longer requires ActiveSupport. Note that proper array
|
4
|
+
pluralization still depends on ActiveSupport's Inflector, so if it's not
|
5
|
+
there, we just pluralize things by tacking 's' at the end.
|
6
|
+
- XMLObject no longer tries to load Hpricot by default (too cumbersome
|
7
|
+
to test). Use "require 'xml-object/adapters/hpricot'" to enable the
|
8
|
+
Hpricot adapter.
|
9
|
+
- Backwards compatible change. For the following XML:
|
10
|
+
|
11
|
+
<foo>
|
12
|
+
<bar>
|
13
|
+
<bez>
|
14
|
+
</foo>
|
15
|
+
|
16
|
+
<foos>Yipes!</foos>
|
17
|
+
|
18
|
+
before:
|
19
|
+
|
20
|
+
xml.foos => # The <foo> "array"
|
21
|
+
|
22
|
+
now:
|
23
|
+
|
24
|
+
xml.foos => # The <foos> element
|
25
|
+
|
26
|
+
It proved too expensive to support that edge case, and for no good
|
27
|
+
reason.
|
28
|
+
|
1
29
|
* 0.9.5 (2008-10-15):
|
2
30
|
- Project renamed to XMLObject, to match project name at Rubyforge.
|
3
31
|
The other names were taken. :(
|
data/lib/jordi-xml-object.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'xml-object'
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'xml-object'))
|
@@ -1,47 +1,51 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
|
1
3
|
module XMLObject::Adapters::Hpricot
|
2
4
|
|
3
5
|
# Can take a String of XML data, or anything that responds to
|
4
6
|
# either +read+ or +to_s+.
|
5
7
|
def self.new(duck)
|
6
8
|
case
|
7
|
-
when duck.is_a?(::Hpricot::Elem)
|
8
|
-
when duck.is_a?(::String)
|
9
|
-
when duck.respond_to?(:read)
|
10
|
-
when duck.respond_to?(:to_s)
|
9
|
+
when duck.is_a?(::Hpricot::Elem) then Element.new(duck)
|
10
|
+
when duck.is_a?(::String) then new(::Hpricot::XML(duck).root)
|
11
|
+
when duck.respond_to?(:read) then new(duck.read)
|
12
|
+
when duck.respond_to?(:to_s) then new(duck.to_s)
|
11
13
|
else raise "Don't know how to deal with '#{duck.class}' object"
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
17
|
private ##################################################################
|
16
18
|
|
17
|
-
class Element # :nodoc:
|
18
|
-
|
19
|
+
class Element < XMLObject::Adapters::Base::Element # :nodoc:
|
20
|
+
def initialize(xml)
|
21
|
+
self.raw, self.name, self.attributes = xml, xml.name, xml.attributes
|
22
|
+
self.children = xml.children.select { |e| e.elem? }.map do |raw_xml|
|
23
|
+
self.class.new(raw_xml)
|
24
|
+
end
|
19
25
|
|
20
|
-
|
21
|
-
|
26
|
+
self.value = case
|
27
|
+
when (not text_value(xml).blank?) then text_value(xml)
|
28
|
+
when (not cdata_value(xml).blank?) then cdata_value(xml)
|
29
|
+
else ''
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private ################################################################
|
34
|
+
|
35
|
+
def text_value(xml)
|
36
|
+
xml.children.select do |e|
|
22
37
|
(e.class == ::Hpricot::Text) && !e.to_s.blank?
|
23
38
|
end.join.to_s
|
24
39
|
end
|
25
40
|
|
26
|
-
def cdata_value(
|
27
|
-
|
41
|
+
def cdata_value(xml)
|
42
|
+
xml.children.select do |e|
|
28
43
|
(e.class == ::Hpricot::CData) && !e.to_s.blank?
|
29
44
|
end.first.to_s
|
30
45
|
end
|
31
|
-
|
32
|
-
def initialize(xml)
|
33
|
-
@raw, @name, @attributes, @children = xml, xml.name, {}, []
|
34
|
-
|
35
|
-
@attributes = xml.attributes
|
36
|
-
xml.children.select { |e| e.elem? }.each do |e|
|
37
|
-
@children << self.class.new(e)
|
38
|
-
end
|
39
|
-
|
40
|
-
@value = case
|
41
|
-
when (not text_value(@raw).blank?) : text_value(@raw)
|
42
|
-
when (not cdata_value(@raw).blank?) : cdata_value(@raw)
|
43
|
-
else ''
|
44
|
-
end
|
45
|
-
end
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def XMLObject.adapter # :nodoc:
|
50
|
+
XMLObject::Adapters::Hpricot
|
51
|
+
end
|
@@ -1,34 +1,35 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
1
3
|
module XMLObject::Adapters::REXML
|
2
|
-
require 'rexml/document'
|
3
4
|
|
4
5
|
# Can take a String of XML data, or anything that responds to
|
5
6
|
# either +read+ or +to_s+.
|
6
7
|
def self.new(duck)
|
7
8
|
case
|
8
|
-
when duck.is_a?(::REXML::Element)
|
9
|
-
when duck.is_a?(::String)
|
10
|
-
when duck.respond_to?(:read)
|
11
|
-
when duck.respond_to?(:to_s)
|
9
|
+
when duck.is_a?(::REXML::Element) then Element.new(duck)
|
10
|
+
when duck.is_a?(::String) then new(::REXML::Document.new(duck).root)
|
11
|
+
when duck.respond_to?(:read) then new(duck.read)
|
12
|
+
when duck.respond_to?(:to_s) then new(duck.to_s)
|
12
13
|
else raise "Don't know how to deal with '#{duck.class}' object"
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
17
|
private ##################################################################
|
17
18
|
|
18
|
-
class Element # :nodoc:
|
19
|
-
attr_reader :raw, :name, :value, :attributes, :children
|
20
|
-
|
19
|
+
class Element < XMLObject::Adapters::Base::Element # :nodoc:
|
21
20
|
def initialize(xml)
|
22
|
-
|
23
|
-
|
24
|
-
@attributes = xml.attributes
|
25
|
-
xml.each_element { |e| @children << self.class.new(e) }
|
21
|
+
self.raw, self.name, self.attributes = xml, xml.name, xml.attributes
|
22
|
+
self.children = xml.elements.map { |raw_xml| self.class.new(raw_xml) }
|
26
23
|
|
27
|
-
|
28
|
-
when (not xml.text.blank?)
|
29
|
-
when (xml.cdatas.
|
24
|
+
self.value = case
|
25
|
+
when (not xml.text.blank?) then xml.text.to_s
|
26
|
+
when (xml.cdatas.any?) then xml.cdatas.first.to_s
|
30
27
|
else ''
|
31
28
|
end
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|
32
|
+
|
33
|
+
def XMLObject.adapter # :nodoc:
|
34
|
+
XMLObject::Adapters::REXML
|
35
|
+
end
|
@@ -24,7 +24,7 @@ module XMLObject::ArrayNotation
|
|
24
24
|
return @__target[name] if @__target && name.is_a?(Numeric)
|
25
25
|
|
26
26
|
unless name.is_a? Hash
|
27
|
-
key = name.to_sym
|
27
|
+
key = name.to_s.to_sym
|
28
28
|
|
29
29
|
return @__children[key] if @__children.has_key?(key)
|
30
30
|
return @__attributes[key] if @__attributes.has_key?(key)
|
@@ -33,10 +33,10 @@ module XMLObject::ArrayNotation
|
|
33
33
|
raise 'one and only one key allowed' if name.size != 1
|
34
34
|
|
35
35
|
case (param = name.keys.first.to_sym)
|
36
|
-
when :element
|
37
|
-
when :child
|
38
|
-
when :attr
|
39
|
-
when :attribute
|
36
|
+
when :element then @__children[name.values.first.to_sym]
|
37
|
+
when :child then @__children[name.values.first.to_sym]
|
38
|
+
when :attr then @__attributes[name.values.first.to_sym]
|
39
|
+
when :attribute then @__attributes[name.values.first.to_sym]
|
40
40
|
else raise %{ Invalid key :#{param.to_s}.
|
41
41
|
Use one of :element, :child, :attr, or :attribute }.squish!
|
42
42
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
class XMLObject::BlankishSlate # :nodoc:
|
2
2
|
|
3
3
|
instance_methods.each do |m|
|
4
|
-
undef_method m unless m =~ /^__/
|
5
|
-
m
|
6
|
-
m
|
4
|
+
undef_method m unless m =~ /^__/ ||
|
5
|
+
m =~ /respond_to/ ||
|
6
|
+
m =~ /extend/ ||
|
7
|
+
m =~ /object_id/ ||
|
7
8
|
m =~ /^instance_/
|
8
9
|
end
|
9
10
|
end
|
@@ -0,0 +1,19 @@
|
|
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
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module XMLObject::Element
|
2
|
+
def self.extended(obj) # :nodoc:
|
3
|
+
obj.instance_variable_set :@__children, {}
|
4
|
+
obj.instance_variable_set :@__attributes, {}
|
5
|
+
obj
|
6
|
+
end
|
7
|
+
|
8
|
+
# The raw, unadapted XML object. Whatever this is, it really depends on
|
9
|
+
# the current_adapter.
|
10
|
+
def raw_xml
|
11
|
+
@__adapted_element.raw if @__adapted_element
|
12
|
+
end
|
13
|
+
|
14
|
+
private ##################################################################
|
15
|
+
|
16
|
+
def method_missing(m, *a, &b) # :nodoc:
|
17
|
+
dp = __question_dispatch(m, *a, &b)
|
18
|
+
dp = __dot_notation_dispatch(m, *a, &b) if dp.nil?
|
19
|
+
dp
|
20
|
+
end
|
21
|
+
end
|
@@ -7,10 +7,10 @@ module XMLObject::MethodMissingDispatchers # :nodoc:
|
|
7
7
|
|
8
8
|
method_sans_question = meth.to_s.chomp('?').to_sym
|
9
9
|
|
10
|
-
if boolish = __send__(method_sans_question)
|
10
|
+
if boolish = __send__(method_sans_question)
|
11
11
|
bool = case
|
12
|
-
when %w[ true yes t y ].include?(boolish)
|
13
|
-
when %w[ false no f n ].include?(boolish)
|
12
|
+
when %w[ true yes t y ].include?(boolish.downcase) then true
|
13
|
+
when %w[ false no f n ].include?(boolish.downcase) then false
|
14
14
|
else nil
|
15
15
|
end
|
16
16
|
|
@@ -25,19 +25,19 @@ module XMLObject::MethodMissingDispatchers # :nodoc:
|
|
25
25
|
def __dot_notation_dispatch(meth, *args, &block)
|
26
26
|
return unless args.empty? && block.nil?
|
27
27
|
|
28
|
-
if @__children.has_key?(
|
29
|
-
@__children[singular].is_a?(Array)
|
30
|
-
|
31
|
-
instance_eval %{ def #{meth}; @__children[%s|#{singular}|]; end }
|
32
|
-
@__children[singular]
|
33
|
-
|
34
|
-
elsif @__children.has_key?(meth)
|
28
|
+
if @__children.has_key?(meth)
|
35
29
|
instance_eval %{ def #{meth}; @__children[%s|#{meth}|]; end }
|
36
30
|
@__children[meth]
|
37
31
|
|
38
32
|
elsif @__attributes.has_key?(meth)
|
39
33
|
instance_eval %{ def #{meth}; @__attributes[%s|#{meth}|]; end }
|
40
34
|
@__attributes[meth]
|
35
|
+
|
36
|
+
elsif @__children.has_key?(singular = meth.to_s.singularize.to_sym) &&
|
37
|
+
@__children[singular].is_a?(Array)
|
38
|
+
|
39
|
+
instance_eval %{ def #{meth}; @__children[%s|#{singular}|]; end }
|
40
|
+
@__children[singular]
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
data/lib/xml-object/string.rb
CHANGED
@@ -1,20 +1,17 @@
|
|
1
1
|
module XMLObject::String
|
2
|
-
def self.extended(obj) # :nodoc:
|
3
|
-
obj.instance_variable_set :@__children, {}
|
4
|
-
obj.instance_variable_set :@__attributes, {}
|
5
|
-
obj
|
6
|
-
end
|
7
2
|
|
8
3
|
# Attempts to detect wether this String is really an integer or float,
|
9
4
|
# and returns accordingly. If not, just returns the string.
|
10
5
|
def rb
|
11
|
-
|
12
|
-
when (self !~ /\S/)
|
13
|
-
when match(/[a-zA-Z]/)
|
14
|
-
when match(/^[+-]?\d+$/)
|
15
|
-
when match(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/)
|
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
|
16
11
|
else ::String.new(self)
|
17
12
|
end
|
13
|
+
|
14
|
+
@__rb ||= result
|
18
15
|
end
|
19
16
|
|
20
17
|
# A decorated String is blank when it has a blank value, no child
|
@@ -24,12 +21,4 @@ module XMLObject::String
|
|
24
21
|
def blank?
|
25
22
|
(self !~ /\S/) && @__children.blank? && @__attributes.blank?
|
26
23
|
end
|
27
|
-
|
28
|
-
private ##################################################################
|
29
|
-
|
30
|
-
def method_missing(m, *a, &b) # :nodoc:
|
31
|
-
dp = __question_dispatch(m, *a, &b)
|
32
|
-
dp = __dot_notation_dispatch(m, *a, &b) if dp.nil?
|
33
|
-
dp
|
34
|
-
end
|
35
24
|
end
|
data/lib/xml-object.rb
CHANGED
@@ -1,33 +1,28 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'activesupport'
|
1
|
+
begin; require 'rubygems'; rescue Exception, StandardError; nil; end
|
2
|
+
begin; require 'activesupport'; rescue Exception, StandardError; nil; end
|
3
3
|
|
4
|
-
module XMLObject
|
5
|
-
|
6
|
-
|
7
|
-
BASE_DIR = File.join(File.dirname(__FILE__), 'xml-object')
|
8
|
-
end
|
4
|
+
module XMLObject # :nodoc:
|
5
|
+
VERSION = '0.9.6'
|
6
|
+
end
|
9
7
|
|
10
|
-
|
11
|
-
require File.join(BASE_DIR, 'method_missing_dispatchers')
|
12
|
-
require File.join(BASE_DIR, 'array_notation')
|
13
|
-
require File.join(BASE_DIR, 'blankish_slate')
|
14
|
-
require File.join(BASE_DIR, 'collection_proxy')
|
15
|
-
require File.join(BASE_DIR, 'string')
|
8
|
+
require 'core_ext'
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
10
|
+
require 'adapters'
|
11
|
+
require 'adapters/rexml'
|
12
|
+
require 'array_notation'
|
13
|
+
require 'blankish_slate'
|
14
|
+
require 'collection_proxy'
|
15
|
+
require 'element'
|
16
|
+
require 'method_missing_dispatchers'
|
17
|
+
require 'string'
|
24
18
|
|
19
|
+
module XMLObject
|
25
20
|
# Returns a String or Array object representing the given XML, decorated
|
26
21
|
# with methods to access attributes and/or child elements.
|
27
22
|
def self.new(duck)
|
28
23
|
case duck
|
29
|
-
when adapter::Element
|
30
|
-
when Array
|
24
|
+
when adapter::Element then new_decorated_obj(duck)
|
25
|
+
when Array then duck.map { |d| new_decorated_obj(d) }
|
31
26
|
else new adapter.new(duck)
|
32
27
|
end
|
33
28
|
end
|
@@ -36,28 +31,29 @@ module XMLObject
|
|
36
31
|
|
37
32
|
# Takes any Element object, and converts it recursively into
|
38
33
|
# the corresponding tree of decorated objects.
|
39
|
-
def self.new_decorated_obj(xml)
|
34
|
+
def self.new_decorated_obj(xml) # :nodoc:
|
40
35
|
obj = if xml.value.blank? &&
|
41
36
|
xml.children.collect { |e| e.name }.uniq.size == 1
|
42
37
|
|
43
38
|
CollectionProxy.new new(xml.children)
|
44
39
|
else
|
45
|
-
|
40
|
+
# Teach our string to behave like and XML Element
|
41
|
+
xml.value.extend String, Element
|
46
42
|
end
|
47
43
|
|
48
|
-
obj.instance_variable_set :@
|
44
|
+
obj.instance_variable_set :@__adapted_element, xml
|
49
45
|
|
50
46
|
xml.children.each { |child| add_child(obj, child.name, new(child)) }
|
51
47
|
xml.attributes.each { |name, value| add_attribute(obj, name, value) }
|
52
48
|
|
53
49
|
# Let's teach our object some new tricks:
|
54
|
-
obj.extend
|
50
|
+
obj.extend ArrayNotation, MethodMissingDispatchers
|
55
51
|
end
|
56
52
|
|
57
53
|
# Decorates the given object 'obj' with a method 'name' that returns the
|
58
54
|
# given 'element'. If 'name' is already taken, takes care of the array
|
59
55
|
# folding behaviour.
|
60
|
-
def self.add_child(obj, name, element)
|
56
|
+
def self.add_child(obj, name, element) # :nodoc:
|
61
57
|
key = name.to_sym
|
62
58
|
children = obj.instance_variable_get :@__children
|
63
59
|
|
data/xml-object.gemspec
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
|
-
gem.
|
3
|
-
|
4
|
-
gem.name = 'xml-object'
|
5
|
-
gem.version = '0.9.5'
|
6
|
-
gem.date = '2008-10-15'
|
2
|
+
gem.rubyforge_project = 'xml-object'
|
7
3
|
|
4
|
+
gem.name = 'xml-object'
|
5
|
+
gem.version = '0.9.6'
|
6
|
+
gem.date = '2008-10-19'
|
8
7
|
gem.author = 'Jordi Bunster'
|
9
8
|
gem.email = 'jordi@bunster.org'
|
10
9
|
gem.homepage = 'http://github.com/jordi/xml-object'
|
@@ -26,10 +25,16 @@ Gem::Specification.new do |gem|
|
|
26
25
|
lib/xml-object/adapters
|
27
26
|
lib/xml-object/adapters/hpricot.rb
|
28
27
|
lib/xml-object/adapters/rexml.rb
|
28
|
+
lib/xml-object/adapters.rb
|
29
29
|
lib/xml-object/array_notation.rb
|
30
30
|
lib/xml-object/blankish_slate.rb
|
31
31
|
lib/xml-object/collection_proxy.rb
|
32
|
-
lib/xml-object/
|
32
|
+
lib/xml-object/core_ext
|
33
|
+
lib/xml-object/core_ext/hash.rb
|
34
|
+
lib/xml-object/core_ext/nil_class.rb
|
35
|
+
lib/xml-object/core_ext/string.rb
|
36
|
+
lib/xml-object/core_ext.rb
|
37
|
+
lib/xml-object/element.rb
|
33
38
|
lib/xml-object/method_missing_dispatchers.rb
|
34
39
|
lib/xml-object/string.rb
|
35
40
|
lib/xml-object.rb
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jordi-xml-object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordi Bunster
|
@@ -9,18 +9,10 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-10-
|
12
|
+
date: 2008-10-19 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
name: activesupport
|
17
|
-
version_requirement:
|
18
|
-
version_requirements: !ruby/object:Gem::Requirement
|
19
|
-
requirements:
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: "0"
|
23
|
-
version:
|
14
|
+
dependencies: []
|
15
|
+
|
24
16
|
description: XMLObject is a library for reading (not writing) XML. It is particularly suited for cases where one is dealing with small documents of a known structure. While not devoid of caveats, it does have a very pleasant, idiomatic Ruby syntax.
|
25
17
|
email: jordi@bunster.org
|
26
18
|
executables: []
|
@@ -40,10 +32,16 @@ files:
|
|
40
32
|
- lib/xml-object/adapters
|
41
33
|
- lib/xml-object/adapters/hpricot.rb
|
42
34
|
- lib/xml-object/adapters/rexml.rb
|
35
|
+
- lib/xml-object/adapters.rb
|
43
36
|
- lib/xml-object/array_notation.rb
|
44
37
|
- lib/xml-object/blankish_slate.rb
|
45
38
|
- lib/xml-object/collection_proxy.rb
|
46
|
-
- lib/xml-object/
|
39
|
+
- lib/xml-object/core_ext
|
40
|
+
- lib/xml-object/core_ext/hash.rb
|
41
|
+
- lib/xml-object/core_ext/nil_class.rb
|
42
|
+
- lib/xml-object/core_ext/string.rb
|
43
|
+
- lib/xml-object/core_ext.rb
|
44
|
+
- lib/xml-object/element.rb
|
47
45
|
- lib/xml-object/method_missing_dispatchers.rb
|
48
46
|
- lib/xml-object/string.rb
|
49
47
|
- lib/xml-object.rb
|
@@ -73,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
71
|
version:
|
74
72
|
requirements: []
|
75
73
|
|
76
|
-
rubyforge_project:
|
74
|
+
rubyforge_project: xml-object
|
77
75
|
rubygems_version: 1.2.0
|
78
76
|
signing_key:
|
79
77
|
specification_version: 2
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module XMLObject # :nodoc:
|
2
|
-
module Adapters # :nodoc:
|
3
|
-
ADAPTERS_PATH = File.join(File.dirname(__FILE__), 'adapters')
|
4
|
-
|
5
|
-
Default = begin
|
6
|
-
require 'hpricot'
|
7
|
-
require File.join(ADAPTERS_PATH, 'hpricot')
|
8
|
-
Hpricot
|
9
|
-
rescue LoadError
|
10
|
-
require File.join(ADAPTERS_PATH, 'rexml')
|
11
|
-
REXML
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|