lutaml-model 0.8.53 → 0.8.54
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ffb19b7e87ec763167dc806fb0fd0b37a1ca292e7627333ba1238f06c3e5f17e
|
|
4
|
+
data.tar.gz: 340c6f96fb82f0d972ca654f548db51bdef12155bc94ae95e3eaf6eacf96af29
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d79e2b5b7fce4f6ba3115cdb190365b8a1fc1212922f00cabf2e9855fa85c2350808c0844f78c55015de4e8c8cf480cbdf5390e8afaa0a401f01ad6e2a1d93a3
|
|
7
|
+
data.tar.gz: c6a29c349be599ddfcbcb53087c17178de7de17aa1afa46fb5e2fc6eb2b3c4b0c0189b68a26aa77d0e2d561966c4001c0bd04abacf2d6e987d8846185b6add29
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -731,18 +731,29 @@ _effective_register)
|
|
|
731
731
|
# each_value scan below is dead whenever the index exists.
|
|
732
732
|
return nil if root_index && !candidates
|
|
733
733
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
734
|
+
matched = if candidates
|
|
735
|
+
candidates.select do |attr|
|
|
736
|
+
local_name_match?(attr, local_name, rule_uri,
|
|
737
|
+
flexible_local)
|
|
738
|
+
end
|
|
739
|
+
else
|
|
740
|
+
doc.root.attributes.each_value.select do |attr|
|
|
741
|
+
local_name_match?(attr, local_name, rule_uri,
|
|
742
|
+
flexible_local)
|
|
743
|
+
end
|
|
744
|
+
end
|
|
745
|
+
# Attribute identity is (namespace URI, local name) — #841. The
|
|
746
|
+
# lenient probe is a recovery mechanism for the single
|
|
747
|
+
# undeclared-prefix case; several distinct matches are an
|
|
748
|
+
# ambiguity the document order must not arbitrate.
|
|
749
|
+
if matched.size > 1
|
|
750
|
+
identities = matched.map(&:namespaced_name).join(", ")
|
|
751
|
+
warn "[Lutaml::Model] ambiguous attribute for rule " \
|
|
752
|
+
"#{rule_name.inspect}: #{identities} all match by local " \
|
|
753
|
+
"name on <#{doc.root.unprefixed_name}>; no value bound"
|
|
754
|
+
return nil
|
|
755
|
+
end
|
|
756
|
+
matched.first&.value
|
|
746
757
|
end
|
|
747
758
|
|
|
748
759
|
# Namespace discipline of the lenient local-name fallback
|
|
@@ -385,11 +385,24 @@ module Lutaml
|
|
|
385
385
|
ensure_attribute_index
|
|
386
386
|
|
|
387
387
|
if attribute_name.is_a?(Array)
|
|
388
|
+
# Alias list: at most one spelling variant may be present.
|
|
389
|
+
# Several simultaneous matches are an authoring ambiguity —
|
|
390
|
+
# attribute identity is (namespace URI, local name) — #841 —
|
|
391
|
+
# and array order must not arbitrate.
|
|
392
|
+
found = nil
|
|
388
393
|
attribute_name.each do |name|
|
|
389
394
|
val = @attribute_index[name]
|
|
390
|
-
|
|
395
|
+
next if val.nil?
|
|
396
|
+
|
|
397
|
+
if found
|
|
398
|
+
warn "[Lutaml::Model] ambiguous attribute aliases " \
|
|
399
|
+
"#{found[0].inspect} and #{name.inspect} both present " \
|
|
400
|
+
"on <#{unprefixed_name}>; no value bound"
|
|
401
|
+
return nil
|
|
402
|
+
end
|
|
403
|
+
found = [name, val]
|
|
391
404
|
end
|
|
392
|
-
|
|
405
|
+
found&.last
|
|
393
406
|
else
|
|
394
407
|
@attribute_index[attribute_name]
|
|
395
408
|
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
# Attribute identity is (namespace URI, local name) — lutaml-model#841.
|
|
6
|
+
# Where matching previously resolved silently by order (document order
|
|
7
|
+
# in the lenient recovery, array order in alias lists), several
|
|
8
|
+
# distinct matches are an ambiguity: no value binds and the collision
|
|
9
|
+
# is surfaced on stderr.
|
|
10
|
+
module AttributeAmbiguitySurfaceSpec
|
|
11
|
+
# Lenient recovery: sole-claimant rule spelled URI:local while the
|
|
12
|
+
# document's prefixes stay undeclared (#754 recovery case).
|
|
13
|
+
class LenientProbe < Lutaml::Model::Serializable
|
|
14
|
+
attribute :ext, :string
|
|
15
|
+
|
|
16
|
+
xml do
|
|
17
|
+
element "probe"
|
|
18
|
+
map_attribute "urn:example:v:ext", to: :ext
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Alias list: spelling variants of one name — at most one may occur.
|
|
23
|
+
class AliasProbe < Lutaml::Model::Serializable
|
|
24
|
+
attribute :status, :string
|
|
25
|
+
|
|
26
|
+
xml do
|
|
27
|
+
element "probe"
|
|
28
|
+
map_attribute %w[status product-status], to: :status
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
RSpec.describe "Ambiguous attribute matches surface instead of resolving by order" do
|
|
34
|
+
describe "lenient local-name recovery" do
|
|
35
|
+
it "recovers the single undeclared-prefix attribute" do
|
|
36
|
+
probe = AttributeAmbiguitySurfaceSpec::LenientProbe.from_xml(
|
|
37
|
+
%(<probe v:ext="1"/>),
|
|
38
|
+
)
|
|
39
|
+
expect(probe.ext).to eq("1")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "binds no value when several same-local attributes match" do
|
|
43
|
+
expect do
|
|
44
|
+
probe = AttributeAmbiguitySurfaceSpec::LenientProbe.from_xml(
|
|
45
|
+
%(<probe v:ext="1" w:ext="2"/>),
|
|
46
|
+
)
|
|
47
|
+
expect(probe.ext).to be_nil
|
|
48
|
+
end.to output(/ambiguous attribute/i).to_stderr
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "prefers the exact qualified match when the prefix IS declared" do
|
|
52
|
+
probe = AttributeAmbiguitySurfaceSpec::LenientProbe.from_xml(
|
|
53
|
+
%(<probe xmlns:v="urn:example:v" v:ext="1" w:ext="2"/>),
|
|
54
|
+
)
|
|
55
|
+
expect(probe.ext).to eq("1")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "alias lists" do
|
|
60
|
+
it "reads the single present alias" do
|
|
61
|
+
probe = AttributeAmbiguitySurfaceSpec::AliasProbe.from_xml(
|
|
62
|
+
%(<probe product-status="draft"/>),
|
|
63
|
+
)
|
|
64
|
+
expect(probe.status).to eq("draft")
|
|
65
|
+
|
|
66
|
+
probe = AttributeAmbiguitySurfaceSpec::AliasProbe.from_xml(
|
|
67
|
+
%(<probe status="open"/>),
|
|
68
|
+
)
|
|
69
|
+
expect(probe.status).to eq("open")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "binds no value when two aliases are simultaneously present" do
|
|
73
|
+
expect do
|
|
74
|
+
probe = AttributeAmbiguitySurfaceSpec::AliasProbe.from_xml(
|
|
75
|
+
%(<probe status="open" product-status="draft"/>),
|
|
76
|
+
)
|
|
77
|
+
expect(probe.status).to be_nil
|
|
78
|
+
end.to output(/ambiguous attribute aliases/i).to_stderr
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -40,11 +40,19 @@ RSpec.describe "XmlElement performance guard specs" do
|
|
|
40
40
|
expect(element.find_attribute_value("missing")).to be_nil
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
it "finds
|
|
44
|
-
result = element.find_attribute_value(["missing1", "class", "
|
|
43
|
+
it "finds the single present name from array of names" do
|
|
44
|
+
result = element.find_attribute_value(["missing1", "class", "missing2"])
|
|
45
45
|
expect(result).to eq("foo")
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
it "binds no value when two names in the array are both present" do
|
|
49
|
+
# Attribute identity is (namespace URI, local name) — #841;
|
|
50
|
+
# array order must not arbitrate an ambiguity.
|
|
51
|
+
expect do
|
|
52
|
+
expect(element.find_attribute_value(["class", "id"])).to be_nil
|
|
53
|
+
end.to output(/ambiguous attribute aliases/i).to_stderr
|
|
54
|
+
end
|
|
55
|
+
|
|
48
56
|
it "returns nil when no name in array matches" do
|
|
49
57
|
expect(element.find_attribute_value(["missing1", "missing2"])).to be_nil
|
|
50
58
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lutaml-model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.54
|
|
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-09-
|
|
11
|
+
date: 2026-09-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -1902,6 +1902,7 @@ files:
|
|
|
1902
1902
|
- spec/lutaml/xml/adapter/ox_adapter_spec.rb
|
|
1903
1903
|
- spec/lutaml/xml/adapter/rexml_adapter_spec.rb
|
|
1904
1904
|
- spec/lutaml/xml/adapter/xml_namespace_spec.rb
|
|
1905
|
+
- spec/lutaml/xml/attribute_ambiguity_surface_spec.rb
|
|
1905
1906
|
- spec/lutaml/xml/attribute_element_namespace_disjoint_spec.rb
|
|
1906
1907
|
- spec/lutaml/xml/attribute_namespace_disjointness_spec.rb
|
|
1907
1908
|
- spec/lutaml/xml/builder/builder_spec.rb
|