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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -5
  3. data/.rubocop_todo.yml +20 -101
  4. data/Gemfile +3 -18
  5. data/README.adoc +109 -6
  6. data/lib/lutaml/model/attribute.rb +15 -2
  7. data/lib/lutaml/model/config.rb +0 -1
  8. data/lib/lutaml/model/json_adapter/json_document.rb +20 -0
  9. data/lib/lutaml/model/json_adapter/json_object.rb +28 -0
  10. data/lib/lutaml/model/json_adapter/{multi_json.rb → multi_json_adapter.rb} +2 -3
  11. data/lib/lutaml/model/json_adapter/{standard.rb → standard_json_adapter.rb} +2 -3
  12. data/lib/lutaml/model/json_adapter.rb +1 -31
  13. data/lib/lutaml/model/key_value_mapping.rb +0 -1
  14. data/lib/lutaml/model/key_value_mapping_rule.rb +0 -1
  15. data/lib/lutaml/model/mapping_hash.rb +0 -2
  16. data/lib/lutaml/model/mapping_rule.rb +0 -1
  17. data/lib/lutaml/model/schema/json_schema.rb +0 -1
  18. data/lib/lutaml/model/schema/relaxng_schema.rb +0 -1
  19. data/lib/lutaml/model/schema/xsd_schema.rb +0 -1
  20. data/lib/lutaml/model/schema/yaml_schema.rb +0 -1
  21. data/lib/lutaml/model/schema.rb +0 -1
  22. data/lib/lutaml/model/serializable.rb +0 -1
  23. data/lib/lutaml/model/serialize.rb +22 -4
  24. data/lib/lutaml/model/toml_adapter/toml_document.rb +20 -0
  25. data/lib/lutaml/model/toml_adapter/toml_object.rb +28 -0
  26. data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +2 -3
  27. data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +2 -3
  28. data/lib/lutaml/model/toml_adapter.rb +0 -31
  29. data/lib/lutaml/model/type/date_time.rb +20 -0
  30. data/lib/lutaml/model/type/json.rb +34 -0
  31. data/lib/lutaml/model/type/time_without_date.rb +4 -3
  32. data/lib/lutaml/model/type.rb +61 -124
  33. data/lib/lutaml/model/version.rb +1 -1
  34. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +5 -6
  35. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +4 -5
  36. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +8 -9
  37. data/lib/lutaml/model/xml_adapter/xml_attribute.rb +27 -0
  38. data/lib/lutaml/model/xml_adapter/xml_document.rb +184 -0
  39. data/lib/lutaml/model/xml_adapter/xml_element.rb +94 -0
  40. data/lib/lutaml/model/xml_adapter/xml_namespace.rb +49 -0
  41. data/lib/lutaml/model/xml_adapter.rb +0 -285
  42. data/lib/lutaml/model/xml_mapping.rb +1 -1
  43. data/lib/lutaml/model/xml_mapping_rule.rb +3 -4
  44. data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +34 -0
  45. data/lib/lutaml/model/yaml_adapter/yaml_document.rb +20 -0
  46. data/lib/lutaml/model/yaml_adapter/yaml_object.rb +28 -0
  47. data/lib/lutaml/model/yaml_adapter.rb +1 -27
  48. data/lib/lutaml/model.rb +0 -5
  49. metadata +17 -5
  50. 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
- if options[:values] && !options[:values].include?(value)
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(name.to_s, to: name,
213
- render_nil: attr.render_nil?)
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 "../toml_adapter"
2
+ require_relative "toml_document"
4
3
 
5
4
  module Lutaml
6
5
  module Model
7
6
  module TomlAdapter
8
- class TomlRbDocument < Document
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 "../toml_adapter"
2
+ require_relative "toml_document"
4
3
 
5
4
  module Lutaml
6
5
  module Model
7
6
  module TomlAdapter
8
- class TomlibDocument < Document
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
- parsed_time = ::Time.parse(value.to_s)
8
- parsed_time.strftime("%H:%M:%S")
7
+ return if value.nil?
8
+
9
+ ::Time.parse(value.to_s)
9
10
  end
10
11
 
11
12
  def self.serialize(value)
@@ -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
- %w(String
13
- Integer
14
- Float
15
- Date
16
- Time
17
- Boolean
18
- Decimal
19
- Hash
20
- UUID
21
- Symbol
22
- BigInteger
23
- Binary
24
- URL
25
- Email
26
- IPAddress
27
- JSON
28
- Enum).each do |t|
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
- class #{t} # class Integer
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
- class TimeWithoutDate
47
- def self.cast(value)
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
- if [String, Email].include?(type)
58
+ case type.to_s.split("::").last
59
+ when "String"
131
60
  value.to_s
