xsd 2.1.0 → 2.2.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/xsd/base_object.rb +7 -0
- data/lib/xsd/objects/schema.rb +101 -6
- data/lib/xsd/version.rb +1 -1
- data/lib/xsd/xml.rb +0 -1
- data/lib/xsd.rb +0 -1
- metadata +1 -2
- 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: ab9eaf4eb6b8aacde5379acdc08cc16c3d85e3dc9d75a5887b2f1db05ea6ed58
|
4
|
+
data.tar.gz: 8c5fdbf108a6867689ff3292a5e208a33160f232b4a3d3a96eb55e42e9b6da7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d75af5531e7763eb3bc9359b2992e03704d963cfbc394a863022a3ff8db87d97db368409666bc7540f2fc772b78e2b25ab59905301e19d370827750050823462
|
7
|
+
data.tar.gz: 2b06fd643f69e41017683b689e614dbef7c42dca4fefbdec753f7f8edcc0978caf80eefe8c7d68e4acdc86aadd2777160a5cd7105a776d13ebfc2c57fc5af45c
|
data/CHANGELOG.md
CHANGED
data/lib/xsd/base_object.rb
CHANGED
@@ -346,5 +346,12 @@ module XSD
|
|
346
346
|
name.to_sym
|
347
347
|
end
|
348
348
|
end
|
349
|
+
|
350
|
+
# Return string if it is not empty, or nil otherwise
|
351
|
+
# @param [String, nil] string
|
352
|
+
# @return String, nil
|
353
|
+
def nil_if_empty(string)
|
354
|
+
string&.empty? ? nil : string
|
355
|
+
end
|
349
356
|
end
|
350
357
|
end
|
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
|
@@ -157,5 +160,97 @@ module XSD
|
|
157
160
|
aliases = [ns, namespaces["xmlns:#{(ns || '').gsub(/^xmlns:/, '')}"], reader.namespace_prefixes[ns]].compact
|
158
161
|
imports.find { |import| aliases.include?(import.namespace) }
|
159
162
|
end
|
163
|
+
|
164
|
+
# Validate XML against current schema
|
165
|
+
# @param [String, Pathname, Nokogiri::XML::Document] xml
|
166
|
+
def validate_xml(xml)
|
167
|
+
# validate input
|
168
|
+
raise ValidationError unless xml.is_a?(Nokogiri::XML::Document) || xml.is_a?(Pathname) || xml.is_a?(String)
|
169
|
+
|
170
|
+
begin
|
171
|
+
document = xml.is_a?(Nokogiri::XML::Document) ? xml : Nokogiri::XML(xml)
|
172
|
+
rescue Nokogiri::XML::SyntaxError => e
|
173
|
+
raise ValidationError, e
|
174
|
+
end
|
175
|
+
|
176
|
+
errors = schema_validator.validate(document)
|
177
|
+
raise ValidationError, errors.map(&:message).join('; ') if errors.any?
|
178
|
+
end
|
179
|
+
|
180
|
+
# Validate current schema against XMLSchema 1.0
|
181
|
+
def validate
|
182
|
+
begin
|
183
|
+
schema_validator
|
184
|
+
rescue Nokogiri::XML::SyntaxError => e
|
185
|
+
# TODO: display import map name for imported_xsd
|
186
|
+
message = e.message + (e.file ? " in file '#{File.basename(e.file)}'" : '')
|
187
|
+
raise ValidationError, message
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
# Get Nokogiri::XML::Schema object to validate against
|
194
|
+
# @return Nokogiri::XML::Schema
|
195
|
+
def schema_validator
|
196
|
+
return @schema_validator if @schema_validator
|
197
|
+
|
198
|
+
# if !imported_xsd.empty?
|
199
|
+
# imports are explicitly provided - put all files in one tmpdir and update import paths appropriately
|
200
|
+
# TODO: save file/path map to display in errors
|
201
|
+
Dir.mktmpdir('XSD', reader.tmp_dir) do |dir|
|
202
|
+
# create primary xsd file
|
203
|
+
file = "#{::SecureRandom.urlsafe_base64}.xsd"
|
204
|
+
|
205
|
+
# create imported xsd files
|
206
|
+
recursive_import_xsd(self, file, Set.new) do |f, data|
|
207
|
+
File.write("#{dir}/#{f}", data)
|
208
|
+
end
|
209
|
+
|
210
|
+
# read schema from tmp file descriptor
|
211
|
+
io = File.open("#{dir}/#{file}")
|
212
|
+
@schema_validator = create_xml_schema(io)
|
213
|
+
end
|
214
|
+
# else
|
215
|
+
# @schema_validator = create_xml_schema(schema.node.to_xml)
|
216
|
+
# end
|
217
|
+
|
218
|
+
@schema_validator
|
219
|
+
end
|
220
|
+
|
221
|
+
# Сформировать имена файлов и содержимое XSD схем для корректной валидации
|
222
|
+
# @param [Schema] schema
|
223
|
+
# @param [String] file
|
224
|
+
# @param [Set] processed
|
225
|
+
def recursive_import_xsd(schema, file, processed, &block)
|
226
|
+
# handle recursion
|
227
|
+
namespace = schema.target_namespace
|
228
|
+
return if processed.include?(namespace)
|
229
|
+
|
230
|
+
processed.add(namespace)
|
231
|
+
|
232
|
+
data = schema.node.to_xml
|
233
|
+
|
234
|
+
schema.imports.each do |import|
|
235
|
+
name = "#{::SecureRandom.urlsafe_base64}.xsd"
|
236
|
+
location = import.schema_location
|
237
|
+
namespace = import.namespace
|
238
|
+
|
239
|
+
if location
|
240
|
+
data = data.sub("schemaLocation=\"#{location}\"", "schemaLocation=\"#{name}\"")
|
241
|
+
else
|
242
|
+
data = data.sub("namespace=\"#{namespace}\"", "namespace=\"#{namespace}\" schemaLocation=\"#{name}\"")
|
243
|
+
end
|
244
|
+
recursive_import_xsd(import.imported_schema, name, processed, &block)
|
245
|
+
end
|
246
|
+
|
247
|
+
block.call(file, data)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Create Nokogiri XML Schema instance with preconfigured options
|
251
|
+
# @param [IO, String] io
|
252
|
+
def create_xml_schema(io)
|
253
|
+
Nokogiri::XML::Schema(io, Nokogiri::XML::ParseOptions.new.nononet)
|
254
|
+
end
|
160
255
|
end
|
161
256
|
end
|
data/lib/xsd/version.rb
CHANGED
data/lib/xsd/xml.rb
CHANGED
data/lib/xsd.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xsd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- d.arkhipov
|
@@ -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
|
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
|