Class: Leptris::XML::Document
- Inherits:
-
Object
- Object
- Leptris::XML::Document
show all
- Includes:
- Searchable
- Defined in:
- lib/leptris/xml/document.rb
Defined Under Namespace
Classes: Freed
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#add_pi(target, data = "") ⇒ Object
Append a document-level processing instruction.
-
#canonicalize(version = Leptris::XML::FFI::C14N_1_0, inclusive_namespaces = nil, with_comments: false, exclusive: false, mode: nil) ⇒ Object
(also: #c14n)
-
#create_cdata(content) ⇒ Object
-
#create_comment(content) ⇒ Object
-
#create_element(name) ⇒ Object
-
#create_processing_instruction(target, data = "") ⇒ Object
-
#create_text_node(content) ⇒ Object
-
#doctype ⇒ Object
(also: #internal_subset)
-
#document ⇒ Object
-
#dup ⇒ Object
(also: #clone)
-
#encoding ⇒ Object
-
#exslt ⇒ Object
Enable the first-party EXSLT-style extension pack on this document: str:/set:/math: prefixed functions (replace, tokenize, split, concat, padding; distinct, intersection, difference, leading, trailing; max, min, abs, sqrt, power) as native C handlers.
-
#fragment(markup) ⇒ Object
-
#free ⇒ Object
-
#initialize(c_ptr = nil, freed = Freed.new(:alive)) ⇒ Document
constructor
A new instance of Document.
-
#last_error ⇒ Object
The most recent error recorded against this document, or nil.
-
#name ⇒ Object
-
#processing_instructions ⇒ Object
Document-level processing instructions (not tree nodes): an array of [target, data] pairs in document order.
-
#root ⇒ Object
-
#root=(element) ⇒ Object
Attach element as the document's root element.
-
#save(path, **opts) ⇒ Object
-
#to_xml(indent: 0, no_decl: false, encoding: nil) ⇒ Object
(also: #to_s, #serialize)
Methods included from Searchable
#at, #at_css, #at_xpath, #css, #search, wrap_xpath_result, #xpath
Constructor Details
#initialize(c_ptr = nil, freed = Freed.new(:alive)) ⇒ Document
Returns a new instance of Document.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# File 'lib/leptris/xml/document.rb', line 17
def initialize(c_ptr = nil, freed = Freed.new(:alive))
@c_ptr = c_ptr
@freed = freed
@wrapper_cache = {}
end
|
Instance Attribute Details
#c_ptr ⇒ Object
Returns the value of attribute c_ptr.
6
7
8
|
# File 'lib/leptris/xml/document.rb', line 6
def c_ptr
@c_ptr
end
|
#wrapper_cache ⇒ Object
Returns the value of attribute wrapper_cache.
6
7
8
|
# File 'lib/leptris/xml/document.rb', line 6
def wrapper_cache
@wrapper_cache
end
|
Class Method Details
.create ⇒ Object
Create an empty document (no root element) backed by its own memory
pool. Elements for the tree are created against it via
#create_element and friends, then attached with #root=.
73
74
75
76
77
78
|
# File 'lib/leptris/xml/document.rb', line 73
def self.create
raw = Leptris::XML::FFI.leptris_document_create
raise Leptris::XML::Error,
"leptris_document_create failed" if raw.null?
wrap(raw)
end
|
.parse(xml_or_io, options: nil) ⇒ Object
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
# File 'lib/leptris/xml/document.rb', line 36
def self.parse(xml_or_io, options: nil)
xml = xml_or_io.respond_to?(:read) ? xml_or_io.read : xml_or_io.to_s
if xml.empty?
raise Leptris::XML::ParseError, "empty input"
end
flags = resolve_flags(options)
status_ptr = ::FFI::MemoryPointer.new(:int)
raw =
if flags.zero?
Leptris::XML::FFI.leptris_parse_string(xml, xml.bytesize, status_ptr)
else
Leptris::XML::FFI.leptris_parse_string_flags(
xml, xml.bytesize, flags, status_ptr)
end
if raw.null?
status = status_ptr.read_int
raise Leptris::XML::ParseError,
"leptris_parse_string failed (status=#{status}): " +
Leptris::XML::FFI.status_message(status)
end
wrap(raw)
end
|
.parse_file(path) ⇒ Object
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/leptris/xml/document.rb', line 59
def self.parse_file(path)
status_ptr = ::FFI::MemoryPointer.new(:int)
raw = Leptris::XML::FFI.leptris_parse_file(path, status_ptr)
if raw.null?
status = status_ptr.read_int
raise Leptris::XML::ParseError,
"leptris_parse_file failed (status=#{status})"
end
wrap(raw)
end
|
.wrap(raw_address) ⇒ Object
Convert a raw LeptrisDocument pointer into a Ruby Document with safe
GC lifetime management. The finalizer captures the raw address
integer (not the Document or Pointer object — those would prevent
GC) and shares a one-shot flag with the instance so explicit
#free and the GC finalizer can never both call
leptris_document_free on the same address.
86
87
88
89
90
91
92
93
|
# File 'lib/leptris/xml/document.rb', line 86
def self.wrap(raw_address)
addr = raw_address.is_a?(::FFI::Pointer) ? raw_address.address : raw_address
ptr = ::FFI::Pointer.new(addr)
freed = Freed.new(:alive)
doc = new(ptr, freed)
ObjectSpace.define_finalizer(doc, finalizer(addr, freed))
doc
end
|
Instance Method Details
#add_pi(target, data = "") ⇒ Object
Append a document-level processing instruction. Returns self.
248
249
250
251
252
253
|
# File 'lib/leptris/xml/document.rb', line 248
def add_pi(target, data = "")
witness = Leptris::XML::FFI.leptris_document_add_pi(
@c_ptr, target.to_s, data.to_s)
raise Leptris::XML::Error, "leptris_document_add_pi failed" if witness.null?
self
end
|
#canonicalize(version = Leptris::XML::FFI::C14N_1_0, inclusive_namespaces = nil, with_comments: false, exclusive: false, mode: nil) ⇒ Object
Also known as:
c14n
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
|
# File 'lib/leptris/xml/document.rb', line 201
def canonicalize(version = Leptris::XML::FFI::C14N_1_0,
inclusive_namespaces = nil,
with_comments: false,
exclusive: false,
mode: nil)
raise Leptris::XML::UseAfterFreeError if @freed.state == :freed
return "" if @c_ptr.nil?
resolved_mode = mode || (exclusive ? Leptris::XML::FFI::C14N_MODE_EXCLUSIVE
: Leptris::XML::FFI::C14N_MODE_CANONICAL)
Leptris::XML::Serialization.canonicalize(
Leptris::XML::FFI.method(:leptris_c14n_canonicalize_ex), @c_ptr,
version: version, mode: resolved_mode,
inclusive_namespaces: inclusive_namespaces,
with_comments: )
end
|
#create_cdata(content) ⇒ Object
150
151
152
153
154
|
# File 'lib/leptris/xml/document.rb', line 150
def create_cdata(content)
ptr = Leptris::XML::FFI.leptris_cdata_node_create(@c_ptr, content.to_s)
raise Leptris::XML::Error, "leptris_cdata_node_create failed" if ptr.null?
Leptris::XML::Node.wrap(ptr, self)
end
|
144
145
146
147
148
|
# File 'lib/leptris/xml/document.rb', line 144
def (content)
ptr = Leptris::XML::FFI.(@c_ptr, content.to_s)
raise Leptris::XML::Error, "leptris_comment_node_create failed" if ptr.null?
Leptris::XML::Node.wrap(ptr, self)
end
|
#create_element(name) ⇒ Object
132
133
134
135
136
|
# File 'lib/leptris/xml/document.rb', line 132
def create_element(name)
ptr = Leptris::XML::FFI.leptris_element_create(@c_ptr, name)
raise Leptris::XML::Error, "leptris_element_create failed" if ptr.null?
Leptris::XML::Node.wrap(ptr, self)
end
|
#create_processing_instruction(target, data = "") ⇒ Object
156
157
158
159
160
|
# File 'lib/leptris/xml/document.rb', line 156
def create_processing_instruction(target, data = "")
ptr = Leptris::XML::FFI.leptris_pi_node_create(@c_ptr, target.to_s, data.to_s)
raise Leptris::XML::Error, "leptris_pi_node_create failed" if ptr.null?
Leptris::XML::Node.wrap(ptr, self)
end
|
#create_text_node(content) ⇒ Object
138
139
140
141
142
|
# File 'lib/leptris/xml/document.rb', line 138
def create_text_node(content)
ptr = Leptris::XML::FFI.leptris_text_node_create(@c_ptr, content.to_s)
raise Leptris::XML::Error, "leptris_text_node_create failed" if ptr.null?
Leptris::XML::Node.wrap(ptr, self)
end
|
#doctype ⇒ Object
Also known as:
internal_subset
173
174
175
176
177
|
# File 'lib/leptris/xml/document.rb', line 173
def doctype
ptr = Leptris::XML::FFI.leptris_document_internal_subset(@c_ptr)
return nil if ptr.null?
Leptris::XML::DocType.new(ptr, self)
end
|
#document ⇒ Object
262
|
# File 'lib/leptris/xml/document.rb', line 262
def document; self; end
|
#dup ⇒ Object
Also known as:
clone
166
167
168
169
170
|
# File 'lib/leptris/xml/document.rb', line 166
def dup
raw = Leptris::XML::FFI.leptris_document_copy(@c_ptr)
raise Leptris::XML::Error, "leptris_document_copy failed" if raw.null?
self.class.wrap(raw)
end
|
#encoding ⇒ Object
263
264
265
266
|
# File 'lib/leptris/xml/document.rb', line 263
def encoding
return nil if @c_ptr.nil?
Leptris::XML::FFI.leptris_document_encoding(@c_ptr)
end
|
#exslt ⇒ Object
Enable the first-party EXSLT-style extension pack on this
document: str:/set:/math: prefixed functions (replace, tokenize,
split, concat, padding; distinct, intersection, difference,
leading, trailing; max, min, abs, sqrt, power) as native C
handlers. Returns self for chaining.
#fragment(markup) ⇒ Object
#free ⇒ Object
218
219
220
221
222
223
224
|
# File 'lib/leptris/xml/document.rb', line 218
def free
return if @freed.state == :freed
@freed.state = :freed
Leptris::XML::FFI.leptris_document_free(@c_ptr) unless @c_ptr.nil?
@c_ptr = nil
@wrapper_cache.clear
end
|
#last_error ⇒ Object
The most recent error recorded against this document, or nil.
256
257
258
259
|
# File 'lib/leptris/xml/document.rb', line 256
def last_error
msg = Leptris::XML::FFI.leptris_document_last_error(@c_ptr)
msg.nil? || msg.empty? ? nil : msg
end
|
#name ⇒ Object
261
|
# File 'lib/leptris/xml/document.rb', line 261
def name; "document"; end
|
#processing_instructions ⇒ Object
Document-level processing instructions (not tree nodes):
an array of [target, data] pairs in document order.
239
240
241
242
243
244
245
|
# File 'lib/leptris/xml/document.rb', line 239
def processing_instructions
count = Leptris::XML::FFI.leptris_document_pi_count(@c_ptr)
count.times.map do |i|
[Leptris::XML::FFI.leptris_document_pi_target(@c_ptr, i),
Leptris::XML::FFI.leptris_document_pi_data(@c_ptr, i)]
end
end
|
#root=(element) ⇒ Object
Attach element as the document's root element. The element must
have been created against this document and must not already have
a parent. Any previous root is left detached (still owned by the
document's pool until #free).
#save(path, **opts) ⇒ Object
190
191
192
193
194
195
196
197
198
199
|
# File 'lib/leptris/xml/document.rb', line 190
def save(path, **opts)
opts_struct, _encoding_anchor = Leptris::XML::Serialization.build_options(
indent: opts.fetch(:indent, 0),
no_decl: opts.fetch(:no_decl, false),
encoding: opts[:encoding])
status = Leptris::XML::FFI.leptris_document_save_file(
@c_ptr, path, opts_struct.pointer)
Leptris::XML::FFI.check_status(status)
self
end
|
#to_xml(indent: 0, no_decl: false, encoding: nil) ⇒ Object
Also known as:
to_s, serialize
180
181
182
183
184
185
186
|
# File 'lib/leptris/xml/document.rb', line 180
def to_xml(indent: 0, no_decl: false, encoding: nil)
raise Leptris::XML::UseAfterFreeError if @freed.state == :freed
return "" if @c_ptr.nil?
Leptris::XML::Serialization.to_xml(
Leptris::XML::FFI.method(:leptris_document_serialize), @c_ptr,
indent: indent, no_decl: no_decl, encoding: encoding)
end
|