pipa-xmlnuts 0.0.2 → 0.0.5

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.
@@ -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: