xmlable 0.0.0.alpha1
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +245 -0
- data/lib/xmlable/attribute.rb +16 -0
- data/lib/xmlable/builder.rb +189 -0
- data/lib/xmlable/document.rb +16 -0
- data/lib/xmlable/element.rb +19 -0
- data/lib/xmlable/exports/base.rb +78 -0
- data/lib/xmlable/exports/json_exporter.rb +208 -0
- data/lib/xmlable/exports/xml_exporter.rb +179 -0
- data/lib/xmlable/exports.rb +11 -0
- data/lib/xmlable/handlers/attribute.rb +41 -0
- data/lib/xmlable/handlers/attribute_none.rb +10 -0
- data/lib/xmlable/handlers/base.rb +103 -0
- data/lib/xmlable/handlers/document.rb +33 -0
- data/lib/xmlable/handlers/element.rb +89 -0
- data/lib/xmlable/handlers/element_none.rb +10 -0
- data/lib/xmlable/handlers/elements.rb +15 -0
- data/lib/xmlable/handlers/mixins/described.rb +19 -0
- data/lib/xmlable/handlers/mixins/namespace.rb +40 -0
- data/lib/xmlable/handlers/mixins/tag.rb +24 -0
- data/lib/xmlable/handlers/namespace.rb +26 -0
- data/lib/xmlable/handlers/root.rb +9 -0
- data/lib/xmlable/handlers/root_none.rb +10 -0
- data/lib/xmlable/handlers/storage.rb +104 -0
- data/lib/xmlable/handlers.rb +23 -0
- data/lib/xmlable/mixins/attributes_storage.rb +195 -0
- data/lib/xmlable/mixins/bare_value.rb +41 -0
- data/lib/xmlable/mixins/castable.rb +93 -0
- data/lib/xmlable/mixins/container.rb +71 -0
- data/lib/xmlable/mixins/content_storage.rb +138 -0
- data/lib/xmlable/mixins/document_storage.rb +136 -0
- data/lib/xmlable/mixins/elements_storage.rb +219 -0
- data/lib/xmlable/mixins/export.rb +45 -0
- data/lib/xmlable/mixins/instantiable.rb +47 -0
- data/lib/xmlable/mixins/namespace_definitions_storage.rb +105 -0
- data/lib/xmlable/mixins/object.rb +95 -0
- data/lib/xmlable/mixins/options_storage.rb +39 -0
- data/lib/xmlable/mixins/root_storage.rb +162 -0
- data/lib/xmlable/mixins/standalone_attribute.rb +34 -0
- data/lib/xmlable/mixins/standalone_element.rb +47 -0
- data/lib/xmlable/mixins/value_storage.rb +84 -0
- data/lib/xmlable/mixins/wrapper.rb +37 -0
- data/lib/xmlable/mixins.rb +25 -0
- data/lib/xmlable/options/nokogiri_export.rb +19 -0
- data/lib/xmlable/options/storage.rb +97 -0
- data/lib/xmlable/options.rb +9 -0
- data/lib/xmlable/types.rb +31 -0
- data/lib/xmlable/version.rb +4 -0
- data/lib/xmlable.rb +49 -0
- metadata +149 -0
@@ -0,0 +1,138 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Mixins
|
3
|
+
#
|
4
|
+
# ContentStorage module contains the logic that helps to store XML element
|
5
|
+
# content.
|
6
|
+
#
|
7
|
+
module ContentStorage
|
8
|
+
def self.included(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Set XML element content
|
14
|
+
#
|
15
|
+
# @param [Nokogiri::XML::Element] node
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def __set_content(node)
|
20
|
+
val = node.children.select(&:text?).map(&:content).join('').strip
|
21
|
+
@__content = __cast(val)
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Override XML node content
|
26
|
+
#
|
27
|
+
# @param [Object] value
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
#
|
31
|
+
def __overwrite_content(val)
|
32
|
+
val = __cast(val)
|
33
|
+
@__node.content = __export_to_xml(val)
|
34
|
+
@__content = val
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Get content value
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
# @return [Object]
|
43
|
+
#
|
44
|
+
def __object
|
45
|
+
__content
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Get content value
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
# @return [Object]
|
54
|
+
#
|
55
|
+
def __content
|
56
|
+
@__content
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Set content value
|
61
|
+
#
|
62
|
+
# @param [Object] value
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
#
|
66
|
+
# @return [Object]
|
67
|
+
#
|
68
|
+
def __content=(val)
|
69
|
+
__overwrite_content(val)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Is this element?
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
#
|
77
|
+
# @return [Boolean]
|
78
|
+
#
|
79
|
+
def __empty?
|
80
|
+
return false unless super
|
81
|
+
__empty(__content)
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
#
|
87
|
+
def to_s
|
88
|
+
__content.to_s
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Get content alias method
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
#
|
96
|
+
# @return [String, nil]
|
97
|
+
#
|
98
|
+
def __content_method
|
99
|
+
self.class.__content_method
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Contents methods
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
#
|
107
|
+
# @return [Array<String>]
|
108
|
+
#
|
109
|
+
def __content_methods
|
110
|
+
ret = ['__content']
|
111
|
+
ret << __content_method.to_s if __content_method
|
112
|
+
ret
|
113
|
+
end
|
114
|
+
|
115
|
+
module ClassMethods
|
116
|
+
#
|
117
|
+
# Define content method
|
118
|
+
# If given +false+ name than content isn't available to this element.
|
119
|
+
#
|
120
|
+
# @param [String, Symbol, false] name
|
121
|
+
#
|
122
|
+
def content(name)
|
123
|
+
@__content_method = name.is_a?(String) ? name.to_sym : name
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Get content method
|
128
|
+
#
|
129
|
+
# @return [String, nil, false]
|
130
|
+
#
|
131
|
+
def __content_method
|
132
|
+
return @__content_method if instance_variable_defined?(:@__content_method)
|
133
|
+
@__content_method = __nested(:@__content_method)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Mixins
|
3
|
+
#
|
4
|
+
# DocumentStorage module contains the logic to work with XML document
|
5
|
+
#
|
6
|
+
module DocumentStorage
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# @param [Hash] args document initial params
|
13
|
+
# @param [Nokogiri::XML::Document] doc XML document
|
14
|
+
# @param [XMLable::Handlers::Document] handler document's handler
|
15
|
+
#
|
16
|
+
def initialize(args = {}, doc = nil, handler = nil)
|
17
|
+
doc ||= Nokogiri::XML::Document.new
|
18
|
+
handler ||= Handlers::Document.new(self.class)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Get XML document version
|
24
|
+
#
|
25
|
+
# @return [String, nil]
|
26
|
+
#
|
27
|
+
def version
|
28
|
+
__node.version
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Get XML document encoding
|
33
|
+
#
|
34
|
+
# @return [String, nil]
|
35
|
+
#
|
36
|
+
def encoding
|
37
|
+
__node.encoding
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Get document's handler
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
#
|
45
|
+
# @return [XMLable::Handlers::Document]
|
46
|
+
#
|
47
|
+
def __document_handler
|
48
|
+
self.class.__document_handler
|
49
|
+
end
|
50
|
+
|
51
|
+
module ClassMethods
|
52
|
+
#
|
53
|
+
# Define document params
|
54
|
+
#
|
55
|
+
# @param [Hash] opts
|
56
|
+
#
|
57
|
+
def document(opts = {})
|
58
|
+
opt(opts) if opts.size > 0
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Set the Nokogiri's parsing params
|
63
|
+
#
|
64
|
+
def nokogiri_parse(*args)
|
65
|
+
args.each do |opt|
|
66
|
+
__nokogiri_parse_options.send(opt) if __nokogiri_parse_options.respond_to?(opt)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Set the Nokogiri's export params
|
72
|
+
#
|
73
|
+
def nokogiri_export(*args)
|
74
|
+
__nokogiri_export_options.tap do |opts|
|
75
|
+
opts.merge!(args.pop) if args.last.is_a?(Hash)
|
76
|
+
args.each { |opt| opts.save_with.send(opt) if opts.save_with.respond_to?(opt) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Nokogiri's options for parsing
|
82
|
+
#
|
83
|
+
# @api private
|
84
|
+
#
|
85
|
+
# @return [Nokogiri::XML::ParseOptions]
|
86
|
+
#
|
87
|
+
def __nokogiri_parse_options
|
88
|
+
@__nokogiri_parse_options ||= Nokogiri::XML::ParseOptions.new.recover
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Nokogiri's options for exporting
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
#
|
96
|
+
# @return [Nokogiri::XML::ParseOptions]
|
97
|
+
#
|
98
|
+
def __nokogiri_export_options
|
99
|
+
@__nokogiri_export_options ||= Options::NokogiriExport.new
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Get document's handler
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
#
|
107
|
+
# @return [XMLable::Handlers::Document]
|
108
|
+
#
|
109
|
+
def __document_handler
|
110
|
+
@__document_handler ||= Handlers::Document.new(self)
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Initialize document from XML
|
115
|
+
#
|
116
|
+
# @param [Nokogiri::XML::Document, String] xml
|
117
|
+
# @param [Hash] _opts
|
118
|
+
#
|
119
|
+
# @return [XMLable::Document]
|
120
|
+
#
|
121
|
+
def from_xml(xml, _opts = {})
|
122
|
+
xml = '' unless xml
|
123
|
+
if xml.is_a?(String)
|
124
|
+
doc = Nokogiri::XML(xml) do |config|
|
125
|
+
config.options = __nokogiri_parse_options.to_i
|
126
|
+
end
|
127
|
+
elsif xml.is?(Nokogiri::XML::Document)
|
128
|
+
doc = xml
|
129
|
+
else raise "Don't know how to parse '#{xml.class}'"
|
130
|
+
end
|
131
|
+
__document_handler.from_xml_document(doc)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Mixins
|
3
|
+
#
|
4
|
+
# ElementsStorage module contains the logic to store XML elements
|
5
|
+
#
|
6
|
+
module ElementsStorage
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Set element from XML Node
|
13
|
+
#
|
14
|
+
# @param [Symbol] name tag name
|
15
|
+
# @param [Nokogiri::XML::Element, nil] el
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def __set_element(el, opts = {})
|
20
|
+
unless el.is_a?(Nokogiri::XML::Element)
|
21
|
+
el = Nokogiri::XML::Element.new(opts[:tag], @__node)
|
22
|
+
@__node << el
|
23
|
+
if opts[:namespace]
|
24
|
+
el.namespace = el.namespace_scopes.find { |n| n.prefix == opts[:namespace] }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
h = __elements_handlers.for_xml_object(el)
|
28
|
+
el.instance_variable_set(:@__handler, h)
|
29
|
+
__initialize_elements_container(h) << h.from_xml_element(el)
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Initialize elements container
|
34
|
+
#
|
35
|
+
# @param [XMLable::Handlers::Element, XMLable::Handlers::Elements, XMLable::Handlers::ElementNone] h
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
#
|
39
|
+
# @return [XMLable::Mixins::Container]
|
40
|
+
#
|
41
|
+
def __initialize_elements_container(h)
|
42
|
+
__elements[h.key] ||= h.container_for_xml_element(__node)
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Elements which current object holds
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
#
|
50
|
+
# @return [Hash(String => Array<XMLable::Mixins::Object>)]
|
51
|
+
#
|
52
|
+
def __elements
|
53
|
+
@__elements ||= {}
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Is this object empty?
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
#
|
63
|
+
def __empty?
|
64
|
+
return false unless super
|
65
|
+
__elements.values.all?(&:__empty?)
|
66
|
+
end
|
67
|
+
|
68
|
+
def method_missing(name, *args, &blocks)
|
69
|
+
h = __has_element_handler?(name)
|
70
|
+
return super unless h
|
71
|
+
|
72
|
+
if name.to_s.end_with?('=')
|
73
|
+
__element_object_set(h, args.first)
|
74
|
+
else
|
75
|
+
__element_object_get(h)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Elements handlers storage
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
#
|
84
|
+
# @return [XMLable::Handlers::Storage]
|
85
|
+
#
|
86
|
+
def __elements_handlers
|
87
|
+
@__elements_handler ||= self.class.__elements_handlers.clone
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Does this object contain element with given key?
|
92
|
+
#
|
93
|
+
# @return [XMLable::Mixins::Object, false]
|
94
|
+
#
|
95
|
+
def key?(key)
|
96
|
+
super || __has_element_handler?(key)
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Get element object by its key
|
101
|
+
#
|
102
|
+
# @param [String] key element key
|
103
|
+
#
|
104
|
+
# @return [XMLable::Mixins::Object, nil]
|
105
|
+
#
|
106
|
+
def [](key)
|
107
|
+
h = __has_element_handler?(key)
|
108
|
+
h ? __element_object_get(h) : super
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Set element value
|
113
|
+
#
|
114
|
+
# @param [String] key element key
|
115
|
+
# @param [Object] val new value
|
116
|
+
#
|
117
|
+
# @return [XMLable::Mixins::Object, nil]
|
118
|
+
#
|
119
|
+
def []=(key, val)
|
120
|
+
h = __has_element_handler?(key)
|
121
|
+
h ? __element_object_set(h, val) : super
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Find element handler by its key
|
126
|
+
#
|
127
|
+
# @param [Symbol, String] key
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
#
|
131
|
+
# @return [XMLable::Handlers::Element, XMLable::Handlers::ElementNone, nil]
|
132
|
+
#
|
133
|
+
def __has_element_handler?(key)
|
134
|
+
key = key.to_s.gsub(/[=!]$/, '')
|
135
|
+
__elements_handlers.storage.find { |h| h.method_name == key }
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Get element object
|
140
|
+
#
|
141
|
+
# @param [XMLable::Handlers::Element, XMLable::Handlers::Elements, XMLable::Handlers::ElementNone] h
|
142
|
+
#
|
143
|
+
# @api private
|
144
|
+
#
|
145
|
+
# @return [XMLable::Mixins::Object]
|
146
|
+
#
|
147
|
+
def __element_object_get(h)
|
148
|
+
unless __elements.key?(h.key)
|
149
|
+
if h.single?
|
150
|
+
__set_element(nil, tag: h.tag, namespace: h.namespace_prefix)
|
151
|
+
else
|
152
|
+
__initialize_elements_container(h)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
ret = __elements[h.key]
|
156
|
+
h.single? ? ret.first : ret
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
# Set element object value
|
161
|
+
#
|
162
|
+
# @param [XMLable::Handlers::Element, XMLable::Handlers::Elements, XMLable::Handlers::ElementNone] h
|
163
|
+
# @param [Object] val
|
164
|
+
#
|
165
|
+
# @api private
|
166
|
+
#
|
167
|
+
# @return [XMLable::Mixins::Object]
|
168
|
+
#
|
169
|
+
def __element_object_set(h, val)
|
170
|
+
__element_object_get(h).__overwrite_content(val)
|
171
|
+
end
|
172
|
+
|
173
|
+
#
|
174
|
+
# Set element object value
|
175
|
+
#
|
176
|
+
# @param [XMLable::Handlers::Element, XMLable::Handlers::Elements, XMLable::Handlers::ElementNone] h
|
177
|
+
# @param [Object] val
|
178
|
+
#
|
179
|
+
# @api private
|
180
|
+
#
|
181
|
+
def __element_object_initialize(h, val)
|
182
|
+
obj = __element_object_get(h)
|
183
|
+
|
184
|
+
val = { '__content' => val } unless val.respond_to?(:each)
|
185
|
+
if h.single?
|
186
|
+
obj.__initialize_with(val)
|
187
|
+
else
|
188
|
+
val.map { |v| obj.new(v) }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
module ClassMethods
|
193
|
+
|
194
|
+
#
|
195
|
+
# Elements handlers storage
|
196
|
+
#
|
197
|
+
# @api private
|
198
|
+
#
|
199
|
+
# @return [XMLable::Handlers::Storage]
|
200
|
+
#
|
201
|
+
def __elements_handlers
|
202
|
+
@__elements_handlers ||=
|
203
|
+
__nested(:@__elements_handlers) || Handlers::Storage.new(default: Handlers::ElementNone)
|
204
|
+
end
|
205
|
+
|
206
|
+
%i[element elements].each do |m|
|
207
|
+
define_method m do |*args, &block|
|
208
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
209
|
+
if __default_namespace && !opts.key?(:namespace)
|
210
|
+
opts[:namespace] = __default_namespace
|
211
|
+
end
|
212
|
+
h = XMLable::Handlers.const_get(__method__.to_s.capitalize).build(*args, opts, &block)
|
213
|
+
__elements_handlers << h
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Mixins
|
3
|
+
#
|
4
|
+
# Export modules contains method to export
|
5
|
+
#
|
6
|
+
module Export
|
7
|
+
#
|
8
|
+
# Export to XML
|
9
|
+
#
|
10
|
+
# @param [Hash] opts
|
11
|
+
#
|
12
|
+
# @return [String] returns exported XML
|
13
|
+
#
|
14
|
+
def to_xml(opts = {})
|
15
|
+
exporter = Exports::XMLExporter.new(self, opts)
|
16
|
+
opts = self.class.__nokogiri_export_options.merge(opts)
|
17
|
+
exporter.export.to_xml(opts).strip
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Export to JSON
|
22
|
+
#
|
23
|
+
# @param [Hash] opts
|
24
|
+
# @option opts [Boolean] :pretty enable pretty print
|
25
|
+
#
|
26
|
+
# @return [String] returns exported JSON
|
27
|
+
#
|
28
|
+
def to_json(opts = {})
|
29
|
+
ret = to_h(opts)
|
30
|
+
opts[:pretty] ? JSON.pretty_generate(ret) : ret.to_json
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Export to hash
|
35
|
+
#
|
36
|
+
# @param [Hash] opts
|
37
|
+
#
|
38
|
+
# @return [Hash]
|
39
|
+
#
|
40
|
+
def to_h(opts = {})
|
41
|
+
Exports::JSONExporter.new(self, opts).export
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Mixins
|
3
|
+
#
|
4
|
+
# Instantiable module contains the logic to initialize the new elements
|
5
|
+
#
|
6
|
+
module Instantiable
|
7
|
+
#
|
8
|
+
# @param [Object] items initial params
|
9
|
+
# @param [Nokogiri::XML::Node] node
|
10
|
+
# @param [XMLable::Handlers::Base] handler
|
11
|
+
#
|
12
|
+
def initialize(items = nil, node = nil, handler = nil)
|
13
|
+
super(node, handler)
|
14
|
+
__initialize_with(items) if items
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Initialize object with given value
|
19
|
+
#
|
20
|
+
# @param [Object] value
|
21
|
+
#
|
22
|
+
def __initialize_with(value)
|
23
|
+
if value.is_a?(Hash)
|
24
|
+
value.each do |key, val|
|
25
|
+
if respond_to?(:__overwrite_content) && __content_methods.include?(key.to_s)
|
26
|
+
next __overwrite_content(val)
|
27
|
+
end
|
28
|
+
|
29
|
+
h = key?(key)
|
30
|
+
case h
|
31
|
+
when Handlers::Attribute then __attribute_object_initialize(h, val)
|
32
|
+
when Handlers::Root then __root_object_initialize(h, val)
|
33
|
+
when Handlers::Element then __element_object_initialize(h, val)
|
34
|
+
else raise h.inspect
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
case __handler
|
39
|
+
when Handlers::Attribute then __overwrite_value(value)
|
40
|
+
when Handlers::Element then __overwrite_content(value)
|
41
|
+
else raise h.inspect
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Mixins
|
3
|
+
#
|
4
|
+
# NamespaceDefinitionsStorage module contains the logic to manage with XML
|
5
|
+
# namespaces definitions
|
6
|
+
#
|
7
|
+
module NamespaceDefinitionsStorage
|
8
|
+
def self.included(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# @see XMLable::Mixins::Object#initialize
|
14
|
+
#
|
15
|
+
def initialize(*)
|
16
|
+
super
|
17
|
+
__define_namespaces(__namespace_definitions)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Define XML namespaces
|
22
|
+
#
|
23
|
+
# @param [Array<XMLable::Handlers::Namespace>] handlers
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def __define_namespaces(handlers)
|
28
|
+
handlers.each do |h|
|
29
|
+
next if __node.namespace_scopes.find { |ns| ns.prefix == h.prefix }
|
30
|
+
__node.add_namespace_definition(h.prefix ? h.prefix.to_s : nil, h.href)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Set XML namespace
|
36
|
+
#
|
37
|
+
# @param [Nokogiri::XML::Namespace] ns
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
#
|
41
|
+
def __set_namespace_definition(ns)
|
42
|
+
__namespace_definitions << ns
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Get namespace definition handlers
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
#
|
50
|
+
# @return [XMLable::Handlers::Storage]
|
51
|
+
#
|
52
|
+
def __namespace_definitions
|
53
|
+
@__namespace_definitions ||= self.class.__namespace_definitions.clone
|
54
|
+
end
|
55
|
+
|
56
|
+
module ClassMethods
|
57
|
+
#
|
58
|
+
# Define XML namespace
|
59
|
+
#
|
60
|
+
# @see XMLable::Handlers::Base#build
|
61
|
+
#
|
62
|
+
def namespace(*args)
|
63
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
64
|
+
default = opts.delete(:default) || true
|
65
|
+
h = Handlers::Namespace.new(*args, opts)
|
66
|
+
self.__default_namespace = h.prefix if default
|
67
|
+
__namespace_definitions << h
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Default namespace prefix
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
# @return [Symbol, nil]
|
76
|
+
#
|
77
|
+
def __default_namespace
|
78
|
+
@__default_namespace
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Set default namespace prefix
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
#
|
86
|
+
# @param [Symbol, nil]
|
87
|
+
#
|
88
|
+
def __default_namespace=(val)
|
89
|
+
@__default_namespace = val
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Get namespace definition handlers
|
94
|
+
#
|
95
|
+
# @api private
|
96
|
+
#
|
97
|
+
# @return [XMLable::Handlers::Storage]
|
98
|
+
#
|
99
|
+
def __namespace_definitions
|
100
|
+
@__namespace_definitions ||= []
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|