xsd 2.9.2 → 2.9.3

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: 81b3091d973a5f08501a01ba6d6b746b4863bc28b5392ec634c4d226b7775a98
4
- data.tar.gz: 5bad6e4209bd42086a25d892a5c8a0845012ad91a57a97c7b80cf13f0656624b
3
+ metadata.gz: 178b66562e4da9833513bd00a12c528231551bac936eb7b72c611c9d3fc0a2bb
4
+ data.tar.gz: e58a38469f83f232583eb23f6fbefda81a86c56edf7cbfce06b305d81d3ce622
5
5
  SHA512:
6
- metadata.gz: fd1216b66f6d84f386850e5eb8160eadac25677d739a5c140eb64a974f300c7e0eca26f7c0d5a1fcd9fd8bb665c16d06c91776ea57d13b322e1b925dce35f765
7
- data.tar.gz: 4a0145cebcb96eaf27b8a00fc7caf3be761a2d83b2809853f51c74c81702ae377168308a652ba716afd68fb2a7001b4a97ba713ea341c4983f11d14f8e007453
6
+ metadata.gz: 7c34d9b9ee21284c3bc3d3b20a6f29de7ff94ac4dae1a85aaf2998dad74a35c043b612bac4691880ddefcddda42bf0734faef1fa64a63a984c301d020f3103ea
7
+ data.tar.gz: 9d846b4eaeff11247851889a133bcb62de24dad598764778be74a81d97d50b251f0257d95801c6aae8e09be588e7676c6aae2ad24e0806f8e8895ccb055f0c2b
data/.rubocop.yml CHANGED
@@ -1,4 +1,4 @@
1
- require:
1
+ plugins:
2
2
  - rubocop-performance
3
3
  - rubocop-rake
4
4
  - rubocop-rspec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [2.9.3] - 2026-10-24
2
+
3
+ ### Fixed
4
+
5
+ - A schema with no target namespace that imports another namespace (an XMLDSig `Signature` referenced as
6
+ `ds:SignatureType`) now finds what it imports. `Schema#targets_namespace?` took a namespace URI for a prefix, looked
7
+ it up among the schema's prefixes, found nothing, and matched that nothing against the absent target namespace:
8
+ every reference by a prefixed name was looked for in the schema itself.
9
+
10
+ ### Changed
11
+
12
+ - Every import of the absent namespace is read from its own location. Schemas with no target namespace are each a
13
+ schema of their own (a provider's documents, every one shipping its own copies of the common types, which may
14
+ differ), so a second import of the absent namespace was not the same schema as the first one; before, it was
15
+ answered with whichever such schema had been loaded first. An import whose location is loaded already is answered
16
+ with that schema in any namespace (`XML#loaded_schema`); an import of a named namespace is still answered with a
17
+ schema known for it before its location is read.
18
+
1
19
  ## [2.9.2] - 2026-10-21
2
20
 
3
21
  ### Changed
data/Gemfile CHANGED
@@ -8,8 +8,8 @@ gemspec
8
8
  group :development do
9
9
  gem 'logger', '~> 1.5'
10
10
  gem 'rspec', '~> 3.12'
11
- gem 'rubocop', '~> 1.50'
12
- gem 'rubocop-performance', '~> 1.17'
13
- gem 'rubocop-rake', '~> 0.6'
14
- gem 'rubocop-rspec', '~> 2.10'
11
+ gem 'rubocop', '~> 1.92'
12
+ gem 'rubocop-performance', '~> 1.27'
13
+ gem 'rubocop-rake', '~> 0.7'
14
+ gem 'rubocop-rspec', '~> 3.8'
15
15
  end
data/README.md CHANGED
@@ -61,6 +61,16 @@ element.multiple_allowed? # => true
61
61
  element.required? # => false
62
62
  ```
63
63
 
64
+ ### Imports and the absent namespace
65
+
66
+ XML Schema leaves it to the processor whether every `<xs:import>` of a namespace is read or only the first (a
67
+ `schemaLocation` is a hint); libxml2, and so Nokogiri's validator, reads the first. This reader reads them all, and
68
+ resolves a name within the include tree of the schema the name is written in. That is what a set of schemas with no
69
+ target namespace needs when one schema imports them all: every document a schema of its own, with its own copies of
70
+ common types that may differ from one copy to another. Put together into one schema they break the rule that names
71
+ are unique within a namespace, so a validator assembling one schema of them (`Schema#validate_xml`, which validates
72
+ through Nokogiri) sees only the first of them.
73
+
64
74
  ## Development
65
75
 
66
76
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can
@@ -73,7 +73,7 @@ module XSD
73
73
  # @param [Boolean] deep
74
74
  # @return Nokogiri::XML::NodeSet
75
75
  def nodes(name = :*, deep = false)
76
- node.xpath("./#{deep ? '/' : ''}xs:#{name}", XML_SCHEMA_NS)
76
+ node.xpath("./#{'/' if deep}xs:#{name}", XML_SCHEMA_NS)
77
77
  end
78
78
 
79
79
  # Get schemas by namespace or prefix
@@ -409,7 +409,7 @@ module XSD
409
409
  # @param [String, nil] string
410
410
  # @return String, nil
411
411
  def nil_if_empty(string)
412
- string&.empty? ? nil : string
412
+ string && string.empty? ? nil : string
413
413
  end
414
414
 
415
415
  private
@@ -7,6 +7,7 @@ module XSD
7
7
  # https://www.w3schools.com/xml/el_attribute.asp
