Class: Taurus::XML::Element

Inherits:
Node
  • Object
show all
Defined in:
lib/taurus/xml/element.rb

Instance Attribute Summary

Attributes inherited from Node

#c_ptr, #document

Instance Method Summary collapse

Methods inherited from Node

#<=>, #==, #cdata?, #child, #children, #comment?, #css_path, #element?, #element_children, #first_element_child, #initialize, #inspect, #last_element_child, #line, #next_element, #next_sibling, #parent, #path, #previous_element, #previous_sibling, #processing_instruction?, #text?, #traverse, #type, #unlink, wrap

Methods included from Searchable

#at, #at_css, #at_xpath, #css, #search, #xpath

Constructor Details

This class inherits a constructor from Taurus::XML::Node

Instance Method Details

#<<Object

Raises:



91
92
93
94
95
96
# File 'lib/taurus/xml/element.rb', line 91

def add_child(node)
  status = Taurus::XML::FFI.taurus_element_append_child(@c_ptr, node.c_ptr)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  node
end

#[](key) ⇒ Object Also known as: attr, get_attribute



28
29
30
# File 'lib/taurus/xml/element.rb', line 28

def [](key)
  Taurus::XML::FFI.taurus_element_attribute(@c_ptr, key.to_s)
end

#[]=(key, value) ⇒ Object Also known as: set_attribute

Raises:



34
35
36
37
38
39
# File 'lib/taurus/xml/element.rb', line 34

def []=(key, value)
  status = Taurus::XML::FFI.taurus_element_set_attribute(@c_ptr, key.to_s, value.to_s)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  value
end

#add_child(node_or_markup) ⇒ Object

Raises:



85
86
87
88
89
90
# File 'lib/taurus/xml/element.rb', line 85

def add_child(node)
  status = Taurus::XML::FFI.taurus_element_append_child(@c_ptr, node.c_ptr)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  node
end

#add_namespace_definition(prefix, href) ⇒ Object Also known as: add_namespace

Raises:



256
257
258
259
260
261
262
# File 'lib/taurus/xml/element.rb', line 256

def add_namespace_definition(prefix, href)
  status = Taurus::XML::FFI.taurus_element_add_namespace_definition(
    @c_ptr, prefix.to_s, href.to_s)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  Taurus::XML::Namespace.new(self, href.to_s, prefix: prefix.nil? ? nil : prefix.to_s)
end

#add_next_sibling(node) ⇒ Object

Raises:



100
101
102
103
104
105
# File 'lib/taurus/xml/element.rb', line 100

def add_next_sibling(node)
  status = Taurus::XML::FFI.taurus_element_insert_after(@c_ptr, node.c_ptr)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  node
end

#add_previous_sibling(node) ⇒ Object

Raises:



107
108
109
110
111
112
# File 'lib/taurus/xml/element.rb', line 107

def add_previous_sibling(node)
  status = Taurus::XML::FFI.taurus_element_insert_before(@c_ptr, node.c_ptr)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  node
end

#attribute_nodesObject



76
77
78
79
80
81
82
83
# File 'lib/taurus/xml/element.rb', line 76

def attribute_nodes
  count = Taurus::XML::FFI.taurus_element_attribute_count(@c_ptr)
  count.times.map do |i|
    name = Taurus::XML::FFI.taurus_element_attribute_name_at(@c_ptr, i)
    value = Taurus::XML::FFI.taurus_element_attribute_value_at(@c_ptr, i)
    Taurus::XML::Attr.new(name, value, self)
  end
end

#attributesObject



65
66
67
68
69
70
71
72
73
74
# File 'lib/taurus/xml/element.rb', line 65

def attributes
  count = Taurus::XML::FFI.taurus_element_attribute_count(@c_ptr)
  result = {}
  count.times do |i|
    name = Taurus::XML::FFI.taurus_element_attribute_name_at(@c_ptr, i)
    value = Taurus::XML::FFI.taurus_element_attribute_value_at(@c_ptr, i)
    result[name] = Taurus::XML::Attr.new(name, value, self)
  end
  result
end

#canonicalize(version = Taurus::XML::FFI::C14N_1_0, inclusive_namespaces = nil, with_comments: false, exclusive: false, mode: nil) ⇒ Object Also known as: c14n



240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/taurus/xml/element.rb', line 240

