Class: Moxml::Adapter::Ox

Inherits:
Base
  • Object
show all
Defined in:
lib/moxml/adapter/ox.rb

Class Method Summary collapse

Methods inherited from Base

create_cdata, create_comment, create_declaration, create_doctype, create_element, create_namespace, create_processing_instruction, create_text, duplicate_node, set_attribute_name, set_attribute_value

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



186
187
188
189
190
# File 'lib/moxml/adapter/ox.rb', line 186

def add_child(element, child)
  element.nodes ||= []
  puts "Add child #{child} for #{element.name}: #{element.nodes.count}"
  element.nodes << child
end

.add_next_sibling(node, sibling) ⇒ Object



199
200
201
202
203
204
# File 'lib/moxml/adapter/ox.rb', line 199

def add_next_sibling(node, sibling)
  return unless parent(node)

  idx = node.parent.nodes.index(node)
  node.parent.nodes.insert(idx + 1, sibling) if idx
end

.add_previous_sibling(node, sibling) ⇒ Object



192
193
194
195
196
197
# File 'lib/moxml/adapter/ox.rb', line 192

def add_previous_sibling(node, sibling)
  return unless parent(node)

  idx = node.parent.nodes.index(node)
  node.parent.nodes.insert(idx, sibling) if idx
end

.at_xpath(node, expression, namespaces = {}) ⇒ Object



281
282
283
284
285
286
# File 'lib/moxml/adapter/ox.rb', line 281

def at_xpath(node, expression, namespaces = {})
  traverse(node) do |n|
    return n if matches_xpath?(n, expression, namespaces)
  end
  nil
end

.attributes(element) ⇒ Object



163
164
165
166
167
# File 'lib/moxml/adapter/ox.rb', line 163

def attributes(element)
  return {} unless element.respond_to?(:attributes) && element.attributes

  element.attributes.reject { |k, _| k.start_with?("xmlns") }
end

.cdata_content(node) ⇒ Object



237
238
239
# File 'lib/moxml/adapter/ox.rb', line 237

def cdata_content(node)
  node.value.to_s
end

.children(node) ⇒ Object



127
128
129
130
131
# File 'lib/moxml/adapter/ox.rb', line 127

def children(node)
  return [] unless node.respond_to?(:nodes)

  node.nodes || []
end

.comment_content(node) ⇒ Object



245
246
247
# File 'lib/moxml/adapter/ox.rb', line 245

def comment_content(node)
  node.value.to_s
end

.create_documentObject



33
34
35
# File 'lib/moxml/adapter/ox.rb', line 33

def create_document
  ::Ox::Document.new
end

.create_native_cdata(content) ⇒ Object



47
48
49
# File 'lib/moxml/adapter/ox.rb', line 47

def create_native_cdata(content)
  ::Ox::CData.new(content)
end

.create_native_comment(content) ⇒ Object



51
52
53
# File 'lib/moxml/adapter/ox.rb', line 51

def create_native_comment(content)
  ::Ox::Comment.new(content)
end

.create_native_declaration(version, encoding, standalone) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/moxml/adapter/ox.rb', line 68

def create_native_declaration(version, encoding, standalone)
  doc = ::Ox::Document.new
  doc.version = version
  doc.encoding = encoding
  doc.standalone = standalone
  doc
end

.create_native_declaration2(version, encoding, standalone) ⇒ Object

TODO: compare to create_native_declaration



62
63
64
65
66
# File 'lib/moxml/adapter/ox.rb', line 62

def create_native_declaration2(version, encoding, standalone)
  inst = ::Ox::Instruct.new("xml")
  inst.value = build_declaration_attrs(version, encoding, standalone)
  inst
end

.create_native_element(name) ⇒ Object



37
38
39
40
41
# File 'lib/moxml/adapter/ox.rb', line 37

def create_native_element(name)
  element = ::Ox::Element.new(name)
  element.instance_variable_set(:@attributes, {})
  element
end

.create_native_namespace(element, prefix, uri) ⇒ Object



76
77
78
79
80
81
# File 'lib/moxml/adapter/ox.rb', line 76

def create_native_namespace(element, prefix, uri)
  element.attributes ||= {}
  attr_name = prefix ? "xmlns:#{prefix}" : "xmlns"
  element.attributes[attr_name] = uri
  [prefix, uri]
