Class: Moxml::Adapter::Rexml
- Inherits:
-
Base
- Object
- Base
- Moxml::Adapter::Rexml
show all
- Defined in:
- lib/moxml/adapter/rexml.rb
Class Method Summary
collapse
-
.add_child(element, child) ⇒ Object
-
.add_next_sibling(node, sibling) ⇒ Object
-
.add_previous_sibling(node, sibling) ⇒ Object
-
.at_xpath(node, expression, namespaces = {}) ⇒ Object
-
.attribute_element(attribute) ⇒ Object
-
.attributes(element) ⇒ Object
-
.cdata_content(node) ⇒ Object
-
.children(node) ⇒ Object
-
.comment_content(node) ⇒ Object
-
.create_document(_native_doc = nil) ⇒ Object
-
.create_native_cdata(content) ⇒ Object
-
.create_native_comment(content) ⇒ Object
-
.create_native_declaration(version, encoding, standalone) ⇒ Object
-
.create_native_doctype(name, external_id, system_id) ⇒ Object
-
.create_native_element(name) ⇒ Object
-
.create_native_namespace(element, prefix, uri) ⇒ Object
add a namespace definition, keep the element name unchanged.
-
.create_native_processing_instruction(target, content) ⇒ Object
-
.create_native_text(content) ⇒ Object
-
.declaration_attribute(node, name) ⇒ Object
-
.document(node) ⇒ Object
-
.duplicate_node(node) ⇒ Object
-
.get_attribute(element, name) ⇒ Object
-
.get_attribute_value(element, name) ⇒ Object
-
.inner_text(node) ⇒ Object
-
.namespace(node) ⇒ Object
-
.namespace_definitions(node) ⇒ Object
-
.namespace_prefix(node) ⇒ Object
-
.namespace_uri(node) ⇒ Object
-
.next_sibling(node) ⇒ Object
-
.node_name(node) ⇒ Object
-
.node_type(node) ⇒ Object
-
.parent(node) ⇒ Object
-
.parse(xml, options = {}) ⇒ Object
-
.prepare_xpath_namespaces(node) ⇒ Object
not used at the moment but may be useful when the xpath is upgraded to work with namespaces.
-
.previous_sibling(node) ⇒ Object
-
.processing_instruction_content(node) ⇒ Object
-
.processing_instruction_target(node) ⇒ Object
-
.remove(node) ⇒ Object
-
.remove_attribute(element, name) ⇒ Object
-
.replace(node, new_node) ⇒ Object
-
.replace_children(element, children) ⇒ Object
-
.root(document) ⇒ Object
-
.serialize(node, options = {}) ⇒ Object
-
.set_attribute(element, name, value) ⇒ Object
-
.set_attribute_name(attribute, name) ⇒ Object
-
.set_attribute_value(attribute, value) ⇒ Object
-
.set_cdata_content(node, content) ⇒ Object
-
.set_comment_content(node, content) ⇒ Object
-
.set_declaration_attribute(node, name, value) ⇒ Object
-
.set_namespace(element, ns) ⇒ Object
add a namespace prefix to the element name AND a namespace definition.
-
.set_node_name(node, name) ⇒ Object
-
.set_processing_instruction_content(node, content) ⇒ Object
-
.set_root(doc, element) ⇒ Object
-
.set_text_content(node, content) ⇒ Object
-
.text_content(node) ⇒ Object
-
.xpath(node, expression, _namespaces = {}) ⇒ Object
Methods inherited from Base
create_cdata, create_comment, create_declaration, create_doctype, create_element, create_namespace, create_processing_instruction, create_text, patch_node
Methods included from XmlUtils
#encode_entities, #normalize_xml_value, #validate_comment_content, #validate_declaration_encoding, #validate_declaration_standalone, #validate_declaration_version, #validate_element_name, #validate_pi_target, #validate_prefix, #validate_uri
Class Method Details
.add_child(element, child) ⇒ Object
229
230
231
232
233
234
235
236
|
# File 'lib/moxml/adapter/rexml.rb', line 229
def add_child(element, child)
case child
when String
element.add_text(child)
else
element.add(child)
end
end
|
.add_next_sibling(node, sibling) ⇒ Object
248
249
250
251
|
# File 'lib/moxml/adapter/rexml.rb', line 248
def add_next_sibling(node, sibling)
parent = node.parent
parent.insert_after(node, sibling)
end
|
.add_previous_sibling(node, sibling) ⇒ Object
238
239
240
241
242
243
244
245
246
|
# File 'lib/moxml/adapter/rexml.rb', line 238
def add_previous_sibling(node, sibling)
parent = node.parent
parent.insert_before(node, sibling)
end
|
.at_xpath(node, expression, namespaces = {}) ⇒ Object
411
412
413
414
|
# File 'lib/moxml/adapter/rexml.rb', line 411
def at_xpath(node, expression, namespaces = {})
results = xpath(node, expression, namespaces)
results.first
end
|
.attribute_element(attribute) ⇒ Object
195
196
197
|
# File 'lib/moxml/adapter/rexml.rb', line 195
def attribute_element(attribute)
attribute.element
end
|
.attributes(element) ⇒ Object
187
188
189
190
191
192
193
|
# File 'lib/moxml/adapter/rexml.rb', line 187
def attributes(element)
return [] unless element.respond_to?(:attributes)
element.attributes.values
.reject { |attr| attr.prefix.to_s.start_with?("xmlns") }
end
|
.cdata_content(node) ⇒ Object
296
297
298
|
# File 'lib/moxml/adapter/rexml.rb', line 296
def cdata_content(node)
node.value
end
|
.children(node) ⇒ Object
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/moxml/adapter/rexml.rb', line 113
def children(node)
return [] unless node.respond_to?(:children)
result = node.children.reject do |child|
child.is_a?(::REXML::Text) &&
child.to_s.strip.empty? &&
!(child.next_sibling.nil? && child.previous_sibling.nil?)
end
result.uniq(&:object_id)
end
|
288
289
290
|
# File 'lib/moxml/adapter/rexml.rb', line 288
def (node)
node.string
end
|
.create_document(_native_doc = nil) ⇒ Object
24
25
26
|
# File 'lib/moxml/adapter/rexml.rb', line 24
def create_document(_native_doc = nil)
::REXML::Document.new
end
|
.create_native_cdata(content) ⇒ Object
36
37
38
|
# File 'lib/moxml/adapter/rexml.rb', line 36
def create_native_cdata(content)
::REXML::CData.new(content.to_s)
end
|
40
41
42
|
# File 'lib/moxml/adapter/rexml.rb', line 40
def (content)
::REXML::Comment.new(content.to_s)
end
|
.create_native_declaration(version, encoding, standalone) ⇒ Object
49
50
51
|
# File 'lib/moxml/adapter/rexml.rb', line 49
def create_native_declaration(version, encoding, standalone)
::REXML::XMLDecl.new(version, encoding&.downcase, standalone)
end
|
.create_native_doctype(name, external_id, system_id) ⇒ Object
53
54
55
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/moxml/adapter/rexml.rb', line 53
def create_native_doctype(name, external_id, system_id)
return nil unless name
parts = [name]
if external_id
parts.concat(["PUBLIC", %("#{external_id}")])
parts << %("#{system_id}") if system_id
elsif system_id
parts.concat(["SYSTEM", %("#{system_id}")])
end
::REXML::DocType.new(parts.join(" "))
end
|
.create_native_element(name) ⇒ Object
28
29
30
|
# File 'lib/moxml/adapter/rexml.rb', line 28
def create_native_element(name)
::REXML::Element.new(name.to_s)
end
|
.create_native_namespace(element, prefix, uri) ⇒ Object
add a namespace definition, keep the element name unchanged
348
349
350
351
|
# File 'lib/moxml/adapter/rexml.rb', line 348
def create_native_namespace(element, prefix, uri)
element.add_namespace(prefix.to_s, uri)
::REXML::Attribute.new(prefix.to_s, uri, element)
end
|
.create_native_processing_instruction(target, content) ⇒ Object
44
45
46
47
|
# File 'lib/moxml/adapter/rexml.rb', line 44
def create_native_processing_instruction(target, content)
::REXML::Instruction.new(target.to_s.dup, content.to_s.dup)
end
|
.create_native_text(content) ⇒ Object
32
33
34
|
# File 'lib/moxml/adapter/rexml.rb', line 32
def create_native_text(content)
::REXML::Text.new(content.to_s, true, nil)
end
|
.declaration_attribute(node, name) ⇒ Object
266
267
268
269
270
271
272
273
274
275
|
# File 'lib/moxml/adapter/rexml.rb', line 266
def declaration_attribute(node, name)
case name
when "version"
node.version
when "encoding"
node.encoding
when "standalone"
node.standalone
end
end
|
.document(node) ⇒ Object
179
180
181
|
# File 'lib/moxml/adapter/rexml.rb', line 179
def document(node)
node.document
end
|
.duplicate_node(node) ⇒ Object
107
108
109
110
111
|
# File 'lib/moxml/adapter/rexml.rb', line 107
def duplicate_node(node)
Marshal.load(Marshal.dump(node))
end
|
.get_attribute(element, name) ⇒ Object
217
218
219
|
# File 'lib/moxml/adapter/rexml.rb', line 217
def get_attribute(element, name)
element.attributes.get_attribute(name)
end
|
.get_attribute_value(element, name) ⇒ Object
221
222
223
|
# File 'lib/moxml/adapter/rexml.rb', line 221
def get_attribute_value(element, name)
element.attributes[name]
end
|
.inner_text(node) ⇒ Object
327
328
329
330
331
332
333
|
# File 'lib/moxml/adapter/rexml.rb', line 327
def inner_text(node)
text_children = node.children
.select { _1.is_a?(::REXML::Text) }
.uniq(&:object_id)
text_children.map(&:value).join
end
|
.namespace(node) ⇒ Object
370
371
372
373
374
375
376
377
|
# File 'lib/moxml/adapter/rexml.rb', line 370
def namespace(node)
prefix = node.prefix
uri = node.namespace(prefix)
return if prefix.to_s.empty? && uri.to_s.empty?
owner = node.is_a?(::REXML::Attribute) ? node.element : node
::REXML::Attribute.new(prefix, uri, owner)
end
|
.namespace_definitions(node) ⇒ Object
379
380
381
382
383
|
# File 'lib/moxml/adapter/rexml.rb', line 379
def namespace_definitions(node)
node.namespaces.map do |prefix, uri|
::REXML::Attribute.new(prefix.to_s, uri, node)
end
end
|
.namespace_prefix(node) ⇒ Object
362
363
364
|
# File 'lib/moxml/adapter/rexml.rb', line 362
def namespace_prefix(node)
node.name unless node.name == "xmlns"
end
|
.namespace_uri(node) ⇒ Object
366
367
368
|
# File 'lib/moxml/adapter/rexml.rb', line 366
def namespace_uri(node)
node.value
end
|
.next_sibling(node) ⇒ Object
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
# File 'lib/moxml/adapter/rexml.rb', line 131
def next_sibling(node)
current = node.next_sibling
seen = Set.new
while current
if current.is_a?(::REXML::Text) && current.to_s.strip.empty?
current = current.next_sibling
next
end
if seen.include?(current.object_id)
current = current.next_sibling
next
end
seen.add(current.object_id)
break
end
current
end
|
.node_name(node) ⇒ Object
96
97
98
99
100
101
102
103
104
105
|
# File 'lib/moxml/adapter/rexml.rb', line 96
def node_name(node)
case node
when ::REXML::Element, ::REXML::DocType
node.name
when ::REXML::XMLDecl
"xml"
when ::REXML::Instruction
node.target
end
end
|
.node_type(node) ⇒ Object
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/moxml/adapter/rexml.rb', line 71
def node_type(node)
case node
when ::REXML::Document then :document
when ::REXML::Element then :element
when ::REXML::CData then :cdata
when ::REXML::Text then :text
when ::REXML::Comment then :comment
when ::REXML::Attribute then :attribute when ::REXML::Namespace then :namespace when ::REXML::Instruction then :processing_instruction
when ::REXML::DocType then :doctype
when ::REXML::XMLDecl then :declaration
else :unknown
end
end
|
.parent(node) ⇒ Object
127
128
129
|
# File 'lib/moxml/adapter/rexml.rb', line 127
def parent(node)
node.parent
end
|
.parse(xml, options = {}) ⇒ Object
13
14
15
16
17
18
19
20
21
22
|
# File 'lib/moxml/adapter/rexml.rb', line 13
def parse(xml, options = {})
native_doc = begin
::REXML::Document.new(xml)
rescue ::REXML::ParseException => e
raise Moxml::ParseError.new(e.message, line: e.line) if options[:strict]
create_document
end
DocumentBuilder.new(Context.new(:rexml)).build(native_doc)
end
|
.prepare_xpath_namespaces(node) ⇒ Object
not used at the moment but may be useful when the xpath is upgraded to work with namespaces
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
|
# File 'lib/moxml/adapter/rexml.rb', line 387
def prepare_xpath_namespaces(node)
ns = {}
all_ns = namespace_definitions(node)
all_ns.each do |prefix, uri|
if prefix.to_s.empty?
ns["xmlns"] = uri
else
ns[prefix] = uri
end
end
ns
end
|
.previous_sibling(node) ⇒ Object
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
# File 'lib/moxml/adapter/rexml.rb', line 155
def previous_sibling(node)
current = node.previous_sibling
seen = Set.new
while current
if current.is_a?(::REXML::Text) && current.to_s.strip.empty?
current = current.previous_sibling
next
end
if seen.include?(current.object_id)
current = current.previous_sibling
next
end
seen.add(current.object_id)
break
end
current
end
|
.processing_instruction_content(node) ⇒ Object
308
309
310
|
# File 'lib/moxml/adapter/rexml.rb', line 308
def processing_instruction_content(node)
node.content
end
|
.processing_instruction_target(node) ⇒ Object
304
305
306
|
# File 'lib/moxml/adapter/rexml.rb', line 304
def processing_instruction_target(node)
node.target
end
|
.remove(node) ⇒ Object
253
254
255
|
# File 'lib/moxml/adapter/rexml.rb', line 253
def remove(node)
node.remove
end
|
.remove_attribute(element, name) ⇒ Object
225
226
227
|
# File 'lib/moxml/adapter/rexml.rb', line 225
def remove_attribute(element, name)
element.delete_attribute(name.to_s)
end
|
.replace(node, new_node) ⇒ Object
257
258
259
|
# File 'lib/moxml/adapter/rexml.rb', line 257
def replace(node, new_node)
node.replace_with(new_node)
end
|
.replace_children(element, children) ⇒ Object
261
262
263
264
|
# File 'lib/moxml/adapter/rexml.rb', line 261
def replace_children(element, children)
element.children.each(&:remove)
children.each { |child| element.add(child) }
end
|
.root(document) ⇒ Object
183
184
185
|
# File 'lib/moxml/adapter/rexml.rb', line 183
def root(document)
document.root
end
|
.serialize(node, options = {}) ⇒ Object
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
|
# File 'lib/moxml/adapter/rexml.rb', line 416
def serialize(node, options = {})
output = String.new
if node.is_a?(::REXML::Document)
decl = node.xml_decl || ::REXML::XMLDecl.new("1.0", options[:encoding] || "UTF-8")
decl.encoding = options[:encoding] if options[:encoding]
output << "<?xml"
output << %( version="#{decl.version}") if decl.version
output << %( encoding="#{decl.encoding}") if decl.encoding
output << %( standalone="#{decl.standalone}") if decl.standalone
output << "?>"
if node.doctype
node.doctype.write(output)
end
node.children.each do |child|
next unless [::REXML::Instruction, ::REXML::CData, ::REXML::Comment, ::REXML::Text].include?(child.class)
write_with_formatter(child, output, options[:indent] || 2)
end
write_with_formatter(node.root, output, options[:indent] || 2) if node.root
else
write_with_formatter(node, output, options[:indent] || 2)
end
output.strip
end
|
.set_attribute(element, name, value) ⇒ Object
199
200
201
202
|
# File 'lib/moxml/adapter/rexml.rb', line 199
def set_attribute(element, name, value)
element.attributes[name&.to_s] = value
::REXML::Attribute.new(name&.to_s, value.to_s, element)
end
|
.set_attribute_name(attribute, name) ⇒ Object
204
205
206
207
208
209
210
211
|
# File 'lib/moxml/adapter/rexml.rb', line 204
def set_attribute_name(attribute, name)
old_name = attribute.expanded_name
attribute.name = name
element = attribute.element
element.attributes.delete(old_name)
element.attributes << attribute
end
|
.set_attribute_value(attribute, value) ⇒ Object
213
214
215
|
# File 'lib/moxml/adapter/rexml.rb', line 213
def set_attribute_value(attribute, value)
attribute.normalized = value
end
|
.set_cdata_content(node, content) ⇒ Object
300
301
302
|
# File 'lib/moxml/adapter/rexml.rb', line 300
def set_cdata_content(node, content)
node.value = content.to_s
end
|
292
293
294
|
# File 'lib/moxml/adapter/rexml.rb', line 292
def (node, content)
node.string = content.to_s
end
|
.set_declaration_attribute(node, name, value) ⇒ Object
277
278
279
280
281
282
283
284
285
286
|
# File 'lib/moxml/adapter/rexml.rb', line 277
def set_declaration_attribute(node, name, value)
case name
when "version"
node.version = value
when "encoding"
node.encoding = value
when "standalone"
node.standalone = value
end
end
|
.set_namespace(element, ns) ⇒ Object
add a namespace prefix to the element name AND a namespace definition
354
355
356
357
358
359
360
|
# File 'lib/moxml/adapter/rexml.rb', line 354
def set_namespace(element, ns)
prefix = ns.name.to_s.empty? ? "xmlns" : ns.name.to_s
element.add_namespace(prefix, ns.value) if element.respond_to?(:add_namespace)
element.name = "#{prefix}:#{element.name}"
owner = element.is_a?(::REXML::Attribute) ? element.element : element
::REXML::Attribute.new(prefix, ns.value, owner)
end
|
.set_node_name(node, name) ⇒ Object
87
88
89
90
91
92
93
94
|
# File 'lib/moxml/adapter/rexml.rb', line 87
def set_node_name(node, name)
case node
when ::REXML::Element
node.name = name.to_s
when ::REXML::Instruction
node.target = name.to_s
end
end
|
.set_processing_instruction_content(node, content) ⇒ Object
312
313
314
|
# File 'lib/moxml/adapter/rexml.rb', line 312
def set_processing_instruction_content(node, content)
node.content = content.to_s
end
|
.set_root(doc, element) ⇒ Object
67
68
69
|
# File 'lib/moxml/adapter/rexml.rb', line 67
def set_root(doc, element)
doc.add_element(element)
end
|
.set_text_content(node, content) ⇒ Object
335
336
337
338
339
340
341
342
343
344
345
|
# File 'lib/moxml/adapter/rexml.rb', line 335
def set_text_content(node, content)
case node
when ::REXML::Text, ::REXML::CData
node.value = content.to_s
when ::REXML::Element
node.texts.each(&:remove)
node.add_text(content.to_s)
end
end
|
.text_content(node) ⇒ Object
316
317
318
319
320
321
322
323
324
325
|
# File 'lib/moxml/adapter/rexml.rb', line 316
def text_content(node)
case node
when ::REXML::Text, ::REXML::CData
node.value.to_s
when ::REXML::Element
text_nodes = node.texts.uniq(&:object_id)
text_nodes.map(&:value).join
end
end
|
.xpath(node, expression, _namespaces = {}) ⇒ Object
405
406
407
408
409
|
# File 'lib/moxml/adapter/rexml.rb', line 405
def xpath(node, expression, _namespaces = {})
node.get_elements(expression).to_a
rescue ::REXML::ParseException => e
raise Moxml::XPathError, e.message
end
|