pipa-xmlnuts 0.0.2 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ require 'monitor'
2
+
3
+ module XmlNuts
4
+ module XmlBackend
5
+ extend MonitorMixin
6
+
7
+ autoload :REXMLBackend, 'xmlnuts/rexml'
8
+
9
+ def self.default
10
+ synchronize do
11
+ unless defined? @@default
12
+ @@default = REXMLBackend.new
13
+ def self.default #:nodoc:
14
+ @@default
15
+ end
16
+ @@default
17
+ end
18
+ end
19
+ end
20
+
21
+ def self.default=(backend)
22
+ @@default = backend
23
+ end
24
+
25
+ def self.current
26
+ Thread.current[:xmlnuts_xml_backend] || default
27
+ end
28
+
29
+ def self.current=(backend)
30
+ Thread.current[:xmlnuts_xml_backend] = backend
31
+ end
32
+
33
+ private
34
+ def backend #:doc:
35
+ XmlBackend.current
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,7 @@
1
+ require 'time'
2
+
1
3
  module XmlNuts
2
- module Converters
4
+ module Converter
3
5
  def self.lookup(type)
4
6
  lookup!(type)
5
7
  rescue ArgumentError
@@ -22,7 +24,7 @@ module XmlNuts
22
24
  lookup!(type).new(options)
23
25
  end
24
26
 
25
- class Convert_string #:nodoc:
27
+ class Convert_string
26
28
  def initialize(options)
27
29
  @whitespace = options[:whitespace] || :trim
28
30
  end
@@ -41,7 +43,7 @@ module XmlNuts
41
43
  end
42
44
  end
43
45
 
44
- class Convert_boolean < Convert_string #:nodoc:
46
+ class Convert_boolean < Convert_string
45
47
  def initialize(options)
46
48
  super
47
49
  @format = options[:format] || :truefalse
@@ -68,7 +70,7 @@ module XmlNuts
68
70
  end
69
71
  end
70
72
 
71
- class Convert_integer < Convert_string #:nodoc:
73
+ class Convert_integer < Convert_string
72
74
  def initialize(options)
73
75
  super
74
76
  end
@@ -82,7 +84,7 @@ module XmlNuts
82
84
  end
83
85
  end
84
86
 
85
- class Convert_datetime < Convert_string #:nodoc:
87
+ class Convert_datetime < Convert_string
86
88
  def initialize(options)
87
89
  super
88
90
  @fraction_digits = options[:fraction_digits] || 0
@@ -92,19 +94,19 @@ module XmlNuts
92
94
  time && time.xmlschema(@fraction_digits)
93
95
  end
94
96
 
95
- def self.from_xml(string)
97
+ def from_xml(string)
96
98
  string && Time.parse(super(string, options))
97
99
  end
98
100
  end
99
101
 
100
- class Convert_list #:nodoc:
102
+ class Convert_list
101
103
  def initialize(options)
102
104
  @item_type = options[:item_type] || :string
103
- @item_converter = Converters.create!(@item_type, options)
105
+ @item_converter = Converter.create!(@item_type, options)
104
106
  end
105
107
 
106
108
  def to_xml(array)
107
- array.map {|x| @item_converter.to_xml(x) } * ' '
109
+ array && array.map {|x| @item_converter.to_xml(x) } * ' '
108
110
  end
109
111
 
110
112
  def from_xml(string)
@@ -1,137 +1,138 @@
1
- module XmlNuts
2
- class Mapping
3
- attr_reader :name, :xmlname, :type, :options, :converter
4
-
5
- def initialize(name, type, options)
6
- @name, @xmlname, @type, @options = name.to_sym, (options.delete(:xmlname) || name).to_s, type, options
7
- @setter = :"#{name}="
8
- @converter = Converters.create(type, options)
9
- end
1
+ require 'enumerator'
2
+ require 'xmlnuts/backend'
3
+ require 'xmlnuts/converters'
10
4
 
11
- def to_xml(nut, node)
12
- setxml(node, toxml(get(nut)))
13
- end
5
+ module XmlNuts
6
+ module Mappings
7
+ class Mapping
8
+ attr_reader :xmlname, :xmlns, :options
14
9
 
15
- def from_xml(nut, node)
16
- set(nut, froxml(getxml(node)))
10
+ def initialize(xmlname, options)
11
+ @xmlname, @xmlns, @options = xmlname.to_s, options.delete(:xmlns), options
12
+ end
17
13
  end