end

.create_native_processing_instruction(target, content) ⇒ Object



55
56
57
58
59
# File 'lib/moxml/adapter/ox.rb', line 55

def create_native_processing_instruction(target, content)
  inst = ::Ox::Instruction.new(target)
  inst.value = content
  inst
end

.create_native_text(content) ⇒ Object



43
44
45
# File 'lib/moxml/adapter/ox.rb', line 43

def create_native_text(content)
  content
end

.document(node) ⇒ Object



153
154
155
156
157
# File 'lib/moxml/adapter/ox.rb', line 153

def document(node)
  current = node
  current = parent(current) while parent(current)
  current
end

.get_attribute(element, name) ⇒ Object



174
175
176
177
178
# File 'lib/moxml/adapter/ox.rb', line 174

def get_attribute(element, name)
  return nil unless element.respond_to?(:attributes) && element.attributes

  element.attributes[name.to_s]
end

.namespace(element) ⇒ Object



90
91
92
93
94
95
96
97
98
# File 'lib/moxml/adapter/ox.rb', line 90

def namespace(element)
  return nil unless element.attributes

  xmlns_attr = element.attributes.find { |k, _| k.start_with?("xmlns:") || k == "xmlns" }
  return nil unless xmlns_attr

  prefix = xmlns_attr[0] == "xmlns" ? nil : xmlns_attr[0].sub("xmlns:", "")
  [prefix, xmlns_attr[1]]
end

.namespace_definitions(node) ⇒ Object



261
262
263
264
265
266
267
268
269
270
# File 'lib/moxml/adapter/ox.rb', line 261

def namespace_definitions(node)
  return [] unless node.respond_to?(:attributes) && node.attributes

  node.attributes.each_with_object([]) do |(name, value), namespaces|
    next unless name.start_with?("xmlns")

    prefix = name == "xmlns" ? nil : name.sub("xmlns:", "")
    namespaces << [prefix, value]
  end
end

.next_sibling(node) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/moxml/adapter/ox.rb', line 137

def next_sibling(node)
  return unless (parent = parent(node))

  siblings = parent.nodes
  idx = siblings.index(node)
  idx ? siblings[idx + 1] : nil
end

.node_name(node) ⇒ Object



116
117
118
119
120
# File 'lib/moxml/adapter/ox.rb', line 116

def node_name(node)
  node.value
rescue StandardError
  node.name
end

.node_type(node) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/moxml/adapter/ox.rb', line 104

def node_type(node)
  case node
  when ::Ox::Document then :document
  when String then :text
  when ::Ox::CData then :cdata
  when ::Ox::Comment then :comment
  when ::Ox::Instruct then :processing_instruction
  when ::Ox::Element then :element
  else :unknown
  end
end

.parent(node) ⇒ Object



133
134
135
# File 'lib/moxml/adapter/ox.rb', line 133

def parent(node)
  node.parent if node.respond_to?(:parent)
end

