lutaml-xsd 1.2.82 → 1.2.83

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: 8c3da66790f16686077f84ff27947241c3fd9290e4a36f92d5b26ee70d340af4
4
- data.tar.gz: 205af1e6a170523b054c34ba0cf43b86203877784bfe471ef88e47bcdbf60ae9
3
+ metadata.gz: efe4fbd2d864e7cbe9218faaf7f67fc879c4e20cc32c54e04761fcee59d2d1dc
4
+ data.tar.gz: 3b5618daa924a8a493645bab5ea7f0408d3b9245c32695306131c1cb9a0cfeb8
5
5
  SHA512:
6
- metadata.gz: 6901b1b6a2fc09e00325fe3e24df146097e6bf6967493e46e04d7eabe8b7a9183cdccc2cc8ccf39cfd9d0f3cf90157b0647c772f61512a68085c041fbf1329be
7
- data.tar.gz: 221ce2f9ce160b0524a99cb9dfb029ccc10040adbe8282e8cb37ecbc94cc9f689e1a6b2e28a6ca27cd069ef2c6547a5d728f37a3254b5fc501b9cce50d27118c
6
+ metadata.gz: 909c81244dd126cbbb8843fcd3a010f5da4a3c70bd325b71ed5865496cc390d101fecb6d6a4c38069b350abad064c4837328f5ee28cdcb583b4ec5e439c629da
7
+ data.tar.gz: 34a60915d85511b36be444dc6903e8f3f221e6740d3d6147fd5966c0fe82a852896dffb20fbf6253376bb78abeaa4a2717da83b4b44e644739acda1e85105c33
data/TODO.conformance.md CHANGED
@@ -120,7 +120,7 @@ pinned commit) is measured via `rake conformance:w3c`:
120
120
 
121
121
  | mode | pass-rate |
122
122
  |---|---|
123
- | pipeline | 4578/4696 (97.49%) |
123
+ | pipeline | 4585/4696 (97.64%) |
124
124
 
125
125
  (2026-11-02, bundled-stack measurement with the escape,
126
126
  hint-following, pattern-alternative, identity-crash, engine-set,
@@ -143,7 +143,8 @@ lockfile refresh) → 4411 (93.9%) → 4430 (94.3%) → 4435 (94.4%) →
143
143
  (96.3%) → 4534 (96.6%) → 4540 (96.7%) → 4542 (96.7%) → 4546 (96.8%)
144
144
  → 4557 (97.0%) → 4565 (97.2%) → 4569 (97.3%) → 4562 (drift raw) →
145
145
  4563 (97.17%, ref-namespace round) → 4573 (97.38%, group-content
146
- round) → 4578 (97.49%, attribute-prohibition round), +617 net over the 1.2.43 baseline. The escapes round (PR #197 — \d→\p{Nd},
146
+ round) → 4578 (97.49%, attribute-prohibition round) → 4585 (97.64%,
147
+ multi-document round), +624 net over the 1.2.43 baseline. The escapes round (PR #197 — \d→\p{Nd},
147
148
  \w/\W/\s to their XSD value spaces) collapses Regex 120→69;
148
149
  same-step pattern facets now behave as alternatives and