18
14
 
19
- private
20
- def get(nut) #:doc:
21
- nut.send(name)
15
+ class Root < Mapping
16
+ def initialize(xmlname, options = {})
17
+ super
18
+ end
22
19
  end
23
20
 
24
- def set(nut, value) #:doc:
25
- nut.send(@setter, value)
26
- end
21
+ class MemberMapping < Mapping
22
+ include XmlBackend
23
+
24
+ attr_reader :name, :type, :converter
25
+
26
+ def initialize(name, type, options)
27
+ super(options.delete(:xmlname) || name, options)
28
+ case type
29
+ when Array
30
+ raise ArgumentError, "invalid value for type: #{type}" if type.length != 1
31
+ options[:item_type] = type.first
32
+ @converter = Converter.create!(:list, options)
33
+ when Class
34
+ options[:object_type] = type
35
+ else
36
+ @converter = Converter.create!(type, options)
37
+ end
38
+ @name, @setter, @type = name.to_sym, :"#{name}=", type
39
+ end
27
40
 
28
- def toxml(value) #:doc:
29
- value
30
- end
41
+ def to_xml(nut, node)
42
+ setxml(node, get(nut))
43
+ end
31
44
 
32
- def froxml(text) #:doc:
33
- text
34
- end
35
- end
45
+ def from_xml(nut, node)
46
+ set(nut, getxml(node))
47
+ end
36
48
 
37
- class PrimitiveMapping < Mapping
38
- def initialize(name, type, options)
39
- if type.is_a?(Array)
40
- raise ArgumentError, "invalid value for type: #{type}" if type.length != 1
41
- type, options[:item_type] = :list, type.first
49
+ private
50
+ def get(nut)
51
+ nut.send(@name)
42
52
  end
43
- super
44
- raise ArgumentError, "converter absent for type #{type.inspect}" unless converter
45
- end
46
53
 
47
- private
48
- def toxml(value) #:doc:
49
- converter.to_xml(value)
50
- end
54
+ def set(nut, value)
55
+ nut.send(@setter, value)
56
+ end
51
57
 
52
- def froxml(text) #:doc:
53
- converter.from_xml(text)
54
- end
55
- end
58
+ def toxml(value)
59
+ @converter ? @converter.to_xml(value) : value
60
+ end
56
61
 
57
- class ElementMapping < PrimitiveMapping
58
- private
59
- def getxml(node) #:doc:
60
- (e = node.elements[xmlname]) && e.text
62
+ def froxml(text)
63
+ @converter ? @converter.from_xml(text) : text
64
+ end
61
65
  end
62
66
 
63
- def setxml(node, value) #:doc:
64
- (node.elements[xmlname] ||= REXML::Element.new(xmlname)).text = value
65
- end
66
- end
67
+ module NestedMixin #:nodoc:
68
+ private
69
+ def parse(node)
70
+ backend.each_element_with_value(node, xmlname, xmlns) {|el, txt| return type.parse_node(type.new, el) }
71
+ nil
72
+ end
67
73
 
68
- class AttributeMapping < PrimitiveMapping
69
- private
70
- def getxml(node) #:doc:
71
- node.attributes[xmlname]
74
+ def build(node, nut)
75
+ nut && type.build_node(nut, backend.add_element(node, xmlname, xmlns, nil))
76
+ end
72
77
  end
73
78
 
74
- def setxml(node, value) #:doc:
75
- node.add_attribute(xmlname, value)
76
- end
77
- end
79
+ module ElementsMixin #:nodoc:
80
+ private
81
+ def getxml(node)
82
+ node && backend.enum_for(:each_element_with_value, node, xmlname, xmlns).map {|el, v| froxml(v) }
83
+ end
78
84
 
79
- module NestedMany
80
- private
81
- def toxml(nested_nuts) #:doc:
82
- nested_nuts && nested_nuts.map {|x| super(x) }
83
- end
85
+ def setxml(node, values)
86
+ values.each {|x| toxml(node, x) } if values
87
+ end
84
88
 
85
- def froxml(nested_nodes) #:doc:
86
- nested_nodes && nested_nodes.map {|x| super(x) }
89
+ def toxml(value, node)
90
+ super(value)
91
+ end
87
92
  end
88
- end
89
93
 
