lutaml-model 0.8.132 → 0.8.133
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: 7ea94bb734406bacfb047edb9c580a3f224f19c497b4f506440da60d381cd1bf
|
|
4
|
+
data.tar.gz: 96f7c71f51a0ec8b863eec77b894ec611ff3a4e8b59354ec9b477e6470258852
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e61d4a02ebb21a794de64a0301a3489b045b8562ce8e1a8f3522b227bea1632882e7e09d1ce6fe18352d41c8fe62d2a5d9652b315dda76a220cbd30fe15f3cf
|
|
7
|
+
data.tar.gz: 60c206b080775425586980a1f3b484db2280be9e9b73bc365237210f64c90fc3faa80f1f9e9a42e94259a9a83ba1edab1ceecc25bb804147ecd3e31ead97c15d
|
|
@@ -18,22 +18,37 @@ module Lutaml
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def self.normalize_hash(hash)
|
|
21
|
-
|
|
21
|
+
xml = hash.is_a?(Lutaml::Model::MappingHash)
|
|
22
|
+
return hash["text"] if text_node?(hash)
|
|
22
23
|
|
|
23
|
-
hash = hash.to_h if
|
|
24
|
+
hash = hash.to_h if xml
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
normalized = hash.transform_values do |value|
|
|
26
27
|
normalize_value(value)
|
|
27
28
|
end
|
|
29
|
+
xml ? (normalized["elements"] || normalized) : normalized
|
|
30
|
+
end
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
# {"text" => string} is the XML text-node convention and
|
|
33
|
+
# collapses to the string. Any other "text" key — structured
|
|
34
|
+
# values, or appearing alongside other keys in non-XML data —
|
|
35
|
+
# is ordinary data and must round-trip verbatim
|
|
36
|
+
# (lutaml/lutaml-model#1013).
|
|
37
|
+
def self.text_node?(hash)
|
|
38
|
+
# ::String — unqualified String resolves to Type::String here
|
|
39
|
+
hash.is_a?(::Hash) && hash.keys == ["text"] &&
|
|
40
|
+
hash["text"].is_a?(::String)
|
|
30
41
|
end
|
|
31
42
|
|
|
32
43
|
def self.normalize_value(value)
|
|
33
44
|
return value unless value.is_a?(::Hash)
|
|
34
45
|
|
|
35
46
|
nested = normalize_hash(value)
|
|
36
|
-
|
|
47
|
+
if value.is_a?(Lutaml::Model::MappingHash) && nested.is_a?(::Hash)
|
|
48
|
+
nested.except("text")
|
|
49
|
+
else
|
|
50
|
+
nested
|
|
51
|
+
end
|
|
37
52
|
end
|
|
38
53
|
|
|
39
54
|
def self.serialize(value)
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -178,8 +178,13 @@ module Lutaml
|
|
|
178
178
|
elsif val.is_a?(Lutaml::Model::Serializable)
|
|
179
179
|
collection_indices[attr_name] += 1
|
|
180
180
|
collection_indices[attr_name] == 1 ? val : nil
|
|
181
|
+
else
|
|
182
|
+
# Scalar mapped elements (e.g. a string-valued
|
|
183
|
+
# <main>) are part of the mixed content too.
|
|
184
|
+
collection_indices[attr_name] += 1
|
|
185
|
+
val
|
|
181
186
|
end
|
|
182
|
-
yield(obj)
|
|
187
|
+
yield(obj) unless obj.nil? || (obj.is_a?(String) && obj.empty?)
|
|
183
188
|
end
|
|
184
189
|
end
|
|
185
190
|
|
|
@@ -1449,4 +1449,36 @@ RSpec.describe "MixedContent" do
|
|
|
1449
1449
|
described_class
|
|
1450
1450
|
end
|
|
1451
1451
|
end
|
|
1452
|
+
|
|
1453
|
+
describe "each_mixed_content with string-valued mapped elements" do
|
|
1454
|
+
it "yields scalar mapped elements, not only Arrays and Serializable children" do
|
|
1455
|
+
xml = "<title-wrap><main>Test Document</main></title-wrap>"
|
|
1456
|
+
model = MixedContentSpec::TitleWrap.from_xml(xml)
|
|
1457
|
+
|
|
1458
|
+
expect(model.main).to eq("Test Document")
|
|
1459
|
+
|
|
1460
|
+
yielded = model.each_mixed_content.to_a
|
|
1461
|
+
expect(yielded).to include("Test Document")
|
|
1462
|
+
end
|
|
1463
|
+
|
|
1464
|
+
it "skips empty scalar values" do
|
|
1465
|
+
xml = "<title-wrap><main></main></title-wrap>"
|
|
1466
|
+
model = MixedContentSpec::TitleWrap.from_xml(xml)
|
|
1467
|
+
|
|
1468
|
+
yielded = model.each_mixed_content.to_a
|
|
1469
|
+
expect(yielded).not_to include("")
|
|
1470
|
+
end
|
|
1471
|
+
end
|
|
1472
|
+
end
|
|
1473
|
+
|
|
1474
|
+
module MixedContentSpec
|
|
1475
|
+
class TitleWrap < Lutaml::Model::Serializable
|
|
1476
|
+
attribute :main, :string
|
|
1477
|
+
|
|
1478
|
+
xml do
|
|
1479
|
+
element "title-wrap"
|
|
1480
|
+
mixed_content
|
|
1481
|
+
map_element "main", to: :main
|
|
1482
|
+
end
|
|
1483
|
+
end
|
|
1452
1484
|
end
|
|
@@ -6,11 +6,30 @@ RSpec.describe Lutaml::Model::Type::Hash do
|
|
|
6
6
|
expect(described_class.cast(nil)).to be_nil
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
it "returns text content from
|
|
10
|
-
hash =
|
|
9
|
+
it "returns text content from a MappingHash with only text key" do
|
|
10
|
+
hash = Lutaml::Model::MappingHash.new
|
|
11
|
+
hash["text"] = "content"
|
|
11
12
|
expect(described_class.cast(hash)).to eq "content"
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
# lutaml/lutaml-model#1013: a "text" key holding structured data
|
|
16
|
+
# (or appearing alongside other keys in non-XML data) is ordinary
|
|
17
|
+
# data and must round-trip verbatim
|
|
18
|
+
it "preserves a structured text key from a plain hash" do
|
|
19
|
+
hash = { "text" => { "type" => "string", "description" => "y" } }
|
|
20
|
+
expect(described_class.cast(hash)).to eq hash
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "preserves text alongside other keys in a plain hash" do
|
|
24
|
+
hash = { "text" => "content", "other" => "value" }
|
|
25
|
+
expect(described_class.cast(hash)).to eq hash
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "preserves an elements key from a plain hash" do
|
|
29
|
+
hash = { "elements" => [{ "a" => 1 }] }
|
|
30
|
+
expect(described_class.cast(hash)).to eq hash
|
|
31
|
+
end
|
|
32
|
+
|
|
14
33
|
it "normalizes MappingHash to regular Hash" do
|
|
15
34
|
mapping_hash = Lutaml::Model::MappingHash.new
|
|
16
35
|
mapping_hash["key"] = "value"
|
|
@@ -18,28 +37,29 @@ RSpec.describe Lutaml::Model::Type::Hash do
|
|
|
18
37
|
end
|
|
19
38
|
|
|
20
39
|
context "with nested hashes" do
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
let(:expected_hash) do
|
|
35
|
-
{
|
|
40
|
+
it "filters out text keys from nested MappingHashes" do
|
|
41
|
+
child1 = Lutaml::Model::MappingHash.new
|
|
42
|
+
child1["text"] = "content1"
|
|
43
|
+
child1["other"] = "value1"
|
|
44
|
+
child2 = Lutaml::Model::MappingHash.new
|
|
45
|
+
child2["text"] = "content2"
|
|
46
|
+
child2["other"] = "value2"
|
|
47
|
+
input = Lutaml::Model::MappingHash.new
|
|
48
|
+
input["key1"] = child1
|
|
49
|
+
input["key2"] = child2
|
|
50
|
+
expected = {
|
|
36
51
|
"key1" => { "other" => "value1" },
|
|
37
52
|
"key2" => { "other" => "value2" },
|
|
38
53
|
}
|
|
54
|
+
expect(described_class.cast(input)).to eq(expected)
|
|
39
55
|
end
|
|
40
56
|
|
|
41
|
-
it "
|
|
42
|
-
|
|
57
|
+
it "preserves text keys in nested plain hashes" do
|
|
58
|
+
input = {
|
|
59
|
+
"key1" => { "text" => "content1", "other" => "value1" },
|
|
60
|
+
"key2" => { "text" => "content2", "other" => "value2" },
|
|
61
|
+
}
|
|
62
|
+
expect(described_class.cast(input)).to eq(input)
|
|
43
63
|
end
|
|
44
64
|
end
|
|
45
65
|
|