lutaml-xsd 1.2.104 → 1.2.106

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: 18b2cd97c729aae1ceb8836fe492b36d0ea829de0e6e47f4f7a992e142d2e7c8
4
- data.tar.gz: 365431275056d9a6bf80a2d4bb256b0c144e52183ca62ca3fcab51822486cc84
3
+ metadata.gz: 642c768f801446e5fb51224ebf418eeaeef08f3e0dd8c4da89b378318eac0d98
4
+ data.tar.gz: cfa8d5e55aec2be1f91e73745c22d7f7afe138471c895eadd8582457528eb79c
5
5
  SHA512:
6
- metadata.gz: cd1b6f0609b6bde57f1947856b7d63e277044ad8d27076d7a6bcc0251ccfc82de133e3226f2795dca5f105fb747c0aebfcc4457832f30ab5c86adb39320609fc
7
- data.tar.gz: e9c1d309c0c544b83c469a2c8fccf13ada15daa5fd401821f1dc71c51a8a49ed4ceff35d928ff0b792fd565c4ecb4e64d34e53fbf7276fdf23061e9c703e8a33
6
+ metadata.gz: 6f05f2bfa287e9df3c90e358945483daaaa560b3a2bcb65c415879d29f65de6064ef8ba1d0340040e0cdf83ea7020663cbd2591e598ee2f8be2212e31df6ff60
7
+ data.tar.gz: fab7a21898846f6a0695506e26b1d980bf58b8348b1f758070e132c7591b5b2fa4ca3eba1ef3520576bfe3110e1fcd0f464abace93ed7d9255123fd1dc6d1bfe
data/TODO.conformance.md CHANGED
@@ -516,7 +516,44 @@ tuple keys, node-set field violations and absent-field rows handled, cross-eleme
516
516
  'true' vs xsd:int — the per-child type plumbing under hint
517
517
  layering), full type-redefine body semantics.
518
518
  - RIDE-407 PIN-BACK (2026-11-05): the leptris 1.9.407.0 + moxml
519
+ - PARENT-CONTEXT ROUND E (2026-11-09): +2 (Schema schA1,
520
+ Particles particlesA002; suite 4636->4638 = 98.76%, zero
521
+ regressions across all 94 batches, rspec green, the four-family
522
+ starvation sweep showing only the 8 known parked/contested). THE
523
+ CHILD→PARTICLE BINDING IS FULLY GENERAL: positional_children
524
+ dropped the duplicate gate — EVERY named child binds through its
525
+ parent's content model (schA1's same-local-name a1/a2 across three
526
+ namespaces resolve through the OWNING parent's type, not the
527
+ name+namespace guess that cross-bound an xsd:int namesake), with
528
+ the attempt-3 guards intact: every candidate particle INDEXED
529
+ (form/ns metadata survives) and the binding's expected namespace
530
+ must AGREE with the child's own (particlesQ016). The attempt-3
531
+ wall (277 regressions from raw-particle binding) is broken: the
532
+ wide DataTypes/Element/Particles/IC sweep is clean. PARKED:
533
+ schD10 (the chameleon form-default conflict — the suite wants the
534
+ chameleon doc's OWN unqualified elementFormDefault while ctE018
535
+ needed the includer's attributeFormDefault; owner decision on
536
+ which xmllint behavior is normative), QFE1700c1 (the suppression
537
+ must follow the NFA's child→particle assignment — matcher
538
+ surgery), addB188 (the ComplexType-capability audit).
539
+
519
540
  0.6.3 + lutaml-model 0.8.166 train carried fixes (the FULL #45
541
+ - LAX-OBIGATION ROUND (2026-11-08, parent-context round D): +5
542
+ DataTypes (duration028/029/030, dateTime013, gMonthDay006; suite
543
+ 4631->4636 = 98.72%, pending measure confirm). THE LAX WILDCARD
544
+ OBLIGATION (XSD 1.0 §3.10.4) now runs: a wildcard-governed
545
+ attribute whose declaration IS AVAILABLE (resolved in the
546
+ attribute's OWN namespace, checked against the declaration's
547
+ expected namespace — the exact-ns discipline that killed the
548
+ first attempt's name-based mis-typing) is VALIDATED against it.
549
+ duration028: the lax-governed "P" hits the global xs:duration
550
+ declaration and rejects. The unexpected-attribute check splits
551
+ into admission / strict-undeclared reporting / the obligation.
552
+ The prior dead-end's regression shapes (idF/G comps, ctZ011_b,
553
+ elemZ014, schQ1, wildZ004) re-verified clean. PARKED REMAINDER:
554
+ QFE1700c1 (matcher assignment), addB188 (ComplexType-capability
555
+ sweep), schA1/D10 (child-value binding).
556
+
520
557
  stE legs, the #522 attgC four + attgD mostly + attJ018 +
521
558
  - PARENT-CONTEXT ROUND C (2026-11-08): +1 Additional (addB065;
522
559
  suite 4630->4631 = 98.61%, pending measure confirm). A declaration
@@ -1032,56 +1032,19 @@ module Lutaml
1032
1032
  wildcards: [], repository: nil,
1033
1033
  schema_element: nil)
