xsd 2.4.3 → 2.6.0

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: 07f0d2e114fa193dacc2ad0d9d74bbc173cbd3ebebcbae3d5a86152cc05abdc9
4
- data.tar.gz: f806f42ee894bd5a14704842d4e2f6da61559d006edce27e3dcb6d29568ab54b
3
+ metadata.gz: 2a5aa03e831e5cf4e88780b18a4ef57217eff54a14e2138669672f33486ba8bd
4
+ data.tar.gz: b6a9ab392e47192a6a286ffa7dc97c5f624c78d9ab117bdea67e11f801c39363
5
5
  SHA512:
6
- metadata.gz: 5ecb651c68e56eac792410385234e8ef48a366d2534978885e2f89023080b6d5de54d6e3d5ad53fe30d6d6eee074a46a1095dec87549bb11a78dea9ef5787773
7
- data.tar.gz: 9d43d08a7281787b1d32f572339718620d1e88eff4f208b4d80fdb753086c4d996c7fb0d7b9277f5f00dcae9ff3bd13660d1207891e9c61265888575e48f7aad
6
+ metadata.gz: a031bc3a3947708a8f6f8e4add4040853f9f8b62cd3465de56421600d9fc2d2b7c45b163efe239c7486dce05bf0427d8f380e119673b644739f736b4598b5276
7
+ data.tar.gz: ad7bbd0268373292a291935599749dc9937784438b398958acf592db4e1648967106f45c1dd402c82f3cdd534f2fe0e177a1250e91f65872fc3aa9d9a8b416a5
data/CHANGELOG.md CHANGED
@@ -1,4 +1,9 @@
1
- ## [Unreleased]
1
+ ## [2.6.0] - 2024-04-12
2
+
3
+ - Fix XSD boolean attributes
4
+ - Add support for element lookup with namespace
5
+ - Add element (with simple content) data type calculation
6
+ - Add element mixed type calculation
2
7
 
3
8
  ## [2.4.3] - 2024-04-04
4
9
 
data/README.md CHANGED
@@ -28,8 +28,13 @@ require 'xsd'
28
28
  # Load ruby-xsd
29
29
  reader = XSD::XML.open('some.xsd')
30
30
 
31
- # Get elements and their child elements
31
+ # Get element by name with hash lookup
32
32
  element = reader['NewReleaseMessage']
33
+
34
+ # Get element by namespace + name with hash lookup
35
+ element = reader['{http://ddex.net/xml/ern/36}NewReleaseMessage']
36
+
37
+ # Get element child elements
33
38
  element.collect_elements.map(&:name) # => ['MessageHeader', 'UpdateIndicator', 'IsBackfill', 'CatalogTransfer', 'WorkList', 'CueSheetList', 'ResourceList', 'CollectionList', 'ReleaseList', 'DealList']
34
39
 
35
40
  # Get attributes
@@ -38,6 +43,7 @@ attribute = reader['NewReleaseMessage']['@MessageSchemaVersionId']
38
43
  # Get attribute information
39
44
  attribute.name # => 'MessageSchemaVersionId'
40
45
  attribute.type # => 'xs:string'
46
+ attribute.data_type # => 'string'
41
47
  attribute.required? # => true
42
48
  attribute.optional? # => false
43
49
  attribute.prohibited? # => true
@@ -48,7 +54,9 @@ element.min_occurs # => 0
48
54
  element.max_occurs # => :unbounded
49
55
  element.type # => 'ern:SoundRecording'
50
56
  element.complex_type # => XSD::ComplexType
51
- element.complex? # => true
57
+ element.complex_content? # => true
58
+ element.simple_content? # => false
59
+ element.mixed_content? # => false
52
60
  element.multiple_allowed? # => true
53
61
  element.required? # => false