8
8
  class Attribute < BaseObject
9
9
  prepend CachedDataType
10
+
10
11
  TYPE_PROPERTY = :type
11
12
 
12
13
  include SimpleTyped
@@ -6,6 +6,7 @@ module XSD
6
6
  # https://www.w3schools.com/xml/el_element.asp
7
7
  class Element < BaseObject
8
8
  prepend CachedDataType
9
+
9
10
  TYPE_PROPERTY = :type
10
11
 
11
12
  include MinMaxOccurs
@@ -15,12 +15,21 @@ module XSD
15
15
  # @return String, nil
16
16
  property :schemaLocation, :string
17
17
 
18
- # Get imported schema
18
+ # Get imported schema: the one at the import's location when that one is loaded already; otherwise one known for
19
+ # the namespace, added manually or by another import. Not for the absent namespace: schemas with no target
20
+ # namespace are each a schema of its own (a provider's documents, every one with its own copies of the common
21
+ # types), so every import of it is read from its own location.
19
22
  # @return Schema
20
23
  def imported_schema
21
- # a schema for the namespace may already be known, either added manually or by another import
22
- known_schema = reader.schemas_for_namespace(namespace).find { |s| !s.equal?(schema) }
23
- return known_schema if known_schema
24
+ if schema_location
25
+ located = reader.loaded_schema(schema_location, base: schema.location)
26
+ return located if located
27
+ end
28
+
29
+ unless namespace.nil?
30
+ known_schema = reader.schemas_for_namespace(namespace).find { |s| !s.equal?(schema) }
31
+ return known_schema if known_schema
32
+ end
24
33
 
25
34
  unless schema_location
26
35
  raise ImportError,
@@ -62,14 +62,14 @@ module XSD
62
62
  def collect_elements(include_base = false)
63
63
  # Don't include elements from base by default, that will lead to element duplicates because
64
64
  # elements in complex restriction MUST be all listen in restricting type
65
- super(include_base)
65
+ super
66
66
  end
67
67
 
68
68
  # Get all available attributes on the current stack level, optionally including base type attributes
69
69
  # @param [Boolean] include_base
70
70
  # @return Array<Attribute>
71
71
  def collect_attributes(include_base = true)
72
- result = super(include_base)
72
+ result = super
73
73
  # Filter restricted attributes to avoid duplicates from restricting and restricted type
74
74
  include_base ? result.to_h { |item| [item.name, item] }.values : result
75
75
  end
@@ -190,7 +190,10 @@ module XSD
190
190
  # @param [String, nil] namespace
191
191
  # @return Boolean
192
192
  def targets_namespace?(namespace)
193
- namespace == target_namespace || namespaces[namespace.nil? ? 'xmlns' : "xmlns:#{namespace}"] == target_namespace ||
193
+ key = namespace.nil? ? 'xmlns' : "xmlns:#{namespace}"
194
+ # a prefix names a namespace only when the schema declares it: looking up a namespace URI as a prefix finds
195
+ # nothing, and nothing must not pass for the absent target namespace of a schema that has none
196
+ namespace == target_namespace || (namespaces.key?(key) && namespaces[key] == target_namespace) ||
194
197
  # an unqualified name in a chameleon schema names something of the namespace it was included into
195
198
  (chameleon? && namespace.nil? && !namespaces.key?('xmlns'))
196
199
  end
@@ -9,7 +9,7 @@ module XSD
9
9
  # @!attribute member_types
10
10
  # @return Array<String>
11
11
  property :memberTypes, :array, default: [] do |union|
12
- union.node['memberTypes']&.split(' ')
12
+ union.node['memberTypes']&.split
13
13
  end
14
14
 
15
15
  # Nested simple and built-in types
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.9.2'
4
+ VERSION = '2.9.3'
5
5
  end
data/lib/xsd/xml.rb CHANGED
@@ -21,7 +21,7 @@ module XSD
21
21
  elsif Pathname.new(location).absolute?
22
22
  File.read(location)
23
23
  else
24
- raise ImportError, "Failed to locate import '#{location}'#{namespace ? " for namespace '#{namespace}'" : ''}"
24
+ raise ImportError, "Failed to locate import '#{location}'#{" for namespace '#{namespace}'" if namespace}"
25
25
  end
26
26
  end
27
27
 
@@ -158,6 +158,14 @@ module XSD
158
158
  @schemas_by_location[expanded] = add_schema_xml(xml, location: expanded)
159
159
  end
160
160
 
161
+ # The schema already read from a location, relative to a base as an import or an include names it
162
+ # @param [String] location
163
+ # @param [String, nil] base Location of the referencing schema
164
+ # @return Schema, nil
165
+ def loaded_schema(location, base: nil)
166
+ @schemas_by_location[expand_location(location.tr('\\', '/'), base)]
167
+ end
168
+
161
169
  # Get first added (considered primary) schema
162
170
  # @return Schema, nil
163
171
  def schema
@@ -256,7 +264,7 @@ module XSD
256
264
  elsif File.file?(location)
257
265
  File.read(location)
258
266
  else
259
- raise ImportError, "Failed to locate import '#{location}'#{namespace ? " for namespace '#{namespace}'" : ''}"
267
+ raise ImportError, "Failed to locate import '#{location}'#{" for namespace '#{namespace}'" if namespace}"
260
268
  end
261
269
  end
262
270
 
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.9.2
4
+ version: 2.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - d.arkhipov