90
- class ElementsMapping < PrimitiveMapping
91
- include NestedMany
94
+ class ElementValue < MemberMapping
95
+ private
96
+ def getxml(node)
97
+ backend.each_element_with_value(node, xmlname, xmlns) {|e, v| return froxml(v) }
98
+ nil
99
+ end
92
100
 
93
- private
94
- def getxml(node) #:doc:
95
- (e = node.get_elements(xmlname)) && e.map {|x| x.text }
101
+ def setxml(node, value)
102
+ backend.add_element(node, xmlname, xmlns, toxml(value))
103
+ end
96
104
  end
97
105
 
98
- def setxml(node, values) #:doc:
99
- values.each {|x| node.add_element(xmlname).text = x } if values
100
- end
101
- end
106
+ class Element < MemberMapping
107
+ include NestedMixin
102
108
 
103
- class NestedMapping < Mapping
104
- private
105
- def toxml(nested_nut) #:doc:
106
- type.build_node(nested_nut, Element.new(xmlname))
109
+ private
110
+ alias getxml parse
111
+ alias setxml build
107
112
  end
108
113
 
109
- def froxml(nested_node) #:doc:
110
- type.parse_node(type.new, nested_node)
111
- end
112
- end
114
+ class Attribute < MemberMapping
115
+ private
116
+ def getxml(node)
117
+ froxml(backend.attribute(node, xmlname, xmlns))
118
+ end
113
119
 
114
- class NestedOneMapping < NestedMapping
115
- private
116
- def getxml(node) #:doc:
117
- node.elements[xmlname]
120
+ def setxml(node, value)
121
+ backend.set_attribute(node, xmlname, xmlns, toxml(value))
122
+ end
118
123
  end
119
124
 
120
- def setxml(node, nested_node) #:doc:
121
- node.elements << nested_node if nested_node
125
+ class ElementValues < MemberMapping
126
+ include ElementsMixin
122
127
  end
123
- end
124
128
 
125
- class NestedManyMapping < NestedMapping
126
- include NestedMany
127
-
128
- private
129
- def getxml(node) #:doc:
130
- node.get_elements(xmlname)
131
- end
129
+ class Elements < MemberMapping
130
+ include NestedMixin
131
+ include ElementsMixin
132
132
 
133
- def setxml(node, nested_nodes) #:doc:
134
- nested_nodes.each {|x| node.add_element(x) }
133
+ private
134
+ alias froxml parse
135
+ alias toxml build
135
136
  end
136
137
  end
137
138
  end
data/lib/xmlnuts/nuts.rb CHANGED
@@ -1,72 +1,211 @@
1
- require 'rexml/document'
2
- require 'time'
3
- require 'xmlnuts/converters'
4
1
  require 'xmlnuts/mappings'
5
2
 
6
3
  module XmlNuts #:nodoc:
4
+ # See also +ClassMethods+
7
5
  module Nut
6
+ include XmlBackend
7
+
8
8
  def self.included(other) #:nodoc:
9
9
  other.extend(ClassMethods)
10
10
  end
11
11
 
12
+ # See also Nut
12
13
  module ClassMethods
14
+ include XmlBackend
15
+ include Mappings
16
+
17
+ # namespaces(hash) -> Hash
18
+ # namespaces -> Hash
19
+ #
20
+ # Updates and returns class-level prefix mappings.
21
+ # When given a hash of mappings merges it over current.
22
+ # When called withot arguments simply returns current mappings.
23
+ #
24
+ # === Example:
25
+ # class Cat
26
+ # include XmlNuts::Nut
27
+ # namespaces :lol => 'urn:lol', ...
28
+ # ...
29
+ # end
30
+ def namespaces(mappings = nil)
31
+ @namespaces ||= {}
32
+ mappings ? @namespaces.update(mappings) : @namespaces
33
+ end
34
+
35
+ # root(xmlname[, :xmlns => ...]) -> Mappings::Root
36
+ # root -> Mappings::Root
37
+ #
38
+ # Defines element name.
39
+ # TODO: moar details
40
+ #
41
+ # === Arguments
42
+ # +xmlname+:: Element name
43
+ # +options+:: +:xmlns+ => Element namespace
44
+ #
45
+ # === Example:
46
+ # class Cat
47
+ # include XmlNuts::Nut
48
+ # ...
49
+ # root :kitteh, :xmlns => 'urn:lol'
50
+ # ...
51
+ # end
52
+ def root(xmlname = nil, options = {})
53
+ @root = Root.new(xmlname, prepare_options(options)) if xmlname
54
+ @root ||= Root.new('root')
55
+ end
56
+
57
+ # element(name, [type[, options]]) -> Mappings::Element or Mappings::ElementValue
58
+ #
59
+ # Defines single-element mapping.
60
+ #
61
+ # === Arguments
62
+ # +name+:: Accessor name
63
+ # +type+:: Element type. +:string+ assumed if omitted (see +Converter+).
64
+ # +options+:: +:xmlname+, +:xmlns+, converter options (see +Converter+).
65
+ #
66
+ # === Example:
67
+ # class Cat
68
+ # include XmlNuts::Nut
69
+ # ...
70
+ # element :name, :string, :whitespace => :collapse
71
+ # element :cheeseburger, Cheeseburger, :xmlname => :cheezburger
72
+ # ...
73
+ # end
13
74
  def element(name, type = :string, options = {})