def canonicalize(version = Taurus::XML::FFI::C14N_1_0,
                 inclusive_namespaces = nil,
                 with_comments: false,
                 exclusive: false,
                 mode: nil)
  resolved_mode = mode || (exclusive ? Taurus::XML::FFI::C14N_MODE_EXCLUSIVE
                                     : Taurus::XML::FFI::C14N_MODE_CANONICAL)
  ns_ptr, _anchor = Taurus::XML.c14n_build_ns_pointer(inclusive_namespaces)
  flags = with_comments ? 1 : 0
  str_ptr = Taurus::XML::FFI.taurus_c14n_canonicalize_subtree_ex(
    @c_ptr, version, resolved_mode, ns_ptr, flags)
  return "" if str_ptr.null?
  str_ptr.read_string.tap { Taurus::XML::FFI.taurus_free_string(str_ptr) }
end

#children=(node_or_nodes) ⇒ Object



121
122
123
124
125
# File 'lib/taurus/xml/element.rb', line 121

def children=(node_or_nodes)
  # Remove existing children, then attach the new ones in source order.
  Taurus::XML::FFI.taurus_element_remove_children(@c_ptr)
  Array(node_or_nodes).each { |n| add_child(n) }
end

#contentObject



17
18
19
# File 'lib/taurus/xml/element.rb', line 17

def content
  Taurus::XML::FFI.taurus_element_text(@c_ptr)
end

#content=(new_content) ⇒ Object

Raises:



21
22
23
24
25
26
# File 'lib/taurus/xml/element.rb', line 21

def content=(new_content)
  status = Taurus::XML::FFI.taurus_element_set_text(@c_ptr, new_content.to_s)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  new_content
end

#default_namespace=(href) ⇒ Object

Raises:



265
266
267
268
269
270
# File 'lib/taurus/xml/element.rb', line 265

def default_namespace=(href)
  status = Taurus::XML::FFI.taurus_element_set_default_namespace(@c_ptr, href.to_s)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  href
end

#dupObject Also known as: clone

Raises:



169
170
171
172
173
# File 'lib/taurus/xml/element.rb', line 169

def dup
  copy_ptr = Taurus::XML::FFI.taurus_element_copy(@c_ptr, @document.c_ptr)
  raise Taurus::XML::Error, "taurus_element_copy failed" if copy_ptr.null?
  Taurus::XML::Element.new(copy_ptr, @document)
end

#key?(name) ⇒ Boolean Also known as: has_attribute?

Returns:

  • (Boolean)


42
43
44
# File 'lib/taurus/xml/element.rb', line 42

def key?(name)
  !Taurus::XML::FFI.taurus_element_attribute(@c_ptr, name.to_s).nil?
end

#keysObject



55
56
57
58
# File 'lib/taurus/xml/element.rb', line 55

def keys
  count = Taurus::XML::FFI.taurus_element_attribute_count(@c_ptr)
  count.times.map { |i| Taurus::XML::FFI.taurus_element_attribute_name_at(@c_ptr, i) }
end

#nameObject Also known as: node_name



4
5
6
# File 'lib/taurus/xml/element.rb', line 4

def name
  Taurus::XML::FFI.taurus_element_name(@c_ptr)
end

#name=(new_name) ⇒ Object Also known as: node_name=

Raises:



9
10
11
12
13
14
# File 'lib/taurus/xml/element.rb', line 9

def name=(new_name)
  status = Taurus::XML::FFI.taurus_element_set_name(@c_ptr, new_name)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  new_name
end

#namespaceObject



198
199
200
201
202
# File 'lib/taurus/xml/element.rb', line 198

def namespace
  uri = Taurus::XML::FFI.taurus_element_namespace(@c_ptr)
  return nil if uri.nil? || uri.empty?
  Taurus::XML::Namespace.new(self, uri)
end

#namespace_definitionsObject



204
205
206
207
208
209
210
211
# File 'lib/taurus/xml/element.rb', line 204

def namespace_definitions
  count = Taurus::XML::FFI.taurus_element_namespace_count(@c_ptr)
  count.times.map do |i|
    prefix = Taurus::XML::FFI.taurus_element_namespace_decl_prefix(@c_ptr, i)
    uri = Taurus::XML::FFI.taurus_element_namespace_decl_uri(@c_ptr, i)
    Taurus::XML::Namespace.new(self, uri, prefix: prefix)
  end
end

#namespacesObject



213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/taurus/xml/element.rb', line 213

