lutaml-model 0.3.1 → 0.3.2
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/.rubocop.yml +0 -5
- data/.rubocop_todo.yml +20 -101
- data/Gemfile +3 -18
- data/README.adoc +109 -6
- data/lib/lutaml/model/attribute.rb +15 -2
- data/lib/lutaml/model/config.rb +0 -1
- data/lib/lutaml/model/json_adapter/json_document.rb +20 -0
- data/lib/lutaml/model/json_adapter/json_object.rb +28 -0
- data/lib/lutaml/model/json_adapter/{multi_json.rb → multi_json_adapter.rb} +2 -3
- data/lib/lutaml/model/json_adapter/{standard.rb → standard_json_adapter.rb} +2 -3
- data/lib/lutaml/model/json_adapter.rb +1 -31
- data/lib/lutaml/model/key_value_mapping.rb +0 -1
- data/lib/lutaml/model/key_value_mapping_rule.rb +0 -1
- data/lib/lutaml/model/mapping_hash.rb +0 -2
- data/lib/lutaml/model/mapping_rule.rb +0 -1
- data/lib/lutaml/model/schema/json_schema.rb +0 -1
- data/lib/lutaml/model/schema/relaxng_schema.rb +0 -1
- data/lib/lutaml/model/schema/xsd_schema.rb +0 -1
- data/lib/lutaml/model/schema/yaml_schema.rb +0 -1
- data/lib/lutaml/model/schema.rb +0 -1
- data/lib/lutaml/model/serializable.rb +0 -1
- data/lib/lutaml/model/serialize.rb +22 -4
- data/lib/lutaml/model/toml_adapter/toml_document.rb +20 -0
- data/lib/lutaml/model/toml_adapter/toml_object.rb +28 -0
- data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +2 -3
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +2 -3
- data/lib/lutaml/model/toml_adapter.rb +0 -31
- data/lib/lutaml/model/type/date_time.rb +20 -0
- data/lib/lutaml/model/type/json.rb +34 -0
- data/lib/lutaml/model/type/time_without_date.rb +4 -3
- data/lib/lutaml/model/type.rb +61 -124
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +5 -6
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +4 -5
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +8 -9
- data/lib/lutaml/model/xml_adapter/xml_attribute.rb +27 -0
- data/lib/lutaml/model/xml_adapter/xml_document.rb +184 -0
- data/lib/lutaml/model/xml_adapter/xml_element.rb +94 -0
- data/lib/lutaml/model/xml_adapter/xml_namespace.rb +49 -0
- data/lib/lutaml/model/xml_adapter.rb +0 -285
- data/lib/lutaml/model/xml_mapping.rb +1 -1
- data/lib/lutaml/model/xml_mapping_rule.rb +3 -4
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +34 -0
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +20 -0
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +28 -0
- data/lib/lutaml/model/yaml_adapter.rb +1 -27
- data/lib/lutaml/model.rb +0 -5
- metadata +17 -5
- data/lib/lutaml/model/xml_namespace.rb +0 -47
@@ -1,4 +1,3 @@
|
|
1
|
-
# lib/lutaml/model/serialize.rb
|
2
1
|
require_relative "yaml_adapter"
|
3
2
|
require_relative "xml_adapter"
|
4
3
|
require_relative "config"
|
@@ -41,6 +40,7 @@ module Lutaml
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
43
|
+
# Define an attribute for the model
|
44
44
|
def attribute(name, type, options = {})
|
45
45
|
attr = Attribute.new(name, type, options)
|
46
46
|
attributes[name] = attr
|
@@ -50,7 +50,7 @@ module Lutaml
|
|
50
50
|
end
|
51
51
|
|
52
52
|
define_method(:"#{name}=") do |value|
|
53
|
-
|
53
|
+
unless self.class.attr_value_valid?(name, value)
|
54
54
|
raise Lutaml::Model::InvalidValueError.new(name, value, options[:values])
|
55
55
|
end
|
56
56
|
|
@@ -58,6 +58,17 @@ module Lutaml
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
# Check if the value to be assigned is valid for the attribute
|
62
|
+
def attr_value_valid?(name, value)
|
63
|
+
attr = attributes[name]
|
64
|
+
|
65
|
+
return true unless attr.options[:values]
|
66
|
+
|
67
|
+
# If value validation failed but there is a default value, do not
|
68
|
+
# raise a validation error
|
69
|
+
attr.options[:values].include?(value || attr.default)
|
70
|
+
end
|
71
|
+
|
61
72
|
FORMATS.each do |format|
|
62
73
|
define_method(format) do |&block|
|
63
74
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
@@ -193,6 +204,8 @@ module Lutaml
|
|
193
204
|
if v.is_a?(Hash)
|
194
205
|
attr_rule.type.new(v)
|
195
206
|
else
|
207
|
+
# TODO: This code is problematic because Type.cast does not know
|
208
|
+
# about all the types.
|
196
209
|
Lutaml::Model::Type.cast(
|
197
210
|
v, attr_rule.type
|
198
211
|
)
|
@@ -201,6 +214,8 @@ module Lutaml
|
|
201
214
|
elsif value.is_a?(Hash) && attr_rule.type != Lutaml::Model::Type::Hash
|
202
215
|
generate_model_object(attr_rule.type, value)
|
203
216
|
else
|
217
|
+
# TODO: This code is problematic because Type.cast does not know
|
218
|
+
# about all the types.
|
204
219
|
Lutaml::Model::Type.cast(value, attr_rule.type)
|
205
220
|
end
|
206
221
|
end
|
@@ -209,8 +224,11 @@ module Lutaml
|
|
209
224
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
210
225
|
klass.new.tap do |mapping|
|
211
226
|
attributes&.each do |name, attr|
|
212
|
-
mapping.map_element(
|
213
|
-
|
227
|
+
mapping.map_element(
|
228
|
+
name.to_s,
|
229
|
+
to: name,
|
230
|
+
render_nil: attr.render_nil?,
|
231
|
+
)
|
214
232
|
end
|
215
233
|
end
|
216
234
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "toml_object"
|
4
|
+
|
5
|
+
module Lutaml
|
6
|
+
module Model
|
7
|
+
module TomlAdapter
|
8
|
+
# Base class for TOML documents
|
9
|
+
class TomlDocument < TomlObject
|
10
|
+
def self.parse(toml)
|
11
|
+
raise NotImplementedError, "Subclasses must implement `parse`."
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_toml(*args)
|
15
|
+
raise NotImplementedError, "Subclasses must implement `to_toml`."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module TomlAdapter
|
6
|
+
# Base class for TOML objects
|
7
|
+
class TomlObject
|
8
|
+
attr_reader :attributes
|
9
|
+
|
10
|
+
def initialize(attributes = {})
|
11
|
+
@attributes = attributes
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@attributes[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
@attributes[key] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_h
|
23
|
+
@attributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# lib/lutaml/model/toml_adapter/toml_rb_adapter.rb
|
2
1
|
require "toml-rb"
|
3
|
-
require_relative "
|
2
|
+
require_relative "toml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module TomlAdapter
|
8
|
-
class
|
7
|
+
class TomlRbAdapter < TomlDocument
|
9
8
|
def self.parse(toml)
|
10
9
|
data = TomlRB.parse(toml)
|
11
10
|
new(data)
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# lib/lutaml/model/toml_adapter/tomlib_adapter.rb
|
2
1
|
require "tomlib"
|
3
|
-
require_relative "
|
2
|
+
require_relative "toml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module TomlAdapter
|
8
|
-
class
|
7
|
+
class TomlibAdapter < TomlDocument
|
9
8
|
def self.parse(toml)
|
10
9
|
data = Tomlib.load(toml)
|
11
10
|
new(data)
|
@@ -1,37 +1,6 @@
|
|
1
|
-
# lib/lutaml/model/toml_adapter.rb
|
2
|
-
|
3
1
|
module Lutaml
|
4
2
|
module Model
|
5
3
|
module TomlAdapter
|
6
|
-
class TomlObject
|
7
|
-
attr_reader :attributes
|
8
|
-
|
9
|
-
def initialize(attributes = {})
|
10
|
-
@attributes = attributes
|
11
|
-
end
|
12
|
-
|
13
|
-
def [](key)
|
14
|
-
@attributes[key]
|
15
|
-
end
|
16
|
-
|
17
|
-
def []=(key, value)
|
18
|
-
@attributes[key] = value
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_h
|
22
|
-
@attributes
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Document < TomlObject
|
27
|
-
def self.parse(toml)
|
28
|
-
raise NotImplementedError, "Subclasses must implement `parse`."
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_toml(*args)
|
32
|
-
raise NotImplementedError, "Subclasses must implement `to_toml`."
|
33
|
-
end
|
34
|
-
end
|
35
4
|
end
|
36
5
|
end
|
37
6
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "date"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Type
|
6
|
+
# Date and time representation
|
7
|
+
class DateTime
|
8
|
+
def self.cast(value)
|
9
|
+
return if value.nil?
|
10
|
+
|
11
|
+
::DateTime.parse(value.to_s).new_offset(0)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.serialize(value)
|
15
|
+
value.iso8601
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Type
|
6
|
+
# JSON representation
|
7
|
+
class Json
|
8
|
+
attr_reader :value
|
9
|
+
|
10
|
+
def initialize(value)
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(*_args)
|
15
|
+
@value.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
@value == (other.is_a?(::Hash) ? other : other.value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.cast(value)
|
23
|
+
return value if value.is_a?(self) || value.nil?
|
24
|
+
|
25
|
+
new(::JSON.parse(value))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.serialize(value)
|
29
|
+
value.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
# lib/lutaml/model/type/time_without_date.rb
|
2
1
|
module Lutaml
|
3
2
|
module Model
|
4
3
|
module Type
|
4
|
+
# Time representation without date
|
5
5
|
class TimeWithoutDate
|
6
6
|
def self.cast(value)
|
7
|
-
|
8
|
-
|
7
|
+
return if value.nil?
|
8
|
+
|
9
|
+
::Time.parse(value.to_s)
|
9
10
|
end
|
10
11
|
|
11
12
|
def self.serialize(value)
|
data/lib/lutaml/model/type.rb
CHANGED
@@ -1,170 +1,97 @@
|
|
1
|
-
# lib/lutaml/model/type.rb
|
2
1
|
require "date"
|
3
2
|
require "bigdecimal"
|
4
3
|
require "securerandom"
|
5
4
|
require "uri"
|
6
5
|
require "ipaddr"
|
7
|
-
require "json"
|
8
6
|
|
9
7
|
module Lutaml
|
10
8
|
module Model
|
11
9
|
module Type
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
10
|
+
# This module provides a set of methods to cast and serialize values
|
11
|
+
|
12
|
+
# TODO: Make Boolean a separate class
|
13
|
+
|
14
|
+
%w(
|
15
|
+
String
|
16
|
+
Integer
|
17
|
+
Float
|
18
|
+
Date
|
19
|
+
Time
|
20
|
+
Boolean
|
21
|
+
Decimal
|
22
|
+
Hash
|
23
|
+
Uuid
|
24
|
+
Symbol
|
25
|
+
Binary
|
26
|
+
Url
|
27
|
+
IpAddress
|
28
|
+
Json
|
29
|
+
).each do |t|
|
29
30
|
class_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
30
|
-
|
31
|
+
class #{t} # class Integer
|
31
32
|
def self.cast(value) # def self.cast(value)
|
32
33
|
return if value.nil? # return if value.nil?
|
33
|
-
|
34
34
|
Type.cast(value, #{t}) # Type.cast(value, Integer)
|
35
35
|
end # end
|
36
36
|
|
37
37
|
def self.serialize(value) # def self.serialize(value)
|
38
38
|
return if value.nil? # return if value.nil?
|
39
|
-
|
40
39
|
Type.serialize(value, #{t}) # Type.serialize(value, Integer)
|
41
40
|
end # end
|
42
41
|
end # end
|
43
42
|
HEREDOC
|
44
43
|
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
return if value.nil?
|
49
|
-
|
50
|
-
::Time.parse(value.to_s)
|
51
|
-
# .strftime("%H:%M:%S")
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.serialize(value)
|
55
|
-
value.strftime("%H:%M:%S")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class DateTime
|
60
|
-
def self.cast(value)
|
61
|
-
return if value.nil?
|
62
|
-
|
63
|
-
::DateTime.parse(value.to_s).new_offset(0)
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.serialize(value)
|
67
|
-
value.iso8601
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
45
|
+
# TODO: Remove this. The XSD code depends on this but actually should
|
46
|
+
# be converted into a collection, not a specific Array type.
|
71
47
|
class Array
|
72
48
|
def initialize(array)
|
73
49
|
Array(array)
|
74
50
|
end
|
75
51
|
end
|
76
52
|
|
77
|
-
class TextWithTags
|
78
|
-
attr_reader :content
|
79
|
-
|
80
|
-
def initialize(ordered_text_with_tags)
|
81
|
-
@content = ordered_text_with_tags
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.cast(value)
|
85
|
-
return value if value.is_a?(self)
|
86
|
-
|
87
|
-
new(value)
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.serialize(value)
|
91
|
-
value.content.join
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
class JSON
|
96
|
-
attr_reader :value
|
97
|
-
|
98
|
-
def initialize(value)
|
99
|
-
@value = value
|
100
|
-
end
|
101
|
-
|
102
|
-
def to_json(*_args)
|
103
|
-
@value.to_json
|
104
|
-
end
|
105
|
-
|
106
|
-
def ==(other)
|
107
|
-
@value == if other.is_a?(::Hash)
|
108
|
-
other
|
109
|
-
else
|
110
|
-
other.value
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def self.cast(value)
|
115
|
-
return value if value.is_a?(self) || value.nil?
|
116
|
-
|
117
|
-
new(::JSON.parse(value))
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.serialize(value)
|
121
|
-
value.to_json
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
53
|
UUID_REGEX = /\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/
|
126
54
|
|
127
55
|
def self.cast(value, type)
|
128
56
|
return if value.nil?
|
129
57
|
|
130
|
-
|
58
|
+
case type.to_s.split("::").last
|
59
|
+
when "String"
|
131
60
|
value.to_s
|
132
|
-
|
61
|
+
when "Integer"
|
133
62
|
value.to_i
|
134
|
-
|
63
|
+
when "Float"
|
135
64
|
value.to_f
|
136
|
-
|
65
|
+
when "Date"
|
137
66
|
begin
|
138
67
|
::Date.parse(value.to_s)
|
139
68
|
rescue ArgumentError
|
140
69
|
nil
|
141
70
|
end
|
142
|
-
|
71
|
+
when "DateTime"
|
143
72
|
DateTime.cast(value)
|
144
|
-
|
73
|
+
when "Time"
|
145
74
|
::Time.parse(value.to_s)
|
146
|
-
|
75
|
+
when "TimeWithoutDate"
|
147
76
|
TimeWithoutDate.cast(value)
|
148
|
-
|
77
|
+
when "Boolean"
|
149
78
|
to_boolean(value)
|
150
|
-
|
79
|
+
when "Decimal"
|
151
80
|
BigDecimal(value.to_s)
|
152
|
-
|
81
|
+
when "Hash"
|
153
82
|
normalize_hash(Hash(value))
|
154
|
-
|
83
|
+
when "Uuid"
|
155
84
|
UUID_REGEX.match?(value) ? value : SecureRandom.uuid
|
156
|
-
|
85
|
+
when "Symbol"
|
157
86
|
value.to_sym
|
158
|
-
|
87
|
+
when "Binary"
|
159
88
|
value.force_encoding("BINARY")
|
160
|
-
|
89
|
+
when "Url"
|
161
90
|
URI.parse(value.to_s)
|
162
|
-
|
91
|
+
when "IpAddress"
|
163
92
|
IPAddr.new(value.to_s)
|
164
|
-
|
165
|
-
|
166
|
-
# elsif type == Enum
|
167
|
-
# value
|
93
|
+
when "Json"
|
94
|
+
Json.cast(value)
|
168
95
|
else
|
169
96
|
value
|
170
97
|
end
|
@@ -173,21 +100,22 @@ module Lutaml
|
|
173
100
|
def self.serialize(value, type)
|
174
101
|
return if value.nil?
|
175
102
|
|
176
|
-
|
103
|
+
case type.to_s.split("::").last
|
104
|
+
when "Date"
|
177
105
|
value.iso8601
|
178
|
-
|
106
|
+
when "DateTime"
|
179
107
|
DateTime.serialize(value)
|
180
|
-
|
108
|
+
when "Integer"
|
181
109
|
value.to_i
|
182
|
-
|
110
|
+
when "Float"
|
183
111
|
value.to_f
|
184
|
-
|
112
|
+
when "Boolean"
|
185
113
|
to_boolean(value)
|
186
|
-
|
114
|
+
when "Decimal"
|
187
115
|
value.to_s("F")
|
188
|
-
|
116
|
+
when "Hash"
|
189
117
|
Hash(value)
|
190
|
-
|
118
|
+
when "Json"
|
191
119
|
value.to_json
|
192
120
|
else
|
193
121
|
value.to_s
|
@@ -195,8 +123,13 @@ module Lutaml
|
|
195
123
|
end
|
196
124
|
|
197
125
|
def self.to_boolean(value)
|
198
|
-
|
199
|
-
|
126
|
+
if value == true || value.to_s =~ (/^(true|t|yes|y|1)$/i)
|
127
|
+
return true
|
128
|
+
end
|
129
|
+
|
130
|
+
if value == false || value.nil? || value.to_s =~ (/^(false|f|no|n|0)$/i)
|
131
|
+
return false
|
132
|
+
end
|
200
133
|
|
201
134
|
raise ArgumentError.new("invalid value for Boolean: \"#{value}\"")
|
202
135
|
end
|
@@ -217,3 +150,7 @@ module Lutaml
|
|
217
150
|
end
|
218
151
|
end
|
219
152
|
end
|
153
|
+
|
154
|
+
require_relative "type/time_without_date"
|
155
|
+
require_relative "type/date_time"
|
156
|
+
require_relative "type/json"
|
data/lib/lutaml/model/version.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
# lib/lutaml/model/xml_adapter/nokogiri_adapter.rb
|
2
1
|
require "nokogiri"
|
3
|
-
require_relative "
|
2
|
+
require_relative "xml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module XmlAdapter
|
8
|
-
class
|
7
|
+
class NokogiriAdapter < XmlDocument
|
9
8
|
def self.parse(xml)
|
10
9
|
parsed = Nokogiri::XML(xml)
|
11
10
|
root = NokogiriElement.new(parsed.root)
|
@@ -154,11 +153,11 @@ module Lutaml
|
|
154
153
|
end
|
155
154
|
end
|
156
155
|
|
157
|
-
class NokogiriElement <
|
156
|
+
class NokogiriElement < XmlElement
|
158
157
|
def initialize(node, root_node: nil)
|
159
158
|
if root_node
|
160
159
|
node.namespaces.each do |prefix, name|
|
161
|
-
namespace =
|
160
|
+
namespace = XmlNamespace.new(name, prefix)
|
162
161
|
|
163
162
|
root_node.add_namespace(namespace)
|
164
163
|
end
|
@@ -172,7 +171,7 @@ module Lutaml
|
|
172
171
|
attr.name
|
173
172
|
end
|
174
173
|
|
175
|
-
attributes[name] =
|
174
|
+
attributes[name] = XmlAttribute.new(
|
176
175
|
name,
|
177
176
|
attr.value,
|
178
177
|
namespace: attr.namespace&.href,
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# lib/lutaml/model/xml_adapter/oga_adapter.rb
|
2
1
|
require "oga"
|
3
|
-
require_relative "
|
2
|
+
require_relative "xml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module XmlAdapter
|
8
|
-
class
|
7
|
+
class OgaAdapter < XmlDocument
|
9
8
|
def self.parse(xml)
|
10
9
|
parsed = Oga.parse_xml(xml)
|
11
10
|
root = OgaElement.new(parsed)
|
@@ -51,10 +50,10 @@ module Lutaml
|
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
54
|
-
class OgaElement <
|
53
|
+
class OgaElement < XmlElement
|
55
54
|
def initialize(node)
|
56
55
|
attributes = node.attributes.each_with_object({}) do |attr, hash|
|
57
|
-
hash[attr.name] =
|
56
|
+
hash[attr.name] = XmlAttribute.new(attr.name, attr.value)
|
58
57
|
end
|
59
58
|
super(node.name, attributes, parse_children(node), node.text)
|
60
59
|
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
# lib/lutaml/model/xml_adapter/ox_adapter.rb
|
2
1
|
require "ox"
|
3
|
-
require_relative "
|
2
|
+
require_relative "xml_document"
|
4
3
|
|
5
4
|
module Lutaml
|
6
5
|
module Model
|
7
6
|
module XmlAdapter
|
8
|
-
class
|
7
|
+
class OxAdapter < XmlDocument
|
9
8
|
def self.parse(xml)
|
10
9
|
parsed = Ox.parse(xml)
|
11
10
|
root = OxElement.new(parsed)
|
@@ -137,16 +136,16 @@ module Lutaml
|
|
137
136
|
end
|
138
137
|
end
|
139
138
|
|
140
|
-
class OxElement <
|
139
|
+
class OxElement < XmlElement
|
141
140
|
def initialize(node, root_node: nil)
|
142
141
|
if node.is_a?(String)
|
143
142
|
super("text", {}, [], node, parent_document: root_node)
|
144
143
|
else
|
145
144
|
namespace_attributes(node.attributes).each do |(name, value)|
|
146
145
|
if root_node
|
147
|
-
root_node.add_namespace(
|
146
|
+
root_node.add_namespace(XmlNamespace.new(value, name))
|
148
147
|
else
|
149
|
-
add_namespace(
|
148
|
+
add_namespace(XmlNamespace.new(value, name))
|
150
149
|
end
|
151
150
|
end
|
152
151
|
|
@@ -156,11 +155,11 @@ module Lutaml
|
|
156
155
|
namespace_prefix = name.to_s.split(":").first
|
157
156
|
if (n = name.to_s.split(":")).length > 1
|
158
157
|
namespace = (root_node || self).namespaces[namespace_prefix]&.uri
|
159
|
-
namespace ||=
|
158
|
+
namespace ||= XML_NAMESPACE_URI
|
160
159
|
prefix = n.first
|
161
160
|
end
|
162
161
|
|
163
|
-
hash[name.to_s] =
|
162
|
+
hash[name.to_s] = XmlAttribute.new(
|
164
163
|
name.to_s,
|
165
164
|
value,
|
166
165
|
namespace: namespace,
|
@@ -173,7 +172,7 @@ module Lutaml
|
|
173
172
|
attributes,
|
174
173
|
parse_children(node, root_node: root_node || self),
|
175
174
|
node.text,
|
176
|
-
parent_document: root_node
|
175
|
+
parent_document: root_node,
|
177
176
|
)
|
178
177
|
end
|
179
178
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module XmlAdapter
|
6
|
+
# Represents an XML attribute
|
7
|
+
class XmlAttribute
|
8
|
+
attr_reader :name, :value, :namespace, :namespace_prefix
|
9
|
+
|
10
|
+
def initialize(name, value, namespace: nil, namespace_prefix: nil)
|
11
|
+
@name = name
|
12
|
+
@value = value
|
13
|
+
@namespace = namespace
|
14
|
+
@namespace_prefix = namespace_prefix
|
15
|
+
end
|
16
|
+
|
17
|
+
def unprefixed_name
|
18
|
+
if namespace_prefix
|
19
|
+
name.split(":").last
|
20
|
+
else
|
21
|
+
name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|