xml-mapping_extensions 0.3.5 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/README.md +63 -6
- data/lib/xml/mapping_extensions/namespace.rb +85 -0
- data/lib/xml/mapping_extensions/version.rb +1 -1
- data/spec/unit/xml/mapping_extensions/mapping_extensions_spec.rb +56 -18
- data/spec/unit/xml/mapping_extensions/namespace_spec.rb +18 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6415479b9ea2414249436f8273893c81b8bfbdb
|
4
|
+
data.tar.gz: 3ada581c17b547c1961e48dd72003a4bcba3c03a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb643f42be329656e36d04acf0f759fbc0edcc8636147c2164182f8a7182ef6415b43fcab66331a7b88ff8b00e696155632a6b2fb3e4e133fb84e211e0c63f21
|
7
|
+
data.tar.gz: 54ab830f4b26b5b56d6d7afe3e5ca8b8d4f8b5feec004ea89b84bb0aa609b5c801a1fcd67d37601dff0fd94fba99cac8dcf5d6b07d44c0930607ab4bf867d4bd
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.3.6 (2 May 2016)
|
2
|
+
|
3
|
+
- Added `XML::MappingExtensions::Namespace`, with corresponding extension module
|
4
|
+
`XML::MappingExtensions::NamespacedElement`, to support more or less proper XML namespace
|
5
|
+
URLs and prefixing
|
6
|
+
|
1
7
|
## 0.3.5 (28 April 2016)
|
2
8
|
|
3
9
|
- `DateNode`: Fix issues with `Date.xmlschema` misbehaving in a Rails / ActiveSupport environment
|
data/README.md
CHANGED
@@ -8,6 +8,19 @@
|
|
8
8
|
Additional mapping nodes and other utility code for working with
|
9
9
|
[XML::Mapping](http://multi-io.github.io/xml-mapping/).
|
10
10
|
|
11
|
+
### Table of contents
|
12
|
+
|
13
|
+
- [Extension methods](#extension-methods)
|
14
|
+
- [Custom nodes](#custom-nodes)
|
15
|
+
- [Abstract nodes](#abstract-nodes)
|
16
|
+
- [Example](#example)
|
17
|
+
- [Provided implementations](#provided-implementations)
|
18
|
+
- [Example](#example-1)
|
19
|
+
- [Reading XML:](#reading-xml)
|
20
|
+
- [Writing XML:](#writing-xml)
|
21
|
+
- [Namespaces](#namespaces)
|
22
|
+
|
23
|
+
|
11
24
|
## Extension methods
|
12
25
|
|
13
26
|
This gem adds two methods, `write_xml` and `parse_xml`, to XML mapping instances and classes respectively, to reduce
|
@@ -153,12 +166,7 @@ elem.time = Time.utc(2000, 1, 1, 2, 34, 56)
|
|
153
166
|
elem.uri = URI('http://example.org')
|
154
167
|
elem.mime_type = MIME::Types['text/plain'].first
|
155
168
|
|
156
|
-
|
157
|
-
|
158
|
-
formatter = REXML::Formatters::Pretty.new
|
159
|
-
formatter.compact = true
|
160
|
-
|
161
|
-
puts(formatter.write(xml, ""))
|
169
|
+
puts(elem.write_xml)
|
162
170
|
```
|
163
171
|
|
164
172
|
Outputs:
|
@@ -172,3 +180,52 @@ Outputs:
|
|
172
180
|
<mime_type>text/plain</mime_type>
|
173
181
|
</my_elem>
|
174
182
|
```
|
183
|
+
|
184
|
+
## Namespaces
|
185
|
+
|
186
|
+
The `Namespace` class encapsulates an XML namespace:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
namespace = Namespace.new(uri: 'http://example.org/px', schema_location: 'http://example.org/px.xsd')
|
190
|
+
```
|
191
|
+
|
192
|
+
Setting a namespace on a mapped object will cause that namespace to be written out when the object is saved
|
193
|
+
to XML:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
obj = MyElem.new(...)
|
197
|
+
obj.namespace = namespace
|
198
|
+
|
199
|
+
puts obj.write_xml
|
200
|
+
```
|
201
|
+
|
202
|
+
Outputs:
|
203
|
+
|
204
|
+
```xml
|
205
|
+
<element xmlns='http://example.org/px/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://example.org/px.xsd' attribute='123'>
|
206
|
+
element text
|
207
|
+
<child>child 1</child>
|
208
|
+
<child>child 2</child>
|
209
|
+
</element>
|
210
|
+
```
|
211
|
+
|
212
|
+
Setting a `prefix` attribute on the namespace will set the prefix on each element in the output:
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
namespace = Namespace.new(prefix: 'px', uri: 'http://example.org/px', schema_location: 'http://example.org/px.xsd')
|
216
|
+
|
217
|
+
obj = MyElem.new(...)
|
218
|
+
obj.namespace = namespace
|
219
|
+
|
220
|
+
puts obj.write_xml
|
221
|
+
```
|
222
|
+
|
223
|
+
Outputs:
|
224
|
+
|
225
|
+
```xml
|
226
|
+
<px:element xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://example.org/px.xsd' xmlns:px='http://example.org/px/' attribute='123'>
|
227
|
+
element text
|
228
|
+
<px:child>child 1</px:child>
|
229
|
+
<px:child>child 2</px:child>
|
230
|
+
</px:element>
|
231
|
+
```
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module XML
|
4
|
+
module MappingExtensions
|
5
|
+
|
6
|
+
# Encapsulates an XML namespace with a URI, schema location, and optional prefix.
|
7
|
+
class Namespace
|
8
|
+
|
9
|
+
# @return [String] the string form of the namespace URI
|
10
|
+
attr_reader :uri
|
11
|
+
|
12
|
+
# @return [String, nil] the namespace prefix
|
13
|
+
attr_reader :prefix
|
14
|
+
|
15
|
+
# @return [String] the schema location URI(s), as a space-separated string list
|
16
|
+
attr_reader :schema_location
|
17
|
+
|
18
|
+
# Creates a new {Namespace}
|
19
|
+
# @param uri [URI, String] the namespace URI
|
20
|
+
# @param prefix [String, nil] the namespace prefix
|
21
|
+
# @param schema_location [String] the schema location(s)
|
22
|
+
def initialize(uri:, prefix: nil, schema_location:)
|
23
|
+
@uri = uri.to_s
|
24
|
+
@prefix = prefix
|
25
|
+
@schema_location = schema_location.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
# Sets `uri` as the default (no-prefix) namespace on `elem`, with
|
29
|
+
# `schema_location` as the schema location.
|
30
|
+
# @param elem [REXML::Element] The element to set the namespace on
|
31
|
+
def set_default_namespace(elem) # rubocop:disable Style/AccessorMethodName
|
32
|
+
elem.add_namespace(uri)
|
33
|
+
elem.add_namespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance')
|
34
|
+
elem.add_attribute('xsi:schemaLocation', schema_location)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sets `prefix` as the prefix for namespace `uri` on the specified document
|
38
|
+
# root element, and all its descendants that have that namespace.
|
39
|
+
# @param root [REXML::Element] The document root to set the namespace on
|
40
|
+
def set_prefix(root) # rubocop:disable Style/AccessorMethodName
|
41
|
+
return unless prefix
|
42
|
+
set_prefix_recursive(root)
|
43
|
+
root.add_namespace(nil) if root.attributes['xmlns'] == uri # clear the no-prefix namespace
|
44
|
+
root.add_namespace(prefix, uri)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def set_prefix_recursive(elem) # rubocop:disable Style/AccessorMethodName
|
50
|
+
return unless elem.namespace == uri
|
51
|
+
# name= with a prefixed name sets namespace by side effect and is the only way to actually output the prefix
|
52
|
+
elem.name = "#{prefix}:#{elem.name}"
|
53
|
+
elem.each_element { |e| set_prefix_recursive(e) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Patches `XML::Mapping` to add a namespace attribute and write the namespace
|
59
|
+
# out when saving to XML.
|
60
|
+
module NamespacedElement
|
61
|
+
|
62
|
+
# @return [Namespace, nil] the namespace, if any
|
63
|
+
attr_accessor :namespace
|
64
|
+
|
65
|
+
# Overrides `XML::Mapping#pre_save` to set the XML namespace and schema location
|
66
|
+
# on the generated element.
|
67
|
+
def pre_save(options = { mapping: :_default })
|
68
|
+
xml = super(options)
|
69
|
+
namespace.set_default_namespace(xml) if namespace
|
70
|
+
xml
|
71
|
+
end
|
72
|
+
|
73
|
+
# Overrides `XML::Mapping#save_to_xml` to set the XML namespace prefix on
|
74
|
+
# the generated element, and all its descendants that have that namespace.
|
75
|
+
def save_to_xml(options = { mapping: :_default })
|
76
|
+
xml = super(options)
|
77
|
+
namespace.set_prefix(xml) if namespace
|
78
|
+
xml
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module Mapping
|
83
|
+
prepend NamespacedElement
|
84
|
+
end
|
85
|
+
end
|
@@ -3,7 +3,7 @@ require 'tempfile'
|
|
3
3
|
|
4
4
|
module XML
|
5
5
|
module Mapping
|
6
|
-
class
|
6
|
+
class MXSpecObject
|
7
7
|
include ::XML::Mapping
|
8
8
|
include Comparable
|
9
9
|
|
@@ -29,17 +29,55 @@ module XML
|
|
29
29
|
|
30
30
|
describe '#write_xml' do
|
31
31
|
it 'writes an XML string' do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
expected_xml =
|
37
|
-
xml_string =
|
32
|
+
obj = MXSpecObject.new
|
33
|
+
obj.attribute = 123
|
34
|
+
obj.text = 'element text'
|
35
|
+
obj.children = ['child 1', 'child 2']
|
36
|
+
expected_xml = obj.save_to_xml
|
37
|
+
xml_string = obj.write_xml
|
38
38
|
expect(xml_string).to be_a(String)
|
39
39
|
expect(xml_string).to be_xml(expected_xml)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
describe ':namespace' do
|
44
|
+
it 'sets the namespace on save' do
|
45
|
+
uri = 'http://example.org/px/'
|
46
|
+
schema_location = 'http://example.org/px.xsd'
|
47
|
+
namespace = MappingExtensions::Namespace.new(uri: uri, prefix: 'px', schema_location: schema_location)
|
48
|
+
|
49
|
+
obj = MXSpecObject.new
|
50
|
+
obj.attribute = 123
|
51
|
+
obj.text = 'element text'
|
52
|
+
obj.children = ['child 1', 'child 2']
|
53
|
+
obj.namespace = namespace
|
54
|
+
|
55
|
+
namespace_attribs = "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='#{schema_location}' xmlns:px='#{uri}'"
|
56
|
+
expected = "<px:element #{namespace_attribs} attribute='123'>element text<px:child>child 1</px:child><px:child>child 2</px:child></px:element>"
|
57
|
+
|
58
|
+
expect(obj.save_to_xml).to be_xml(expected)
|
59
|
+
puts(obj.write_xml)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'works without prefixes' do
|
63
|
+
uri = 'http://example.org/px/'
|
64
|
+
schema_location = 'http://example.org/px.xsd'
|
65
|
+
namespace = MappingExtensions::Namespace.new(uri: uri, schema_location: schema_location)
|
66
|
+
|
67
|
+
obj = MXSpecObject.new
|
68
|
+
obj.attribute = 123
|
69
|
+
obj.text = 'element text'
|
70
|
+
obj.children = ['child 1', 'child 2']
|
71
|
+
obj.namespace = namespace
|
72
|
+
|
73
|
+
namespace_attribs = "xmlns='#{uri}' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='#{schema_location}'"
|
74
|
+
expected = "<element #{namespace_attribs} attribute='123'>element text<child>child 1</child><child>child 2</child></element>"
|
75
|
+
|
76
|
+
expect(obj.save_to_xml).to be_xml(expected)
|
77
|
+
puts(obj.write_xml)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
43
81
|
module ClassMethods
|
44
82
|
describe '#parse_xml' do
|
45
83
|
|
@@ -51,28 +89,28 @@ module XML
|
|
51
89
|
</element>'
|
52
90
|
@xml_document = REXML::Document.new(@xml_string)
|
53
91
|
@xml_element = @xml_document.root
|
54
|
-
@expected_element =
|
92
|
+
@expected_element = MXSpecObject.load_from_xml(@xml_element)
|
55
93
|
end
|
56
94
|
|
57
95
|
it 'parses a String' do
|
58
|
-
|
59
|
-
expect(
|
96
|
+
obj = MXSpecObject.parse_xml(@xml_string)
|
97
|
+
expect(obj).to eq(@expected_element)
|
60
98
|
end
|
61
99
|
|
62
100
|
it 'parses a REXML::Document' do
|
63
|
-
|
64
|
-
expect(
|
101
|
+
obj = MXSpecObject.parse_xml(@xml_document)
|
102
|
+
expect(obj).to eq(@expected_element)
|
65
103
|
end
|
66
104
|
|
67
105
|
it 'parses a REXML::Element' do
|
68
|
-
|
69
|
-
expect(
|
106
|
+
obj = MXSpecObject.parse_xml(@xml_element)
|
107
|
+
expect(obj).to eq(@expected_element)
|
70
108
|
end
|
71
109
|
|
72
110
|
it 'parses an IO' do
|
73
111
|
xml_io = StringIO.new(@xml_string)
|
74
|
-
|
75
|
-
expect(
|
112
|
+
obj = MXSpecObject.parse_xml(xml_io)
|
113
|
+
expect(obj).to eq(@expected_element)
|
76
114
|
end
|
77
115
|
|
78
116
|
it 'parses a file' do
|
@@ -80,8 +118,8 @@ module XML
|
|
80
118
|
begin
|
81
119
|
xml_file.write(@xml_string)
|
82
120
|
xml_file.rewind
|
83
|
-
|
84
|
-
expect(
|
121
|
+
obj = MXSpecObject.parse_xml(xml_file)
|
122
|
+
expect(obj).to eq(@expected_element)
|
85
123
|
ensure
|
86
124
|
xml_file.close(true)
|
87
125
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module XML
|
4
|
+
module MappingExtensions
|
5
|
+
describe Namespace do
|
6
|
+
describe '#set_default_namespace' do
|
7
|
+
it 'sets the default namespace'
|
8
|
+
it 'sets the schema location'
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#set_prefix' do
|
12
|
+
it 'sets the prefix'
|
13
|
+
it 'clears the no-prefix namespace, if previously present'
|
14
|
+
it 'leaves an unrelated no-prefix namespace intact'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xml-mapping_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Moles
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mime-types
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- lib/xml/mapping_extensions.rb
|
191
191
|
- lib/xml/mapping_extensions/date_node.rb
|
192
192
|
- lib/xml/mapping_extensions/mime_type_node.rb
|
193
|
+
- lib/xml/mapping_extensions/namespace.rb
|
193
194
|
- lib/xml/mapping_extensions/node_base.rb
|
194
195
|
- lib/xml/mapping_extensions/time_node.rb
|
195
196
|
- lib/xml/mapping_extensions/typesafe_enum_node.rb
|
@@ -202,6 +203,7 @@ files:
|
|
202
203
|
- spec/unit/xml/mapping_extensions/date_node_spec.rb
|
203
204
|
- spec/unit/xml/mapping_extensions/mapping_extensions_spec.rb
|
204
205
|
- spec/unit/xml/mapping_extensions/mime_type_node_spec.rb
|
206
|
+
- spec/unit/xml/mapping_extensions/namespace_spec.rb
|
205
207
|
- spec/unit/xml/mapping_extensions/node_base_spec.rb
|
206
208
|
- spec/unit/xml/mapping_extensions/time_node_spec.rb
|
207
209
|
- spec/unit/xml/mapping_extensions/typesafe_enum_node_spec.rb
|
@@ -239,6 +241,7 @@ test_files:
|
|
239
241
|
- spec/unit/xml/mapping_extensions/date_node_spec.rb
|
240
242
|
- spec/unit/xml/mapping_extensions/mapping_extensions_spec.rb
|
241
243
|
- spec/unit/xml/mapping_extensions/mime_type_node_spec.rb
|
244
|
+
- spec/unit/xml/mapping_extensions/namespace_spec.rb
|
242
245
|
- spec/unit/xml/mapping_extensions/node_base_spec.rb
|
243
246
|
- spec/unit/xml/mapping_extensions/time_node_spec.rb
|
244
247
|
- spec/unit/xml/mapping_extensions/typesafe_enum_node_spec.rb
|