lutaml-xsd 1.2.102 → 1.2.104

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: c1b37fc4af01d8c2f652a899644d9f85f13fec225d6ae0ce393b7d16f19df5bc
4
- data.tar.gz: 2b08927d906be739a784888c3e1d9c9fb5a303362cc6dcc565404e0500b4f74d
3
+ metadata.gz: 18b2cd97c729aae1ceb8836fe492b36d0ea829de0e6e47f4f7a992e142d2e7c8
4
+ data.tar.gz: 365431275056d9a6bf80a2d4bb256b0c144e52183ca62ca3fcab51822486cc84
5
5
  SHA512:
6
- metadata.gz: 95823a7f86274b2363e65b1a36d0b9aff1078c55196c8f53982d065ec67f0b32b60d1c18436ff8839f65f150373ffa822fa0c4cdaf046f042694ef94279fb0cc
7
- data.tar.gz: f85b40f50b7ac8d93bfe7341feb8eaf4442ea4ac3b0fb9f3ea51cbb3f832835ac3f36033f9897e816371ba99ddf206f7c271a81389b3bf32370acc2104670968
6
+ metadata.gz: cd1b6f0609b6bde57f1947856b7d63e277044ad8d27076d7a6bcc0251ccfc82de133e3226f2795dca5f105fb747c0aebfcc4457832f30ab5c86adb39320609fc
7
+ data.tar.gz: e9c1d309c0c544b83c469a2c8fccf13ada15daa5fd401821f1dc71c51a8a49ed4ceff35d928ff0b792fd565c4ecb4e64d34e53fbf7276fdf23061e9c703e8a33
data/TODO.conformance.md CHANGED
@@ -518,7 +518,45 @@ tuple keys, node-set field violations and absent-field rows handled, cross-eleme
518
518
  - RIDE-407 PIN-BACK (2026-11-05): the leptris 1.9.407.0 + moxml