14
- mappings << (type.is_a?(Class) ? NestedOneMapping : ElementMapping).new(name, type, options)
15
- attr_accessor name
75
+ define_accessor name
76
+ (mappings << (type.is_a?(Class) ? Element : ElementValue).new(name, type, prepare_options(options))).last
16
77
  end
17
78
 
79
+ # elements(name, [type[, options]]) -> Mappings::Element or Mappings::ElementValue
80
+ #
81
+ # Defines multiple elements mapping.
82
+ #
83
+ # === Arguments
84
+ # +name+:: Accessor name
85
+ # +type+:: Element type. +:string+ assumed if omitted (see +Converter+).
86
+ # +options+:: +:xmlname+, +:xmlns+, converter options (see +Converter+).
87
+ #
88
+ # === Example:
89
+ # class RichCat
90
+ # include XmlNuts::Nut
91
+ # ...
92
+ # elements :ration, :string, :whitespace => :collapse
93
+ # elements :cheeseburgers, Cheeseburger, :xmlname => :cheezburgers
94
+ # ...
95
+ # end
18
96
  def elements(name, type = :string, options = {})
19
- mappings << (type.is_a?(Class) ? NestedManyMapping : ElementsMapping).new(name, type, options)
20
- attr_accessor name
97
+ define_accessor name
98
+ (mappings << (type.is_a?(Class) ? Elements : ElementValues).new(name, type, prepare_options(options))).last
21
99
  end
22
100
 
101
+ # attribute(name, [type[, options]]) -> Mappings::Attribute or Mappings::AttributeValue
102
+ #
103
+ # Defines attribute mapping.
104
+ #
105
+ # === Arguments
106
+ # +name+:: Accessor name
107
+ # +type+:: Element type. +:string+ assumed if omitted (see +Converter+).
108
+ # +options+:: +:xmlname+, +:xmlns+, converter options (see +Converter+).
109
+ #
110
+ # === Example:
111
+ # class Cat
112
+ # include XmlNuts::Nut
113
+ # ...
114
+ # element :name, :string, :whitespace => :collapse
115
+ # element :cheeseburger, Cheeseburger, :xmlname => :cheezburger
116
+ # ...
117
+ # end
23
118
  def attribute(name, type = :string, options = {})
24
- mappings << AttributeMapping.new(name, type, options)
25
- attr_accessor name
119
+ define_accessor name
120
+ mappings << Attribute.new(name, type, prepare_options(options))
26
121
  end
27
122
 
123
+ # mappings -> Array
124
+ #
125
+ # Returns all previously defined XmlNuts mappings on a class.
28
126
  def mappings
29
127
  @mappings ||= []
30
128
  end
31
129
 
32
- def build(nut, destination = nil)
33
- case destination
34
- when nil
35
- destination = REXML::Document.new
36
- e = destination.add_element('root')
37
- build_node(nut, e)
38
- when REXML::Node
39
- build_node(nut, destination)
40
- end
41
- destination
130
+ def parse(source, options = {})
131
+ backend.parse(source, options) {|node| new.parse_node(node) }
42
132
  end
43
133
 
