xsd 2.0.0 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee4b9e2059eeb7c7109e687ca866c3617514e167f2d93de816d452fdf01be85b
4
- data.tar.gz: ee5451af6e745dbdfffc55fa26329fd2c68b3257699a6e65fd923da3278769ea
3
+ metadata.gz: d3b12830c536c37e72b109727f470d45de29b6c852e62476cd3aa5578dd3b9c7
4
+ data.tar.gz: 248b65a3794a6c83a6aca695b0d565d55b971991272fd5f7f0a8a841fb8847ec
5
5
  SHA512:
6
- metadata.gz: c937c9501cac27b7d1a003d34feec5fc927663656793c0e2a4abb62112f7b36ee7001532eccc1f1557913c23355feddab616a9df493fe2c7556fb3eaa74d50ce
7
- data.tar.gz: 588d4649a016ed883a401447435a3a01512a610d1bc5b46b8abae0d6b0367ffe2369073f4f0f8bdb834643321f2a22eda196d89315d6e84f3b0222f4eee0c622
6
+ metadata.gz: ac15d2c2c163bd70f007fd76b5c007fbc786ed09d5609a2d6dba5aa8836144917a5159a32c1b7f47aa250bd18034d8339f445180fc4cd330745138ec60283e32
7
+ data.tar.gz: 7db0b9ac2ba0c97aab16d84db5145b4a8a18c901f3c24c8fd13a73b96a1998083a41cff38c3b0f7098dc53457b693e0ee5d3d941ceb1712f38a54924d32ce544
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.1.0] - 2023-07-10
4
+
5
+ - Add support for <xs:include> element
6
+ - Changed method "schema_for_namespace(namespace) -> XSD::Schema" signature to "schemas_for_namespace(namespace) -> Array<XSD::Schema>"
7
+
3
8
  ## [2.0.0] - 2023-07-07
4
9
 
5
10
  - Change XSD::XML.new(file, **options) -> XSD::XML.open(file, **options)
data/README.md CHANGED
@@ -28,20 +28,29 @@ require 'xsd'
28
28
  # Load ruby-xsd
29
29
  reader = XSD::XML.open('some.xsd')
30
30
 
31
+ # Get elements and their child elements
32
+ element = reader['NewReleaseMessage']
33
+ element.collect_elements.map(&:name) # => ['MessageHeader', 'UpdateIndicator', 'IsBackfill', 'CatalogTransfer', 'WorkList', 'CueSheetList', 'ResourceList', 'CollectionList', 'ReleaseList', 'DealList']
34
+
31
35
  # Get attributes
32
36
  attribute = reader['NewReleaseMessage']['@MessageSchemaVersionId']
33
37
 
34
- # Get atrribute information
38
+ # Get attribute information
35
39
  attribute.name # => 'MessageSchemaVersionId'
36
40
  attribute.type # => 'xs:string'
37
41
  attribute.required? # => true
42
+ attribute.optional? # => false
43
+ attribute.prohibited? # => true
38
44
 
39
45
  # Get element information
40
- element = reader['NewReleaseMessage']['ResourceList']['SoundRecording']
46
+ element = reader['NewReleaseMessage']['ResourceList']['SoundRecording'] # => XSD::Element
41
47
  element.min_occurs # => 0
42
48
  element.max_occurs # => :unbounded
43
49
  element.type # => 'ern:SoundRecording'
44
50
  element.complex_type # => XSD::ComplexType
