xsd-populator 0.2.0 → 0.2.1
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/.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
|
+
[](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
|