xseed 1.0.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/.github/workflows/rake.yml +16 -0
- data/.github/workflows/release.yml +25 -0
- data/.gitignore +72 -0
- data/.rspec +3 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +432 -0
- data/CHANGELOG.adoc +446 -0
- data/Gemfile +21 -0
- data/LICENSE.adoc +29 -0
- data/README.adoc +386 -0
- data/Rakefile +11 -0
- data/examples/README.adoc +334 -0
- data/examples/advanced_usage.rb +286 -0
- data/examples/html_generation.rb +167 -0
- data/examples/parser_usage.rb +102 -0
- data/examples/schemas/person.xsd +171 -0
- data/examples/simple_generation.rb +149 -0
- data/exe/xseed +6 -0
- data/lib/xseed/cli.rb +376 -0
- data/lib/xseed/documentation/config.rb +101 -0
- data/lib/xseed/documentation/constants.rb +76 -0
- data/lib/xseed/documentation/generators/hierarchy_table_generator.rb +554 -0
- data/lib/xseed/documentation/generators/instance_sample_generator.rb +723 -0
- data/lib/xseed/documentation/generators/properties_table_generator.rb +983 -0
- data/lib/xseed/documentation/html_generator.rb +836 -0
- data/lib/xseed/documentation/html_generator.rb.bak +723 -0
- data/lib/xseed/documentation/presentation/css_generator.rb +510 -0
- data/lib/xseed/documentation/presentation/javascript_generator.rb +151 -0
- data/lib/xseed/documentation/presentation/navigation_builder.rb +169 -0
- data/lib/xseed/documentation/schema_loader.rb +121 -0
- data/lib/xseed/documentation/utils/helpers.rb +205 -0
- data/lib/xseed/documentation/utils/namespaces.rb +149 -0
- data/lib/xseed/documentation/utils/references.rb +135 -0
- data/lib/xseed/documentation/utils/strings.rb +75 -0
- data/lib/xseed/models/element_declaration.rb +144 -0
- data/lib/xseed/parser/xsd_parser.rb +192 -0
- data/lib/xseed/version.rb +5 -0
- data/lib/xseed.rb +76 -0
- data/xseed.gemspec +39 -0
- metadata +158 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "nokogiri"
|
|
4
|
+
require_relative "../config"
|
|
5
|
+
require_relative "../constants"
|
|
6
|
+
|
|
7
|
+
module Xseed
|
|
8
|
+
module Documentation
|
|
9
|
+
module Generators
|
|
10
|
+
# Generates HTML hierarchy tables for schema components
|
|
11
|
+
# Shows type hierarchies and substitution groups
|
|
12
|
+
# Ported from XS3P hierarchy-tables.xsl
|
|
13
|
+
class HierarchyTableGenerator
|
|
14
|
+
include Constants
|
|
15
|
+
|
|
16
|
+
attr_reader :component, :parser, :config
|
|
17
|
+
|
|
18
|
+
# Initialize the hierarchy table generator
|
|
19
|
+
#
|
|
20
|
+
# @param component [Nokogiri::XML::Element] Schema component
|
|
21
|
+
# @param parser [Xseed::Parser::XsdParser] XSD parser instance
|
|
22
|
+
# @param config [Config] Configuration options
|
|
23
|
+
def initialize(component, parser, config = Config.new)
|
|
24
|
+
raise ArgumentError, "Component cannot be nil" if component.nil?
|
|
25
|
+
raise ArgumentError, "Parser cannot be nil" if parser.nil?
|
|
26
|
+
|
|
27
|
+
@component = component
|
|
28
|
+
@parser = parser
|
|
29
|
+
@config = config
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Generate HTML hierarchy table
|
|
33
|
+
#
|
|
34
|
+
# @return [String, nil] HTML table markup or nil if no hierarchy
|
|
35
|
+
def generate
|
|
36
|
+
return nil unless has_hierarchy?
|
|
37
|
+
|
|
38
|
+
builder = Nokogiri::HTML::Builder.new do |html|
|
|
39
|
+
html.div(class: "hierarchy") do
|
|
40
|
+
html.table(class: "table table-striped xs3p-in-panel-table") do
|
|
41
|
+
html.tbody do
|
|
42
|
+
if element?
|
|
43
|
+
generate_substitution_groups(html)
|
|
44
|
+
elsif complex_type?
|
|
45
|
+
generate_complex_type_hierarchy(html)
|
|
46
|
+
elsif simple_type?
|
|
47
|
+
generate_simple_type_hierarchy(html)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
builder.to_html
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Check if component has hierarchy to display
|
|
59
|
+
#
|
|
60
|
+
# @return [Boolean]
|
|
61
|
+
def has_hierarchy?
|
|
62
|
+
if element?
|
|
63
|
+
# Element has hierarchy if it has substitutionGroup or is head of one
|
|
64
|
+
!component["substitutionGroup"].nil? || has_substitution_members?
|
|
65
|
+
elsif complex_type?
|
|
66
|
+
# Complex type has hierarchy if it has base type or derived types
|
|
67
|
+
has_base_type? || !find_subtypes.empty?
|
|
68
|
+
elsif simple_type?
|
|
69
|
+
# Simple type has hierarchy if it has restriction base or derived types
|
|
70
|
+
has_restriction_base? || !find_simple_subtypes.empty?
|
|
71
|
+
else
|
|
72
|
+
false
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Generate substitution groups section for elements
|
|
77
|
+
#
|
|
78
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
79
|
+
def generate_substitution_groups(html)
|
|
80
|
+
# Show substitution group this element belongs to
|
|
81
|
+
if component["substitutionGroup"]
|
|
82
|
+
html.tr do
|
|
83
|
+
html.td do
|
|
84
|
+
html.ul do
|
|
85
|
+
html.li do
|
|
86
|
+
html.em do
|
|
87
|
+
html.text "This element can be used wherever the following element is referenced:"
|
|
88
|
+
end
|
|
89
|
+
html.ul do
|
|
90
|
+
html.li do
|
|
91
|
+
html.text component["substitutionGroup"]
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Show substitution group members (elements that can substitute this one)
|
|
101
|
+
return unless has_substitution_members?
|
|
102
|
+
|
|
103
|
+
members = find_substitution_members
|
|
104
|
+
html.tr do
|
|
105
|
+
html.td do
|
|
106
|
+
html.ul do
|
|
107
|
+
html.li do
|
|
108
|
+
html.em do
|
|
109
|
+
html.text "The following elements can be used wherever this element is referenced:"
|
|
110
|
+
end
|
|
111
|
+
html.ul do
|
|
112
|
+
members.each do |member|
|
|
113
|
+
html.li do
|
|
114
|
+
html.text member["name"]
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Generate type hierarchy for complex types
|
|
125
|
+
#
|
|
126
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
127
|
+
def generate_complex_type_hierarchy(html)
|
|
128
|
+
# Show supertypes
|
|
129
|
+
if has_base_type?
|
|
130
|
+
html.tr do
|
|
131
|
+
html.th do
|
|
132
|
+
if config.print_all_super_types
|
|
133
|
+
html.text "Super-types:"
|
|
134
|
+
else
|
|
135
|
+
html.text "Parent type:"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
html.td do
|
|
139
|
+
generate_supertypes(html)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Show subtypes
|
|
145
|
+
subtypes = find_subtypes
|
|
146
|
+
return if subtypes.empty?
|
|
147
|
+
|
|
148
|
+
html.tr do
|
|
149
|
+
html.th do
|
|
150
|
+
if config.print_all_sub_types
|
|
151
|
+
html.text "Sub-types:"
|
|
152
|
+
else
|
|
153
|
+
html.text "Direct sub-types:"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
html.td do
|
|
157
|
+
generate_subtypes(html, subtypes)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Generate type hierarchy for simple types
|
|
163
|
+
#
|
|
164
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
165
|
+
def generate_simple_type_hierarchy(html)
|
|
166
|
+
# Show supertypes
|
|
167
|
+
if has_restriction_base?
|
|
168
|
+
html.tr do
|
|
169
|
+
html.th do
|
|
170
|
+
if config.print_all_super_types
|
|
171
|
+
html.text "Super-types:"
|
|
172
|
+
else
|
|
173
|
+
html.text "Parent type:"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
html.td do
|
|
177
|
+
generate_simple_supertypes(html)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Show subtypes
|
|
183
|
+
subtypes = find_simple_subtypes
|
|
184
|
+
return if subtypes.empty?
|
|
185
|
+
|
|
186
|
+
html.tr do
|
|
187
|
+
html.th do
|
|
188
|
+
if config.print_all_sub_types
|
|
189
|
+
html.text "Sub-types:"
|
|
190
|
+
else
|
|
191
|
+
html.text "Direct sub-types:"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
html.td do
|
|
195
|
+
generate_simple_derived_types(html, subtypes)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Generate supertypes chain for complex types
|
|
201
|
+
#
|
|
202
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
203
|
+
def generate_supertypes(html)
|
|
204
|
+
base_ref = extract_base_type_ref
|
|
205
|
+
return unless base_ref
|
|
206
|
+
|
|
207
|
+
if config.print_all_super_types
|
|
208
|
+
# Show full hierarchy
|
|
209
|
+
chain = build_supertype_chain(base_ref)
|
|
210
|
+
html.text chain.join(" < ")
|
|
211
|
+
else
|
|
212
|
+
# Show only immediate parent
|
|
213
|
+
html.text "#{base_ref} (#{derivation_method})"
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Generate supertypes for simple types
|
|
218
|
+
#
|
|
219
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
220
|
+
def generate_simple_supertypes(html)
|
|
221
|
+
restriction = component.at_xpath("xsd:restriction", "xsd" => XSD_NS)
|
|
222
|
+
return unless restriction
|
|
223
|
+
|
|
224
|
+
base_ref = restriction["base"]
|
|
225
|
+
return unless base_ref
|
|
226
|
+
|
|
227
|
+
if config.print_all_super_types
|
|
228
|
+
# Show full hierarchy
|
|
229
|
+
chain = build_simple_supertype_chain(base_ref)
|
|
230
|
+
html.text chain.join(" < ")
|
|
231
|
+
else
|
|
232
|
+
# Show only immediate parent
|
|
233
|
+
html.text "#{base_ref} (by restriction)"
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Generate subtypes list
|
|
238
|
+
#
|
|
239
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
240
|
+
# @param subtypes [Array<Nokogiri::XML::Element>] Subtype elements
|
|
241
|
+
def generate_subtypes(html, subtypes)
|
|
242
|
+
html.ul do
|
|
243
|
+
subtypes.each do |subtype|
|
|
244
|
+
html.li do
|
|
245
|
+
html.text subtype["name"]
|
|
246
|
+
html.text " (by #{get_derivation_method(subtype)})"
|
|
247
|
+
|
|
248
|
+
# Recursively show sub-subtypes if config allows
|
|
249
|
+
if config.print_all_sub_types
|
|
250
|
+
sub_subtypes = find_subtypes_of(subtype)
|
|
251
|
+
unless sub_subtypes.empty?
|
|
252
|
+
generate_subtypes(html,
|
|
253
|
+
sub_subtypes)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Generate subtypes list for simple types
|
|
262
|
+
#
|
|
263
|
+
# @param html [Nokogiri::HTML::Builder] HTML builder
|
|
264
|
+
# @param subtypes [Array<Nokogiri::XML::Element>] Subtype elements
|
|
265
|
+
def generate_simple_derived_types(html, subtypes)
|
|
266
|
+
html.ul do
|
|
267
|
+
subtypes.each do |subtype|
|
|
268
|
+
html.li do
|
|
269
|
+
html.text "#{subtype['name']} (by restriction)"
|
|
270
|
+
|
|
271
|
+
# Recursively show sub-subtypes if config allows
|
|
272
|
+
if config.print_all_sub_types
|
|
273
|
+
sub_subtypes = find_simple_subtypes_of(subtype)
|
|
274
|
+
unless sub_subtypes.empty?
|
|
275
|
+
generate_simple_derived_types(html, sub_subtypes)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Check if component is an element
|
|
284
|
+
#
|
|
285
|
+
# @return [Boolean]
|
|
286
|
+
def element?
|
|
287
|
+
component.name == "element"
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Check if component is a complex type
|
|
291
|
+
#
|
|
292
|
+
# @return [Boolean]
|
|
293
|
+
def complex_type?
|
|
294
|
+
component.name == "complexType"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Check if component is a simple type
|
|
298
|
+
#
|
|
299
|
+
# @return [Boolean]
|
|
300
|
+
def simple_type?
|
|
301
|
+
component.name == "simpleType"
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Check if element has substitution group members
|
|
305
|
+
#
|
|
306
|
+
# @return [Boolean]
|
|
307
|
+
def has_substitution_members?
|
|
308
|
+
!find_substitution_members.empty?
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Find elements that can substitute this element
|
|
312
|
+
#
|
|
313
|
+
# @return [Array<Nokogiri::XML::Element>]
|
|
314
|
+
def find_substitution_members
|
|
315
|
+
element_name = component["name"]
|
|
316
|
+
return [] unless element_name
|
|
317
|
+
|
|
318
|
+
parser.elements.select do |elem|
|
|
319
|
+
elem["substitutionGroup"] == element_name
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Check if complex type has base type
|
|
324
|
+
#
|
|
325
|
+
# @return [Boolean]
|
|
326
|
+
def has_base_type?
|
|
327
|
+
return false unless complex_type?
|
|
328
|
+
|
|
329
|
+
!extract_base_type_ref.nil?
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# Check if simple type has restriction base
|
|
333
|
+
#
|
|
334
|
+
# @return [Boolean]
|
|
335
|
+
def has_restriction_base?
|
|
336
|
+
return false unless simple_type?
|
|
337
|
+
|
|
338
|
+
restriction = component.at_xpath("xsd:restriction", "xsd" => XSD_NS)
|
|
339
|
+
!!(restriction && restriction["base"])
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Extract base type reference from complex type
|
|
343
|
+
#
|
|
344
|
+
# @return [String, nil]
|
|
345
|
+
def extract_base_type_ref
|
|
346
|
+
# Check simpleContent
|
|
347
|
+
if (extension = component.at_xpath(
|
|
348
|
+
"xsd:simpleContent/xsd:extension",
|
|
349
|
+
"xsd" => XSD_NS,
|
|
350
|
+
))
|
|
351
|
+
return extension["base"]
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
if (restriction = component.at_xpath(
|
|
355
|
+
"xsd:simpleContent/xsd:restriction",
|
|
356
|
+
"xsd" => XSD_NS,
|
|
357
|
+
))
|
|
358
|
+
return restriction["base"]
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Check complexContent
|
|
362
|
+
if (extension = component.at_xpath(
|
|
363
|
+
"xsd:complexContent/xsd:extension",
|
|
364
|
+
"xsd" => XSD_NS,
|
|
365
|
+
))
|
|
366
|
+
return extension["base"]
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
if (restriction = component.at_xpath(
|
|
370
|
+
"xsd:complexContent/xsd:restriction",
|
|
371
|
+
"xsd" => XSD_NS,
|
|
372
|
+
))
|
|
373
|
+
return restriction["base"]
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
nil
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Get derivation method (extension or restriction)
|
|
380
|
+
#
|
|
381
|
+
# @return [String]
|
|
382
|
+
def derivation_method
|
|
383
|
+
if component.at_xpath(
|
|
384
|
+
"xsd:simpleContent/xsd:extension | xsd:complexContent/xsd:extension",
|
|
385
|
+
"xsd" => XSD_NS,
|
|
386
|
+
)
|
|
387
|
+
"extension"
|
|
388
|
+
elsif component.at_xpath(
|
|
389
|
+
"xsd:simpleContent/xsd:restriction | xsd:complexContent/xsd:restriction",
|
|
390
|
+
"xsd" => XSD_NS,
|
|
391
|
+
)
|
|
392
|
+
"restriction"
|
|
393
|
+
else
|
|
394
|
+
"unknown"
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
# Get derivation method for a given type
|
|
399
|
+
#
|
|
400
|
+
# @param type [Nokogiri::XML::Element] Type element
|
|
401
|
+
# @return [String]
|
|
402
|
+
def get_derivation_method(type)
|
|
403
|
+
if type.at_xpath(
|
|
404
|
+
"xsd:complexContent/xsd:extension | xsd:simpleContent/xsd:extension",
|
|
405
|
+
"xsd" => XSD_NS,
|
|
406
|
+
)
|
|
407
|
+
"extension"
|
|
408
|
+
else
|
|
409
|
+
"restriction"
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# Build supertype chain
|
|
414
|
+
#
|
|
415
|
+
# @param base_ref [String] Base type reference
|
|
416
|
+
# @return [Array<String>]
|
|
417
|
+
def build_supertype_chain(base_ref)
|
|
418
|
+
chain = [base_ref]
|
|
419
|
+
current_type_name = strip_namespace_prefix(base_ref)
|
|
420
|
+
|
|
421
|
+
# Find the type in the schema
|
|
422
|
+
current_type = parser.complex_types.find do |t|
|
|
423
|
+
t["name"] == current_type_name
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# Walk up the hierarchy
|
|
427
|
+
while current_type
|
|
428
|
+
generator = self.class.new(current_type, parser, config)
|
|
429
|
+
next_base = generator.send(:extract_base_type_ref)
|
|
430
|
+
break unless next_base
|
|
431
|
+
|
|
432
|
+
chain.unshift(next_base)
|
|
433
|
+
current_type_name = strip_namespace_prefix(next_base)
|
|
434
|
+
current_type = parser.complex_types.find do |t|
|
|
435
|
+
t["name"] == current_type_name
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
chain << "#{component['name']} (by #{derivation_method})"
|
|
440
|
+
chain
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
# Build supertype chain for simple types
|
|
444
|
+
#
|
|
445
|
+
# @param base_ref [String] Base type reference
|
|
446
|
+
# @return [Array<String>]
|
|
447
|
+
def build_simple_supertype_chain(base_ref)
|
|
448
|
+
chain = [base_ref]
|
|
449
|
+
current_type_name = strip_namespace_prefix(base_ref)
|
|
450
|
+
|
|
451
|
+
# Find the type in the schema
|
|
452
|
+
current_type = parser.simple_types.find do |t|
|
|
453
|
+
t["name"] == current_type_name
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Walk up the hierarchy
|
|
457
|
+
while current_type
|
|
458
|
+
restriction = current_type.at_xpath(
|
|
459
|
+
"xsd:restriction",
|
|
460
|
+
"xsd" => XSD_NS,
|
|
461
|
+
)
|
|
462
|
+
break unless restriction
|
|
463
|
+
|
|
464
|
+
next_base = restriction["base"]
|
|
465
|
+
break unless next_base
|
|
466
|
+
|
|
467
|
+
chain.unshift(next_base)
|
|
468
|
+
current_type_name = strip_namespace_prefix(next_base)
|
|
469
|
+
current_type = parser.simple_types.find do |t|
|
|
470
|
+
t["name"] == current_type_name
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
chain << "#{component['name']} (by restriction)"
|
|
475
|
+
chain
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# Find direct subtypes of this complex type
|
|
479
|
+
#
|
|
480
|
+
# @return [Array<Nokogiri::XML::Element>]
|
|
481
|
+
def find_subtypes
|
|
482
|
+
type_name = component["name"]
|
|
483
|
+
return [] unless type_name
|
|
484
|
+
|
|
485
|
+
parser.complex_types.select do |ct|
|
|
486
|
+
base_ref = self.class.new(ct, parser, config)
|
|
487
|
+
.send(:extract_base_type_ref)
|
|
488
|
+
base_ref && strip_namespace_prefix(base_ref) == type_name
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
# Find direct subtypes of a given type
|
|
493
|
+
#
|
|
494
|
+
# @param type [Nokogiri::XML::Element] Type element
|
|
495
|
+
# @return [Array<Nokogiri::XML::Element>]
|
|
496
|
+
def find_subtypes_of(type)
|
|
497
|
+
type_name = type["name"]
|
|
498
|
+
return [] unless type_name
|
|
499
|
+
|
|
500
|
+
parser.complex_types.select do |ct|
|
|
501
|
+
next if ct == type
|
|
502
|
+
|
|
503
|
+
base_ref = self.class.new(ct, parser, config)
|
|
504
|
+
.send(:extract_base_type_ref)
|
|
505
|
+
base_ref && strip_namespace_prefix(base_ref) == type_name
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# Find direct subtypes of this simple type
|
|
510
|
+
#
|
|
511
|
+
# @return [Array<Nokogiri::XML::Element>]
|
|
512
|
+
def find_simple_subtypes
|
|
513
|
+
type_name = component["name"]
|
|
514
|
+
return [] unless type_name
|
|
515
|
+
|
|
516
|
+
parser.simple_types.select do |st|
|
|
517
|
+
restriction = st.at_xpath("xsd:restriction", "xsd" => XSD_NS)
|
|
518
|
+
next unless restriction
|
|
519
|
+
|
|
520
|
+
base_ref = restriction["base"]
|
|
521
|
+
base_ref && strip_namespace_prefix(base_ref) == type_name
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
# Find direct subtypes of a given simple type
|
|
526
|
+
#
|
|
527
|
+
# @param type [Nokogiri::XML::Element] Type element
|
|
528
|
+
# @return [Array<Nokogiri::XML::Element>]
|
|
529
|
+
def find_simple_subtypes_of(type)
|
|
530
|
+
type_name = type["name"]
|
|
531
|
+
return [] unless type_name
|
|
532
|
+
|
|
533
|
+
parser.simple_types.select do |st|
|
|
534
|
+
next if st == type
|
|
535
|
+
|
|
536
|
+
restriction = st.at_xpath("xsd:restriction", "xsd" => XSD_NS)
|
|
537
|
+
next unless restriction
|
|
538
|
+
|
|
539
|
+
base_ref = restriction["base"]
|
|
540
|
+
base_ref && strip_namespace_prefix(base_ref) == type_name
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
# Strip namespace prefix from a type reference
|
|
545
|
+
#
|
|
546
|
+
# @param ref [String] Type reference (may include prefix)
|
|
547
|
+
# @return [String] Type name without prefix
|
|
548
|
+
def strip_namespace_prefix(ref)
|
|
549
|
+
ref.to_s.split(":").last
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
end
|