51
+ element.complex? # => true
52
+ element.multiple_allowed? # => true
53
+ element.required? # => false
45
54
  ```
46
55
 
47
56
  ## Development
@@ -67,13 +67,13 @@ module XSD
67
67
  end
68
68
 
69
69
  # Get schema by namespace or namespace prefix
70
- # @param [String] namespace
71
- # @return Schema
72
- def schema_for_namespace(namespace)
70
+ # @param [String, nil] namespace
71
+ # @return Array<Schema>
72
+ def schemas_for_namespace(namespace)
73
73
  if schema.targets_namespace?(namespace)
74
- schema
74
+ [schema, *schema.includes.map(&:imported_schema)]
75
75
  elsif (import = schema.import_by_namespace(namespace))
76
- import.imported_schema
76
+ [import.imported_schema]
77
77
  else
78
78
  raise Error, "Schema not found for namespace '#{namespace}' in '#{schema.id || schema.target_namespace}'"
79
79
  end
@@ -112,12 +112,15 @@ module XSD
112
112
  return nil if schema.namespace_prefix == name_prefix
113
113
 
114
114
  # determine schema for namespace
115
- search_schema = schema_for_namespace(name_prefix)
115
+ search_schemas = schemas_for_namespace(name_prefix)
116
116
 
117
117
  # find element in target schema
118
- result = search_schema.node.xpath("./xs:#{node_name}[@name=\"#{name_local}\"]", { 'xs' => XML_SCHEMA }).first
118
+ search_schemas.each do |s|
119
+ node = s.node.xpath("./xs:#{node_name}[@name=\"#{name_local}\"]", { 'xs' => XML_SCHEMA }).first
120
+ return s.node_to_object(node) if node
121
+ end
119
122
 
120
- result ? search_schema.node_to_object(result) : nil
123
+ nil
121
124
  end
122
125
 
123
126
  # Get reader object for node
@@ -169,9 +172,9 @@ module XSD
169
172
 
170
173
  # Get namespace prefix from node name
171
174
  # @param [String, nil] name Name to strip from
172
- # @return String
175
+ # @return String, nil
173
176
  def get_prefix(name)
174
- name&.include?(':') ? name.split(':').first : ''
177
+ name&.include?(':') ? name.split(':').first : nil
175
178
  end
176
179
 
177
180
  # Return element documentation
@@ -8,7 +8,26 @@ module XSD
8
8
  TYPE_PROPERTY = nil
9
9
 
10
10
  include Based
11
- include SimpleTyped
12
11
  include AttributeContainer
12
+
13
+ # Nested group
14
+ # @!attribute group
15
+ # @return Group
16
+ child :group, :group
17
+
18
+ # Nested all
19
+ # @!attribute all
20
+ # @return All
21
+ child :all, :all
22
+
23
+ # Nested choice
24
+ # @!attribute choice
25
+ # @return Choice
26
+ child :choice, :choice
27
+
28
+ # Nested sequence
29
+ # @!attribute sequence
30
+ # @return Sequence
31
+ child :sequence, :sequence
13
32
  end
14
33
  end
@@ -16,23 +16,23 @@ module XSD
16
16
  property :schemaLocation, :string
17
17
 
18
18
  # Get imported schema
19
- # @return XSD:Schema
19
+ # @return Schema
20
20
  def imported_schema
21
- schema = reader.schema_for_namespace(namespace)
22
- return schema if schema
21
+ known_schemas = reader.schemas_for_namespace(namespace)
22
+ return known_schemas.first if known_schemas.any?
23
23
 
24
24
  unless schema_location
25
25
  raise ImportError, "Schema location not provided for namespace '#{namespace}', use add_schema_xml()/add_schema_node()"
26
26
  end
27
27
 
28
28
  xml = reader.resource_resolver.call(schema_location, namespace)
29
- schema = reader.add_schema_xml(xml)
29
+ new_schema = reader.add_schema_xml(xml)
30
30
 
31
- unless namespace == schema.target_namespace
32
- raise ImportError, 'Import location does not match imported schema targetNamespace'
31
+ unless namespace == new_schema.target_namespace
32
+ raise ImportError, 'Import namespace does not match imported schema targetNamespace'
33
33
  end
34
34
 
35
- schema
35
+ new_schema
36
36
  end
37
37
  end
38
38
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XSD
4
+ # The include element is used to add multiple schemas with the same target namespace to a document.
5
+ # Parent elements: schema
6
+ # https://www.w3schools.com/xml/el_include.asp
7
+ class Include < BaseObject
8
+ # Required. Specifies the URI to the schema to include in the target namespace of the containing schema
9
+ # @!attribute schema_location
10
+ # @return String
11
+ property :schemaLocation, :string
12
+
13
+ # Get imported schema
14
+ # @return Schema
15
+ def imported_schema
16
+ # cache included schema locally as it has no unique namespace to check in global registry
17
+ return @imported_schema if @imported_schema
18
+
19
+ xml = reader.resource_resolver.call(schema_location)
20
+ new_schema = reader.add_schema_xml(xml)
21
+
22
+ unless schema.target_namespace == new_schema.target_namespace
23
+ raise ImportError, 'Schema targetNamespace does not match included schema targetNamespace'
24
+ end
25
+
26
+ @imported_schema = new_schema
27
+ end
28
+ end
29
+ end
@@ -16,6 +16,26 @@ module XSD
16
16
  fractionDigits length minLength maxLength enumeration whiteSpace pattern
17
17
  ].freeze
18
18
 
19
+ # Nested group
20
+ # @!attribute group
21
+ # @return Group
22
+ child :group, :group
23
+
24
+ # Nested all
25
+ # @!attribute all
26
+ # @return All
27
+ child :all, :all
28
+
29
+ # Nested choice
30
+ # @!attribute choice
31
+ # @return Choice
32
+ child :choice, :choice
33
+
34
+ # Nested sequence
35
+ # @!attribute sequence
36
+ # @return Sequence
37
+ child :sequence, :sequence
38
+
19
39
  # Get restriction facets
20
40
  # @return Hash
21
41
  def facets
@@ -85,6 +85,11 @@ module XSD
85
85
  # @return Array<Import>
86
86
  child :imports, [:import]
87
87
 
88
+ # Schema includes
89
+ # @!attribute includes
90
+ # @return Array<Include>
91
+ child :includes, [:include]
92
+
88
93
  # Get current schema object
89
94
  # @return Schema
90
95
  def schema
@@ -116,30 +121,31 @@ module XSD
116
121
  end
117
122
 
118
123
  # Check if namespace is a target namespace
119
- # @param [String] namespace
124
+ # @param [String, nil] namespace
120
125
  # @return Boolean
121
126
  def targets_namespace?(namespace)
122
127
  namespace == target_namespace || namespaces[namespace.empty? ? 'xmlns' : "xmlns:#{namespace}"] == target_namespace
123
128
  end
124
129
 
125
- # Override map_children on schema to get objects from all imported schemas
130
+ # Override map_children on schema to get objects from all loaded schemas
126
131
  # @param [Symbol] name
127
132
  # @return Array<BaseObject>
128
133
  def map_children(name, cache = {})
129
134
  super(name) + import_map_children(name, cache)
130
135
  end
131
136
 
132
- # Get children from all imported schemas
137
+ # Get children from all loaded schemas
133
138
  # @param [Symbol] name
134
139
  # @return Array<BaseObject>
135
140
  def import_map_children(name, cache)
136
- return [] if name.to_sym == :import
141
+ return [] if %i[import include].include?(name.to_sym)
137
142
 
138
- imports.map do |import|
139
- if cache[import.namespace]
143
+ (includes + imports).map do |import|
144
+ key = import.respond_to?(:namespace) && import.namespace ? import.namespace : import.schema_location
145
+ if cache.key?(key)
140
146
  nil
141
147
  else
142
- cache[import.namespace] = true
148
+ cache[key] = true
143
149
  import.imported_schema.map_children(name, cache)
144
150
  end
145
151
  end.compact.flatten
data/lib/xsd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module XSD
4
- VERSION = '2.0.0'
4
+ VERSION = '2.1.0'
5
5
  end
data/lib/xsd/xml.rb CHANGED
@@ -31,6 +31,7 @@ module XSD
31
31
  'complexContent' => ComplexContent,
32
32
  'extension' => Extension,
33
33
  'import' => Import,
34
+ 'include' => Include,
34
35
  'simpleType' => SimpleType,
35
36
  'all' => All,
36
37
  'restriction' => Restriction,
@@ -63,6 +64,10 @@ module XSD
63
64
  'pattern' => Facet
64
65
  }.freeze
65
66
 
67
+ # Create reader from a file path
68
+ # @param [String] path
69
+ # @param [Hash] options
70
+ # @return XML
66
71
  def self.open(path, **options)
67
72
  reader = new(**options)
68
73
  reader.add_schema_xml(File.read(path))
@@ -92,8 +97,8 @@ module XSD
92
97
  Nokogiri::XML(xml)
93
98
  end
94
99
 
95
- # Get imported schema
96
- # @return XSD:Schema
100
+ # Add schema xml to reader instance
101
+ # @return Schema
97
102
  def add_schema_xml(xml)
98
103
  doc = read_document(xml)
99
104
  raise Error, 'Schema node not found, xml does not seem to be a valid XSD' unless doc.root&.name == 'schema'
@@ -101,15 +106,14 @@ module XSD
101
106
  add_schema_node(doc.root)
102
107
  end
103
108
 
104
- # Get imported schema
109
+ # Add schema node to reader instance
105
110
  # @return Schema
106
111
  def add_schema_node(node)
107
112
  raise Error, 'Added schema must be of type Nokogiri::XML::Node' unless node.is_a?(Nokogiri::XML::Node)
108
113
 
109
- schema = Schema.new(self.options.merge(node: node, reader: self))
110
- schemas.push(schema)
111
-
112
- schema
114
+ new_schema = Schema.new(options.merge(node: node, reader: self))
115
+ schemas.push(new_schema)
116
+ new_schema
113
117
  end
114
118
 
115
119
  # Add prefixes defined outside of processed schemas, for example in WSDL document
@@ -126,10 +130,11 @@ module XSD
126
130
  end
127
131
 
128
132
  # Get schema by namespace or namespace prefix
129
- # @return Schema, nil
130
- def schema_for_namespace(namespace)
133
+ # @param [String, nil] namespace
134
+ # @return Array<Schema>
135
+ def schemas_for_namespace(namespace)
131
136
  namespace = namespace_prefixes[namespace] if namespace_prefixes.key?(namespace)
132
- schemas.find { |schema| schema.target_namespace == namespace }
137
+ schemas.select { |schema| schema.target_namespace == namespace }
133
138
  end
134
139
 
135
140
  def [](*args)
data/lib/xsd.rb CHANGED
@@ -18,6 +18,7 @@ require 'xsd/objects/simple_content'
18
18
  require 'xsd/objects/complex_content'
19
19
  require 'xsd/objects/extension'
20
20
  require 'xsd/objects/import'
21
+ require 'xsd/objects/include'
21
22
  require 'xsd/objects/restriction'
22
23
  require 'xsd/objects/group'
23
24
  require 'xsd/objects/all'
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.0.0
4
+ version: 2.1.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-07-07 00:00:00.000000000 Z
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder
@@ -90,6 +90,7 @@ files:
90
90
  - lib/xsd/objects/field.rb
91
91
  - lib/xsd/objects/group.rb
92
92
  - lib/xsd/objects/import.rb
93
+ - lib/xsd/objects/include.rb
93
94
  - lib/xsd/objects/key.rb
94
95
  - lib/xsd/objects/keyref.rb
95
96
  - lib/xsd/objects/list.rb