lutaml-xsd 1.2.81 → 1.2.82
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 +30 -10
- data/lib/lutaml/xsd/validation/rules/attribute_validation_rule.rb +108 -11
- data/lib/lutaml/xsd/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c3da66790f16686077f84ff27947241c3fd9290e4a36f92d5b26ee70d340af4
|
|
4
|
+
data.tar.gz: 205af1e6a170523b054c34ba0cf43b86203877784bfe471ef88e47bcdbf60ae9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6901b1b6a2fc09e00325fe3e24df146097e6bf6967493e46e04d7eabe8b7a9183cdccc2cc8ccf39cfd9d0f3cf90157b0647c772f61512a68085c041fbf1329be
|
|
7
|
+
data.tar.gz: 221ce2f9ce160b0524a99cb9dfb029ccc10040adbe8282e8cb37ecbc94cc9f689e1a6b2e28a6ca27cd069ef2c6547a5d728f37a3254b5fc501b9cce50d27118c
|
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 |
|
|
123
|
+
| pipeline | 4578/4696 (97.49%) |
|
|
124
124
|
|
|
125
125
|
(2026-11-02, bundled-stack measurement with the escape,
|
|
126
126
|
hint-following, pattern-alternative, identity-crash, engine-set,
|
|
@@ -142,7 +142,8 @@ lockfile refresh) → 4411 (93.9%) → 4430 (94.3%) → 4435 (94.4%) →
|
|
|
142
142
|
4436 (94.5%) → 4439 (94.5%) → 4454 (94.9%) → 4495 (95.7%) → 4524
|
|
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
|
-
4563 (97.17%, ref-namespace round) → 4573 (97.38%, group-content
|
|
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
147
|
\w/\W/\s to their XSD value spaces) collapses Regex 120→69;
|
|
147
148
|
same-step pattern facets now behave as alternatives and
|
|
148
149
|
whitespace-only text reaches the facets intact (PR #200), Regex
|
|
@@ -232,15 +233,19 @@ corners.
|
|
|
232
233
|
|
|
233
234
|
| Class | Cases | Filed |
|
|
234
235
|
|---|---|---|
|
|
235
|
-
|
|
|
236
|
-
|
|
|
237
|
-
|
|
|
238
|
-
|
|
|
239
|
-
|
|
|
240
|
-
|
|
|
236
|
+
| Empty content against a fixed element value rejected (1.9.402.0 regression — isDefault001/002/076, ctZ013a, elemQ019, stE065/066/096, particlesZ040; attribute leg addB104, attO006) | 15 | leptris-rs#25 (+ case-list comment) |
|
|
237
|
+
| Content model enforced on NILLED elements (QFE1700g2, particlesIa002) | 2 | leptris-rs#26 |
|
|
238
|
+
| dateTime enumeration rejects timezone-equal forms (dateTime_enumeration005a/b) | 2 | leptris-rs#27 |
|
|
239
|
+
| "-0" rejected against nonNegativeInteger (errE002) | 1 | leptris-rs#28 |
|
|
240
|
+
| xsi:type override / substitution-member type binding false rejects (elemZ002, elemZ020) | 2 | leptris-rs#29 |
|
|
241
|
+
| Built-in lexical tables (char-reference shapes reZ003v/004v/005v/006v/006i, reK88; \D vintage reT51) | 7 | leptris/leptris#1936 (+ case-list comment) |
|
|
242
|
+
| Facade strict re-check on composed schemas — attributes (attgD005/019/020/021/022/025/027/029/031/033/034, attJ018) and composed type binding (schF1/G2/G7/P2) | 15 | moxml#510 (+ consolidated evidence comment) |
|
|
241
243
|
| Unresolvable include/import/redefine schemaLocation raises at parse instead of warning (anyURI_a001/a002, schD7, schG8) | 4 | lutaml-model#1087 |
|
|
242
|
-
|
|
|
243
|
-
|
|
|
244
|
+
| Automaton size cap surfaces as an instance error instead of engine-inert silence | 0 — FIXED in leptris 1.9.398 | moxml#514 (follow-up to #473) |
|
|
245
|
+
| Redefine self-extension drops the extension content model | 0 — FIXED in leptris 1.9.396 | leptris#1926 (closed) |
|
|
246
|
+
| Ruby-side under-detections and false rejects (Regex dialect 18 — reJ/reS/reDH disputed families excluded; DataTypes corners duration028-030/dateTime013/gMonthDay006/dtZ86723; IC idK/idZ singletons; SimpleType stZ; Wildcards wildZ013; Group/Particles stragglers; Schema schT/D10/F2/errC007; Q032 chameleon import; particlesA013/A002/Ie004/Ig003/Ob012/015/Z001; mgO006/034; attF001/attJ002/003/attLa005; isDefault079) | ~55 | OURS — the remaining Ruby work queue |
|
|
247
|
+
|
|
248
|
+
Engine-attribution census (2026-11-03): of the 123 current failures, 50 carry engine findings (all attributed above), 73 are Ruby-side.
|
|
244
249
|
|
|
245
250
|
Suite history (same-stack where known): 71.8% baseline → 83.5%
|
|
246
251
|
(pre-NFA) → 83.6% (NFA + guard, 1.2.41) → 84.3% (#180) → 86.0%
|
|
@@ -450,6 +455,21 @@ tuple keys, node-set field violations and absent-field rows handled, cross-eleme
|
|
|
450
455
|
import; our index keeps them no-namespace so the four e2 refs
|
|
451
456
|
mis-resolve). Zero regressions; the drift entries above remain
|
|
452
457
|
(fixed-empty 9, reU6).
|
|
458
|
+
- ATTRIBUTE-PROHIBITION ROUND (2026-11-03): +5 Attribute (9→4,
|
|
459
|
+
attF001/J002/J003/Z007i under-detections + attLa005 fixed-facet;
|
|
460
|
+
suite 4573→4578 = 97.49%, ZERO regressions, rspec green).
|
|
461
|
+
use=prohibited was never enforced — instances could carry a
|
|
462
|
+
prohibited attribute unchecked. The declaration binds now, with
|
|
463
|
+
THREE suite-arbitrated exemptions for incoherent shapes: a
|
|
464
|
+
wildcard admitting the attribute shadows it (attZ002); fixed +
|
|
465
|
+
prohibited is an illegal combo treated as inert (attP031); a
|
|
466
|
+
prohibited member inside an attributeGroup DEFINITION is illegal
|
|
467
|
+
placement the suite ignores (attZ015). A derived type's OWN
|
|
468
|
+
declaration overrides the base chain's prohibited (attZ007v) while
|
|
469
|
+
a restriction body's own prohibited stands (attZ007i). A ref's
|
|
470
|
+
use-site fixed overlays the global declaration in the value check
|
|
471
|
+
(attLa005). Attribute remainder (4): attJ018 + attO009/011
|
|
472
|
+
(engine-silent — queue), attO006 (leptris-rs#25 attribute leg).
|
|
453
473
|
- REGEX SEMANTICS ROUND (2026-10-31, PR #208): \w/\W now carry their
|
|
454
474
|
Appendix F complements (\w = [^\p{P}\p{Z}\p{C}], class interiors
|
|
455
475
|
via the exact positive partition L/M/N/S), \I/\C complements added
|
|
@@ -94,11 +94,24 @@ module Lutaml
|
|
|
94
94
|
resolved_attributes,
|
|
95
95
|
xml_attributes, collector)
|
|
96
96
|
|
|
97
|
+
# Step 1b: Check prohibited attributes are absent — the
|
|
98
|
+
# declaration exists, its USE does not (attF001). Three
|
|
99
|
+
# suite-arbitrated exemptions: a wildcard that admits the
|
|
100
|
+
# attribute shadows the prohibition (attZ002); fixed plus
|
|
101
|
+
# prohibited is an illegal declaration combo and the suite
|
|
102
|
+
# treats the whole declaration as inert (attP031); and a
|
|
103
|
+
# prohibition arriving through DERIVATION is refinement
|
|
104
|
+
# incoherence the suite ignores (attZ007v, attZ015).
|
|
105
|
+
validate_prohibited_attributes(xml_element, schema_attributes,
|
|
106
|
+
xml_attributes, collector,
|
|
107
|
+
wildcards: wildcards)
|
|
108
|
+
|
|
97
109
|
# Step 2: Validate attribute values
|
|
98
110
|
validate_attribute_values(xml_element, resolved_attributes,
|
|
99
111
|
xml_attributes, collector,
|
|
100
112
|
repository: repository,
|
|
101
|
-
schema_element: schema_element
|
|
113
|
+
schema_element: schema_element,
|
|
114
|
+
raw_attrs: schema_attributes)
|
|
102
115
|
|
|
103
116
|
# Step 3: Check for unexpected attributes
|
|
104
117
|
validate_no_unexpected_attributes(xml_element,
|
|
@@ -224,9 +237,35 @@ module Lutaml
|
|
|
224
237
|
attributes.concat(inherited_attributes(part.base, repository)) if part
|
|
225
238
|
end
|
|
226
239
|
|
|
240
|
+
override_base_prohibitions(schema_def, attributes)
|
|
227
241
|
attributes
|
|
228
242
|
end
|
|
229
243
|
|
|
244
|
+
# A derived type's OWN (type-level or derivation-body)
|
|
245
|
+
# non-prohibited declaration for a name overrides the base
|
|
246
|
+
# chain's prohibited (attZ007v: the extension re-adds att1
|
|
247
|
+
# required over Two's prohibited). A restriction body's own
|
|
248
|
+
# prohibited stands against the inherited plain declaration
|
|
249
|
+
# (attZ007i: e2 carrying att1 is invalid).
|
|
250
|
+
#
|
|
251
|
+
# @return [void]
|
|
252
|
+
def override_base_prohibitions(schema_def, attributes)
|
|
253
|
+
own_declarations = Array(schema_def.attribute)
|
|
254
|
+
content = schema_def.complex_content || schema_def.simple_content
|
|
255
|
+
CONTENT_PART_KINDS.each do |kind|
|
|
256
|
+
part = content && Array(content.public_send(kind)).first
|
|
257
|
+
own_declarations += Array(part&.attribute) if part
|
|
258
|
+
end
|
|
259
|
+
own_names = own_declarations
|
|
260
|
+
.reject { |a| a.use.to_s == "prohibited" }
|
|
261
|
+
.map { |a| a.name.to_s }
|
|
262
|
+
attributes.reject! do |a|
|
|
263
|
+
a.use.to_s == "prohibited" &&
|
|
264
|
+
own_names.include?(a.name.to_s) &&
|
|
265
|
+
!own_declarations.include?(a)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
230
269
|
# The base type's attribute set flows into the derived type
|
|
231
270
|
# through extension and restriction alike.
|
|
232
271
|
#
|
|
@@ -275,7 +314,11 @@ module Lutaml
|
|
|
275
314
|
return [] unless group
|
|
276
315
|
|
|
277
316
|
own = (group.name || group.ref).to_s.split(":").last
|
|
278
|
-
|
|
317
|
+
# use=prohibited is illegal inside an attributeGroup
|
|
318
|
+
# DEFINITION (attZ015): the suite ignores such members.
|
|
319
|
+
attrs = Array(group.attribute).reject do |attr|
|
|
320
|
+
attr.use.to_s == "prohibited"
|
|
321
|
+
end
|
|
279
322
|
|
|
280
323
|
# An attributeGroup may reference other attributeGroups —
|
|
281
324
|
# their declarations flow into the expansion (attgD004). A
|
|
@@ -393,6 +436,44 @@ module Lutaml
|
|
|
393
436
|
schema_attr.use == "required"
|
|
394
437
|
end
|
|
395
438
|
|
|
439
|
+
# A prohibited attribute is DECLARED but its use is banned:
|
|
440
|
+
# any instance occurrence violates the schema (attF001).
|
|
441
|
+
#
|
|
442
|
+
# @return [void]
|
|
443
|
+
def validate_prohibited_attributes(xml_element, schema_attrs,
|
|
444
|
+
xml_attrs, collector,
|
|
445
|
+
wildcards: [])
|
|
446
|
+
schema_attrs.each do |schema_attr|
|
|
447
|
+
next unless schema_attr.use.to_s == "prohibited"
|
|
448
|
+
# fixed + prohibited is an illegal declaration combo
|
|
449
|
+
# (attP031): the suite treats the declaration as inert.
|
|
450
|
+
next if schema_attr.fixed
|
|
451
|
+
|
|
452
|
+
attr_name = schema_attr.name.to_s
|
|
453
|
+
next if attr_name.empty?
|
|
454
|
+
|
|
455
|
+
xml_attr = xml_attrs.find { |xa| xa.name == attr_name }
|
|
456
|
+
next unless xml_attr
|
|
457
|
+
next if wildcards.any? do |wildcard|
|
|
458
|
+
wildcard_permits_attribute?(wildcard, xml_element, xml_attr,
|
|
459
|
+
nil)
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
report_error(
|
|
463
|
+
collector,
|
|
464
|
+
code: "prohibited_attribute_present",
|
|
465
|
+
message: "Attribute '#{attr_name}' is prohibited here " \
|
|
466
|
+
"but present",
|
|
467
|
+
location: xml_element.xpath,
|
|
468
|
+
context: {
|
|
469
|
+
attribute: attr_name,
|
|
470
|
+
element: xml_element.name,
|
|
471
|
+
},
|
|
472
|
+
suggestion: "Remove attribute: #{attr_name}",
|
|
473
|
+
)
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
396
477
|
# Validate attribute values
|
|
397
478
|
#
|
|
398
479
|
# @param xml_element [XmlElement] The element
|
|
@@ -402,14 +483,23 @@ module Lutaml
|
|
|
402
483
|
# @return [void]
|
|
403
484
|
def validate_attribute_values(xml_element, schema_attrs, xml_attrs,
|
|
404
485
|
collector, repository: nil,
|
|
405
|
-
schema_element: nil)
|
|
486
|
+
schema_element: nil, raw_attrs: [])
|
|
406
487
|
xml_attrs.each do |xml_attr|
|
|
407
488
|
schema_attr = find_schema_attribute(schema_attrs, xml_attr,
|
|
408
489
|
repository, schema_element)
|
|
409
490
|
next unless schema_attr
|
|
410
491
|
|
|
492
|
+
# A ref's use site may carry facets the global declaration
|
|
493
|
+
# lacks (attLa005: ref="x:ga1" fixed="abc" at the use
|
|
494
|
+
# site); the instance value is checked against them too.
|
|
495
|
+
use_site = raw_attrs.find do |r|
|
|
496
|
+
r.name == schema_attr.name ||
|
|
497
|
+
r.ref.to_s.split(":").last == schema_attr.name
|
|
498
|
+
end
|
|
411
499
|
validate_attribute_value(xml_element, xml_attr, schema_attr,
|
|
412
|
-
collector,
|
|
500
|
+
collector,
|
|
501
|
+
repository: repository,
|
|
502
|
+
use_site: use_site)
|
|
413
503
|
end
|
|
414
504
|
end
|
|
415
505
|
|
|
@@ -461,10 +551,11 @@ module Lutaml
|
|
|
461
551
|
# "123").
|
|
462
552
|
#
|
|
463
553
|
# @return [Boolean]
|
|
464
|
-
def fixed_value_matches?(value, schema_attr)
|
|
554
|
+
def fixed_value_matches?(value, schema_attr, fixed_override = nil)
|
|
555
|
+
fixed = fixed_override || schema_attr.fixed
|
|
465
556
|
rule = attribute_whitespace_rule(schema_attr)
|
|
466
557
|
canonical_lexical(value, rule) ==
|
|
467
|
-
canonical_lexical(
|
|
558
|
+
canonical_lexical(fixed, rule)
|
|
468
559
|
end
|
|
469
560
|
|
|
470
561
|
# @return [Symbol] :preserve, :replace or :collapse
|
|
@@ -499,21 +590,27 @@ module Lutaml
|
|
|
499
590
|
# @param collector [ResultCollector] Result collector
|
|
500
591
|
# @return [void]
|
|
501
592
|
def validate_attribute_value(xml_element, xml_attr, schema_attr,
|
|
502
|
-
collector, repository: nil
|
|
593
|
+
collector, repository: nil,
|
|
594
|
+
use_site: nil)
|
|
503
595
|
value = xml_attr.value
|
|
596
|
+
fixed = if use_site && !use_site.fixed.nil?
|
|
597
|
+
use_site.fixed
|
|
598
|
+
else
|
|
599
|
+
schema_attr.fixed
|
|
600
|
+
end
|
|
504
601
|
|
|
505
602
|
# Check fixed value constraint
|
|
506
|
-
if
|
|
507
|
-
unless fixed_value_matches?(value, schema_attr)
|
|
603
|
+
if fixed
|
|
604
|
+
unless fixed_value_matches?(value, schema_attr, fixed)
|
|
508
605
|
report_error(
|
|
509
606
|
collector,
|
|
510
607
|
code: "fixed_attribute_value_mismatch",
|
|
511
608
|
message: "Attribute '#{xml_attr.name}' must have fixed " \
|
|
512
|
-
"value '#{
|
|
609
|
+
"value '#{fixed}'",
|
|
513
610
|
location: xml_element.xpath,
|
|
514
611
|
context: {
|
|
515
612
|
attribute: xml_attr.name,
|
|
516
|
-
expected:
|
|
613
|
+
expected: fixed,
|
|
517
614
|
actual: value,
|
|
518
615
|
},
|
|
519
616
|
)
|
data/lib/lutaml/xsd/version.rb
CHANGED
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.
|
|
4
|
+
version: 1.2.82
|
|
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-
|
|
11
|
+
date: 2026-11-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: liquid
|