149
150
  whitespace-only text reaches the facets intact (PR #200), Regex
@@ -470,6 +471,29 @@ tuple keys, node-set field violations and absent-field rows handled, cross-eleme
470
471
  use-site fixed overlays the global declaration in the value check
471
472
  (attLa005). Attribute remainder (4): attJ018 + attO009/011
472
473
  (engine-silent — queue), attO006 (leptris-rs#25 attribute leg).
474
+ - MULTI-DOCUMENT ROUND (2026-11-03): +7 (Schema 12→9 — the schT3/T9/
475
+ T10 redefine trio; ComplexType 4→1, Particles 12→10, Additional
476
+ 10→9, IC 7→6 — same-namespace collision pairs; suite 4578→4585 =
477
+ 97.64%, zero regressions, rspec green). TWO defects: (a) the
478
+ conformance repository keyed documents by TARGET NAMESPACE, so two
479
+ schemaDocuments sharing a namespace silently overwrote each other
480
+ and only one survived (schT3's redefine pair, both ns-a); a
481
+ same-namespace collision now suffixes the key instead of dropping
482
+ the document — every other case keeps the production one-doc-per-
483
+ namespace semantics (a naive path-key for everything cost 25
484
+ regressions via the unique-name fallback and first-match type
485
+ lookup, caught and reverted in-round). (b) resolve_named_type now
486
+ falls back to the parsed xs:redefine target documents: types living
487
+ only in the target (schT3 b-ct/b-st) resolve for plain references;
488
+ names a redefine BODY redefines stay OFF that path (the body is the
489
+ effective type and is not resolvable here — idF/idG/idH keep the
490
+ lenient path). KNOWN GAPS left open: schA1/schQ1/schD10/schF2
491
+ (hint-composition with same-local-name ct-A across namespaces —
492
+ per-namespace type binding), full type-redefine body semantics
493
+ (the body as effective type with the self-base hook — a
494
+ lutaml-model Redefine model shape study). Remaining Schema 9:
495
+ schA1/Q1/D10/F2 (ours), schD7/G8 (lutaml-model#1087),
496
+ schF1/G2/G7/P2 (moxml#510 composed bindings).
473
497
  - REGEX SEMANTICS ROUND (2026-10-31, PR #208): \w/\W now carry their
474
498
  Appendix F complements (\w = [^\p{P}\p{Z}\p{C}], class interiors
475
499
  via the exact positive partition L/M/N/S), \I/\C complements added
@@ -154,8 +154,17 @@ module Lutaml
154
154
  test_case.schema_paths.each do |path|
155
155
  schema = Lutaml::Xml::Schema::Xsd.parse(File.read(path),
156
156
  location: path)
157
- key = schema.target_namespace if
158
- schema.target_namespace.to_s.match?(/\S/)
157
+ # Keyed by target namespace like production, EXCEPT that a
158
+ # same-namespace collision suffixes the key instead of
159
+ # dropping the document (schT3's redefine pair both declare
160
+ # ns-a). The resolver iterates values; keys only need to
161
+ # keep every document present.
162
+ key = if schema.target_namespace.to_s.match?(/\S/)
163
+ schema.target_namespace
164
+ else
165
+ path
166
+ end
167
+ key = "#{key}##{path}" while schemas.key?(key)
159
168
  schemas[key] = schema
160
169
  locations[path] = schema
161
170
  end
@@ -222,7 +222,11 @@ module Lutaml
222
222
  # Base attributes flow through both derivations — a
223
223
  # restriction narrows them but cannot drop them (XSD 1.0
224
224
  # §3.4.2).
225
- attributes.concat(inherited_attributes(part.base, repository)) if part
225
+ if part
226
+ attributes.concat(
227
+ inherited_attributes(part, repository),
228
+ )
229
+ end
226
230
  end
227
231
 
228
232
  # Handle simple content
@@ -234,7 +238,11 @@ module Lutaml
234
238
  )
235
239
  part = Array(schema_def.simple_content.extension).first ||
236
240
  Array(schema_def.simple_content.restriction).first
237
- attributes.concat(inherited_attributes(part.base, repository)) if part
241
+ if part
242
+ attributes.concat(
243
+ inherited_attributes(part, repository),
244
+ )
245
+ end
238
246
  end
239
247
 
240
248
  override_base_prohibitions(schema_def, attributes)
@@ -267,11 +275,13 @@ module Lutaml
267
275
  end
268
276
 
269
277
  # The base type's attribute set flows into the derived type
270
- # through extension and restriction alike.
278
+ # through extension and restriction alike. The base resolves
279
+ # through the derivation so a redefine body's own base hooks
280
+ # to the original definition.
271
281
  #
272
282
  # @return [Array<Lutaml::Xml::Schema::Xsd::Attribute>]
273
- def inherited_attributes(base_name, repository)
274
- local = base_name.to_s.split(":").last
283
+ def inherited_attributes(part, repository)
284
+ local = part.base.to_s.split(":").last
275
285
  return [] if local.to_s.empty?
276
286
 
277
287
  base = repository&.resolve_named_type(local)
@@ -302,7 +302,8 @@ module Lutaml
302
302
  restriction = Array(content.restriction).first
303
303
  if extension
304
304
  base_local = extension.base.to_s.split(":").last
305
- base_type = base_local && repository&.resolve_named_type(base_local)
305
+ base_type = base_local &&
306
+ repository&.resolve_named_type(base_local)
306
307
  particles = type_particles(base_type, repository, seen) +
307
308
  particles
308
309
  COMPLEX_PARTICLE_KINDS.each do |kind|
@@ -50,6 +50,14 @@ module Lutaml
50
50
  @attributes = Hash.new { |hash, key| hash[key] = [] }
51
51
  @attribute_groups = {}
52
52
  @redefined_originals = {}
53
+ # Parsed xs:redefine target documents: their named types back
54
+ # the redefined bodies (schT3: b-ct/b-st live in the target,
55
+ # which the repository does not hold). Names a redefine BODY
56
+ # redefines are NOT served from the target: the body is the
57
+ # effective type and is not resolvable here, so those keep
58
+ # the lenient unresolvable path (idF/idG/idH class).
59
+ @redefined_targets = []
60
+ @redefined_body_names = []
53
61
  @elements = index_elements
54
62
  end
55
63
 
@@ -200,18 +208,29 @@ module Lutaml
200
208
 
201
209
  result = nil
202
210
  schemas.each do |schema|
203
- found = Array(schema.complex_type).find do |ct|
204
- ct.name == local_name
205
- end
206
- found ||= Array(schema.simple_type).find do |st|
207
- st.name == local_name
208
- end
209
- result = found || find_nested_named_type(local_name, schema)
211
+ result = named_type_in(local_name, schema)
210
212
  break if result
211
213
  end
214
+ if result.nil? && !@redefined_body_names.include?(local_name)
215
+ @redefined_targets.each do |schema|
216
+ result = named_type_in(local_name, schema)
217
+ break if result
218
+ end
219
+ end
212
220
  @named_types[local_name] = result
213
221
  end
214
222
 
223
+ # @return [Object, nil]
224
+ def named_type_in(local_name, schema)
225
+ found = Array(schema.complex_type).find do |ct|
226
+ ct.name == local_name
227
+ end
228
+ found ||= Array(schema.simple_type).find do |st|
229
+ st.name == local_name
230
+ end
231
+ found || find_nested_named_type(local_name, schema)
232
+ end
233
+
215
234
  # Named types declared in documents reached through resolved
216
235
  # includes/imports — chameleon types (ctE018) live in a
217
236
  # no-namespace include target.
@@ -602,35 +621,60 @@ module Lutaml
602
621
  # indexed under the name (attgC007/attgD036). Runs after the
603
622
  # nested descent so included declarations are already in.
604
623
  Array(schema.redefine).each do |red|
605
- target_path = nil
606
- base = begin
607
- File.dirname(@repository.source_path_for(schema))
624
+ index_redefine(index, schema, red, held_signatures, namespace,
625
+ defaults_schema)
626
+ end
627
+ end
628
+
629
+ # xs:redefine replaces an attributeGroup with a body whose
630
+ # self-reference is the §4.2.2 hook to the ORIGINAL
631
+ # definition. lutaml-model does NOT chase the redefine
632
+ # target, so the original document is parsed here (relative
633
+ # to the defining file) and indexed; the original
634
+ # declaration is kept for that hook and the redefining body
635
+ # indexed under the name (attgC007/attgD036). Runs after the
636
+ # nested descent so included declarations are already in.
637
+ def index_redefine(index, schema, red, held_signatures, namespace,
638
+ defaults_schema)
639
+ target_path = nil
640
+ base = begin
641
+ File.dirname(@repository.source_path_for(schema))
642
+ rescue StandardError
643
+ nil
644
+ end
645
+ if base && red.schema_path.to_s.match?(/\S/)
646
+ candidate = File.expand_path(red.schema_path.to_s, base)
647
+ target_path = candidate if File.exist?(candidate)
648
+ end
649
+ if target_path
650
+ begin
651
+ target = Lutaml::Xml::Schema::Xsd.parse(
652
+ File.read(target_path), location: target_path
653
+ )
654
+ @redefined_targets << target
655
+ index_schema(index, target, held_signatures, namespace,
656
+ defaults_schema)
608
657
  rescue StandardError
609
658
  nil
610
659
  end
611
- if base && red.schema_path.to_s.match?(/\S/)
612
- candidate = File.expand_path(red.schema_path.to_s, base)
613
- target_path = candidate if File.exist?(candidate)
614
- end
615
- if target_path
616
- begin
617
- target = Lutaml::Xml::Schema::Xsd.parse(
618
- File.read(target_path), location: target_path
619
- )
620
- index_schema(index, target, held_signatures, namespace,
621
- defaults_schema)
622
- rescue StandardError
623
- nil
624
- end
625
- end
626
- Array(red.attribute_group).each do |group|
627
- name = group.name.to_s
628
- next if name.empty?
660
+ end
661
+ # Names the body redefines: served by the body (not
662
+ # resolvable here), never by the target originals.
663
+ Array(red.complex_type).each do |body|
664
+ name = body.name.to_s
665
+ @redefined_body_names << name unless name.empty?
666
+ end
667
+ Array(red.simple_type).each do |body|
668
+ name = body.name.to_s
669
+ @redefined_body_names << name unless name.empty?
670
+ end
671
+ Array(red.attribute_group).each do |group|
672
+ name = group.name.to_s
673
+ next if name.empty?
629
674
 
630
- original = @attribute_groups[name]
631
- @redefined_originals[name] = original if original
632
- @attribute_groups[name] = group
633
- end
675
+ original = @attribute_groups[name]
676
+ @redefined_originals[name] = original if original
677
+ @attribute_groups[name] = group
634
678
  end
635
679
  end
636
680
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Xsd
5
- VERSION = "1.2.82"
5
+ VERSION = "1.2.83"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-xsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.82
4
+ version: 1.2.83
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.