.parse(xml, _options = {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/moxml/adapter/ox.rb', line 14

def parse(xml, _options = {})
  native_doc = begin
    result = ::Ox.parse(xml)

    # result can be either Document or Element
    if result.is_a?(::Ox::Document)
      result
    else
      doc = ::Ox::Document.new
      doc << result
      doc
    end
  rescue ::Ox::ParseError => e
    raise Moxml::ParseError, e.message
  end

  DocumentBuilder.new(Context.new(:ox)).build(native_doc)
end

.previous_sibling(node) ⇒ Object



145
146
147
148
149
150
151
# File 'lib/moxml/adapter/ox.rb', line 145

def previous_sibling(node)
  return unless (parent = parent(node))

  siblings = parent.nodes
  idx = siblings.index(node)
  idx&.positive? ? siblings[idx - 1] : nil
end

.processing_instruction_content(node) ⇒ Object



253
254
255
# File 'lib/moxml/adapter/ox.rb', line 253

def processing_instruction_content(node)
  node.value.to_s
end

.processing_instruction_target(node) ⇒ Object



100
101
102
# File 'lib/moxml/adapter/ox.rb', line 100

def processing_instruction_target(node)
  node.name
end

.remove(node) ⇒ Object



206
207
208
209
210
# File 'lib/moxml/adapter/ox.rb', line 206

def remove(node)
  return unless parent(node)

  node.parent.nodes.delete(node)
end

.remove_attribute(element, name) ⇒ Object



180
181
182
183
184
# File 'lib/moxml/adapter/ox.rb', line 180

def remove_attribute(element, name)
  return unless element.respond_to?(:attributes) && element.attributes

  element.attributes.delete(name.to_s)
end

.replace(node, new_node) ⇒ Object



212
213
214
215
216
217
# File 'lib/moxml/adapter/ox.rb', line 212

def replace(node, new_node)
  return unless parent(node)

  idx = node.parent.nodes.index(node)
  node.parent.nodes[idx] = new_node if idx
end

.replace_children(node, new_children) ⇒ Object



219
220
221
222
223
# File 'lib/moxml/adapter/ox.rb', line 219

def replace_children(node, new_children)
  node.remove_children_by_path("*")
  new_children.each { |child| node << child }
  node
end

.root(document) ⇒ Object



159
160
161
# File 'lib/moxml/adapter/ox.rb', line 159

def root(document)
  document.nodes&.find { |node| node.is_a?(::Ox::Element) }
end

.serialize(node, options = {}) ⇒ Object



288
289
290
291
292
293
294
295
296
# File 'lib/moxml/adapter/ox.rb', line 288

def serialize(node, options = {})
  ox_options = {
    indent: options[:indent] || -1,
    with_xml: true,
    with_instructions: true,
    encoding: options[:encoding]
  }
  ::Ox.dump(node, ox_options)
end

.set_attribute(element, name, value) ⇒ Object



169
170
171
172
# File 'lib/moxml/adapter/ox.rb', line 169

def set_attribute(element, name, value)
  element.attributes ||= {}
  element.attributes[name.to_s] = value.to_s
end

.set_cdata_content(node, content) ⇒ Object



241
242
243
# File 'lib/moxml/adapter/ox.rb', line 241

def set_cdata_content(node, content)
  node.value = content.to_s
end

.set_comment_content(node, content) ⇒ Object



249
250
251
# File 'lib/moxml/adapter/ox.rb', line 249

def set_comment_content(node, content)
  node.value = content.to_s
end

.set_namespace(element, ns) ⇒ Object



83
84
85
86
87
88
# File 'lib/moxml/adapter/ox.rb', line 83

def set_namespace(element, ns)
  prefix, uri = ns
  element.attributes ||= {}
  attr_name = prefix ? "xmlns:#{prefix}" : "xmlns"
  element.attributes[attr_name] = uri
end

.set_node_name(node, name) ⇒ Object



122
123
124
125
# File 'lib/moxml/adapter/ox.rb', line 122

def set_node_name(node, name)
  node.value = name if node.respond_to?(:value=)
  node.name = name if node.respond_to?(:name=)
end

.set_processing_instruction_content(node, content) ⇒ Object



257
258
259
# File 'lib/moxml/adapter/ox.rb', line 257

def set_processing_instruction_content(node, content)
  node.value = content.to_s
end

.set_root(doc, element) ⇒ Object



10
11
12
# File 'lib/moxml/adapter/ox.rb', line 10

def set_root(doc, element)
  replace_children(doc, [element])
end

.set_text_content(node, content) ⇒ Object



229
230
231
232
233
234
235
# File 'lib/moxml/adapter/ox.rb', line 229

def set_text_content(node, content)
  if node.is_a?(String)
    node.replace(content.to_s)
  else
    node.value = content.to_s
  end
end

.text_content(node) ⇒ Object



225
226
227
# File 'lib/moxml/adapter/ox.rb', line 225

def text_content(node)
  node.is_a?(String) ? node : node.value.to_s
end

.xpath(node, expression, namespaces = {}) ⇒ Object



272
273
274
275
276
277
278
279
# File 'lib/moxml/adapter/ox.rb', line 272

def xpath(node, expression, namespaces = {})
  # Ox doesn't support XPath, implement basic path matching
  results = []
  traverse(node) do |n|
    results << n if matches_xpath?(n, expression, namespaces)
  end
  results
end