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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8dac25c2580eed75d306634e799b8dc03d104da5
|
4
|
+
data.tar.gz: f764b71e734d47c4505e89c4b065ac5ba03b743a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 27a75c87ddd0b08449cd2e0e1da18885aec9b3dbfe113b1cfc6236d1e8e3afd23676aafabcae610eeac48b2525811ab1723c10c3b35e763c446b71e6bee8a4f3
|
7
|
+
data.tar.gz: 0203c91ea3564b0ee5d590bbc5f6ad38785e3943046a30c88e0c131105ca2e94b942bbd0ae6eaa5d25ecd8e854aef074ffbe33942c04952d91522ef18208ceed
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Oleg Yashchuk
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
# XMLable
|
2
|
+
[](https://travis-ci.org/zoer/lexer)
|
3
|
+
[](https://codeclimate.com/github/zoer/xmlable)
|
4
|
+
[](https://www.versioneye.com/ruby/xmlable)
|
5
|
+
[](http://inch-ci.org/github/zoer/xmlable)
|
6
|
+
[](http://badge.fury.io/rb/xmlable)
|
7
|
+
|
8
|
+
XMLable provides an ability to convert XML to Ruby object and back.
|
9
|
+
|
10
|
+
This probject is in active development and isn't ready for production yet.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'xmlable'
|
18
|
+
```
|
19
|
+
|
20
|
+
## Examples
|
21
|
+
|
22
|
+
### Basic usage
|
23
|
+
```ruby
|
24
|
+
# Describe XML structure
|
25
|
+
class Catalog
|
26
|
+
include XMLable::Document
|
27
|
+
|
28
|
+
root :catalog do
|
29
|
+
attribute :date, Date
|
30
|
+
element :size, Integer
|
31
|
+
elements :items, tag: 'item' do
|
32
|
+
attribute :position, Integer
|
33
|
+
element :title
|
34
|
+
element :desc, tag: 'description'
|
35
|
+
element :amount, Integer
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
xml = <<-XML
|
41
|
+
<?xml version="1.0"?>
|
42
|
+
<catalog date="2014-12-20">
|
43
|
+
<size>10</size>
|
44
|
+
<item position="1">
|
45
|
+
<title>Sumac Shoes</title>
|
46
|
+
<description>Capture the beauty</description>
|
47
|
+
<amount>3</amount>
|
48
|
+
</item>
|
49
|
+
<item position="2">
|
50
|
+
<title>Channing Oxford Shoes</title>
|
51
|
+
<description>Hand finished with a wash of color</description>
|
52
|
+
</item>
|
53
|
+
</catalog>
|
54
|
+
XML
|
55
|
+
|
56
|
+
doc = Catalog.from_xml(xml)
|
57
|
+
doc.catalog.date # => #<Date: 2014-12-20 ((2457012j,0s,0n),+0s,2299161j)>
|
58
|
+
doc.catalog.size # => 10
|
59
|
+
doc.catalog.items.size # => 2
|
60
|
+
doc.catalog.items[0].title # => "Sumac Shoes"
|
61
|
+
doc.catalog.items[0].desc # => "Capture the beauty"
|
62
|
+
doc.catalog.items[0].amount # => 3
|
63
|
+
doc.catalog.items[0].position # => 1
|
64
|
+
|
65
|
+
doc.to_json
|
66
|
+
#{
|
67
|
+
# "catalog": {
|
68
|
+
# "date": "2014-12-20",
|
69
|
+
# "size": 10,
|
70
|
+
# "items": [
|
71
|
+
# { "title": "Sumac Shoes", "desc": "Capture the beauty", "amount": 3, "position": 1 },
|
72
|
+
# { "title": "Channing Oxford Shoes", "desc": "Hand finished with a wash of color", "position": 2 }
|
73
|
+
# ]
|
74
|
+
# }
|
75
|
+
#}
|
76
|
+
|
77
|
+
json = {
|
78
|
+
catalog: {
|
79
|
+
date: "2014-12-20",
|
80
|
+
size: 10,
|
81
|
+
items: [
|
82
|
+
{ title: "Sumac Shoes", desc: "Capture the beauty", amount: 3, position: 1 },
|
83
|
+
{ title: "Channing Oxford Shoes", desc: "Hand finished with a wash of color", position: 2 }
|
84
|
+
]
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
# Initialize with JSON
|
89
|
+
doc = Catalog.new(json)
|
90
|
+
doc.catalog.date # => #<Date: 2014-12-20 ((2457012j,0s,0n),+0s,2299161j)>
|
91
|
+
doc.catalog.size # => 10
|
92
|
+
doc.catalog.items.size # => 2
|
93
|
+
doc.catalog.items[0].title # => "Sumac Shoes"
|
94
|
+
doc.catalog.items[0].desc # => "Capture the beauty"
|
95
|
+
doc.catalog.items[0].amount # => 3
|
96
|
+
doc.catalog.items[0].position # => 1
|
97
|
+
|
98
|
+
# By default all elements and attribute values are proxied. If you for some
|
99
|
+
# reason need to get real value just use the exclamation mark.
|
100
|
+
doc.catalog.date! # => #<Date: 2014-12-20 ((2457012j,0s,0n),+0s,2299161j)>
|
101
|
+
|
102
|
+
doc.to_xml
|
103
|
+
#<?xml version="1.0"?>
|
104
|
+
#<catalog date="2014-12-20">
|
105
|
+
# <size>10</size>
|
106
|
+
# <item position="1">
|
107
|
+
# <title>Sumac Shoes</title>
|
108
|
+
# <description>Capture the beauty</description>
|
109
|
+
# <amount>3</amount>
|
110
|
+
# </item>
|
111
|
+
# <item position="2">
|
112
|
+
# <title>Channing Oxford Shoes</title>
|
113
|
+
# <description>Hand finished with a wash of color</description>
|
114
|
+
# </item>
|
115
|
+
#</catalog>
|
116
|
+
```
|
117
|
+
|
118
|
+
### XML with namespaces
|
119
|
+
```ruby
|
120
|
+
xml = <<-XML
|
121
|
+
<?xml version="1.0"?>
|
122
|
+
<d:student xmlns="http://example.com" xmlns:d="http://foo.com/student" d:id="11">
|
123
|
+
<d:name d:position="2">Jeff Smith</d:name>
|
124
|
+
<info>
|
125
|
+
<city number="7">Beijing</city>
|
126
|
+
</info>
|
127
|
+
</d:student>
|
128
|
+
XML
|
129
|
+
|
130
|
+
class Student
|
131
|
+
include XMLable::Document
|
132
|
+
|
133
|
+
root :student, namespace: 'd' do
|
134
|
+
namespace nil, 'http://example.com'
|
135
|
+
# the last defined namespace will be set as default for the all following
|
136
|
+
# and nested elements and attributes. If you need to overwrite namespace
|
137
|
+
# just pass namespace: 'prefix' (see the root definition above).
|
138
|
+
namespace :d, 'http://foo.com/student'
|
139
|
+
|
140
|
+
attribute :id, :int
|
141
|
+
|
142
|
+
element :name do
|
143
|
+
attribute :position, :int
|
144
|
+
# You can describe content method of element which has also attributes
|
145
|
+
# besides the content. By default content if present will be exported into JSON with
|
146
|
+
# '__content' key. You can pase 'false' instead of name to ignore it.
|
147
|
+
content :fullname
|
148
|
+
end
|
149
|
+
|
150
|
+
# If namespace setting is passed it will be set as default for the all
|
151
|
+
# nested element and attributes.
|
152
|
+
element :info, namespace: nil do
|
153
|
+
element :city do
|
154
|
+
attribute :number, Integer
|
155
|
+
content :name
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
student = Student.from_xml(xml)
|
162
|
+
student.to_json
|
163
|
+
#{
|
164
|
+
# "student": {
|
165
|
+
# "id": 11,
|
166
|
+
# "name": {
|
167
|
+
# "fullname": "Jeff Smith",
|
168
|
+
# "position": 2
|
169
|
+
# },
|
170
|
+
# "info": {
|
171
|
+
# "city": {
|
172
|
+
# "name": "Beijing",
|
173
|
+
# "number": 7
|
174
|
+
# }
|
175
|
+
# }
|
176
|
+
# }
|
177
|
+
#}
|
178
|
+
|
179
|
+
# Back direction
|
180
|
+
other = Student.new(student.to_h)
|
181
|
+
|
182
|
+
other.to_xml
|
183
|
+
#<?xml version="1.0"?>
|
184
|
+
#<d:student xmlns="http://example.com" xmlns:d="http://foo.com/student" d:id="11">
|
185
|
+
# <d:name d:position="2">Jeff Smith</d:name>
|
186
|
+
# <info>
|
187
|
+
# <city number="7">Beijing</city>
|
188
|
+
# </info>
|
189
|
+
#</d:student>
|
190
|
+
```
|
191
|
+
|
192
|
+
### Undescribed document
|
193
|
+
It's also possible to load undescribed XML. In this case each XML element(not
|
194
|
+
attribute) will be represented as an array, so you have to use indexes to
|
195
|
+
access element values.
|
196
|
+
```ruby
|
197
|
+
xml = <<-XML
|
198
|
+
<?xml version="1.0"?>
|
199
|
+
<item id="11">
|
200
|
+
<name position="2">Bolt</name>
|
201
|
+
<info>
|
202
|
+
<color>Silver</color>
|
203
|
+
</info>
|
204
|
+
</item>
|
205
|
+
XML
|
206
|
+
|
207
|
+
class Item
|
208
|
+
include XMLable::Document
|
209
|
+
end
|
210
|
+
|
211
|
+
item = Item.from_xml(xml)
|
212
|
+
|
213
|
+
item.root.id # => "11"
|
214
|
+
item.root.name[0].position # => "2"
|
215
|
+
item.root.name[0] # => "Bolt"
|
216
|
+
item.root.info[0].color[0] # => "Silver"
|
217
|
+
|
218
|
+
item.to_h
|
219
|
+
#{
|
220
|
+
# "item": {
|
221
|
+
# "id": "11"
|
222
|
+
# "name": [{"position": 2", "__content": "Bolt"}]
|
223
|
+
# "info": [{ "color": ["Silver"]}]
|
224
|
+
# }
|
225
|
+
#}
|
226
|
+
|
227
|
+
item.to_xml
|
228
|
+
#<?xml version="1.0"?>
|
229
|
+
#<item id="11">
|
230
|
+
# <name position="2">Bolt</name>
|
231
|
+
# <info>
|
232
|
+
# <color>Silver</color>
|
233
|
+
# </info>
|
234
|
+
#</item>
|
235
|
+
```
|
236
|
+
|
237
|
+
## Contributing
|
238
|
+
|
239
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/zoer/xmlable.
|
240
|
+
|
241
|
+
|
242
|
+
## License
|
243
|
+
|
244
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
245
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module XMLable
|
2
|
+
#
|
3
|
+
# Attribute module contains logic for standalone attribute object
|
4
|
+
#
|
5
|
+
module Attribute
|
6
|
+
def self.included(base)
|
7
|
+
base.include Mixins::Object
|
8
|
+
base.include Mixins::Castable
|
9
|
+
base.include Mixins::ValueStorage
|
10
|
+
base.include Mixins::StandaloneAttribute
|
11
|
+
base.include Mixins::OptionsStorage
|
12
|
+
base.include Mixins::BareValue
|
13
|
+
base.include Mixins::Instantiable
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module XMLable
|
2
|
+
#
|
3
|
+
# Builder class builds object that represents XML attribute and values
|
4
|
+
#
|
5
|
+
class Builder
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
class << self
|
9
|
+
#
|
10
|
+
# Build document object from XML document
|
11
|
+
#
|
12
|
+
# @param [Nokogiri::XML::Document] document
|
13
|
+
# @param [XMLable::Handlers::Document] handler
|
14
|
+
#
|
15
|
+
# @return [XMLable::Mixins::Object]
|
16
|
+
#
|
17
|
+
def build_document(document, handler)
|
18
|
+
obj = handler.proxy.new({}, document, handler)
|
19
|
+
populate_document(obj, document)
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Build attribute object from XML attribute
|
24
|
+
#
|
25
|
+
# @param [Nogogiri::XML::Attribute] attribute
|
26
|
+
# @param [XMLable::Handlers::Base] handler
|
27
|
+
#
|
28
|
+
# @return [XMLable::Mixins::Object]
|
29
|
+
#
|
30
|
+
def build_attribute(attribute, handler)
|
31
|
+
obj = handler.proxy.new({}, attribute, handler)
|
32
|
+
populate_attribute(obj, attribute)
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Build element object from XML element
|
37
|
+
#
|
38
|
+
# @param [Nogogiri::XML::Element] node
|
39
|
+
# @param [XMLable::Handlers::Base] handler
|
40
|
+
#
|
41
|
+
# @return [XMLable::Mixins::Object]
|
42
|
+
#
|
43
|
+
def build_element(node, handler)
|
44
|
+
obj = handler.proxy.new({}, node, handler)
|
45
|
+
populate_element(obj, node)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Populate document object
|
50
|
+
#
|
51
|
+
# @param [XMLable::Mixins::Object] obj
|
52
|
+
# @param [Nogogiri::XML::Document] node
|
53
|
+
#
|
54
|
+
# @return [XMLable::Mixins::Object]
|
55
|
+
#
|
56
|
+
def populate_document(obj, node)
|
57
|
+
obj.__set_root(node.root)
|
58
|
+
obj
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Populate element object
|
63
|
+
#
|
64
|
+
# @param [XMLable::Mixins::Object] obj
|
65
|
+
# @param [Nogogiri::XML::Element] node
|
66
|
+
#
|
67
|
+
# @return [XMLable::Mixins::Object]
|
68
|
+
#
|
69
|
+
def populate_element(obj, node)
|
70
|
+
node.namespace_definitions.each { |ns| obj.__set_namespace_definition(ns) }
|
71
|
+
node.elements.each { |el| obj.__set_element(el) }
|
72
|
+
node.attributes.each { |_, att| obj.__set_attribute(att) }
|
73
|
+
obj.__set_content(node)
|
74
|
+
obj
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Populate attribute object
|
79
|
+
#
|
80
|
+
# @param [XMLable::Mixins::Object] obj
|
81
|
+
# @param [Nogogiri::XML::Attr] node
|
82
|
+
#
|
83
|
+
# @return [XMLable::Mixins::Object]
|
84
|
+
#
|
85
|
+
def populate_attribute(obj, node)
|
86
|
+
obj.tap { |o| o.__set_value(node) }
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Find defined type
|
91
|
+
#
|
92
|
+
# @param [Object] type
|
93
|
+
#
|
94
|
+
# @return [Class] returns found type or define new one if it's not found
|
95
|
+
#
|
96
|
+
def find_type(type)
|
97
|
+
type = type.to_s if type.is_a?(Symbol)
|
98
|
+
klass = instance.defined_types[type]
|
99
|
+
klass ? klass : define_type(type)
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Wrap type with additional logic
|
104
|
+
#
|
105
|
+
# @param [Class] klass
|
106
|
+
#
|
107
|
+
# @return [Class] returns wrapped class
|
108
|
+
#
|
109
|
+
def wrap_type(klass, &block)
|
110
|
+
Class.new do
|
111
|
+
include Mixins::Object
|
112
|
+
include Mixins::Wrapper
|
113
|
+
include Mixins::Castable
|
114
|
+
include Mixins::OptionsStorage
|
115
|
+
class_eval(&block) if block_given?
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Inherit type and set additional settings
|
121
|
+
#
|
122
|
+
# @param [Class] klass
|
123
|
+
#
|
124
|
+
# @return [Class] returns wrapped class
|
125
|
+
#
|
126
|
+
def inherit_type(klass, &block)
|
127
|
+
Class.new(klass) do
|
128
|
+
class_eval(&block) if block_given?
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Define new type
|
134
|
+
#
|
135
|
+
# @param [Array<Object>] names type's names(aliases)
|
136
|
+
#
|
137
|
+
# @return [Class]
|
138
|
+
#
|
139
|
+
def define_type(*names, &block)
|
140
|
+
names = names.map { |n| n.is_a?(Symbol) ? n.to_s : n }
|
141
|
+
main = names.first
|
142
|
+
klass = wrapped_type?(main) ? wrap_type(main, &block) : inherit_type(main, &block)
|
143
|
+
names.each { |n| instance.defined_types[n] = klass }
|
144
|
+
klass
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Is the given class wrapped?
|
149
|
+
#
|
150
|
+
# @return [Boolean]
|
151
|
+
#
|
152
|
+
def wrapped_type?(klass)
|
153
|
+
return true if !klass.is_a?(Class)
|
154
|
+
return false if klass.ancestors.include?(Mixins::StandaloneElement)
|
155
|
+
return false if klass.ancestors.include?(Mixins::StandaloneAttribute)
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
# Get proxy for the given type
|
161
|
+
#
|
162
|
+
# @param [Object] type type's name
|
163
|
+
#
|
164
|
+
# @return [Class] returns type's proxy class
|
165
|
+
#
|
166
|
+
def proxy_for(type)
|
167
|
+
find_type(type).dup
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# Get container proxy for the given class
|
172
|
+
#
|
173
|
+
# @param [Class] klass
|
174
|
+
#
|
175
|
+
# @return [Class]
|
176
|
+
#
|
177
|
+
def container_proxy_for(klass)
|
178
|
+
Class.new(klass) { include Mixins::Container }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# @return [Hash]
|
183
|
+
attr_reader :defined_types
|
184
|
+
|
185
|
+
def initialize
|
186
|
+
@defined_types = {}
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module XMLable
|
2
|
+
#
|
3
|
+
# Document module contains logic for XML document object
|
4
|
+
#
|
5
|
+
module Document
|
6
|
+
def self.included(base)
|
7
|
+
base.include Mixins::Object
|
8
|
+
base.include Mixins::Export
|
9
|
+
base.include Mixins::OptionsStorage
|
10
|
+
base.include Mixins::Instantiable
|
11
|
+
base.include Mixins::Castable
|
12
|
+
base.include Mixins::DocumentStorage
|
13
|
+
base.include Mixins::RootStorage
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module XMLable
|
2
|
+
#
|
3
|
+
# Element module contains logic for standalone element object
|
4
|
+
#
|
5
|
+
module Element
|
6
|
+
def self.included(base)
|
7
|
+
base.include Mixins::Object
|
8
|
+
base.include Mixins::Castable
|
9
|
+
base.include Mixins::ElementsStorage
|
10
|
+
base.include Mixins::AttributesStorage
|
11
|
+
base.include Mixins::ContentStorage
|
12
|
+
base.include Mixins::StandaloneElement
|
13
|
+
base.include Mixins::OptionsStorage
|
14
|
+
base.include Mixins::NamespaceDefinitionsStorage
|
15
|
+
base.include Mixins::BareValue
|
16
|
+
base.include Mixins::Instantiable
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module XMLable
|
2
|
+
module Exports
|
3
|
+
#
|
4
|
+
# Base class contains the base export logic
|
5
|
+
#
|
6
|
+
class Base
|
7
|
+
#
|
8
|
+
# Initialize
|
9
|
+
#
|
10
|
+
# @param [XMLable::Mixins::Object] element
|
11
|
+
# @param [Hash] opts
|
12
|
+
#
|
13
|
+
def initialize(element, opts = {})
|
14
|
+
@element = element
|
15
|
+
@opts = opts
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Is this object empty?
|
20
|
+
#
|
21
|
+
# @param [Nokogiri::XML::Node] node
|
22
|
+
#
|
23
|
+
# @return [Boolean]
|
24
|
+
#
|
25
|
+
def empty?(node)
|
26
|
+
node.instance_variable_get(:@__element).__empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Is the object described by user?
|
31
|
+
#
|
32
|
+
# @param [Nokogiri::XML::Node] node
|
33
|
+
#
|
34
|
+
# @return [Boolean]
|
35
|
+
#
|
36
|
+
def described?(node)
|
37
|
+
node.instance_variable_get(:@__handler).described?
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Get node's nested options
|
42
|
+
#
|
43
|
+
# @param [Nokogiri::XML::Node] node
|
44
|
+
#
|
45
|
+
# @return [XMLable::Options::Storage]
|
46
|
+
#
|
47
|
+
def node_nested_options(node)
|
48
|
+
return Options::Storage.new unless node
|
49
|
+
parent = node.respond_to?(:parent) ? node.parent : nil
|
50
|
+
node_nested_options(parent).merge_opts(node_options(node))
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Get node's options
|
55
|
+
#
|
56
|
+
# @param [Nokogiri::XML::Node] node
|
57
|
+
#
|
58
|
+
# @return [XMLable::Options::Storage]
|
59
|
+
#
|
60
|
+
def node_options(node)
|
61
|
+
h = node.instance_variable_get(:@__handler)
|
62
|
+
h && h.options? ? h.options : Options::Storage.new
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Merge node's options
|
67
|
+
#
|
68
|
+
# @param [Nokogiri::XML::Node] node
|
69
|
+
# @param [XMLable::Options::Storage] opts
|
70
|
+
#
|
71
|
+
# @return [XMLable::Options::Storage]
|
72
|
+
#
|
73
|
+
def node_merged_opts(node, opts = Options::Storage.new)
|
74
|
+
opts.merge_opts(node_options(node))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|