xsd 2.1.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile +1 -0
- data/lib/xsd/base_object.rb +33 -17
- data/lib/xsd/generator.rb +14 -9
- data/lib/xsd/objects/list.rb +1 -1
- data/lib/xsd/objects/schema.rb +122 -9
- data/lib/xsd/version.rb +1 -1
- data/lib/xsd/xml.rb +5 -15
- data/lib/xsd.rb +0 -1
- metadata +3 -4
- data/lib/xsd/validator.rb +0 -90
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dce377d21632c6a26b8cf654ec519d7fa7664a6518b136280433a1411580159c
|
4
|
+
data.tar.gz: 57ff6cd7eb787f93d1ab51b8ebcc170da4f9726105a584a3a9d69f24711fdd0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95c494a1699eee86c90989c1de42ef8f1532ea805273e1f35b2b7f2f6d68cc74f4a056ba1c71b5b3f3e9b7b80d9500b206fc684d4bddf4cb3563dda59d21fc48
|
7
|
+
data.tar.gz: d58a3a37ebd8104cbcd58eb416f127bd862f2c9e510bafafc83ffbefb257ce5ef1093d56db8a6ad0682137fbe9de04d67fa8d0e5d2b32f38a56e1b1a3fe0e0cc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [2.3.0] - 2023-09-06
|
4
|
+
|
5
|
+
- Fixed reading of SimpleType in List
|
6
|
+
- Add support for Restriction without base
|
7
|
+
- Support Any generation in simple scenarios
|
8
|
+
|
9
|
+
## [2.2.0] - 2023-07-10
|
10
|
+
|
11
|
+
- Fixed built-in types detection for unprefixed schema namespace
|
12
|
+
- Move validation to Schema object
|
13
|
+
|
3
14
|
## [2.1.0] - 2023-07-10
|
4
15
|
|
5
16
|
- Add support for <xs:include> element
|
data/Gemfile
CHANGED
data/lib/xsd/base_object.rb
CHANGED
@@ -32,14 +32,6 @@ module XSD
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
# Optional. Specifies a unique ID for the element
|
36
|
-
# @!attribute id
|
37
|
-
# @return String
|
38
|
-
# property :id, :string
|
39
|
-
def id
|
40
|
-
node['id']
|
41
|
-
end
|
42
|
-
|
43
35
|
def initialize(options = {})
|
44
36
|
@options = options
|
45
37
|
@cache = {}
|
@@ -53,6 +45,20 @@ module XSD
|
|
53
45
|
options[:node]
|
54
46
|
end
|
55
47
|
|
48
|
+
# Get object string representation
|
49
|
+
# @return String
|
50
|
+
def inspect
|
51
|
+
"#<#{self.class.name} path=#{node.path}>"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Optional. Specifies a unique ID for the element
|
55
|
+
# @!attribute id
|
56
|
+
# @return String
|
57
|
+
# property :id, :string
|
58
|
+
def id
|
59
|
+
node['id']
|
60
|
+
end
|
61
|
+
|
56
62
|
# Get current namespaces
|
57
63
|
# @return Hash
|
58
64
|
def namespaces
|
@@ -62,20 +68,20 @@ module XSD
|
|
62
68
|
# Get child nodes
|
63
69
|
# @param [Symbol] name
|
64
70
|
# @return Nokogiri::XML::NodeSet
|
65
|
-
def nodes(name =
|
66
|
-
node.xpath("
|
71
|
+
def nodes(name = :*, deep = false)
|
72
|
+
node.xpath("./#{deep ? '/' : ''}xs:#{name}", { 'xs' => XML_SCHEMA })
|
67
73
|
end
|
68
74
|
|
69
|
-
# Get
|
70
|
-
# @param [String, nil]
|
75
|
+
# Get schemas by namespace or prefix
|
76
|
+
# @param [String, nil] ns_or_prefix
|
71
77
|
# @return Array<Schema>
|
72
|
-
def schemas_for_namespace(
|
73
|
-
if schema.targets_namespace?(
|
78
|
+
def schemas_for_namespace(ns_or_prefix)
|
79
|
+
if schema.targets_namespace?(ns_or_prefix)
|
74
80
|
[schema, *schema.includes.map(&:imported_schema)]
|
75
|
-
elsif (import = schema.import_by_namespace(
|
81
|
+
elsif (import = schema.import_by_namespace(ns_or_prefix))
|
76
82
|
[import.imported_schema]
|
77
83
|
else
|
78
|
-
raise Error, "Schema not found for namespace '#{
|
84
|
+
raise Error, "Schema not found for namespace '#{ns_or_prefix}' in '#{schema.id || schema.target_namespace}'"
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
@@ -187,7 +193,7 @@ module XSD
|
|
187
193
|
# @param [Nokogiri::XML::Node] node
|
188
194
|
# @return Array<String>
|
189
195
|
def documentation_for(node)
|
190
|
-
node.xpath('./xs:annotation/xs:documentation/text()', { 'xs' => XML_SCHEMA }).map
|
196
|
+
node.xpath('./xs:annotation/xs:documentation/text()', { 'xs' => XML_SCHEMA }).map { |x| x.to_s.strip }
|
191
197
|
end
|
192
198
|
|
193
199
|
# Get all available elements on the current stack level
|
@@ -315,6 +321,9 @@ module XSD
|
|
315
321
|
name = link[:property] ? send(link[:property]) : nil
|
316
322
|
if name
|
317
323
|
return @cache[method] = object_by_name(link[:type], name)
|
324
|
+
elsif is_a?(Restriction) && method == :base_simple_type
|
325
|
+
# handle restriction without base
|
326
|
+
return nil
|
318
327
|
end
|
319
328
|
end
|
320
329
|
|
@@ -346,5 +355,12 @@ module XSD
|
|
346
355
|
name.to_sym
|
347
356
|
end
|
348
357
|
end
|
358
|
+
|
359
|
+
# Return string if it is not empty, or nil otherwise
|
360
|
+
# @param [String, nil] string
|
361
|
+
# @return String, nil
|
362
|
+
def nil_if_empty(string)
|
363
|
+
string&.empty? ? nil : string
|
364
|
+
end
|
349
365
|
end
|
350
366
|
end
|
data/lib/xsd/generator.rb
CHANGED
@@ -59,13 +59,13 @@ module XSD
|
|
59
59
|
# configure namespaces
|
60
60
|
# TODO: попытаться использовать collect_namespaces?
|
61
61
|
attributes = {}
|
62
|
-
|
62
|
+
all_attributes = element.collect_attributes
|
63
63
|
if element.complex?
|
64
|
-
|
64
|
+
all_elements = element.collect_elements
|
65
65
|
|
66
66
|
# get namespaces for current element and it's children
|
67
67
|
prefix = nil
|
68
|
-
[*
|
68
|
+
[*all_elements, element].each do |elem|
|
69
69
|
prefix = get_namespace_prefix(elem, attributes, namespaces)
|
70
70
|
end
|
71
71
|
else
|
@@ -75,7 +75,7 @@ module XSD
|
|
75
75
|
# iterate through each item
|
76
76
|
data.each do |item|
|
77
77
|
# prepare attributes
|
78
|
-
|
78
|
+
all_attributes.each do |attribute|
|
79
79
|
value = item["@#{attribute.name}"]
|
80
80
|
if value
|
81
81
|
attributes[attribute.name] = value
|
@@ -88,13 +88,18 @@ module XSD
|
|
88
88
|
if element.complex?
|
89
89
|
# generate tag recursively
|
90
90
|
xml.tag!("#{prefix}:#{element.name}", attributes) do
|
91
|
-
|
91
|
+
all_elements.each do |elem|
|
92
92
|
build_element(xml, elem, item, namespaces.dup)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
else
|
96
|
-
|
97
|
-
|
96
|
+
has_text = item.is_a?(Hash)
|
97
|
+
if has_text && element.complex_type&.nodes(:any, true)&.any?
|
98
|
+
xml.tag!("#{prefix}:#{element.name}", attributes) { |res| res << item['#text'].to_s }
|
99
|
+
else
|
100
|
+
value = has_text ? item['#text'] : item
|
101
|
+
xml.tag!("#{prefix}:#{element.name}", attributes, (value == '' ? nil : value))
|
102
|
+
end
|
98
103
|
end
|
99
104
|
end
|
100
105
|
end
|
@@ -108,7 +113,7 @@ module XSD
|
|
108
113
|
namespace = (element.referenced? ? element.reference : element).target_namespace
|
109
114
|
prefix = namespaces.key(namespace)
|
110
115
|
unless prefix
|
111
|
-
prefix = "
|
116
|
+
prefix = "n#{@namespace_index += 1}"
|
112
117
|
namespaces[prefix] = attributes["xmlns:#{prefix}"] = namespace
|
113
118
|
end
|
114
119
|
|
@@ -119,7 +124,7 @@ module XSD
|
|
119
124
|
# @param [String, Array<String>, nil] lookup
|
120
125
|
def find_root_element(lookup)
|
121
126
|
if lookup
|
122
|
-
element =
|
127
|
+
element = self[*lookup]
|
123
128
|
raise Error, "Cant find start element #{lookup}" unless element.is_a?(Element)
|
124
129
|
|
125
130
|
element
|
data/lib/xsd/objects/list.rb
CHANGED
data/lib/xsd/objects/schema.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'securerandom'
|
5
|
+
|
3
6
|
module XSD
|
4
7
|
# The schema element defines the root element of a schema.
|
5
8
|
# Parent elements: NONE
|
@@ -108,23 +111,23 @@ module XSD
|
|
108
111
|
attributes
|
109
112
|
end
|
110
113
|
|
111
|
-
# Get target namespace prefix
|
112
|
-
# @return String
|
114
|
+
# Get target namespace prefix
|
115
|
+
# @return String, nil
|
113
116
|
def target_namespace_prefix
|
114
|
-
@target_namespace_prefix ||= namespaces.key(target_namespace)&.sub(/^xmlns:?/, '') || ''
|
117
|
+
nil_if_empty(@target_namespace_prefix ||= namespaces.key(target_namespace)&.sub(/^xmlns:?/, '') || '')
|
115
118
|
end
|
116
119
|
|
117
120
|
# Get schema namespace prefix
|
118
|
-
# @return String
|
121
|
+
# @return String, nil
|
119
122
|
def namespace_prefix
|
120
|
-
@namespace_prefix ||= namespaces.key(XML_SCHEMA).sub(/^xmlns:?/, '')
|
123
|
+
nil_if_empty(@namespace_prefix ||= namespaces.key(XML_SCHEMA).sub(/^xmlns:?/, ''))
|
121
124
|
end
|
122
125
|
|
123
126
|
# Check if namespace is a target namespace
|
124
127
|
# @param [String, nil] namespace
|
125
128
|
# @return Boolean
|
126
129
|
def targets_namespace?(namespace)
|
127
|
-
namespace == target_namespace || namespaces[namespace.
|
130
|
+
namespace == target_namespace || namespaces[namespace.nil? ? 'xmlns' : "xmlns:#{namespace}"] == target_namespace
|
128
131
|
end
|
129
132
|
|
130
133
|
# Override map_children on schema to get objects from all loaded schemas
|
@@ -151,11 +154,121 @@ module XSD
|
|
151
154
|
end.compact.flatten
|
152
155
|
end
|
153
156
|
|
154
|
-
# Get import by namespace
|
157
|
+
# Get import by namespace or prefix
|
158
|
+
# @param [String, nil] ns_or_prefix
|
155
159
|
# @return Import
|
156
|
-
def import_by_namespace(
|
157
|
-
aliases = [
|
160
|
+
def import_by_namespace(ns_or_prefix)
|
161
|
+
aliases = [
|
162
|
+
ns_or_prefix,
|
163
|
+
namespaces["xmlns:#{(ns_or_prefix || '').gsub(/^xmlns:/, '')}"]
|
164
|
+
].compact
|
165
|
+
|
158
166
|
imports.find { |import| aliases.include?(import.namespace) }
|
159
167
|
end
|
168
|
+
|
169
|
+
# Validate XML against current schema
|
170
|
+
# @param [String, Pathname, Nokogiri::XML::Document] xml
|
171
|
+
def validate_xml(xml)
|
172
|
+
# validate input
|
173
|
+
raise ValidationError unless xml.is_a?(Nokogiri::XML::Document) || xml.is_a?(Pathname) || xml.is_a?(String)
|
174
|
+
|
175
|
+
begin
|
176
|
+
document = xml.is_a?(Nokogiri::XML::Document) ? xml : Nokogiri::XML(xml)
|
177
|
+
rescue Nokogiri::XML::SyntaxError => e
|
178
|
+
raise ValidationError, e
|
179
|
+
end
|
180
|
+
|
181
|
+
errors = schema_validator.validate(document)
|
182
|
+
raise ValidationError, errors.map(&:message).join('; ') if errors.any?
|
183
|
+
end
|
184
|
+
|
185
|
+
# Validate current schema against XMLSchema 1.0
|
186
|
+
def validate
|
187
|
+
begin
|
188
|
+
schema_validator
|
189
|
+
rescue Nokogiri::XML::SyntaxError => e
|
190
|
+
# TODO: display import map name for imported_xsd
|
191
|
+
message = e.message + (e.file ? " in file '#{File.basename(e.file)}'" : '')
|
192
|
+
raise ValidationError, message
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
# Get Nokogiri::XML::Schema object to validate against
|
199
|
+
# @return Nokogiri::XML::Schema
|
200
|
+
def schema_validator
|
201
|
+
return @schema_validator if @schema_validator
|
202
|
+
|
203
|
+
# if !imported_xsd.empty?
|
204
|
+
# imports are explicitly provided - put all files in one tmpdir and update import paths appropriately
|
205
|
+
# TODO: save file/path map to display in errors
|
206
|
+
Dir.mktmpdir('XSD', reader.tmp_dir) do |dir|
|
207
|
+
# create primary xsd file
|
208
|
+
file = "#{::SecureRandom.urlsafe_base64}.xsd"
|
209
|
+
|
210
|
+
# create imported xsd files
|
211
|
+
recursive_import_xsd(self, file, Set.new) do |f, data|
|
212
|
+
File.write("#{dir}/#{f}", data)
|
213
|
+
end
|
214
|
+
|
215
|
+
# read schema from tmp file descriptor
|
216
|
+
io = File.open("#{dir}/#{file}")
|
217
|
+
@schema_validator = create_xml_schema(io)
|
218
|
+
end
|
219
|
+
# else
|
220
|
+
# @schema_validator = create_xml_schema(schema.node.to_xml)
|
221
|
+
# end
|
222
|
+
|
223
|
+
@schema_validator
|
224
|
+
end
|
225
|
+
|
226
|
+
# Сформировать имена файлов и содержимое XSD схем для корректной валидации
|
227
|
+
# @param [Schema] schema
|
228
|
+
# @param [String] file
|
229
|
+
# @param [Set] processed
|
230
|
+
def recursive_import_xsd(schema, file, processed, &block)
|
231
|
+
# handle recursion
|
232
|
+
return if processed.include?(schema.target_namespace)
|
233
|
+
|
234
|
+
processed.add(schema.target_namespace)
|
235
|
+
|
236
|
+
# prepare schema XML with all namespaces included, clone node to avoid mutating original schema
|
237
|
+
node = schema.node
|
238
|
+
if node.namespaces.size != node.namespace_definitions.size
|
239
|
+
prefixes = node.namespace_definitions.map(&:prefix)
|
240
|
+
node = schema.node.dup
|
241
|
+
|
242
|
+
schema.node.namespaces.each do |attr, ns|
|
243
|
+
prefix = attr == 'xmlns' ? nil : attr.sub('xmlns:', '')
|
244
|
+
# does not work!
|
245
|
+
# node.add_namespace_definition(prefix, ns) unless prefixes.include?(prefix)
|
246
|
+
node[attr] = ns unless prefixes.include?(prefix)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
data = node.to_xml
|
251
|
+
|
252
|
+
schema.imports.each do |import|
|
253
|
+
name = "#{::SecureRandom.urlsafe_base64}.xsd"
|
254
|
+
location = import.schema_location
|
255
|
+
namespace = import.namespace
|
256
|
+
|
257
|
+
if location
|
258
|
+
data = data.sub("schemaLocation=\"#{location}\"", "schemaLocation=\"#{name}\"")
|
259
|
+
else
|
260
|
+
data = data.sub("namespace=\"#{namespace}\"", "namespace=\"#{namespace}\" schemaLocation=\"#{name}\"")
|
261
|
+
end
|
262
|
+
recursive_import_xsd(import.imported_schema, name, processed, &block)
|
263
|
+
end
|
264
|
+
|
265
|
+
block.call(file, data)
|
266
|
+
end
|
267
|
+
|
268
|
+
# Create Nokogiri XML Schema instance with preconfigured options
|
269
|
+
# @param [IO, String] io
|
270
|
+
def create_xml_schema(io)
|
271
|
+
Nokogiri::XML::Schema(io, Nokogiri::XML::ParseOptions.new.nononet)
|
272
|
+
end
|
160
273
|
end
|
161
274
|
end
|
data/lib/xsd/version.rb
CHANGED
data/lib/xsd/xml.rb
CHANGED
@@ -6,9 +6,8 @@ require 'net/http'
|
|
6
6
|
module XSD
|
7
7
|
class XML
|
8
8
|
include Generator
|
9
|
-
include Validator
|
10
9
|
|
11
|
-
attr_reader :options, :object_cache, :schemas
|
10
|
+
attr_reader :options, :object_cache, :schemas
|
12
11
|
|
13
12
|
DEFAULT_RESOURCE_RESOLVER = proc do |location, namespace|
|
14
13
|
if location =~ /^https?:/
|
@@ -75,10 +74,9 @@ module XSD
|
|
75
74
|
end
|
76
75
|
|
77
76
|
def initialize(**options)
|
78
|
-
@options
|
79
|
-
@object_cache
|
80
|
-
@schemas
|
81
|
-
@namespace_prefixes = {}
|
77
|
+
@options = options
|
78
|
+
@object_cache = {}
|
79
|
+
@schemas = []
|
82
80
|
end
|
83
81
|
|
84
82
|
def logger
|
@@ -116,24 +114,16 @@ module XSD
|
|
116
114
|
new_schema
|
117
115
|
end
|
118
116
|
|
119
|
-
# Add prefixes defined outside of processed schemas, for example in WSDL document
|
120
|
-
# @param [String] prefix
|
121
|
-
# @param [String] namespace
|
122
|
-
def add_namespace_prefix(prefix, namespace)
|
123
|
-
@namespace_prefixes[prefix] = namespace
|
124
|
-
end
|
125
|
-
|
126
117
|
# Get first added (considered primary) schema
|
127
118
|
# @return Schema, nil
|
128
119
|
def schema
|
129
120
|
schemas.first
|
130
121
|
end
|
131
122
|
|
132
|
-
# Get
|
123
|
+
# Get schemas by namespace
|
133
124
|
# @param [String, nil] namespace
|
134
125
|
# @return Array<Schema>
|
135
126
|
def schemas_for_namespace(namespace)
|
136
|
-
namespace = namespace_prefixes[namespace] if namespace_prefixes.key?(namespace)
|
137
127
|
schemas.select { |schema| schema.target_namespace == namespace }
|
138
128
|
end
|
139
129
|
|
data/lib/xsd.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xsd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- d.arkhipov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: builder
|
@@ -109,7 +109,6 @@ files:
|
|
109
109
|
- lib/xsd/shared/min_max_occurs.rb
|
110
110
|
- lib/xsd/shared/referenced.rb
|
111
111
|
- lib/xsd/shared/simple_typed.rb
|
112
|
-
- lib/xsd/validator.rb
|
113
112
|
- lib/xsd/version.rb
|
114
113
|
- lib/xsd/xml.rb
|
115
114
|
- xsd.gemspec
|
@@ -135,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
134
|
- !ruby/object:Gem::Version
|
136
135
|
version: '0'
|
137
136
|
requirements: []
|
138
|
-
rubygems_version: 3.
|
137
|
+
rubygems_version: 3.4.10
|
139
138
|
signing_key:
|
140
139
|
specification_version: 4
|
141
140
|
summary: The Ruby XSD library is an XML Schema implementation for Ruby.
|
data/lib/xsd/validator.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module XSD
|
4
|
-
module Validator
|
5
|
-
# Validate XML against XSD
|
6
|
-
# @param [String, Pathname, Nokogiri::XML::Document] xml
|
7
|
-
def validate_xml(xml)
|
8
|
-
# validate input
|
9
|
-
raise ValidationError unless xml.is_a?(Nokogiri::XML::Document) || xml.is_a?(Pathname) || xml.is_a?(String)
|
10
|
-
|
11
|
-
begin
|
12
|
-
document = xml.is_a?(Nokogiri::XML::Document) ? xml : Nokogiri::XML(xml)
|
13
|
-
rescue Nokogiri::XML::SyntaxError => e
|
14
|
-
raise ValidationError, e
|
15
|
-
end
|
16
|
-
|
17
|
-
errors = schema_validator.validate(document)
|
18
|
-
raise ValidationError, errors.map(&:message).join('; ') if errors.any?
|
19
|
-
end
|
20
|
-
|
21
|
-
# Validate XSD against another XSD (by default uses XMLSchema 1.0)
|
22
|
-
def validate
|
23
|
-
begin
|
24
|
-
schema_validator
|
25
|
-
rescue Nokogiri::XML::SyntaxError => e
|
26
|
-
# TODO: display import map name for imported_xsd
|
27
|
-
message = e.message + (e.file ? " in file '#{File.basename(e.file)}'" : '')
|
28
|
-
raise ValidationError, message
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
# Get Nokogiri::XML::Schema object to validate against
|
35
|
-
# @return Nokogiri::XML::Schema
|
36
|
-
def schema_validator
|
37
|
-
return @schema_validator if @schema_validator
|
38
|
-
|
39
|
-
if !imported_xsd.empty?
|
40
|
-
# imports are explicitly provided - put all files in one tmpdir and update import paths appropriately
|
41
|
-
# TODO: save file/path map to display in errors
|
42
|
-
Dir.mktmpdir('XSD', tmp_dir) do |dir|
|
43
|
-
# create primary xsd file
|
44
|
-
file = "#{SecureRandom.urlsafe_base64}.xsd"
|
45
|
-
|
46
|
-
# create imported xsd files
|
47
|
-
recursive_import_xsd(self, file, Set.new) do |f, data|
|
48
|
-
File.write("#{dir}/#{f}", data)
|
49
|
-
end
|
50
|
-
|
51
|
-
# read schema from tmp file descriptor
|
52
|
-
io = File.open("#{dir}/#{file}")
|
53
|
-
@schema_validator = create_xml_schema(io)
|
54
|
-
end
|
55
|
-
else
|
56
|
-
@schema_validator = create_xml_schema(self.xsd)
|
57
|
-
end
|
58
|
-
|
59
|
-
@schema_validator
|
60
|
-
end
|
61
|
-
|
62
|
-
# Сформировать имена файлов и содержимое XSD схем для корректной валидации
|
63
|
-
# @param [XML] reader
|
64
|
-
# @param [String] file
|
65
|
-
# @param [Set] processed
|
66
|
-
def recursive_import_xsd(reader, file, processed, &block)
|
67
|
-
# handle recursion
|
68
|
-
namespace = reader.schema.target_namespace
|
69
|
-
return if processed.include?(namespace)
|
70
|
-
|
71
|
-
processed.add(namespace)
|
72
|
-
|
73
|
-
data = reader.xml
|
74
|
-
|
75
|
-
reader.imports.each do |import|
|
76
|
-
name = "#{SecureRandom.urlsafe_base64}.xsd"
|
77
|
-
data = data.sub("schemaLocation=\"#{import.schema_location}\"", "schemaLocation=\"#{name}\"")
|
78
|
-
recursive_import_xsd(import.imported_reader, name, processed, &block)
|
79
|
-
end
|
80
|
-
|
81
|
-
block.call(file, data)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Create Nokogiri XML Schema instance with preconfigured options
|
85
|
-
# @param [IO] io
|
86
|
-
def create_xml_schema(io)
|
87
|
-
Nokogiri::XML::Schema(io, Nokogiri::XML::ParseOptions.new.nononet)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|