54
62
  ```
@@ -34,7 +34,7 @@ module XSD
34
34
 
35
35
  def initialize(options = {})
36
36
  @options = options
37
- @cache = {}
37
+ @cache = {}
38
38
 
39
39
  raise Error, "#{self.class}.new expects a hash parameter" unless @options.is_a?(Hash)
40
40
  end
@@ -100,9 +100,9 @@ module XSD
100
100
  curname = curname.to_s
101
101
 
102
102
  if curname[0] == '@'
103
- result = result.collect_attributes.find { |attr| attr.name == curname[1..-1] }
103
+ result = result.collect_attributes.find { |attr| definition_match?(attr, curname[1..]) }
104
104
  else
105
- result = result.collect_elements.find { |elem| elem.name == curname }
105
+ result = result.collect_elements.find { |elem| definition_match?(elem, curname) }
106
106
  end
107
107
  end
108
108
 
@@ -116,7 +116,7 @@ module XSD
116
116
  def object_by_name(node_name, name)
117
117
  # get prefix and local name
118
118
  name_prefix = get_prefix(name)
119
- name_local = strip_prefix(name)
119
+ name_local = strip_prefix(name)
120
120
 
121
121
  # do not search for built-in types
122
122
  return nil if schema.namespace_prefix == name_prefix
@@ -126,7 +126,7 @@ module XSD
126
126
 
127
127
  # find element in target schema
128
128
  search_schemas.each do |s|
129
- node = s.node.xpath("./xs:#{node_name}[@name=\"#{name_local}\"]", { 'xs' => XML_SCHEMA }).first
129
+ node = s.node.at_xpath("./xs:#{node_name}[@name=\"#{name_local}\"]", { 'xs' => XML_SCHEMA })
130
130
  return s.node_to_object(node) if node
131
131
  end
132
132
 
@@ -138,7 +138,6 @@ module XSD
138
138
  # @return BaseObject
139
139
  def node_to_object(node)
140
140
  # check object in cache first
141
- # TODO: проверить работу!
142
141
  return reader.object_cache[node.object_id] if reader.object_cache[node.object_id]
143
142
 
144
143
  klass = XML::CLASS_MAP[node.name]
@@ -203,43 +202,49 @@ module XSD
203
202
  # Get all available elements on the current stack level
204
203
  # @return Array<Element>
205
204
  def collect_elements(*)
206
- # exclude element that can not have elements
207
- return [] if NO_ELEMENTS_CONTAINER.include?(self.class.mapped_name)
205
+ return @collect_elements if @collect_elements
208
206
 
209
- if is_a?(Referenced) && ref
210
- reference.collect_elements
211
- else
212
- # map children recursive
213
- map_children(:*).map do |obj|
214
- if obj.is_a?(Element)
215
- obj
207
+ r = if NO_ELEMENTS_CONTAINER.include?(self.class.mapped_name)
208
+ []
209
+ elsif is_a?(Referenced) && ref
210
+ reference.collect_elements
216
211
  else
217
- # get elements considering references
218
- (obj.is_a?(Referenced) && obj.ref ? obj.reference : obj).collect_elements
212
+ # map children recursive
213
+ map_children(:*).map do |obj|
214
+ if obj.is_a?(Element)
215
+ obj
216
+ else
217
+ # get elements considering references
218
+ (obj.is_a?(Referenced) && obj.ref ? obj.reference : obj).collect_elements
219
+ end
220
+ end.flatten
219
221
  end
220
- end.flatten
221
- end
222
+
223
+ @collect_elements = r
222
224
  end
223
225
 
224
226
  # Get all available attributes on the current stack level
225
227
  # @return Array<Attribute>
226
228
  def collect_attributes(*)
227
- # exclude element that can not have elements
228
- return [] if NO_ATTRIBUTES_CONTAINER.include?(self.class.mapped_name)
229
+ return @collect_attributes if @collect_attributes
229
230
 
230
- if is_a?(Referenced) && ref
231
- reference.collect_attributes
232
- else
233
- # map children recursive
234
- map_children(:*).map do |obj|
235
- if obj.is_a?(Attribute)
236
- obj
231
+ r = if NO_ATTRIBUTES_CONTAINER.include?(self.class.mapped_name)
232
+ []
233
+ elsif is_a?(Referenced) && ref
234
+ reference.collect_attributes
237
235
  else
238
- # get attributes considering references
239
- (obj.is_a?(Referenced) && obj.ref ? obj.reference : obj).collect_attributes
236
+ # map children recursive
237
+ map_children(:*).map do |obj|
238
+ if obj.is_a?(Attribute)
239
+ obj
240
+ else
241
+ # get attributes considering references
242
+ (obj.is_a?(Referenced) && obj.ref ? obj.reference : obj).collect_attributes
243
+ end
244
+ end.flatten
240
245
  end
241
- end.flatten
242
- end
246
+
247
+ @collect_attributes = r
243
248
  end
244
249
 
245
250
  # Get reader instance
@@ -260,8 +265,8 @@ module XSD
260
265
  # @param [Hash] options
261
266
  def self.property(name, type, options = {}, &block)
262
267
  properties[to_underscore(name)] = {
263
- name: name,
264
- type: type,
268
+ name: name,
269
+ type: type,
265
270
  resolve: block,
266
271
  **options
267
272
  }
@@ -298,7 +303,7 @@ module XSD
298
303
 
299
304
  # check for property first
300
305
  if (property = self.class.properties[method])
301
- value = property[:resolve] ? property[:resolve].call(self) : node[property[:name].to_s]
306
+ value = property[:resolve] ? property[:resolve].call(self) : node[property[:name].to_s]
302
307
  result = if value.nil?
303
308
  # if object has reference - search property in referenced object
304
309
  node['ref'] ? reference.send(method, *args) : property[:default]
@@ -307,7 +312,7 @@ module XSD
307
312
  when :integer
308
313
  property[:name] == :maxOccurs && value == 'unbounded' ? :unbounded : value.to_i
309
314
  when :boolean
310
- !!value
315
+ value == 'true'
311
316
  else
312
317
  value
313
318
  end
@@ -354,10 +359,10 @@ module XSD
354
359
  def self.mapped_name
355
360
  # @mapped_name ||= XML::CLASS_MAP.each { |k, v| return k.to_sym if v == self }
356
361
  @mapped_name ||= begin
357
- name = self.name.split('::').last
358
- name[0] = name[0].downcase
359
- name.to_sym
360
- end
362
+ name = self.name.split('::').last
363
+ name[0] = name[0].downcase
364
+ name.to_sym
365
+ end
361
366
  end
362
367
 
363
368
  # Return string if it is not empty, or nil otherwise
@@ -366,5 +371,24 @@ module XSD
366
371
  def nil_if_empty(string)
367
372
  string&.empty? ? nil : string
368
373
  end
374
+
375
+ private
376
+
377
+ def definition_match?(definition, query)
378
+ actual_definition = definition.referenced? ? definition.reference : definition
379
+
380
+ if query.start_with?('{')
381
+ parts = query[1..].split('}')
382
+ raise Error, "Invalid element/attribute query: #{query}" if parts.size != 2
383
+
384
+ namespace, name = parts
385
+
386
+ return false if namespace != actual_definition.namespace
387
+ else
388
+ name = query
389
+ end
390
+
391
+ name == '*' || actual_definition.name == name
392
+ end
369
393
  end
370
394
  end
@@ -10,10 +10,11 @@ module XSD
10
10
 
11
11
  include SimpleTyped
12
12
  include Referenced
13
+ include Named
13
14
 
14
15
  # Optional. Specifies the name of the attribute. Name and ref attributes cannot both be present
15
16
  # @!attribute name
16
- # @return String
17
+ # @return String, nil
17
18
  property :name, :string
18
19
 
19
20
  # Optional. Specifies a default value for the attribute. Default and fixed attributes cannot both be present
@@ -34,7 +35,7 @@ module XSD
34
35
  # matched against the (NCName) of the attribute
35
36
  # @!attribute form
36
37
  # @return String, nil
37
- # TODO: поддержка default значения с вычислением родителя
38
+ # TODO: support default value from parent
38
39
  property :form, :string
39
40
 
40
41
  # Optional. Specifies a built-in data type or a simple type. The type attribute can only be present when the
@@ -68,5 +69,15 @@ module XSD
68
69
  def prohibited?
69
70
  use == 'prohibited'
70
71
  end
72
+
73
+ # Get base data type
74
+ # @return String, nil
75
+ def data_type
76
+ if simple_type
77
+ simple_type.data_type
78
+ else
79
+ strip_prefix(type)
80
+ end
81
+ end
71
82
  end
72
83
  end
@@ -9,10 +9,11 @@ module XSD
9
9
  class AttributeGroup < BaseObject
10
10
  include Referenced
11
11
  include AttributeContainer
12
+ include Named
12
13
 
13
- # Optional. Specifies the name of the attribute. Name and ref attributes cannot both be present
14
+ # Optional. Specifies the name of the attribute group. Name and ref attributes cannot both be present
14
15
  # @!attribute name
15
- # @return String
16
+ # @return String, nil
16
17
  property :name, :string
17
18
  end
18
19
  end
@@ -7,8 +7,9 @@ module XSD
7
7
  # https://www.w3schools.com/xml/el_complextype.asp
8
8
  class ComplexType < BaseObject
9
9
  include AttributeContainer
10
+ include Named
10
11
 
11
- # Optional. Specifies the name of the attribute. Name and ref attributes cannot both be present
12
+ # Optional. Specifies a name for the element
12
13
  # @!attribute name
13
14
  # @return String
14
15
  property :name, :string
@@ -78,5 +79,55 @@ module XSD
78
79
  def linked?
79
80
  !name.nil?
80
81
  end
82
+
83
+ # Determine if this type has mixed content definition
84
+ # @return Boolean
85
+ def mixed_content?
86
+ return true if mixed
87
+
88
+ if complex_content
89
+ return true if complex_content.mixed
90
+
91
+ return (complex_content.extension || complex_content.restriction).base_complex_type&.mixed_content?
92
+ end
93
+
94
+ false
95
+ end
96
+
97
+ # Determine if this type has complex content definition
98
+ # @return Boolean
99
+ def complex_content?
100
+ if simple_content
101
+ false
102
+ elsif complex_content
103
+ true
104
+ else
105
+ group || all || choice || sequence
106
+ end
107
+ end
108
+
109
+ # Determine if this type has simple content definition
110
+ # @return Boolean
111
+ def simple_content?
112
+ !!simple_content
113
+ end
114
+
115
+ # Get simple content data type
116
+ # @return String, nil
117
+ def data_type
118
+ return nil unless simple_content
119
+
120
+ restriction = simple_content.restriction
121
+ if restriction
122
+ if restriction.base
123
+ restriction.base_simple_type&.data_type || strip_prefix(restriction.base)
124
+ else
125
+ restriction.simple_type&.data_type
126
+ end
127
+ else
128
+ extension = simple_content.extension
129
+ extension.base_simple_type&.data_type || strip_prefix(extension.base)
130
+ end
131
+ end
81
132
  end
82
133
  end
@@ -11,10 +11,11 @@ module XSD
11
11
  include SimpleTyped
12
12
  include ComplexTyped
13
13
  include Referenced
14
+ include Named
14
15
 
15
- # Optional. Specifies the name of the attribute. Name and ref attributes cannot both be present
16
+ # Optional. Specifies a name for the element. This attribute is required if the parent element is the schema element
16
17
  # @!attribute name
17
- # @return String
18
+ # @return String, nil
18
19
  property :name, :string
19
20
 
20
21
  # Optional. Specifies either the name of a built-in data type, or the name of a simpleType or complexType element
@@ -107,8 +108,32 @@ module XSD
107
108
 
108
109
  # Determine if element has complex content
109
110
  # @return Boolean
110
- def complex?
111
- complex_type && !complex_type.simple_content && collect_elements.any?
111
+ def complex_content?
112
+ # this is not an opposite to simple_content?, element may have neither
113
+ complex_type&.complex_content? || false
114
+ end
115
+
116
+ # Determine if element has simple content
117
+ # @return Boolean
118
+ def simple_content?
119
+ # this is not an opposite to complex_content?, element may have neither
120
+ if complex_type
121
+ complex_type.simple_content?
122
+ else
123
+ true
124
+ end
125
+ end
126
+
127
+ # Determine if element has attributes
128
+ # @return Boolean
129
+ def attributes?
130
+ complex_type && collect_attributes.any?
131
+ end
132
+
133
+ # Determine if element has mixed content
134
+ # @return Boolean
135
+ def mixed_content?
136
+ complex_type&.mixed_content? || false
112
137
  end
113
138
 
114
139
  # Get elements that can appear instead of this one
@@ -117,14 +142,20 @@ module XSD
117
142
  # TODO: for now we do not search in parent schemas (that imported current schema)
118
143
  # TODO: refactor for better namespace handling (use xpath with namespaces or correct comparison)
119
144
  schema.collect_elements.select do |element|
120
- element.substitution_group&.split(':')&.last == name
145
+ strip_prefix(element.substitution_group) == name
121
146
  end
122
147
  end
123
148
 
124
- # Get target namespace
125
- # @return String
126
- def target_namespace
127
- schema.target_namespace
149
+ # Get base data type
150
+ # @return String, nil
151
+ def data_type
152
+ if complex_type
153
+ complex_type.data_type
154
+ elsif simple_type
155
+ simple_type.data_type
156
+ else
157
+ strip_prefix(type)
158
+ end
128
159
  end
129
160
  end
130
161
  end
@@ -6,9 +6,12 @@ module XSD
6
6
  # Parent elements: attribute, element, list, restriction, schema, union
7
7
  # https://www.w3schools.com/xml/el_simpletype.asp
8
8
  class SimpleType < BaseObject
9
- # Optional. Specifies the name of the attribute. Name and ref attributes cannot both be present
9
+ include Named
10
+
11
+ # Specifies a name for the element. This attribute is required if the simpleType element is a child of the
12
+ # schema element, otherwise it is not allowed
10
13
  # @!attribute name
11
- # @return String
14
+ # @return String, nil
12
15
  property :name, :string
13
16
 
14
17
  # Nested restriction
@@ -31,5 +34,23 @@ module XSD
31
34
  def linked?
32
35
  !name.nil?
33
36
  end
37
+
38
+ # Get base data type
39
+ # @return String, nil
40
+ def data_type
41
+ if restriction
42
+ if restriction.base
43
+ restriction.base_simple_type&.data_type || strip_prefix(restriction.base)
44
+ else
45
+ restriction.simple_type&.data_type
46
+ end
47
+ elsif union
48
+ types = union.types.map { |type| type.is_a?(String) ? strip_prefix(type) : type.data_type }.uniq
49
+ types.size == 1 ? types.first : types
50
+ else
51
+ # list is always a sting
52
+ 'string'
53
+ end
54
+ end
34
55
  end
35
56
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XSD
4
+ module Named
5
+ # Get definition namespace
6
+ # @return String
7
+ def namespace
8
+ schema.target_namespace
9
+ end
10
+
11
+ # Get absolute definition name
12
+ # @return String
13
+ def absolute_name
14
+ name ? "{#{namespace}}#{name}" : nil
15
+ end
16
+ end
17
+ end
data/lib/xsd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module XSD
4
- VERSION = '2.4.3'
4
+ VERSION = '2.6.0'
5
5
  end
data/lib/xsd/xml.rb CHANGED
@@ -5,8 +5,6 @@ require 'net/http'
5
5
 
6
6
  module XSD
7
7
  class XML
8
- include Generator
9
-
10
8
  attr_reader :options, :object_cache, :schemas
11
9
 
12
10
  DEFAULT_RESOURCE_RESOLVER = proc do |location, namespace|
data/lib/xsd.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'xsd/base_object'
4
+ require 'xsd/shared/named'
4
5
  require 'xsd/shared/min_max_occurs'
5
6
  require 'xsd/shared/referenced'
6
7
  require 'xsd/shared/attribute_container'
@@ -37,6 +38,5 @@ require 'xsd/objects/appinfo'
37
38
  require 'xsd/objects/any_attribute'
38
39
  require 'xsd/objects/key'
39
40
  require 'xsd/objects/keyref'
40
- require 'xsd/generator'
41
41
  require 'xsd/exceptions'
42
42
  require 'xsd/xml'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.3
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - d.arkhipov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-04 00:00:00.000000000 Z
11
+ date: 2024-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder
@@ -72,7 +72,6 @@ files:
72
72
  - lib/xsd.rb
73
73
  - lib/xsd/base_object.rb
74
74
  - lib/xsd/exceptions.rb
75
- - lib/xsd/generator.rb
76
75
  - lib/xsd/objects/all.rb
77
76
  - lib/xsd/objects/annotation.rb
78
77
  - lib/xsd/objects/any.rb
@@ -107,6 +106,7 @@ files:
107
106
  - lib/xsd/shared/complex_typed.rb
108
107
  - lib/xsd/shared/element_container.rb
109
108
  - lib/xsd/shared/min_max_occurs.rb
109
+ - lib/xsd/shared/named.rb
110
110
  - lib/xsd/shared/referenced.rb
111
111
  - lib/xsd/shared/simple_typed.rb
112
112
  - lib/xsd/version.rb
data/lib/xsd/generator.rb DELETED
@@ -1,146 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'builder'
4
-
5
- module XSD
6
- module Generator
7
- # Generate XML from provided data
8
- # @param [Hash] data
9
- # @param [String, Array<String>] element
10
- # @param [Builder::XmlMarkup] builder
11
- # @return Builder::XmlMarkup
12
- def generate(data, element = nil, builder = nil)
13
- # find root element
14
- root = find_root_element(element)
15
-
16
- # create builder
17
- builder ||= default_builder
18
-
19
- # build element tree
20
- @namespace_index = 0
21
- build_element(builder, root, data)
22
-
23
- builder
24
- end
25
-
26
- private
27
-
28
- # Build element tree
29
- # @param [Builder::XmlMarkup] xml
30
- # @param [Element] element
31
- # @param [Hash] data
32
- # @param [Hash] namespaces
33
- def build_element(xml, element, data, namespaces = {})
34
- # get item data
35
- elements = (element.abstract ? [] : [element]) + element.substitution_elements
36
- provided_element = elements.find { |elem| !data[elem.name].nil? }
37
-
38
- if element.required? && provided_element.nil?
39
- raise Error, "Element #{element.name} is required, but no data in provided for it"
40
- end
41
- return unless provided_element
42
-
43
- element = provided_element
44
- data = data[element.name]
45
-
46
- # handle repeated items
47
- if element.multiple_allowed?
48
- unless data.is_a?(Array)
49
- raise Error, "Element #{element.name} is allowed to occur multiple times, but non-array is provided"
50
- end
51
- else
52
- if data.is_a?(Array)
53
- raise Error, "Element #{element.name} is not allowed to occur multiple times, but an array is provided"
54
- end
55
-
56
- data = [data]
57
- end
58
-
59
- # configure namespaces
60
- # TODO: попытаться использовать collect_namespaces?
61
- attributes = {}
62
- all_attributes = element.collect_attributes
63
- if element.complex?
64
- all_elements = element.collect_elements
65
-
66
- # get namespaces for current element and it's children
67
- prefix = nil
68
- [*all_elements, element].each do |elem|
69
- prefix = get_namespace_prefix(elem, attributes, namespaces)
70
- end
71
- else
72
- prefix = get_namespace_prefix(element, attributes, namespaces)
73
- end
74
-
75
- # iterate through each item
76
- data.each do |item|
77
- # prepare attributes
78
- all_attributes.each do |attribute|
79
- value = item["@#{attribute.name}"]
80
- if !value.nil?
81
- attributes[attribute.name] = value
82
- elsif attribute.required?
83
- raise Error, "Attribute #{attribute.name} is required, but no data in provided for it" if attribute.fixed.nil?
84
-
85
- attributes[attribute.name] = attribute.fixed
86
- else
87
- attributes.delete(attribute.name)
88
- end
89
- end
90
-
91
- # generate element
92
- if element.complex?
93
- # generate tag recursively
94
- xml.tag!("#{prefix}:#{element.name}", attributes) do
95
- all_elements.each do |elem|
96
- build_element(xml, elem, item, namespaces.dup)
97
- end
98
- end
99
- else
100
- has_text = item.is_a?(Hash)
101
- if has_text && element.complex_type&.nodes(:any, true)&.any?
102
- xml.tag!("#{prefix}:#{element.name}", attributes) { |res| res << item['#text'].to_s }
103
- else
104
- value = has_text ? item['#text'] : item
105
- xml.tag!("#{prefix}:#{element.name}", attributes, (value == '' ? nil : value))
106
- end
107
- end
108
- end
109
- end
110
-
111
- # Get namespace prefix for element
112
- # @param [Element] element
113
- # @param [Hash] attributes
114
- # @param [Hash] namespaces
115
- # @return String
116
- def get_namespace_prefix(element, attributes, namespaces)
117
- namespace = (element.referenced? ? element.reference : element).target_namespace
118
- prefix = namespaces.key(namespace)
119
- unless prefix
120
- prefix = "n#{@namespace_index += 1}"
121
- namespaces[prefix] = attributes["xmlns:#{prefix}"] = namespace
122
- end
123
-
124
- prefix
125
- end
126
-
127
- # Find root element with provided lookup
128
- # @param [String, Array<String>, nil] lookup
129
- def find_root_element(lookup)
130
- if lookup
131
- element = self[*lookup]
132
- raise Error, "Cant find start element #{lookup}" unless element.is_a?(Element)
133
-
134
- element
135
- else
136
- raise Error, 'XSD contains more that one root element. Please, specify starting element' if elements.size > 1
137
-
138
- elements.first
139
- end
140
- end
141
-
142
- def default_builder
143
- Builder::XmlMarkup.new
144
- end
145
- end
146
- end