132
- elsif [Integer, BigInteger].include?(type)
61
+ when "Integer"
133
62
  value.to_i
134
- elsif type == Float
63
+ when "Float"
135
64
  value.to_f
136
- elsif type == Date
65
+ when "Date"
137
66
  begin
138
67
  ::Date.parse(value.to_s)
139
68
  rescue ArgumentError
140
69
  nil
141
70
  end
142
- elsif type == DateTime
71
+ when "DateTime"
143
72
  DateTime.cast(value)
144
- elsif type == Time
73
+ when "Time"
145
74
  ::Time.parse(value.to_s)
146
- elsif type == TimeWithoutDate
75
+ when "TimeWithoutDate"
147
76
  TimeWithoutDate.cast(value)
148
- elsif type == Boolean
77
+ when "Boolean"
149
78
  to_boolean(value)
150
- elsif type == Decimal
79
+ when "Decimal"
151
80
  BigDecimal(value.to_s)
152
- elsif type == Hash
81
+ when "Hash"
153
82
  normalize_hash(Hash(value))
154
- elsif type == UUID
83
+ when "Uuid"
155
84
  UUID_REGEX.match?(value) ? value : SecureRandom.uuid
156
- elsif type == Symbol
85
+ when "Symbol"
157
86
  value.to_sym
158
- elsif type == Binary
87
+ when "Binary"
159
88
  value.force_encoding("BINARY")
160
- elsif type == URL
89
+ when "Url"
161
90
  URI.parse(value.to_s)
162
- elsif type == IPAddress
91
+ when "IpAddress"
163
92
  IPAddr.new(value.to_s)
164
- elsif type == JSON
165
- JSON.cast(value)
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
- if type == Date
103
+ case type.to_s.split("::").last
104
+ when "Date"
177
105
  value.iso8601
178
- elsif type == DateTime
106
+ when "DateTime"
179
107
  DateTime.serialize(value)
180
- elsif type == Integer
108
+ when "Integer"
181
109
  value.to_i
182
- elsif type == Float
110
+ when "Float"
183
111
  value.to_f
184
- elsif type == Boolean
112
+ when "Boolean"
185
113
  to_boolean(value)
186
- elsif type == Decimal
114
+ when "Decimal"
187
115
  value.to_s("F")
188
- elsif type == Hash
116
+ when "Hash"
189
117
  Hash(value)
190
- elsif type == JSON
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
- return true if value == true || value.to_s =~ (/^(true|t|yes|y|1)$/i)
199
- return false if value == false || value.nil? || value.to_s =~ (/^(false|f|no|n|0)$/i)
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"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.3.1"
5
+ VERSION = "0.3.2"
6
6
  end
7
7
  end
@@ -1,11 +1,10 @@
1
- # lib/lutaml/model/xml_adapter/nokogiri_adapter.rb
2
1
  require "nokogiri"
3
- require_relative "../xml_adapter"
2
+ require_relative "xml_document"
4
3
 
5
4
  module Lutaml
6
5
  module Model
7
6
  module XmlAdapter
8
- class NokogiriDocument < Document
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 < Element
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 = Lutaml::Model::XmlNamespace.new(name, prefix)
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] = Attribute.new(
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 "../xml_adapter"
2
+ require_relative "xml_document"
4
3
 
5
4
  module Lutaml
6
5
  module Model
7
6
  module XmlAdapter
8
- class OgaDocument < Document
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 < Element
53
+ class OgaElement < XmlElement
55
54
  def initialize(node)
56
55
  attributes = node.attributes.each_with_object({}) do |attr, hash|
57
- hash[attr.name] = Attribute.new(attr.name, attr.value)
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 "../xml_adapter"
2
+ require_relative "xml_document"
4
3
 
5
4
  module Lutaml
6
5
  module Model
7
6
  module XmlAdapter
8
- class OxDocument < Document
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 < Element
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(Lutaml::Model::XmlNamespace.new(value, name))
146
+ root_node.add_namespace(XmlNamespace.new(value, name))
148
147
  else
149
- add_namespace(Lutaml::Model::XmlNamespace.new(value, name))
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 ||= Lutaml::Model::XmlAdapter::XML_NAMESPACE_URI
158
+ namespace ||= XML_NAMESPACE_URI
160
159
  prefix = n.first
161
160
  end
162
161
 
163
- hash[name.to_s] = Attribute.new(
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