def namespaces
  scopes = {}
  node = self
  while node.is_a?(Taurus::XML::Element)
    node.namespace_definitions.each do |ns|
      key = ns.prefix ? "xmlns:#{ns.prefix}" : "xmlns"
      scopes[key] ||= ns.href
    end
    node = node.parent
  end
  scopes
end

#prepend_child(node) ⇒ Object

Raises:



93
94
95
96
97
98
# File 'lib/taurus/xml/element.rb', line 93

def prepend_child(node)
  status = Taurus::XML::FFI.taurus_element_prepend_child(@c_ptr, node.c_ptr)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  node
end

#remove_attribute(name) ⇒ Object Also known as: delete

Raises:



47
48
49
50
51
52
# File 'lib/taurus/xml/element.rb', line 47

def remove_attribute(name)
  status = Taurus::XML::FFI.taurus_element_remove_attribute(@c_ptr, name.to_s)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  self
end

#remove_child(node) ⇒ Object

Raises:



114
115
116
117
118
119
# File 'lib/taurus/xml/element.rb', line 114

def remove_child(node)
  status = Taurus::XML::FFI.taurus_element_remove_child(@c_ptr, node.c_ptr)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  node
end

#remove_namespace_definition(prefix) ⇒ Object

Raises:



272
273
274
275
276
277
# File 'lib/taurus/xml/element.rb', line 272

def remove_namespace_definition(prefix)
  status = Taurus::XML::FFI.taurus_element_remove_namespace_definition(@c_ptr, prefix.to_s)
  raise Taurus::XML::Error,
    Taurus::XML::FFI.taurus_status_string(status) unless status == Taurus::XML::FFI::TAURUS_OK
  self
end

#replace(new_node) ⇒ Object

Replace this element with new_node in the parent's child list. new_node must belong to the same document. Returns new_node.

Raises:



129
130
131
132
133
134
135
# File 'lib/taurus/xml/element.rb', line 129

def replace(new_node)
  parent = self.parent
  raise Taurus::XML::Error, "cannot replace a node with no parent" unless parent
  add_next_sibling(new_node)
  parent.remove_child(self)
  new_node
end

#swap(new_node) ⇒ Object

Like #replace but returns self for chaining.



138
139
140
141
# File 'lib/taurus/xml/element.rb', line 138

def swap(new_node)
  replace(new_node)
  self
end

#to_xml(indent: 0, no_decl: false, encoding: nil) ⇒ Object



226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/taurus/xml/element.rb', line 226

def to_xml(indent: 0, no_decl: false, encoding: nil)
  opts = Taurus::XML::FFI::SerializeOptions.new
  opts[:indent] = indent.to_i
  opts[:xml_declaration] = no_decl ? 0 : 1
  enc_ptr = nil
  if encoding
    enc_ptr = ::FFI::MemoryPointer.from_string(encoding.to_s)
    opts[:encoding] = enc_ptr
  end
  str_ptr = Taurus::XML::FFI.taurus_element_serialize(@c_ptr, opts.pointer)
  return "" if str_ptr.null?
  str_ptr.read_string.tap { Taurus::XML::FFI.taurus_free_string(str_ptr) }
end

#valuesObject



60
61
62
63
# File 'lib/taurus/xml/element.rb', line 60

def values
  count = Taurus::XML::FFI.taurus_element_attribute_count(@c_ptr)
  count.times.map { |i| Taurus::XML::FFI.taurus_element_attribute_value_at(@c_ptr, i) }
end

#wrap(node_or_markup) ⇒ Object

Wrap this element in a new element parsed from markup or a dup of node. The wrapper takes this element's place in the tree, and this element becomes its only child. Returns self for chaining.

Raises:



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/taurus/xml/element.rb', line 146

def wrap(node_or_markup)
  wrapper =
    case node_or_markup
    when Taurus::XML::Element then node_or_markup.dup
    when String
      frag_doc = Taurus::XML::Document.parse(node_or_markup)
      frag_doc.root or raise Taurus::XML::Error, "wrap markup has no root element"
    else
      raise ArgumentError, "wrap expects a String or Element, got #{node_or_markup.class}"
    end

  parent = self.parent
  raise Taurus::XML::Error, "cannot wrap a node with no parent" unless parent

  # Insert wrapper at self's position, then move self into wrapper.
  # add_child moves self (unlinks from old parent first), so no explicit
  # remove_child needed — and trying to remove after the move corrupts
  # the C tree (libtaurus silently handles non-child args badly).
  add_next_sibling(wrapper)
  wrapper.add_child(self)
  self
end