xsd-populator 0.1.0
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/.gitignore +35 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +71 -0
- data/LICENSE +22 -0
- data/README.md +2 -0
- data/Rakefile +20 -0
- data/lib/ddex_provider.rb +84 -0
- data/lib/xsd_explanation_provider.rb +28 -0
- data/lib/xsd_populator.rb +272 -0
- data/spec/ddex_spec.rb +57 -0
- data/spec/examples/MessageHeader.xml +70 -0
- data/spec/examples/avs.xsd +11257 -0
- data/spec/examples/ddex-ern-v36-CatalogListMessage.xml +1 -0
- data/spec/examples/ddex-ern-v36-MessageHeader.xml +1 -0
- data/spec/examples/ddex-ern-v36-NewReleaseMessage.xml +1 -0
- data/spec/examples/ddex-ern-v36.xsd +8815 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/xsd_explanation_provider_spec.rb +44 -0
- data/spec/xsd_populator_spec.rb +211 -0
- data/xsd-populator.gemspec +24 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a1fbb89bcd1d5fe7c9625230958c20b87d5b342c
|
4
|
+
data.tar.gz: 8a73b16dcb2de6df15f5f39a7c31e7a748f01343
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ddf9a33da6ed9f56877f073f620cfa40d67a619e89b84070f77dfb25074c36af12b040842bbd997cdc09668c4cdeb6245a7b3931c29f137bdbfd2110581aa8e3
|
7
|
+
data.tar.gz: ffd6b497de51f6cda4af3e8f2d6597961cc686db808ce559ba26617fa3dd7599e68a95492ab30c80ce81751290ca9deb6c2a18fd2f35e1f6b62529c2a9a1962e
|
data/.gitignore
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/vendor/bundle
|
26
|
+
/lib/bundler/man/
|
27
|
+
|
28
|
+
# for a library or gem, you might want to ignore these files since the code is
|
29
|
+
# intended to run in multiple environments; otherwise, check them in:
|
30
|
+
# Gemfile.lock
|
31
|
+
.ruby-version
|
32
|
+
.ruby-gemset
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
xsd-populator (0.0.1)
|
5
|
+
builder
|
6
|
+
data-provider (>= 0.0.1)
|
7
|
+
xsd-reader (>= 0.0.1)
|
8
|
+
|
9
|
+
PATH
|
10
|
+
remote: /srv/data-provider
|
11
|
+
specs:
|
12
|
+
data-provider (0.0.1)
|
13
|
+
|
14
|
+
PATH
|
15
|
+
remote: /srv/xsd-reader
|
16
|
+
specs:
|
17
|
+
xsd-reader (0.1.0)
|
18
|
+
nokogiri
|
19
|
+
rest-client
|
20
|
+
|
21
|
+
GEM
|
22
|
+
remote: https://rubygems.org/
|
23
|
+
specs:
|
24
|
+
builder (3.2.2)
|
25
|
+
byebug (5.0.0)
|
26
|
+
columnize (= 0.9.0)
|
27
|
+
columnize (0.9.0)
|
28
|
+
diff-lcs (1.2.5)
|
29
|
+
domain_name (0.5.24)
|
30
|
+
unf (>= 0.0.5, < 1.0.0)
|
31
|
+
http-cookie (1.0.2)
|
32
|
+
domain_name (~> 0.5)
|
33
|
+
mime-types (2.6.1)
|
34
|
+
mini_portile (0.6.2)
|
35
|
+
netrc (0.10.3)
|
36
|
+
nokogiri (1.6.6.2)
|
37
|
+
mini_portile (~> 0.6.0)
|
38
|
+
rest-client (1.8.0)
|
39
|
+
http-cookie (>= 1.0.2, < 2.0)
|
40
|
+
mime-types (>= 1.16, < 3.0)
|
41
|
+
netrc (~> 0.7)
|
42
|
+
rspec (3.3.0)
|
43
|
+
rspec-core (~> 3.3.0)
|
44
|
+
rspec-expectations (~> 3.3.0)
|
45
|
+
rspec-mocks (~> 3.3.0)
|
46
|
+
rspec-core (3.3.1)
|
47
|
+
rspec-support (~> 3.3.0)
|
48
|
+
rspec-expectations (3.3.0)
|
49
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
50
|
+
rspec-support (~> 3.3.0)
|
51
|
+
rspec-mocks (3.3.1)
|
52
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
53
|
+
rspec-support (~> 3.3.0)
|
54
|
+
rspec-support (3.3.0)
|
55
|
+
unf (0.1.4)
|
56
|
+
unf_ext
|
57
|
+
unf_ext (0.0.7.1)
|
58
|
+
|
59
|
+
PLATFORMS
|
60
|
+
ruby
|
61
|
+
|
62
|
+
DEPENDENCIES
|
63
|
+
byebug
|
64
|
+
data-provider!
|
65
|
+
nokogiri
|
66
|
+
rspec
|
67
|
+
xsd-populator!
|
68
|
+
xsd-reader!
|
69
|
+
|
70
|
+
BUNDLED WITH
|
71
|
+
1.10.5
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Mark
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# rxsd project Rakefile
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
|
4
|
+
# Licensed under the LGPLv3+ http://www.gnu.org/licenses/lgpl.txt
|
5
|
+
|
6
|
+
require 'rdoc/task'
|
7
|
+
require "rspec/core/rake_task"
|
8
|
+
|
9
|
+
task :default => :rspec do; end
|
10
|
+
|
11
|
+
desc "Run all specs"
|
12
|
+
RSpec::Core::RakeTask.new('rspec') do |t|
|
13
|
+
t.pattern = 'spec/**/*_spec.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
Rake::RDocTask.new do |rd|
|
17
|
+
rd.main = "README.rdoc"
|
18
|
+
rd.rdoc_dir = "doc/site/api"
|
19
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
20
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'data_provider'
|
2
|
+
|
3
|
+
module DdexProvider
|
4
|
+
|
5
|
+
module MessageSender
|
6
|
+
include DataProvider::Base
|
7
|
+
|
8
|
+
provider '@LanguageAndScriptCode' do 'EN' end
|
9
|
+
provider 'PartyId' do 404 end
|
10
|
+
|
11
|
+
end # module MessageSender
|
12
|
+
|
13
|
+
module MessageRecipient
|
14
|
+
include DataProvider::Base
|
15
|
+
|
16
|
+
# provides multiple party ids; this will result in 3 <PartyId> nodes
|
17
|
+
# within the <MessageRecipient> node
|
18
|
+
provider 'PartyId' do
|
19
|
+
[12, 34, 56]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Because the 'PartyId' provides 3 values, 3 nodes will be created
|
23
|
+
# because the ['PartyId', '@IsDPID'] provider provides only one value,
|
24
|
+
# all 3 PartyId nodes will get the same value for their IsDPID attribute
|
25
|
+
provider ['PartyId', '@IsDPID'] do
|
26
|
+
'TRUTH'
|
27
|
+
end
|
28
|
+
|
29
|
+
end # module MessageRecipient
|
30
|
+
|
31
|
+
module SentOnBehalfOf
|
32
|
+
include DataProvider::Base
|
33
|
+
|
34
|
+
# provides multiple party ids; this will result in 3 <PartyId> nodes
|
35
|
+
# within the <SentOnBehalfOf> node
|
36
|
+
provider 'PartyId' do
|
37
|
+
[9,8,7]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Because the 'PartyId' provides 3 values, 3 nodes will be created
|
41
|
+
# because the ['PartyId', '@IsDPID'] provider provides only two values for the third,
|
42
|
+
# nil value will be assumed and a warning will be logged
|
43
|
+
provider ['PartyId', '@IsDPID'] do
|
44
|
+
['true', 'false']
|
45
|
+
end
|
46
|
+
|
47
|
+
end # module SentOnBehalfOf
|
48
|
+
|
49
|
+
|
50
|
+
module MessageHeader
|
51
|
+
include DataProvider::Base
|
52
|
+
|
53
|
+
provider '@LanguageAndScriptCode' do
|
54
|
+
'NL'
|
55
|
+
end
|
56
|
+
|
57
|
+
provider 'MessageThreadId' do
|
58
|
+
123.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
add_scoped MessageSender, :scope => 'MessageSender'
|
62
|
+
add_scoped SentOnBehalfOf, :scope => 'SentOnBehalfOf'
|
63
|
+
add_scoped MessageRecipient, :scope => 'MessageRecipient'
|
64
|
+
|
65
|
+
provider ['MessageAuditTrail', 'MessageAuditTrailEvent'] do
|
66
|
+
# gives three new data providers with each their own :name
|
67
|
+
['John', 'Billy', 'Bob'].map do |name|
|
68
|
+
self.give(:name => name)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
provider ['MessageAuditTrail', 'MessageAuditTrailEvent', 'MessagingPartyDescriptor', 'PartyName', 'FullName'], :requires => [:name] do
|
73
|
+
given(:name)
|
74
|
+
end
|
75
|
+
|
76
|
+
end # module MessageHeader
|
77
|
+
|
78
|
+
|
79
|
+
class MessageHeaderProvider
|
80
|
+
include DataProvider::Base
|
81
|
+
add_scoped MessageHeader, :scope => 'MessageHeader'
|
82
|
+
end # class Provider
|
83
|
+
|
84
|
+
end # module DdexProvider
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'data_provider'
|
2
|
+
|
3
|
+
class XsdExplanationProvider
|
4
|
+
include DataProvider::Base
|
5
|
+
|
6
|
+
provider_missing do
|
7
|
+
raise 'XsdExplanationProvider needs an xsd reader' if (reader = get_data(:xsd_reader)).nil?
|
8
|
+
|
9
|
+
logger.debug "XsdExplanationProvider got provider id: #{missing_provider}"
|
10
|
+
item = reader[missing_provider]
|
11
|
+
|
12
|
+
if item.is_a?(XsdReader::Attribute)
|
13
|
+
item.type
|
14
|
+
elsif item.is_a?(XsdReader::Element) && item.child_elements?
|
15
|
+
# return self, the data provider, so the populator can continue with the child elements
|
16
|
+
self
|
17
|
+
elsif item
|
18
|
+
if item.complex_type && item.complex_type.simple_content && item.complex_type.simple_content.extension
|
19
|
+
item.complex_type.simple_content.extension.base
|
20
|
+
else
|
21
|
+
item.type
|
22
|
+
end
|
23
|
+
else
|
24
|
+
logger.warn "XsdExplanationProvider could not find XSD information for provider `#{missing_provider.inspect}` in XSD file `#{reader.options[:xsd_file]}`"
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end # class XsdExplanationProvider
|
@@ -0,0 +1,272 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'builder'
|
3
|
+
require 'xsd_reader'
|
4
|
+
require 'xsd_explanation_provider'
|
5
|
+
|
6
|
+
class XsdPopulator
|
7
|
+
|
8
|
+
class ElementNotFoundException < Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
def initialize(_opts = {})
|
14
|
+
configure _opts
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure _opts = {}
|
18
|
+
@options = (@options || {}).merge(_opts.is_a?(Hash) ? _opts : {})
|
19
|
+
# remove some cached values
|
20
|
+
@logger = nil if _opts[:logger]
|
21
|
+
@xsd_reader = nil if _opts[:xsd_reader] || _opts[:reader]
|
22
|
+
uncache if _opts[:strategy]
|
23
|
+
end
|
24
|
+
|
25
|
+
def uncache
|
26
|
+
@populated_xml = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger
|
30
|
+
return @logger || options[:logger] if @logger || options[:logger]
|
31
|
+
@logger = Logger.new(STDOUT)
|
32
|
+
@logger.level = Logger::WARN
|
33
|
+
return @logger
|
34
|
+
end
|
35
|
+
|
36
|
+
def xsd_file
|
37
|
+
options[:xsd_file] || options[:xsd]
|
38
|
+
end
|
39
|
+
|
40
|
+
def xsd_reader
|
41
|
+
@xsd_reader ||= options[:xsd_reader] || options[:reader] || (xsd_file.nil? ? nil : XsdReader::XML.new(:xsd_file => xsd_file, :logger => logger))
|
42
|
+
end
|
43
|
+
|
44
|
+
alias :reader :xsd_reader
|
45
|
+
|
46
|
+
def provider
|
47
|
+
options[:provider] || options[:data_provider] || default_provider
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_provider
|
51
|
+
@default_provider ||= XsdExplanationProvider.new(:data => {:xsd_reader => xsd_reader}, :logger => logger)
|
52
|
+
end
|
53
|
+
|
54
|
+
def populated_xml
|
55
|
+
@populated_xml ||= populate_xml
|
56
|
+
end
|
57
|
+
|
58
|
+
def populate_element(element_specifier = nil)
|
59
|
+
element_specifier.nil? ? populated_xml : populate_xml(element_specifier)
|
60
|
+
end
|
61
|
+
|
62
|
+
def write_file(path)
|
63
|
+
# logger.debug "XsdPopulator#write_file to: #{path}"
|
64
|
+
File.write(path, populated_xml)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def populate_xml(element_specifier = nil)
|
70
|
+
if (root_el = root_xsd_element(element_specifier)).nil?
|
71
|
+
logger.warn "Couldn't find element definition, aborting"
|
72
|
+
return nil
|
73
|
+
end
|
74
|
+
|
75
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
76
|
+
xml.instruct!
|
77
|
+
|
78
|
+
stack = options[:relative_provider] == true ? [] : [element_specifier || options[:element]].flatten.compact
|
79
|
+
stack.pop
|
80
|
+
build_element(xml, root_el, self.provider, stack)
|
81
|
+
|
82
|
+
return xml.target!
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_element(xml, element, provider = self.provider, stack = [])
|
86
|
+
# TODO; more sophisticated recursion detection;
|
87
|
+
# multiple elements of the same name should be able
|
88
|
+
# to occur insid the stack
|
89
|
+
if stack.include?(element.name)
|
90
|
+
logger.warn("XsdPopulator#build_element aborting because of potential endless recursion\n - Current element: #{element.name}\n - stack: #{stack.inspect}")
|
91
|
+
return
|
92
|
+
end
|
93
|
+
|
94
|
+
# let's log positive stuff as well
|
95
|
+
logger.debug("XsdPopulator#build_element element: #{element.name}, stack: #{stack.inspect}")
|
96
|
+
|
97
|
+
# get node content data from provider
|
98
|
+
content_data = provider.nil? ? nil : provider.try_take(stack + [element.name])
|
99
|
+
# get attributes content from the provider
|
100
|
+
attributes_data_hash = attributes_data_hash_for(element, provider, stack)
|
101
|
+
|
102
|
+
if explain_xml? && element.multiple_allowed?
|
103
|
+
xml.comment!("Multiple instances of #{element.name} allowed here")
|
104
|
+
end
|
105
|
+
|
106
|
+
# just log a warning if we got an array value for an element that is not allowed
|
107
|
+
# to occurs multiple times according to the XSD schema (but still allow data provider to generate the xml)
|
108
|
+
if content_data.is_a?(Array) && !element.multiple_allowed?
|
109
|
+
logger.warn("Got array value (provider id: #{(stack + [element.name]).inspect}) but element definition doesn't allow multiple instances")
|
110
|
+
end
|
111
|
+
|
112
|
+
# make sure it's an array
|
113
|
+
content_data = [content_data].flatten # if element.multiple_allowed? && content_data.is_a?(Array)
|
114
|
+
# NOTE: this doesn't array-values for single elements, which we don't support (would be turned into a string anway)
|
115
|
+
|
116
|
+
content_data.each_with_index do |node_content, idx|
|
117
|
+
# let's see if the provided data is good for building this node, accoridng to the current strategy
|
118
|
+
next if !build?(element, provider, stack, :content => node_content)
|
119
|
+
|
120
|
+
attributes_hash = attributes_hash_for_index(attributes_data_hash, idx)
|
121
|
+
|
122
|
+
# simple node; name, value, attributes
|
123
|
+
if !element.child_elements?
|
124
|
+
xml.tag!(element.name, node_content, attributes_hash)
|
125
|
+
next
|
126
|
+
end
|
127
|
+
|
128
|
+
# complex node
|
129
|
+
if node_content.respond_to?(:try_take)
|
130
|
+
child_provider = node_content
|
131
|
+
else
|
132
|
+
logger.warn "Got non-nil and non-provider value for element with child elements (value: #{node_content}, element: #{element.name}, stack: #{stack.inspect})" if node_content
|
133
|
+
# strategy dictates to continue; just use the current element's provider for its children
|
134
|
+
child_provider = provider
|
135
|
+
end
|
136
|
+
|
137
|
+
# create complex node
|
138
|
+
xml.tag!(element.name, attributes_hash) do
|
139
|
+
# loop over all child node definitions
|
140
|
+
element.elements.each do |child|
|
141
|
+
# this method call itself recursively for every child node definition of the current element
|
142
|
+
build_element(xml, child, child_provider, stack + [element.name])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
#
|
150
|
+
# Attribute data
|
151
|
+
#
|
152
|
+
|
153
|
+
def attributes_data_hash_for(element, provider, stack)
|
154
|
+
element.attributes.inject({}) do |result, attribute|
|
155
|
+
attribute_data = provider.nil? ? nil : provider.try_take(stack + [element.name, "@#{attribute.name}"])
|
156
|
+
# attribute_data ||= attribute.type if provider.nil? # assume demo xml
|
157
|
+
if add_attribute?(attribute, provider, stack, :content => attribute_data)
|
158
|
+
result.merge(attribute.name => attribute_data)
|
159
|
+
else
|
160
|
+
result
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def attribute_value_for_index(values, idx)
|
166
|
+
# if the provided attribute content is an array, just use the appropriate element
|
167
|
+
# if the array does not have enough element, this will default to nil
|
168
|
+
# if values is not an array, just always use its singular value
|
169
|
+
values.is_a?(Array) ? values[idx] : values
|
170
|
+
end
|
171
|
+
|
172
|
+
def attributes_hash_for_index(attribute_data_hash, idx)
|
173
|
+
# each of the attribute values can be an array as well. If not,
|
174
|
+
# we'll just use it's singular value for all instances of this node
|
175
|
+
# if there
|
176
|
+
current_attrs = attribute_data_hash.to_a.inject({}) do |result, key_value|
|
177
|
+
key = key_value[0]
|
178
|
+
value = key_value[1]
|
179
|
+
logger.warn "XsdPopulator#attributes_hash_for_index - got an array with insufficient values for attribute `#{key}`. Attribute data hash: #{attribute_data_hash}, index: #{idx}" if value.is_a?(Array) && value.length <= idx
|
180
|
+
attr_value = attribute_value_for_index(value, idx)
|
181
|
+
result.merge(key => attr_value)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
#
|
187
|
+
# Root element
|
188
|
+
#
|
189
|
+
def specified_xsd_element(specifier = nil)
|
190
|
+
# nothing specified
|
191
|
+
return nil if (specifier || options[:element]).nil?
|
192
|
+
# find specified element
|
193
|
+
el = xsd_reader[[(specifier || options[:element])].flatten.compact]
|
194
|
+
raise ElementNotFoundException.new(:message => "Could not find specified root element (#{(specifier || options[:element]).inspect}).") if el.nil?
|
195
|
+
# log warning if specified element not found
|
196
|
+
logger.warn "XsdPopulator#populate_xml - Specified element (#{options[:element].inspect}) not found, reverting to default" if el.nil?
|
197
|
+
# return result
|
198
|
+
return el
|
199
|
+
end
|
200
|
+
|
201
|
+
def root_xsd_element(specifier = nil)
|
202
|
+
el = specified_xsd_element(specifier)
|
203
|
+
|
204
|
+
# no element specified? (or found)
|
205
|
+
if el
|
206
|
+
# log inform notice that we're using the explicitly specified element
|
207
|
+
logger.info "XsdPopulator#populate_xml - Starting at specified element: #{el.name}"
|
208
|
+
else
|
209
|
+
# default: just take the first defined element
|
210
|
+
el ||= xsd_reader.elements.first
|
211
|
+
|
212
|
+
# if there are multiple root-level elements in the xsd, let the user know, we're only processing the fist one
|
213
|
+
if el && xsd_reader.elements.length > 1
|
214
|
+
logger.info "XsdPopulator#populate_xml - Multiple root-level element definitions found in XSD schema, only processing the first one (#{el.name})"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
return el
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
# Strategy
|
223
|
+
#
|
224
|
+
public
|
225
|
+
|
226
|
+
def strategy
|
227
|
+
options[:strategy] || (explain_xml? ? :complete : :smart)
|
228
|
+
end
|
229
|
+
|
230
|
+
def explain_xml?
|
231
|
+
provider == default_provider
|
232
|
+
end
|
233
|
+
|
234
|
+
def build_node_without_provider?
|
235
|
+
strategy == :complete
|
236
|
+
end
|
237
|
+
|
238
|
+
def add_simple_nodes_without_data?
|
239
|
+
strategy == :nil_to_empty || strategy == :complete
|
240
|
+
end
|
241
|
+
|
242
|
+
def build?(element, provider, stack, opts = {})
|
243
|
+
content = opts[:content] || provider.try_take([stack, element.name].flatten.compact)
|
244
|
+
|
245
|
+
# For comlex nodes we need either;
|
246
|
+
# - a data provider or
|
247
|
+
# - explicit confirmation to build without providers or
|
248
|
+
# - providers available for offspring elements
|
249
|
+
if element.child_elements?
|
250
|
+
return content.respond_to?(:try_take) || build_node_without_provider? || provider.has_providers_with_scope?(stack + [element.name])
|
251
|
+
end
|
252
|
+
|
253
|
+
# we got a non-nil value for a simple node? Go ahead
|
254
|
+
return true if content || add_simple_nodes_without_data?
|
255
|
+
|
256
|
+
return false
|
257
|
+
|
258
|
+
# !build_node_without_provider? ||
|
259
|
+
# return true if provider
|
260
|
+
end
|
261
|
+
|
262
|
+
def add_empty_attributes?
|
263
|
+
strategy == :nil_to_empty || strategy == :complete
|
264
|
+
end
|
265
|
+
|
266
|
+
def add_attribute?(attribute, provider, stack = [], opts = {})
|
267
|
+
return true if attribute.required?
|
268
|
+
content = opts[:content] || provider.try_take(stack + ["@#{attribute.name}"])
|
269
|
+
return (!content.nil?) || add_empty_attributes?
|
270
|
+
end
|
271
|
+
end # class XsdPopulator
|
272
|
+
|