44
- def parse(source)
45
- case source
46
- when nil
47
- nil
48
- when REXML::Node
49
- parse_node(new, source)
50
- when String
51
- doc = REXML::Document.new(source)
52
- (root = doc.root) ? parse_node(new, root) : nil
53
- end
54
- end
55
-
56
- def build_node(nut, node)
134
+ def build_node(nut, node) #:nodoc:
135
+ backend.add_namespaces(node, namespaces)
57
136
  callem(:to_xml, nut, node)
58
137
  node
59
138
  end
60
139
 
61
- def parse_node(nut, node)
62
- callem(:from_xml ,nut, node)
140
+ def parse_node(nut, node) #:nodoc:
141
+ callem(:from_xml, nut, node)
63
142
  nut
64
143
  end
65
144
 
66
145
  private
67
- def callem(method, nut, node)
68
- mappings.each {|m| m.send(method, nut, node) }
146
+ def prepare_options(options)
147
+ ns = options[:xmlns]
148
+ if ns.is_a?(Symbol)
149
+ raise ArgumentError, "undefined prefix: #{ns}" unless options[:xmlns] = namespaces[ns]
150
+ end
151
+ options
69
152
  end
153
+
154
+ def define_accessor(name)
155
+ if method_defined?(name) || method_defined?("#{name}=")
156
+ raise ArgumentError, "#{name}: name already defined or reserved"
157
+ end
158
+ attr_accessor name
159
+ end
160
+
161
+ def callem(method, *args)
162
+ mappings.each {|m| m.send(method, *args) }
163
+ end
164
+ end
165
+
166
+ def parse(source, options = {})
167
+ backend.parse(source, options) {|node| parse_node(node) }
168
+ end
169
+
170
+ # build([options]) -> root element or string
171
+ # build([options]) -> root element or string
172
+ # build(destination[, options]) -> destination
173
+ #
174
+ # Defines attribute mapping.
175
+ #
176
+ # === Arguments
177
+ # +destination+:: Can be given a symbol a backend-specific object,
178
+ # an instance of String or IO classes.
179
+ # - +:string+ -> will return an XML string.
180
+ # - +:document+ -> will return a backend specific document object.
181
+ # - +:object+ -> will return a backend specific object. New document will be created.
182
+ # - an instance of +String+: the contents of the string will be replaced with
183
+ # the generated XML.
184
+ # - an instance of +IO+: the IO will be written to.
185
+ # +options+:: Backend-specific options
186
+ #
187
+ # === Example:
188
+ # cat = Cat.new
189
+ # cat.name = 'Pussy'
190
+ # puts cat.build
191
+ # ...
192
+ # doc = REXML::Document.new
193
+ # cat.build(doc)
194
+ # puts doc.to_s
195
+ def build(result = :string, options = {})
196
+ options, result = result, :string if result.is_a?(Hash)
197
+ root = self.class.root
198
+ options[:xmlname] ||= root.xmlname
199
+ options[:xmlns_prefix] = self.class.namespaces.invert[options[:xmlns] ||= root.xmlns]
200
+ backend.build(result, options) {|node| build_node(node) }
201
+ end
202
+
203
+ def parse_node(node) #:nodoc:
204
+ self.class.parse_node(self, node)
205
+ end
206
+
207
+ def build_node(node) #:nodoc:
208
+ self.class.build_node(self, node)
70
209
  end
71
210
  end
72
211
  end
