lutaml-xsd 1.2.97 → 1.2.98
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 +4 -4
- data/TODO.conformance.md +20 -0
- data/lib/lutaml/xsd/validation/rules/identity_constraints_rule.rb +106 -0
- data/lib/lutaml/xsd/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e129470c8c939e17b19e748ffaebf593f7f3909876fbe05e1b733e1129f448ba
|
|
4
|
+
data.tar.gz: '03015085efe53c4dca6dec3bc5115d9081b42a24c2f758b19c4c3424b672521f'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e1be4de4f925cb152fa5f69e2cb57fb42d9337ab37628b71314ab0e3bc7a5d10da9cf829173a78303c0e8e495682286bb9ecf4bde0d72056324d6e572d309cc
|
|
7
|
+
data.tar.gz: ae47a5ca4b9bc803c7e7c35aaeb0a9e8a35e9610bddacdd82d14b269310863f91d64a9f59f1cd9f0014ea72dd0040f975098feccd30914fc6e7cf053845a9b91
|
data/TODO.conformance.md
CHANGED
|
@@ -524,6 +524,26 @@ tuple keys, node-set field violations and absent-field rows handled, cross-eleme
|
|
|
524
524
|
series — filed leptris-rs#47; moxml 0.6.3 regressed 5 attribute
|
|
525
525
|
cases (addB059/196c/197c, attO009/011) — filed moxml#529. THE
|
|
526
526
|
STACK IS PINNED BACK to the known-good 1.9.406.0/0.6.2/0.8.161
|
|
527
|
+
- SKIP-WILDCARD-FIELD ROUND (2026-11-07): +1 IC (idZ015; suite
|
|
528
|
+
4621->4622 = 98.42%, zero regressions, rspec green). THE LAST IC
|
|
529
|
+
SINGLETON — the idK/idZ family is now CLEAN (all six roots fixed
|
|
530
|
+
across the four rounds). An attribute admitted by a
|
|
531
|
+
processContents=skip wildcard is NOT ASSESSED, so it supplies no
|
|
532
|
+
identity-constraint field value: the field treats it as absent and
|
|
533
|
+
a key whose fields do not all evaluate is violated (idZ015: foo's
|
|
534
|
+
##any skip anyAttribute + key field @bar; xmllint: "Not all fields
|
|
535
|
+
of key identity-constraint evaluate to a node"). The skip check
|
|
536
|
+
walks the selector node's declaration anyAttribute wildcards
|
|
537
|
+
(own + content parts + attributeGroup members, depth 3) and the
|
|
538
|
+
namespace constraint reads the attribute's URI from the MOXML
|
|
539
|
+
element wrapper — xpath result attributes are ADAPTER objects
|
|
540
|
+
(leptris ResultAttr carries no namespace). GOTCHA: the first
|
|
541
|
+
implementation read node.namespace and CRASHED under leptris —
|
|
542
|
+
the suite probe "passed" as CRASH-AS-INVALID, caught by writing
|
|
543
|
+
the rule-level spec FIRST (rule_execution_error instead of the
|
|
544
|
+
finding). Suite verdicts from crashes are not fixes; assert the
|
|
545
|
+
finding code.
|
|
546
|
+
|
|
527
547
|
(98.28% restored, zero regressions vs the 406 baseline). The
|
|
528
548
|
- IDREF-RESOLUTION ROUND (2026-11-07): +1 IC (idZ012; suite
|
|
529
549
|
4620->4621 = 98.40%, zero regressions, rspec green). Every
|
|
@@ -128,6 +128,14 @@ module Lutaml
|
|
|
128
128
|
ambiguous = true if matched.size > 1
|
|
129
129
|
values << if matched.first.nil?
|
|
130
130
|
field_supply_value(node, field, repository)
|
|
131
|
+
elsif !matched.first.is_a?(Moxml::Element) &&
|
|
132
|
+
skip_governed_attribute?(node, matched.first,
|
|
133
|
+
repository)
|
|
134
|
+
# A skip-wildcard-governed attribute is not
|
|
135
|
+
# assessed, so it supplies no identity-
|
|
136
|
+
# constraint value: the field treats it as
|
|
137
|
+
# absent (idZ015).
|
|
138
|
+
nil
|
|
131
139
|
elsif matched.first.is_a?(Moxml::Element) &&
|
|
132
140
|
field_node_non_simple?(
|
|
133
141
|
matched.first, constraint, raws[index],
|
|
@@ -337,6 +345,104 @@ module Lutaml
|
|
|
337
345
|
repository.declared_attribute_supply(parent_type, attr_local)
|
|
338
346
|
end
|
|
339
347
|
|
|
348
|
+
# Whether the instance attribute is governed by a SKIP
|
|
349
|
+
# wildcard on the selector node's declaration: a skip-
|
|
350
|
+
# governed attribute is not assessed, so it supplies no
|
|
351
|
+
# identity-constraint field value (idZ015).
|
|
352
|
+
#
|
|
353
|
+
# @return [Boolean]
|
|
354
|
+
def skip_governed_attribute?(element_node, attribute_node,
|
|
355
|
+
repository)
|
|
356
|
+
declaration = repository&.resolve(element_node.name,
|
|
357
|
+
element_node.namespace_uri)
|
|
358
|
+
return false unless declaration
|
|
359
|
+
|
|
360
|
+
type = declaration.complex_type ||
|
|
361
|
+
repository.resolve_type(declaration)
|
|
362
|
+
return false unless type.is_a?(Lutaml::Xml::Schema::Xsd::ComplexType)
|
|
363
|
+
|
|
364
|
+
target_ns = repository.target_namespace_for(declaration)
|
|
365
|
+
attribute_ns = attribute_namespace(element_node, attribute_node)
|
|
366
|
+
attribute_skip_wildcards(type, repository, 0).any? do |wildcard|
|
|
367
|
+
wildcard_process_mode(wildcard) == "skip" &&
|
|
368
|
+
wildcard_admits_namespace?(wildcard, attribute_ns, target_ns)
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# The attribute's namespace URI: the xpath result nodes are
|
|
373
|
+
# adapter objects (leptris ResultAttr carries no namespace),
|
|
374
|
+
# so the name-matched attribute on the MOXML element wrapper
|
|
375
|
+
# resolves it.
|
|
376
|
+
#
|
|
377
|
+
# @return [String]
|
|
378
|
+
def attribute_namespace(element_node, attribute_node)
|
|
379
|
+
found = element_node.attributes.find do |candidate|
|
|
380
|
+
candidate.name == attribute_node.name
|
|
381
|
+
end
|
|
382
|
+
found&.namespace&.uri.to_s
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# The anyAttribute wildcards reachable from the type: its own,
|
|
386
|
+
# content-part bodies, and attributeGroup members (nested
|
|
387
|
+
# refs depth-guarded).
|
|
388
|
+
#
|
|
389
|
+
# @return [Array<Lutaml::Xml::Schema::Xsd::AnyAttribute>]
|
|
390
|
+
def attribute_skip_wildcards(type, repository, depth)
|
|
391
|
+
return [] if depth > 3
|
|
392
|
+
|
|
393
|
+
wildcards = Array(type.any_attribute)
|
|
394
|
+
Array(type.attribute_group).each do |group|
|
|
395
|
+
wildcards.concat(Array(group.any_attribute))
|
|
396
|
+
local = (group.ref || group.name).to_s.split(":").last
|
|
397
|
+
declaration = local && repository.resolve_attribute_group(local)
|
|
398
|
+
if declaration
|
|
399
|
+
wildcards.concat(attribute_skip_wildcards(declaration,
|
|
400
|
+
repository,
|
|
401
|
+
depth + 1))
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
content_kinds = %i[complex_content simple_content]
|
|
405
|
+
part_kinds = %i[extension restriction]
|
|
406
|
+
content_kinds.each do |content_kind|
|
|
407
|
+
content = type.public_send(content_kind)
|
|
408
|
+
next unless content
|
|
409
|
+
|
|
410
|
+
part_kinds.each do |part_kind|
|
|
411
|
+
Array(content.public_send(part_kind)).each do |part|
|
|
412
|
+
wildcards.concat(Array(part.any_attribute))
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
wildcards
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# Whether the wildcard's namespace constraint admits the
|
|
420
|
+
# attribute's namespace (mirrors WildcardScope#wildcard_permits?
|
|
421
|
+
# for attribute nodes, against the declaration's target
|
|
422
|
+
# namespace).
|
|
423
|
+
#
|
|
424
|
+
# @return [Boolean]
|
|
425
|
+
def wildcard_admits_namespace?(wildcard, uri, target_ns)
|
|
426
|
+
case wildcard.namespace.to_s
|
|
427
|
+
when "##any", ""
|
|
428
|
+
true
|
|
429
|
+
when "##other"
|
|
430
|
+
!uri.empty? && uri != target_ns.to_s
|
|
431
|
+
when "##local"
|
|
432
|
+
uri.empty?
|
|
433
|
+
when "##targetNamespace"
|
|
434
|
+
uri == target_ns.to_s
|
|
435
|
+
else
|
|
436
|
+
wildcard.namespace.to_s.split(/\s+/).any? do |entry|
|
|
437
|
+
case entry
|
|
438
|
+
when "##local" then uri.empty?
|
|
439
|
+
when "##targetNamespace" then uri == target_ns.to_s
|
|
440
|
+
else entry == uri
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
340
446
|
# Whether an element field's node supplies no identity value:
|
|
341
447
|
# it has element children, is declared non-simple (complex
|
|
342
448
|
# content or xsd:anyType — the typeless default), or carries a
|
data/lib/lutaml/xsd/version.rb
CHANGED