519
519
  0.6.3 + lutaml-model 0.8.166 train carried fixes (the FULL #45
520
520
  stE legs, the #522 attgC four + attgD mostly + attJ018 +
521
+ - PARENT-CONTEXT ROUND C (2026-11-08): +1 Additional (addB065;
522
+ suite 4630->4631 = 98.61%, pending measure confirm). A declaration
523
+ carrying a FIXED value constraint rejects xsi:nil=true outright
524
+ (XSD 1.0 §4.2.3 as the errata reads it; xmllint: "cannot be
525
+ 'nilled' because there is a fixed value constraint defined for
526
+ it") — the nil-true branch now reports xsi_nil_with_fixed and
527
+ treats the element as nilled-handled. PARKED same-day: addB188
528
+ (an undeclared root anchored by xsi:type must assess against the
529
+ named type — the override-type dispatch was TRIED and reverted:
530
+ constraint-category rules assume Element schema_defs and crash on
531
+ ComplexType; the fix needs a per-rule ComplexType-capability
532
+ audit, a sibling of the parent-context charter). addB187's valid
533
+ twin re-verified after the revert.
534
+
521
535
  schF1/P2, stE065/066/096) AND a WHOLESALE 407 regex regression:
536
+ - PARENT-CONTEXT ROUND B (2026-11-08): +1 Additional (isDefault079;
537
+ suite 4629->4630 = 98.59%, zero regressions, rspec green).
538
+ POSITIONAL BINDING for duplicate same-named locals: a model with
539
+ two regvalueop locals carrying DIFFERENT fixed values never bound
540
+ the second child to the second particle — the name-only dispatch
541
+ always hit the first. The engine computes each child's same-name
542
+ sibling index (on the RAW moxml nodes — wrapper objects are not
543
+ identity-stable across accessor calls, the IdUniquenessRule
544
+ lesson) and dispatches the positionally-bound declaration when
545
+ (a) the parent's model holds MORE THAN ONE same-named particle,
546
+ (b) every particle is INDEXED (attempt-3's starvation guard: raw
547
+ parent-model particles carry none of the form/ns metadata the
548
+ rules assume — resolver positional_children returns [] otherwise),
549
+ and (c) the candidate's expected namespace AGREES with the child's
550
+ (particlesQ016's global/local namesake guard). The ordered walk
551
+ keeps a PER-CALL visited set — the resolver's
552
+ each_particle_element memoizes on the instance and would poison
553
+ repeats. LESSON: scripted line-surgery on lib files dropped a
554
+ class end and leaked methods to top level (runtime-only
555
+ uninitialized-constant failures, caught by sentinel probes) —
556
+ structural edits go through the Edit tool only. Remaining parked
557
+ (matcher-assignment + root-assessment shapes): QFE1700c1,
558
+ addB065, addB188, schA1/D10 + the lax-wildcard six.
559
+
522
560
  ~177 cases — the ENTIRE Unicode-block escape family (~80
523
561
  - PARENT-CONTEXT ROUND A (2026-11-08): +1 Errata10 (errC007; suite
524
562
  4628->4629 = 98.57%, zero regressions, rspec green). The
@@ -65,6 +65,25 @@ module Lutaml
65
65
  schema_def = resolver.resolve(
66
66
  xml_element.name, xml_element.namespace_uri
67
67
  )
68
+ if parent
69
+ parent_declaration =
70
+ resolver.resolve(parent.name, parent.namespace_uri)
71
+ candidates = resolver.positional_children(parent_declaration,
72
+ xml_element.name)
73
+ positional = candidates[same_name_sibling_index(xml_element,
74
+ parent)]
75
+ # The binding must agree with the child's OWN namespace:
76
+ # an unqualified ref's global namesake never serves a
77
+ # qualified local namesake (particlesQ016).
78
+ child_ns = xml_element.namespace_uri.to_s
79
+ expected_ns =
80
+ resolver.expected_namespace_for(positional).to_s
81
+ if positional &&
82
+ ((child_ns.empty? && expected_ns.empty?) ||
83
+ child_ns == expected_ns)
84
+ schema_def = positional
85
+ end
86
+ end
68
87
  rules.each do |rule|
69
88
  argument = rule.schema_argument(schema_def, repository: resolver)
70
89
  next if argument.nil? && !rule.runs_without_schema?
@@ -204,6 +223,23 @@ module Lutaml
204
223
  end
205
224
  end
206
225
 
226
+ # The child's position among its same-named siblings — the index
227
+ # the positional binding (duplicate same-named declarations,
228
+ # isDefault079) binds to. Computed on the RAW moxml nodes: the
229
+ # wrapper objects are not identity-stable across accessor calls
230
+ # (the IdUniquenessRule lesson).
231
+ #
232
+ # @return [Integer]
233
+ def same_name_sibling_index(element, parent)
234
+ raw_children = Array(parent.moxml_element.elements)
235
+ position = raw_children.index do |node|
236
+ node.equal?(element.moxml_element)
237
+ end
238
+ return 0 if position.nil?
239
+
240
+ raw_children.take(position).count { |node| node.name == element.name }
241
+ end
242
+
207
243
  # Whether the parent's content model holds a processContents
208
244
  # skip wildcard whose namespace range admits the child — the
209
245
  # child subtree then escapes assessment entirely (addB125).
@@ -333,6 +333,22 @@ module Lutaml
333
333
  return true
334
334
  end
335
335
 
336
+ # A fixed value constraint forbids nilled elements
337
+ # outright (addB065; xmllint: "cannot be 'nilled' because
338
+ # there is a fixed value constraint").
339
+ unless schema_element.fixed.to_s.empty?
340
+ report_error(
341
+ collector,
342
+ code: "xsi_nil_with_fixed",
343
+ message: "Element '#{xml_element.name}' cannot be " \
344
+ "nilled because there is a fixed value " \
345
+ "constraint defined for it",
346
+ location: xml_element.xpath,
347
+ context: { element: xml_element.name },
348
+ )
349
+ return true
350
+ end
351
+
336
352
  if xml_element.children.empty? &&
337
353
  xml_element.text_content.to_s.strip.empty?
338
354
  return true
@@ -587,8 +587,92 @@ module Lutaml
587
587
  element_declaration_simple?(field_decl)
588
588
  end
589
589
 
590
+ # The ordered same-named inline particles of the parent's
591
+ # content model — the POSITIONAL binding for duplicate
592
+ # declarations (isDefault079: two regvalueop locals with
593
+ # different fixed values; the second child binds to the second
594
+ # particle). Returns [] unless the name appears MORE THAN ONCE
595
+ # and every particle is INDEXED (attempt-3's starvation: raw
596
+ # particles carry none of the form/ns metadata the rules
597
+ # assume). The walk keeps its own cycle guard — the resolver's
598
+ # each_particle_element memoizes visited nodes on the instance
599
+ # and would poison repeated walks.
600
+ #
601
+ # @param parent_declaration [Lutaml::Xml::Schema::Xsd::Element, nil]
602
+ # @param local_name [String]
603
+ # @return [Array<Lutaml::Xml::Schema::Xsd::Element>]
604
+ def positional_children(parent_declaration, local_name)
605
+ type = parent_declaration&.complex_type ||
606
+ resolve_type(parent_declaration)
607
+ return [] unless type.is_a?(Lutaml::Xml::Schema::Xsd::ComplexType)
608
+
609
+ particles = []
610
+ collect_named_particles(particle_for_type(type), local_name,
611
+ particles, {}.compare_by_identity, 0)
612
+ return [] if particles.length < 2
613
+ return [] unless particles.all? { |p| @namespaces.key?(p) }
614
+
615
+ particles
616
+ end
617
+
590
618
  private
591
619
 
620
+ # Depth-first ordered collection of same-named element
621
+ # particles; per-call visited set (identity-keyed), group refs
622
+ # expanded.
623
+ #
624
+ # @return [void]
625
+ def collect_named_particles(node, local_name, out, visited, depth)
626
+ return if node.nil? || depth > 24
627
+
628
+ if node.is_a?(Array)
629
+ node.each do |child|
630
+ collect_named_particles(child, local_name, out, visited,
631
+ depth + 1)
632
+ end
633
+ return
634
+ end
635
+ return if visited[node]
636
+
637
+ visited[node] = true
638
+
639
+ if node.is_a?(Lutaml::Xml::Schema::Xsd::Element)
640
+ if node.name.to_s.split(":").last == local_name
641
+ out << node
642
+ elsif node.ref.to_s.match?(/\S/) &&
643
+ node.ref.to_s.split(":").last == local_name
644
+ global = resolve_global(node.ref.to_s.split(":").last, nil)
645
+ out << global if global
646
+ end
647
+ return
648
+ end
649
+
650
+ nested = CONTAINER_NESTED_KINDS[node.class]
651
+ nested&.each do |kind|
652
+ collect_named_particles(Array(node.public_send(kind)),
653
+ local_name, out, visited, depth + 1)
654
+ end
655
+ (CONTAINER_LEAF_KINDS[node.class] || []).each do |kind|
656
+ Array(node.public_send(kind)).each do |leaf|
657
+ next unless leaf
658
+
659
+ if leaf.is_a?(Lutaml::Xml::Schema::Xsd::Group)
660
+ resolved = if leaf.ref
661
+ resolve_group(leaf.ref.to_s
662
+ .split(":").last)
663
+ else
664
+ leaf
665
+ end
666
+ collect_named_particles(resolved, local_name, out, visited,
667
+ depth + 1)
668
+ elsif leaf.is_a?(Lutaml::Xml::Schema::Xsd::Element)
669
+ collect_named_particles(leaf, local_name, out, visited,
670
+ depth + 1)
671
+ end
672
+ end
673
+ end
674
+ end
675
+
592
676
  # Whether a TYPE carries an identity value for a field bound to
593
677
  # the selector node itself (a "." field): a simple type or a
594
678
  # complex type with simple content does; complex content does not.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Xsd
5
- VERSION = "1.2.102"
5
+ VERSION = "1.2.104"
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.102
4
+ version: 1.2.104
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.