@@ -0,0 +1,94 @@
1
+ require 'rexml/document'
2
+ require 'xmlnuts/backend'
3
+
4
+ class XmlNuts::XmlBackend::REXMLBackend #:nodoc:
5
+ def parse(source, options)
6
+ case source
7
+ when nil
8
+ return nil
9
+ when REXML::Document
10
+ node = source.root
11
+ when REXML::Node
12
+ node = source
13
+ when String, IO
14
+ node = REXML::Document.new(source).root
15
+ else
16
+ raise ArgumentError, 'invalid destination'
17
+ end
18
+ node && yield(node)
19
+ end
20
+
21
+ def build(result, options)
22
+ case result
23
+ when :string, :document, :object, String, IO
24
+ doc = REXML::Document.new
25
+ when REXML::Document
26
+ doc = result
27
+ when REXML::Node
28
+ node, doc = result, result.document
29
+ else
30
+ raise ArgumentError, 'invalid destination'
31
+ end
32
+ node ||= doc.root
33
+ unless node
34
+ name, ns, prefix = options[:xmlname], options[:xmlns], options[:xmlns_prefix]
35
+ name, ns = "#{prefix}:#{name}", nil if prefix
36
+ node = add_element(doc, name, ns, nil)
37
+ end
38
+
39
+ yield node
40
+
41
+ case result
42
+ when :string
43
+ doc.to_s
44
+ when String
45
+ result.replace(doc.to_s)
46
+ when IO
47
+ doc.write(result)
48
+ result
49
+ when REXML::Document, :document
50
+ doc
51
+ when REXML::Node, :object
52
+ node
53
+ end
54
+ end
55
+
56
+ def add_namespaces(context, namespaces)
57
+ namespaces.each {|prefix, uri| context.add_namespace(prefix.to_s, uri) }
58
+ end
59
+
60
+ def each_element_with_value(context, name, ns)
61
+ ns = context.namespace unless ns
62
+ REXML::XPath.each(context, "ns:#{name}", 'ns' => ns) {|el| yield el, el.text }
63
+ end
64
+
65
+ def attribute(context, name, ns)
66
+ name, ns = to_prefixed_name(context, name, ns, true)
67
+ context.attributes[name]
68
+ end
69
+
70
+ def set_attribute(context, name, ns, text)
71
+ name, ns = to_prefixed_name(context, name, ns, true)
72
+ context.add_attribute(name, text)
73
+ end
74
+
75
+ def add_element(context, name, ns, text)
76
+ name, ns = to_prefixed_name(context, name, ns, false)
77
+ elem = context.add_element(name)
78
+ elem.add_namespace(ns) if ns
79
+ elem.text = text if text
80
+ elem
81
+ end
82
+
83
+ private
84
+ def to_prefixed_name(context, name, ns, prefix_required)
85
+ if ns
86
+ if prefix = context.namespaces.invert[ns]
87
+ name, ns = "#{prefix}:#{name}", nil
88
+ else
89
+ raise ArgumentError, "no prefix defined for #{ns}" if prefix_required
90
+ end
91
+ end
92
+ return name, ns
93
+ end
94
+ end
data/lib/xmlnuts.rb CHANGED
@@ -1 +1,48 @@
1
1
  require 'xmlnuts/nuts'
2
+
3
+ #class Cheezburger
4
+ # include XmlNuts::Nut
5
+ #
6
+ # attribute :weight, :integer
7
+ #end
8
+ #
9
+ #class Pet
10
+ # include XmlNuts::Nut
11
+ #
12
+ # namespaces :pipi => 'a', :piz => 'b'
13
+ #
14
+ # root 'anus', :xmlns => :piz
15
+ #
16
+ # element :eats, [:string], :xmlname => :ration, :xmlns => 'a'
17
+ # element :species, :string, :whitespace => :collapse
18
+ # elements :paws, :string, :xmlname => :paw
19
+ #
20
+ # attribute :has_tail, :boolean, :xmlname => 'has-tail', :xmlns => 'b'
21
+ # attribute :height, :integer
22
+ #
23
+ # element :cheezburger, Cheezburger
24
+ #end
25
+ #
26
+ #xml_fragment = <<-EOS
27
+ # <mypet xmlns='lol' xmlns:pizda="b" height=' 12 ' pizda:has-tail=' yes '>
28
+ # <species>
29
+ #silly
30
+ # mouse
31
+ # </species>
32
+ # <pi:ration xmlns:pi="a">
33
+ # tigers
34
+ # lions
35
+ # </pi:ration>
36
+ # <paw> one</paw>
37
+ # <paw> two </paw>
38
+ # <paw>three</paw>
39
+ # <paw>four</paw>
40
+ # <cheezburger weight='2'>
41
+ # </cheezburger>
42
+ # <cub age='4'>
43
+ # </cub>
44
+ # </mypet>
45
+ #EOS
46
+ #pet = Pet.parse(xml_fragment)
47
+ #
48
+ #puts pet.build
data/test/parsing_test.rb CHANGED
@@ -10,30 +10,35 @@ class Cheezburger
10
10
  attribute :weight, :integer
11
11
  end
12
12
 
13
- class Pet
13
+ class Cat
14
14
  include XmlNuts::Nut
15
15
 
16
- element :eats, [:string], :xmlname => :ration
17
- element :species, :string, :whitespace => :collapse
16
+ namespaces :lol => 'urn:lol', :p => 'b'
17
+
18
+ root 'kitteh', :xmlns => 'lol'
19
+
20
+ element :eats, [:string], :xmlname => :ration, :xmlns => :lol
21
+ element :friend, :string, :whitespace => :collapse, :xmlns => 'c'
18
22
  elements :paws, :string, :xmlname => :paw