1034
1034
  xml_attrs.each do |xml_attr|
1035
- # Skip xmlns attributes
1036
- next if xml_attr.name == "xmlns" ||
1037
- xml_attr.prefix == "xmlns"
1038
-
1039
- # Skip xsi attributes
1040
- next if xml_attr.namespace_uri ==
1041
- "http://www.w3.org/2001/XMLSchema-instance"
1035
+ next if spec_namespace_attribute?(xml_attr)
1042
1036
 
1043
1037
  schema_attr = find_schema_attribute(schema_attrs, xml_attr,
1044
1038
  repository, schema_element)
1045
1039
  next if schema_attr
1046
1040
 
1047
- # xml:lang and friends are declared by the spec, not by
1048
- # the schema document.
1049
- next if xml_attr.namespace_uri == XmlBuiltins::NAMESPACE &&
1050
- XmlBuiltins.attribute(xml_attr.name)
1051
-
1052
- # The derivation's wildcard GROUPS admit: ACROSS groups
1053
- # (derivation layers) any group admits the attribute — the
1054
- # extension union; WITHIN a group every wildcard must
1055
- # admit — same-type wildcards intersect (wildZ013b/c/e).
1056
- admitted = false
1057
- strict_undeclared = false
1058
- wildcards.each do |group|
1059
- next unless group.all? do |wildcard|
1060
- wildcard_permits_attribute?(wildcard, xml_element,
1061
- xml_attr, repository)
1062
- end
1063
-
1064
- admitted = true
1065
- group.each do |wildcard|
1066
- next unless wildcard_process_mode(wildcard) == "strict" &&
1067
- !attribute_declared?(xml_attr, repository)
1068
-
1069
- strict_undeclared = true
1070
- end
1071
- end
1041
+ admitted, strict_undeclared =
1042
+ wildcard_admission(xml_attr, xml_element, wildcards,
1043
+ repository)
1072
1044
 
1073
1045
  if admitted
1074
- if strict_undeclared
1075
- report_error(
1076
- collector,
1077
- code: "wildcard_undeclared_attribute",
1078
- message: "Attribute '#{xml_attr.qualified_name}' " \
1079
- "matches xs:anyAttribute with " \
1080
- "processContents=strict but is not declared",
1081
- location: xml_element.xpath,
1082
- context: { attribute: xml_attr.qualified_name },
1083
- )
1084
- end
1046
+ report_wildcard_finding(xml_element, xml_attr, collector,
1047
+ strict_undeclared, repository)
1085
1048
  next
1086
1049
  end
1087
1050
 
@@ -1100,6 +1063,78 @@ module Lutaml
1100
1063
  end
1101
1064
  end
1102
1065
 
