xsd 2.1.0 → 2.2.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 +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
|