19
23
 
20
- attribute :has_tail, :boolean, :xmlname => 'has-tail'
24
+ attribute :has_tail, :boolean, :xmlname => 'has-tail', :xmlns => 'b'
21
25
  attribute :height, :integer
22
26
 
23
27
  element :cheezburger, Cheezburger
24
28
  end
25
29
 
26
30
  class ParsingTest < Test::Unit::TestCase
27
- context "Old McDonald's pet" do
28
- setup do
29
- @xml_fragment = <<-EOS
30
- <mypet height=' 12 ' has-tail=' yes '>
31
- <species> silly
31
+ def setup
32
+ @xml_fragment = <<-EOS
33
+ <mypet xmlns='lol' xmlns:aa='urn:lol' xmlns:bb='b' height=' 12 ' bb:has-tail=' yes '>
34
+ <friend xmlns='c'>
35
+ silly
32
36
  mouse
33
- </species>
34
- <ration> tigers
35
- lions
36
- </ration>
37
+ </friend>
38
+ <aa:ration>
39
+ tigers
40
+ lions
41
+ </aa:ration>
37
42
  <paw> one</paw>
38
43
  <paw> two </paw>
39
44
  <paw>three</paw>
@@ -43,43 +48,45 @@ class ParsingTest < Test::Unit::TestCase
43
48
  <cub age='4'>
44
49
  </cub>
45
50
  </mypet>
46
- EOS
47
- @pet = Pet.parse(@xml_fragment)
48
- end
51
+ EOS
52
+ @cat = Cat.parse(@xml_fragment)
53
+ end
49
54
 
50
- should 'be a silly mouse' do
51
- assert_equal 'silly mouse', @pet.species
55
+ context "A cat" do
56
+ should 'be a friend of a silly mouse' do
57
+ assert_equal 'silly mouse', @cat.friend
52
58
  end
53
59
 
54
60
  should 'eat tigers and lions' do
55
- assert_equal ['tigers', 'lions'], @pet.eats
61
+ assert_equal ['tigers', 'lions'], @cat.eats
56
62
  end
57
63
 
58
64
  should 'be 12 meters tall' do
59
- assert_equal 12, @pet.height
65
+ assert_equal 12, @cat.height
60
66
  end
61
67
 
62
68
  should 'have tail' do
63
- assert_equal true, @pet.has_tail
69
+ assert_equal true, @cat.has_tail
64
70
  end
65
71
 
66
72
  should 'have four paws' do
67
- assert_not_nil @pet.paws
68
- assert_equal 4, @pet.paws.length
69
- assert_equal %w(one two three four), @pet.paws
73
+ assert_not_nil @cat.paws
74
+ assert_equal 4, @cat.paws.length
75
+ assert_equal %w(one two three four), @cat.paws
76
+ end
77
+
78
+ should 'has cheezburger' do
79
+ assert_kind_of Cheezburger, @cat.cheezburger
80
+ end
81
+ end
82
+
83
+ context 'A cheezburger' do
84
+ setup do
85
+ @burger = @cat.cheezburger
70
86
  end
71
87
 
72
- context 'should has cheezburger' do
73
- setup do
74
- assert_not_nil @burger = @pet.cheezburger
75
- assert_kind_of Cheezburger, @pet.cheezburger
76
- end
77
-
78
- context 'that' do
79
- should 'weigh 2 kg' do
80
- assert_equal 2, @burger.weight
81
- end
82
- end
88
+ should 'weigh 2 kg' do
89
+ assert_equal 2, @burger.weight
83
90
  end
84
91
  end
85
92
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pipa-xmlnuts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Gunko
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-14 00:00:00 -08:00
12
+ date: 2008-12-16 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -29,6 +29,8 @@ files:
29
29
  - lib/xmlnuts/nuts.rb
30
30
  - lib/xmlnuts/mappings.rb
31
31
  - lib/xmlnuts/converters.rb
32
+ - lib/xmlnuts/backend.rb
33
+ - lib/xmlnuts/rexml.rb
32
34
  has_rdoc: true
33
35
  homepage: http://github.com/pipa/xmlnuts
34
36
  post_install_message: