xsd-populator 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +10 -18
- data/README.md +68 -1
- data/lib/informer.rb +53 -0
- data/lib/xsd_populator.rb +52 -31
- data/spec/informer_spec.rb +162 -0
- data/spec/spec_helper.rb +14 -2
- data/spec/xsd_populator_spec.rb +42 -69
- data/xsd-populator.gemspec +4 -3
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ebc1e85e1cd52ecfb538ab4b7a19d4519246ed6
|
4
|
+
data.tar.gz: 3507861603505bebe389482309a9d8bb8b91573a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd3ed398300a5cd61bdbd28991ec285ba5edb1c27aff7e85e779f0aec49905679d5de18eeb3f2bc16a82361489052d35d1e3dbe3c73e529c36aeb28f2d0f964b
|
7
|
+
data.tar.gz: 1c9bd6860e771cc7de54246aa39117330226c1d676b2170e4bf46b468576c33a51ed32725bf4e728e85d77548926e204bab18e88e1a6cfd81776d9557bc19e96
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -6,18 +6,6 @@ PATH
|
|
6
6
|
data-provider (~> 0.2)
|
7
7
|
xsd-reader (~> 0.2)
|
8
8
|
|
9
|
-
PATH
|
10
|
-
remote: /srv/data-provider
|
11
|
-
specs:
|
12
|
-
data-provider (0.2.0)
|
13
|
-
|
14
|
-
PATH
|
15
|
-
remote: /srv/xsd-reader
|
16
|
-
specs:
|
17
|
-
xsd-reader (0.2.0)
|
18
|
-
nokogiri (~> 1.6)
|
19
|
-
rest-client (~> 1.8)
|
20
|
-
|
21
9
|
GEM
|
22
10
|
remote: https://rubygems.org/
|
23
11
|
specs:
|
@@ -25,16 +13,18 @@ GEM
|
|
25
13
|
byebug (5.0.0)
|
26
14
|
columnize (= 0.9.0)
|
27
15
|
columnize (0.9.0)
|
16
|
+
data-provider (0.2.0)
|
28
17
|
diff-lcs (1.2.5)
|
29
|
-
domain_name (0.5.
|
18
|
+
domain_name (0.5.25)
|
30
19
|
unf (>= 0.0.5, < 1.0.0)
|
31
20
|
http-cookie (1.0.2)
|
32
21
|
domain_name (~> 0.5)
|
33
|
-
mime-types (2.6.
|
22
|
+
mime-types (2.6.2)
|
34
23
|
mini_portile (0.6.2)
|
35
|
-
netrc (0.
|
24
|
+
netrc (0.11.0)
|
36
25
|
nokogiri (1.6.6.2)
|
37
26
|
mini_portile (~> 0.6.0)
|
27
|
+
rake (10.1.0)
|
38
28
|
rest-client (1.8.0)
|
39
29
|
http-cookie (>= 1.0.2, < 2.0)
|
40
30
|
mime-types (>= 1.16, < 3.0)
|
@@ -55,17 +45,19 @@ GEM
|
|
55
45
|
unf (0.1.4)
|
56
46
|
unf_ext
|
57
47
|
unf_ext (0.0.7.1)
|
48
|
+
xsd-reader (0.2.0)
|
49
|
+
nokogiri (~> 1.6)
|
50
|
+
rest-client (~> 1.8)
|
58
51
|
|
59
52
|
PLATFORMS
|
60
53
|
ruby
|
61
54
|
|
62
55
|
DEPENDENCIES
|
63
|
-
byebug
|
64
|
-
data-provider!
|
56
|
+
byebug
|
65
57
|
nokogiri (~> 1.6)
|
58
|
+
rake (~> 10.1)
|
66
59
|
rspec (~> 3.3)
|
67
60
|
xsd-populator!
|
68
|
-
xsd-reader!
|
69
61
|
|
70
62
|
BUNDLED WITH
|
71
63
|
1.10.5
|
data/README.md
CHANGED
@@ -1,2 +1,69 @@
|
|
1
1
|
# xsd-populator
|
2
|
-
A Ruby gem to produce XML data from XSD schemas
|
2
|
+
A Ruby gem to produce XML data from XSD schemas and DataProvider objects.
|
3
|
+
|
4
|
+
See the data-provider gem: [https://github.com/markkorput/data-provider](https://github.com/markkorput/data-provider)
|
5
|
+
|
6
|
+
[![Build Status](https://travis-ci.org/markkorput/xsd-populator.svg)](https://travis-ci.org/markkorput/xsd-populator)
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
|
13
|
+
Rubygems:
|
14
|
+
|
15
|
+
```
|
16
|
+
gem install xsd-populator
|
17
|
+
```
|
18
|
+
|
19
|
+
Bundler:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'xsd-populator'
|
23
|
+
````
|
24
|
+
|
25
|
+
## Examples
|
26
|
+
|
27
|
+
Load xsd
|
28
|
+
```ruby
|
29
|
+
require 'xsd_populator'
|
30
|
+
reader = XsdPopulator.new(:xsd => 'ddex-ern-v36.xsd')
|
31
|
+
reader.populated_xml # => XML-string
|
32
|
+
```
|
33
|
+
|
34
|
+
Not that in this minimal implementation, no custom data provider is given to the populator, causing it to use the default internal 'XsdExplanationProvider', which produces explanatory XML.
|
35
|
+
|
36
|
+
For this [elaborate example XSD](https://github.com/markkorput/xsd-populator/blob/master/spec/examples/ddex-ern-v36.xsd), this would produce [this xml](https://github.com/markkorput/xsd-populator/blob/master/spec/examples/ddex-ern-v36-NewReleaseMessage.xml)
|
37
|
+
|
38
|
+
|
39
|
+
### Using actual custom data providers
|
40
|
+
|
41
|
+
In practice, you'd implement a custom DataProvider class (see the [data-provider gem](https://github.com/markkorput/data-provider)) and pass it into the XsdPopulator.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
require 'xsd_populator'
|
45
|
+
|
46
|
+
data_provider = CustomDataProvider.new(:some => 'data')
|
47
|
+
reader = XsdPopulator.new(:xsd => 'ddex-ern-v36.xsd', :provider => data_provider)
|
48
|
+
reader.populated_xml # => XML-string
|
49
|
+
```
|
50
|
+
|
51
|
+
### Producing specific parts of an XML structure
|
52
|
+
|
53
|
+
In case you want to produce only a specific part of an XML hierarchy, you can specify an element when initializing the populator object:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
reader = XsdPopulator.new(:xsd => 'ddex-ern-v36.xsd', :element => ['NewReleaseMessage', 'MessageHeader'])
|
57
|
+
reader.populated_xml # => XML-string containing only the part
|
58
|
+
```
|
59
|
+
|
60
|
+
The :element option takes an array-value representing an element's XPath (in this case that XPath is /NewReleaseMessage/MessageHeader). The specified element become(s) the root-element(s) in the produced XML.
|
61
|
+
|
62
|
+
This example would produce [this XML](https://github.com/markkorput/xsd-populator/blob/master/spec/examples/ddex-ern-v36-MessageHeader.xml)
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
data/lib/informer.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
class XsdPopulator
|
2
|
+
class Informer
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize(_opts = {})
|
6
|
+
@options = _opts || {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def skip?
|
10
|
+
options[:skip] == true
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.skip
|
14
|
+
self.new(:skip => true)
|
15
|
+
end
|
16
|
+
|
17
|
+
def attributes
|
18
|
+
options[:attributes] || {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def attributes?
|
22
|
+
self.options.keys.include?(:attributes)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.attributes(attrs)
|
26
|
+
self.new(:attributes => attrs)
|
27
|
+
end
|
28
|
+
|
29
|
+
def namespace
|
30
|
+
options[:namespace]
|
31
|
+
end
|
32
|
+
|
33
|
+
def namespace?
|
34
|
+
options.keys.include?(:namespace)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.namespace(ns)
|
38
|
+
self.new(:namespace => ns)
|
39
|
+
end
|
40
|
+
|
41
|
+
def content
|
42
|
+
options[:content]
|
43
|
+
end
|
44
|
+
|
45
|
+
def content?
|
46
|
+
self.options.keys.include?(:content)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.content(content)
|
50
|
+
self.new(:content => content)
|
51
|
+
end
|
52
|
+
end # class Informer
|
53
|
+
end # module XsdPopulator
|
data/lib/xsd_populator.rb
CHANGED
@@ -2,33 +2,13 @@ require 'bundler/setup'
|
|
2
2
|
require 'builder'
|
3
3
|
require 'xsd_reader'
|
4
4
|
require 'xsd_explanation_provider'
|
5
|
+
require 'informer'
|
5
6
|
|
6
7
|
class XsdPopulator
|
7
8
|
|
8
9
|
class ElementNotFoundException < Exception
|
9
10
|
end
|
10
11
|
|
11
|
-
class Informer
|
12
|
-
attr_reader :options
|
13
|
-
|
14
|
-
def initialize(_opts = {})
|
15
|
-
@options = _opts || {}
|
16
|
-
end
|
17
|
-
|
18
|
-
def skip?
|
19
|
-
options[:skip] == true
|
20
|
-
end
|
21
|
-
|
22
|
-
def attributes
|
23
|
-
options[:attributes] || {}
|
24
|
-
end
|
25
|
-
|
26
|
-
def namespace
|
27
|
-
options[:namespace]
|
28
|
-
end
|
29
|
-
end # class Informer
|
30
|
-
|
31
|
-
|
32
12
|
attr_reader :options
|
33
13
|
|
34
14
|
def initialize(_opts = {})
|
@@ -77,7 +57,11 @@ class XsdPopulator
|
|
77
57
|
end
|
78
58
|
|
79
59
|
def populate_element(element_specifier = nil)
|
80
|
-
element_specifier.nil? ? populated_xml : populate_xml(element_specifier)
|
60
|
+
element_specifier.nil? ? populated_xml : populate_xml(:element_specifier => element_specifier)
|
61
|
+
end
|
62
|
+
|
63
|
+
def populate(opts = {})
|
64
|
+
populate_xml(opts.merge(:element_specifier => opts.delete(:element)))
|
81
65
|
end
|
82
66
|
|
83
67
|
def write_file(path)
|
@@ -91,22 +75,42 @@ class XsdPopulator
|
|
91
75
|
|
92
76
|
private
|
93
77
|
|
94
|
-
def populate_xml(
|
95
|
-
|
78
|
+
def populate_xml(opts = {})
|
79
|
+
# supported opts:
|
80
|
+
# :element_specifier
|
81
|
+
# :builder
|
82
|
+
|
83
|
+
if (root_el = root_xsd_element(opts[:element_specifier])).nil?
|
96
84
|
logger.warn "Couldn't find element definition, aborting"
|
97
85
|
return nil
|
98
86
|
end
|
99
87
|
|
100
|
-
|
101
|
-
xml.instruct!
|
102
|
-
|
103
|
-
stack = options[:relative_provider] == true ? [] : [element_specifier || options[:element]].flatten.compact
|
88
|
+
stack = options[:relative_provider] == true ? [] : [opts[:element_specifier] || options[:element]].flatten.compact
|
104
89
|
stack.pop
|
105
|
-
|
90
|
+
|
91
|
+
if (xml = opts[:builder]).nil?
|
92
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
93
|
+
xml.instruct!
|
94
|
+
end
|
95
|
+
|
96
|
+
build_element(xml, root_el, start_provider(root_el, stack), stack)
|
106
97
|
|
107
98
|
return xml.target!
|
108
99
|
end
|
109
100
|
|
101
|
+
def start_provider(el, stack)
|
102
|
+
p = self.provider
|
103
|
+
|
104
|
+
1.upto(stack.length) do |cnt|
|
105
|
+
new_p = p.try_take(stack[0, cnt])
|
106
|
+
if new_p.respond_to?(:try_take)
|
107
|
+
p = new_p
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
return p
|
112
|
+
end
|
113
|
+
|
110
114
|
def stack_recursion_count(stack = [])
|
111
115
|
stack.select{|el| el == stack.last}.length - 1
|
112
116
|
end
|
@@ -152,12 +156,28 @@ class XsdPopulator
|
|
152
156
|
else
|
153
157
|
attributes_data_hash ||= attributes_data_hash_for(element, provider, stack)
|
154
158
|
attributes_hash = attributes_hash_for_index(attributes_data_hash, idx)
|
155
|
-
|
159
|
+
|
160
|
+
if node_content.is_a?(Informer) && node_content.attributes?
|
161
|
+
informer_attributes = node_content.attributes.keys.inject({}) do |result, key|
|
162
|
+
if (informer = node_content.attributes[key]).is_a?(Informer)
|
163
|
+
if informer.skip?
|
164
|
+
result
|
165
|
+
else
|
166
|
+
result.merge(key => informer.content)
|
167
|
+
end
|
168
|
+
else
|
169
|
+
result.merge(key => informer)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
attributes_hash.merge!(informer_attributes)
|
174
|
+
end
|
156
175
|
end
|
157
176
|
|
158
177
|
# simple node; name, value, attributes
|
159
178
|
if !element.child_elements?
|
160
|
-
|
179
|
+
cont = node_content.is_a?(Informer) && node_content.content? ? node_content.content : node_content
|
180
|
+
xml.tag!(element.name, cont, attributes_hash)
|
161
181
|
next
|
162
182
|
end
|
163
183
|
|
@@ -323,6 +343,7 @@ class XsdPopulator
|
|
323
343
|
def add_attribute?(attribute, provider, stack = [], opts = {})
|
324
344
|
return true if attribute.required?
|
325
345
|
content = opts[:content] || provider.try_take(stack + ["@#{attribute.name}"])
|
346
|
+
return false if content.is_a?(Informer) and content.skip?
|
326
347
|
return (!content.nil?) || add_empty_attributes?
|
327
348
|
end
|
328
349
|
end # class XsdPopulator
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe XsdPopulator::Informer do
|
4
|
+
class InformProvider
|
5
|
+
include DataProvider::Base
|
6
|
+
|
7
|
+
provides({
|
8
|
+
['NewReleaseMessage', 'MessageHeader'] => XsdPopulator::Informer.new(:skip => true),
|
9
|
+
['NewReleaseMessage', 'MessageHeader', 'MessageId'] => 123,
|
10
|
+
['NewReleaseMessage', 'ResourceList', '@LanguageAndScriptCode'] => XsdPopulator::Informer.skip,
|
11
|
+
['NewReleaseMessage', 'ResourceList', 'SoundRecording', 'SoundRecordingType'] => XsdPopulator::Informer.content('SuperMegaBox'),
|
12
|
+
['NewReleaseMessage', 'ResourceList', 'SoundRecording', 'ReferenceTitle', 'TitleText'] => XsdPopulator::Informer.new(:content => 'SuperSmashHitsDeluxe', :attibutes => {'LanguageAndScriptCode' => XsdPopulator::Informer.skip})
|
13
|
+
|
14
|
+
})
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:xsd_reader){
|
18
|
+
XsdReader::XML.new(:xsd_file => File.expand_path(File.join(File.dirname(__FILE__), 'examples', 'ddex-ern-v36.xsd')))
|
19
|
+
}
|
20
|
+
|
21
|
+
let(:logger){
|
22
|
+
logger = Logger.new(STDOUT)
|
23
|
+
logger.level = Logger::WARN
|
24
|
+
logger
|
25
|
+
}
|
26
|
+
|
27
|
+
let(:populator){
|
28
|
+
XsdPopulator.new({
|
29
|
+
:reader=> xsd_reader,
|
30
|
+
:logger => logger,
|
31
|
+
:provider => InformProvider.new
|
32
|
+
})
|
33
|
+
}
|
34
|
+
|
35
|
+
describe "#skip?" do
|
36
|
+
it "specifies if the skip flag is enabled" do
|
37
|
+
expect(XsdPopulator::Informer.new(:skip => true).skip?).to eq true
|
38
|
+
expect(XsdPopulator::Informer.new(:skip => false).skip?).to eq false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "is false by default" do
|
42
|
+
expect(XsdPopulator::Informer.new.skip?).to eq false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#attributes?" do
|
47
|
+
it "tells if attributes were explicitly specified" do
|
48
|
+
expect(XsdPopulator::Informer.new(:attributes => {}).attributes?).to eq true
|
49
|
+
expect(XsdPopulator::Informer.new(:attributes => nil).attributes?).to eq true
|
50
|
+
expect(XsdPopulator::Informer.new(:attrs => {}).attributes?).to eq false
|
51
|
+
end
|
52
|
+
|
53
|
+
it "is false by default" do
|
54
|
+
expect(XsdPopulator::Informer.new.attributes?).to eq false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#content?" do
|
59
|
+
it "tells if the informer was explicitly given content" do
|
60
|
+
expect(XsdPopulator::Informer.new(:content => {}).content?).to eq true
|
61
|
+
expect(XsdPopulator::Informer.new(:content => 'Something').content?).to eq true
|
62
|
+
expect(XsdPopulator::Informer.new(:content => nil).content?).to eq true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "is false by default" do
|
66
|
+
expect(XsdPopulator::Informer.new(:attributes => {}).content?).to eq false
|
67
|
+
expect(XsdPopulator::Informer.new.content?).to eq false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#namespace?" do
|
72
|
+
it "tells if namespace information was explicitly specified" do
|
73
|
+
expect(XsdPopulator::Informer.new(:namespace => {}).namespace?).to eq true
|
74
|
+
expect(XsdPopulator::Informer.new(:namespace => 'Something').namespace?).to eq true
|
75
|
+
expect(XsdPopulator::Informer.new(:namespace => nil).namespace?).to eq true
|
76
|
+
end
|
77
|
+
|
78
|
+
it "is false by default" do
|
79
|
+
expect(XsdPopulator::Informer.new(:attributes => {}).namespace?).to eq false
|
80
|
+
expect(XsdPopulator::Informer.new.namespace?).to eq false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe ":skip" do
|
85
|
+
it "informs the populator to skip an element" do
|
86
|
+
expect(Nokogiri.XML(populator.populated_xml).at('/NewReleaseMessage/MessageHeader')).to eq nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it "informs the populator to skip an attribute" do
|
90
|
+
expect(Nokogiri.XML(populator.populated_xml).at('/NewReleaseMessage/ResourceList').attributes['Namespace']).to eq nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "informs the populator to skip an attribute" do
|
94
|
+
expect(Nokogiri.XML(populator.populated_xml).at('/NewReleaseMessage/ResourceList/SoundRecording/ReferenceTitle/TitleText').attributes['LanguageAndScriptCode']).to eq nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe ":attributes" do
|
99
|
+
it "informs the populator to explicitly add a set of attributes to an element" do
|
100
|
+
provider_class = Class.new(Object) do
|
101
|
+
include DataProvider::Base
|
102
|
+
|
103
|
+
provider ['NewReleaseMessage', '@MessageSchemaVersionId']{ '2010/ern-main/32' }
|
104
|
+
|
105
|
+
provider ['NewReleaseMessage']{
|
106
|
+
XsdPopulator::Informer.new(:attributes => {
|
107
|
+
'xmlns:ern' => 'http://ddex.net/xml/2010/ern-main/32',
|
108
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
109
|
+
'xsi:schemaLocation' => 'http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd'
|
110
|
+
})
|
111
|
+
}
|
112
|
+
|
113
|
+
provides(['NewReleaseMessage', 'MessageHeader', 'MessageId'] => 123)
|
114
|
+
end
|
115
|
+
|
116
|
+
populator = XsdPopulator.new({
|
117
|
+
:reader=> xsd_reader,
|
118
|
+
:logger => logger,
|
119
|
+
:provider => provider_class.new
|
120
|
+
})
|
121
|
+
|
122
|
+
el = Nokogiri.XML(populator.populated_xml).at('NewReleaseMessage')
|
123
|
+
expect(el.attributes['schemaLocation'].value).to eq 'http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd'
|
124
|
+
expect(el.attributes['MessageSchemaVersionId'].value).to eq '2010/ern-main/32'
|
125
|
+
expect(el.attributes.keys.length).to eq 2
|
126
|
+
|
127
|
+
expect(el.namespace_definitions.map{|nsdef| [nsdef.prefix, nsdef.href]}.sort).to eq([
|
128
|
+
['ern', 'http://ddex.net/xml/2010/ern-main/32'],
|
129
|
+
['xsi', 'http://www.w3.org/2001/XMLSchema-instance']
|
130
|
+
])
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe ":namespace" do
|
135
|
+
it "informs the populator to prefix a node with a namespace" do
|
136
|
+
provider_class = Class.new(Object) do
|
137
|
+
include DataProvider::Base
|
138
|
+
|
139
|
+
provider ['NewReleaseMessage']{ XsdPopulator::Informer.new(:namespace => 'ern') }
|
140
|
+
provides(['NewReleaseMessage', 'MessageHeader', 'MessageId'] => 123)
|
141
|
+
end
|
142
|
+
|
143
|
+
populator = XsdPopulator.new({
|
144
|
+
:reader=> xsd_reader,
|
145
|
+
:logger => logger,
|
146
|
+
:provider => provider_class.new
|
147
|
+
})
|
148
|
+
|
149
|
+
expect(Nokogiri.XML(populator.populated_xml).root.name).to eq 'ern:NewReleaseMessage'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe ":content" do
|
154
|
+
it "informs the populator to use the specified content for the element" do
|
155
|
+
expect(Nokogiri.XML(populator.populated_xml).at('/NewReleaseMessage/ResourceList/SoundRecording/SoundRecordingType').text).to eq 'SuperMegaBox'
|
156
|
+
end
|
157
|
+
|
158
|
+
it "informs the populator to skip an attribute" do
|
159
|
+
expect(Nokogiri.XML(populator.populated_xml).at('/NewReleaseMessage/ResourceList/SoundRecording/ReferenceTitle/TitleText').text).to eq 'SuperSmashHitsDeluxe'
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,10 +4,22 @@
|
|
4
4
|
# Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
|
5
5
|
|
6
6
|
require 'rspec'
|
7
|
+
require 'nokogiri'
|
8
|
+
require 'logger'
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'byebug'
|
12
|
+
rescue LoadError => e
|
13
|
+
Logger.new(STDOUT).warn("Could not load byebug, continuing without it")
|
14
|
+
end
|
15
|
+
|
16
|
+
def spec_logger
|
17
|
+
@spec_logger_cache ||= Logger.new(STDOUT).tap do |logr|
|
18
|
+
logr.level = Logger::WARN
|
19
|
+
end
|
20
|
+
end
|
7
21
|
|
8
22
|
CURRENT_DIR=File.dirname(__FILE__)
|
9
23
|
$: << File.expand_path(CURRENT_DIR + "/../lib")
|
10
24
|
|
11
25
|
require 'xsd_populator'
|
12
|
-
require 'byebug'
|
13
|
-
require 'nokogiri'
|
data/spec/xsd_populator_spec.rb
CHANGED
@@ -102,7 +102,7 @@ describe "XsdPopulator for partial layouts" do
|
|
102
102
|
expect(doc.root.element_children.map(&:name)).to eq ['PartyId', 'PartyName', 'TradingName']
|
103
103
|
end
|
104
104
|
|
105
|
-
describe ':relative_provider
|
105
|
+
describe ':relative_provider option' do
|
106
106
|
class RelativeProviderTester
|
107
107
|
include DataProvider::Base
|
108
108
|
|
@@ -245,86 +245,59 @@ describe "XsdPopulator for partial layouts" do
|
|
245
245
|
expect(doc.search('/SoundRecordingDetailsByTerritory/Title').map{|node| node.attributes['TitleType'].value}).to eq ['typeA', 'typeB']
|
246
246
|
end
|
247
247
|
end
|
248
|
-
end
|
249
|
-
|
250
|
-
describe XsdPopulator::Informer do
|
251
|
-
class InformProvider
|
252
|
-
include DataProvider::Base
|
253
|
-
|
254
|
-
provides(['NewReleaseMessage', 'MessageHeader'] => XsdPopulator::Informer.new(:skip => true))
|
255
|
-
provides(['NewReleaseMessage', 'MessageHeader', 'MessageId'] => 123)
|
256
|
-
end
|
257
248
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
logger.level = Logger::WARN
|
265
|
-
logger
|
266
|
-
}
|
249
|
+
describe ':builder option' do
|
250
|
+
let(:builder){
|
251
|
+
b = Builder::XmlMarkup.new(:indent => 2)
|
252
|
+
b.instruct!
|
253
|
+
b
|
254
|
+
}
|
267
255
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
256
|
+
it 'lets you populate XML into an existing builder instance' do
|
257
|
+
# create two levels of arbitrary xml nodes
|
258
|
+
builder.genericRootNode do |xml|
|
259
|
+
xml.genericSubNode do |xml|
|
260
|
+
# insert the DDEX MessageSender (with nested content) inside our generic XML
|
261
|
+
populator.populate(:builder => xml, :element => ['NewReleaseMessage', 'MessageHeader', 'MessageSender'])
|
262
|
+
end
|
263
|
+
end
|
275
264
|
|
276
|
-
|
277
|
-
|
265
|
+
# verify our generic XML layout contains the MessageSender part of the DDEX xml
|
266
|
+
xml_string = builder.target!
|
267
|
+
doc = Nokogiri.XML(xml_string)
|
268
|
+
expect(doc.search('//genericRootNode/genericSubNode/MessageSender/PartyName/FullName').length).to eq 1
|
269
|
+
end
|
278
270
|
end
|
279
271
|
|
280
|
-
|
281
|
-
|
272
|
+
describe "full stack traversal" do
|
273
|
+
class FullStackProvider
|
282
274
|
include DataProvider::Base
|
283
275
|
|
284
|
-
provider ['NewReleaseMessage'
|
285
|
-
|
286
|
-
|
287
|
-
XsdPopulator::Informer.new(:attributes => {
|
288
|
-
'xmlns:ern' => 'http://ddex.net/xml/2010/ern-main/32',
|
289
|
-
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
290
|
-
'xsi:schemaLocation' => 'http://ddex.net/xml/2010/ern-main/32 http://ddex.net/xml/2010/ern-main/32/ern-main.xsd'
|
291
|
-
})
|
292
|
-
}
|
276
|
+
provider ['NewReleaseMessage'] do
|
277
|
+
self.add_data!(:party_id => 'NewReleaseID__')
|
278
|
+
end
|
293
279
|
|
294
|
-
|
280
|
+
provider ['NewReleaseMessage', 'MessageHeader', 'MessageId'] do
|
281
|
+
self.get_data(:party_id) || 'ID-Missing'
|
282
|
+
end
|
295
283
|
end
|
296
284
|
|
297
|
-
populator
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
expect(el.attributes.keys.length).to eq 2
|
307
|
-
|
308
|
-
expect(el.namespace_definitions.map{|nsdef| [nsdef.prefix, nsdef.href]}.sort).to eq([
|
309
|
-
['ern', 'http://ddex.net/xml/2010/ern-main/32'],
|
310
|
-
['xsi', 'http://www.w3.org/2001/XMLSchema-instance']
|
311
|
-
])
|
312
|
-
end
|
285
|
+
let(:populator){
|
286
|
+
XsdPopulator.new({
|
287
|
+
:element => ['NewReleaseMessage', 'MessageHeader'],
|
288
|
+
:reader=> xsd_reader,
|
289
|
+
:logger => logger,
|
290
|
+
:strategy => :complete,
|
291
|
+
:provider => FullStackProvider.new
|
292
|
+
})
|
293
|
+
}
|
313
294
|
|
314
|
-
|
315
|
-
|
316
|
-
|
295
|
+
let(:doc){
|
296
|
+
Nokogiri.XML(populator.populated_xml)
|
297
|
+
}
|
317
298
|
|
318
|
-
|
319
|
-
|
299
|
+
it "executes the data providers for the omitted parent elements" do
|
300
|
+
expect(doc.at('/MessageHeader/MessageId').inner_text).to eq 'NewReleaseID__'
|
320
301
|
end
|
321
|
-
|
322
|
-
populator = XsdPopulator.new({
|
323
|
-
:reader=> xsd_reader,
|
324
|
-
:logger => logger,
|
325
|
-
:provider => provider_class.new
|
326
|
-
})
|
327
|
-
|
328
|
-
expect(Nokogiri.XML(populator.populated_xml).root.name).to eq 'ern:NewReleaseMessage'
|
329
302
|
end
|
330
303
|
end
|
data/xsd-populator.gemspec
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "xsd-populator"
|
3
|
-
s.version = '0.2.
|
3
|
+
s.version = '0.2.1'
|
4
|
+
s.date = '2016-01-23'
|
4
5
|
s.files = `git ls-files`.split($/)
|
5
6
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
6
7
|
|
7
8
|
s.add_dependency 'builder', '~> 3.2'
|
8
9
|
s.add_dependency 'xsd-reader', '~> 0.2'
|
9
10
|
s.add_dependency 'data-provider', '~> 0.2'
|
11
|
+
s.add_development_dependency 'rake', '~> 10.1'
|
10
12
|
s.add_development_dependency 'nokogiri', '~> 1.6'
|
11
13
|
s.add_development_dependency 'rspec', '~> 3.3'
|
12
|
-
s.add_development_dependency 'byebug', '~> 5.0'
|
13
14
|
|
14
15
|
s.author = "Mark van de Korput"
|
15
16
|
s.email = "dr.theman@gmail.com"
|
16
|
-
|
17
|
+
|
17
18
|
s.summary = %q{A Ruby gem to build XML data from XSD schemas}
|
18
19
|
s.description = s.summary
|
19
20
|
s.homepage = %q{https://github.com/markkorput/xsd-populator}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xsd-populator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark van de Korput
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: builder
|
@@ -53,47 +53,47 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '1
|
61
|
+
version: '10.1'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '1
|
68
|
+
version: '10.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: nokogiri
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '1.6'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '1.6'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3.3'
|
97
97
|
description: A Ruby gem to build XML data from XSD schemas
|
98
98
|
email: dr.theman@gmail.com
|
99
99
|
executables: []
|
@@ -101,12 +101,14 @@ extensions: []
|
|
101
101
|
extra_rdoc_files: []
|
102
102
|
files:
|
103
103
|
- ".gitignore"
|
104
|
+
- ".travis.yml"
|
104
105
|
- Gemfile
|
105
106
|
- Gemfile.lock
|
106
107
|
- LICENSE
|
107
108
|
- README.md
|
108
109
|
- Rakefile
|
109
110
|
- lib/ddex_provider.rb
|
111
|
+
- lib/informer.rb
|
110
112
|
- lib/xsd_explanation_provider.rb
|
111
113
|
- lib/xsd_populator.rb
|
112
114
|
- spec/ddex_spec.rb
|
@@ -116,6 +118,7 @@ files:
|
|
116
118
|
- spec/examples/ddex-ern-v36-MessageHeader.xml
|
117
119
|
- spec/examples/ddex-ern-v36-NewReleaseMessage.xml
|
118
120
|
- spec/examples/ddex-ern-v36.xsd
|
121
|
+
- spec/informer_spec.rb
|
119
122
|
- spec/spec_helper.rb
|
120
123
|
- spec/xsd_explanation_provider_spec.rb
|
121
124
|
- spec/xsd_populator_spec.rb
|