1066
+ # xmlns declarations, xsi, and the xml: builtins (lang, base,
1067
+ # space — declared by the spec, not by the schema document)
1068
+ # are not content.
1069
+ #
1070
+ # @return [Boolean]
1071
+ def spec_namespace_attribute?(xml_attr)
1072
+ return true if xml_attr.name == "xmlns" ||
1073
+ xml_attr.prefix == "xmlns"
1074
+
1075
+ return true if xml_attr.namespace_uri == XSI_NAMESPACE
1076
+
1077
+ xml_attr.namespace_uri == XmlBuiltins::NAMESPACE &&
1078
+ XmlBuiltins.attribute(xml_attr.name)
1079
+ end
1080
+
1081
+ # The derivation's wildcard GROUPS admit: ACROSS groups
1082
+ # (derivation layers) any group admits the attribute — the
1083
+ # extension union; WITHIN a group every wildcard must admit —
1084
+ # same-type wildcards intersect (wildZ013b/c/e). A strict
1085
+ # wildcard in an admitting group still demands a declaration.
1086
+ #
1087
+ # @return [Array(Boolean, Boolean)] [admitted, strict_undeclared]
1088
+ def wildcard_admission(xml_attr, xml_element, wildcards, repository)
1089
+ admitted = false
1090
+ strict_undeclared = false
1091
+ wildcards.each do |group|
1092
+ next unless group.all? do |wildcard|
1093
+ wildcard_permits_attribute?(wildcard, xml_element,
1094
+ xml_attr, repository)
1095
+ end
1096
+
1097
+ admitted = true
1098
+ group.each do |wildcard|
1099
+ next unless wildcard_process_mode(wildcard) == "strict" &&
1100
+ !attribute_declared?(xml_attr, repository)
1101
+
1102
+ strict_undeclared = true
1103
+ end
1104
+ end
1105
+ [admitted, strict_undeclared]
1106
+ end
1107
+
1108
+ # An admitted wildcard attribute reports the strict-undeclared
1109
+ # finding when strict demanded a declaration, then runs the
1110
+ # lax obligation (XSD 1.0 §3.10.4): a wildcard-governed
1111
+ # attribute whose declaration IS available (in the attribute's
1112
+ # own namespace) is validated against it — duration028: the
1113
+ # lax-governed "P" must still hit its global xs:duration
1114
+ # declaration.
1115
+ #
1116
+ # @return [void]
1117
+ def report_wildcard_finding(xml_element, xml_attr, collector,
1118
+ strict_undeclared, repository)
1119
+ if strict_undeclared
1120
+ report_error(
1121
+ collector,
1122
+ code: "wildcard_undeclared_attribute",
1123
+ message: "Attribute '#{xml_attr.qualified_name}' " \
1124
+ "matches xs:anyAttribute with " \
1125
+ "processContents=strict but is not declared",
1126
+ location: xml_element.xpath,
1127
+ context: { attribute: xml_attr.qualified_name },
1128
+ )
1129
+ end
1130
+
1131
+ found = wildcard_declaration(xml_attr, repository)
1132
+ return unless found
1133
+
1134
+ validate_attribute_value(xml_element, xml_attr, found,
1135
+ collector, repository: repository)
1136
+ end
1137
+
1103
1138
  # Whether the loaded lutaml-model parses xs:anyAttribute on
1104
1139
  # complexType (the mapping landed after 0.8.121); probed once
1105
1140
  # with a minimal schema.
@@ -1290,14 +1325,28 @@ module Lutaml
1290
1325
  def attribute_declared?(xml_attr, repository)
1291
1326
  return true if repository.nil?
1292
1327
 
1328
+ !wildcard_declaration(xml_attr, repository).nil?
1329
+ end
1330
+
1331
+ # The global declaration the wildcard-governed attribute
1332
+ # resolves to, resolved in the attribute's OWN namespace and
1333
+ # checked against the declaration's expected namespace
1334
+ # (duration028's lax obligation uses it for value validation).
1335
+ #
1336
+ # @return [Lutaml::Xml::Schema::Xsd::Attribute, nil]
1337
+ def wildcard_declaration(xml_attr, repository)
1338
+ return nil if repository.nil?
1339
+
1293
1340
  declaration = repository.resolve_attribute(
1294
1341
  xml_attr.name, xml_attr.namespace_uri
1295
1342
  )
1296
- return false unless declaration
1343
+ return nil unless declaration
1297
1344
 
1298
1345
  expected = repository.expected_attribute_namespace(declaration)
1299
- expected.nil? ||
1300
- expected == xml_attr.namespace_uri.to_s
1346
+ if expected.nil? ||
1347
+ expected == xml_attr.namespace_uri.to_s
1348
+ declaration
1349
+ end
1301
1350
  end
1302
1351
 
1303
1352
  # Target namespace of the schema owning the parent's declaration.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Xsd
5
- VERSION = "1.2.104"
5
+ VERSION = "1.2.106"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-xsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.104
4
+ version: 1.2.106
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-11-08 00:00:00.000000000 Z
11
+ date: 2026-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid