canon 0.3.7 → 0.3.8
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 +4 -4
- data/lib/canon/version.rb +1 -1
- data/lib/canon/xml/data_model.rb +40 -35
- data/lib/canon/xml_backend.rb +11 -13
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7e6a28999cdd57c9fb642e7f334546ef2ebe4802057481ef9c9bcf93252b8590
|
|
4
|
+
data.tar.gz: 072ae76310a6f936b81a73f2305bac61cb0b1100f36509724f67c5a763fb718f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '049a48f66a243b20993f677e8789eff4b08ed72f0b22fa9288453d3806718f2a9f7414c7774e51de30290d19d5b012419f50eb8cdf75762944b4f5c28ed6d54b'
|
|
7
|
+
data.tar.gz: b57afbf6f649b27c8a4833742673f2ae7dea0a4608610795d8ae38c76398ed66e833d4a5d29f832e45ecb1f5ced1e23125afc6b383f45ffc545b6257aca986bb
|
data/lib/canon/version.rb
CHANGED
data/lib/canon/xml/data_model.rb
CHANGED
|
@@ -212,7 +212,6 @@ inherited_namespaces: nil)
|
|
|
212
212
|
doc = Canon::XmlParsing.moxml_context.parse(xml_string,
|
|
213
213
|
readonly: true,
|
|
214
214
|
strict: false)
|
|
215
|
-
check_moxml_relative_namespace_uris(doc)
|
|
216
215
|
result = build_from_moxml(doc, preserve_whitespace: preserve_whitespace)
|
|
217
216
|
result.parse_errors = doc.parse_errors if doc.parse_errors.any?
|
|
218
217
|
# Canon owns this document's full lifecycle: the canon tree holds
|
|
@@ -223,23 +222,6 @@ inherited_namespaces: nil)
|
|
|
223
222
|
result
|
|
224
223
|
end
|
|
225
224
|
|
|
226
|
-
def self.check_moxml_relative_namespace_uris(node)
|
|
227
|
-
case node
|
|
228
|
-
when Moxml::Element
|
|
229
|
-
node.namespace_definitions.each do |ns|
|
|
230
|
-
href = ns.uri
|
|
231
|
-
next if href.nil? || href.empty?
|
|
232
|
-
if relative_uri?(href)
|
|
233
|
-
raise Canon::Error,
|
|
234
|
-
"Relative namespace URI not allowed: #{href}"
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
node.children.each { |child| check_moxml_relative_namespace_uris(child) }
|
|
238
|
-
when Moxml::Document
|
|
239
|
-
node.children.each { |child| check_moxml_relative_namespace_uris(child) }
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
|
|
243
225
|
def self.build_from_moxml(moxml_doc, preserve_whitespace: false)
|
|
244
226
|
root = Nodes::RootNode.new
|
|
245
227
|
skip_types = [Moxml::Doctype]
|
|
@@ -267,32 +249,52 @@ preserve_whitespace: false)
|
|
|
267
249
|
frames = []
|
|
268
250
|
own_namespaces = {}.compare_by_identity
|
|
269
251
|
|
|
270
|
-
|
|
252
|
+
# materialize_fields: the zero-allocation hot path (moxml#143).
|
|
253
|
+
# Flat reused buffers — attributes stride 4, namespaces stride
|
|
254
|
+
# 2 — valid only inside the block, so the element builder
|
|
255
|
+
# copies them into pairs before returning.
|
|
256
|
+
moxml_element.materialize_fields do |kind, qname, prefix, namespace_uri, namespaces, attributes, text, depth|
|
|
271
257
|
# The record contract is root-subtree-only since moxml 0.5.11
|
|
272
258
|
# (moxml#140). Older 0.5.x releases — still allowed by canon's
|
|
273
259
|
# gemspec floor — leaked epilog document-level records at depth
|
|
274
260
|
# 0, which the document-children enumeration also covers; one
|
|
275
261
|
# integer compare per record keeps those working.
|
|
276
|
-
next if
|
|
262
|
+
next if depth.zero? && kind != :element
|
|
263
|
+
|
|
264
|
+
# Relative-namespace validation rides the stream (the
|
|
265
|
+
# namespaces buffer is the element's own declarations) — no
|
|
266
|
+
# separate wrapper-tree walk per parse.
|
|
267
|
+
if kind == :element
|
|
268
|
+
i = 1
|
|
269
|
+
while i < namespaces.size
|
|
270
|
+
href = namespaces[i]
|
|
271
|
+
if !href.nil? && !href.empty? && relative_uri?(href)
|
|
272
|
+
raise Canon::Error,
|
|
273
|
+
"Relative namespace URI not allowed: #{href}"
|
|
274
|
+
end
|
|
275
|
+
i += 2
|
|
276
|
+
end
|
|
277
|
+
end
|
|
277
278
|
|
|
278
|
-
node = case
|
|
279
|
+
node = case kind
|
|
279
280
|
when :element
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
build_moxml_element_from_fields(
|
|
282
|
+
qname, prefix, namespace_uri, namespaces, attributes,
|
|
283
|
+
depth, frames, own_namespaces
|
|
284
|
+
)
|
|
282
285
|
when :text, :cdata
|
|
283
|
-
content =
|
|
286
|
+
content = text.to_s
|
|
284
287
|
TreeBuilder::DEFAULT.text(content,
|
|
285
288
|
keep: WhitespacePolicy.keep_dom_text?(
|
|
286
289
|
content, preserve_whitespace: preserve_whitespace
|
|
287
290
|
))
|
|
288
291
|
when :comment
|
|
289
|
-
TreeBuilder::DEFAULT.comment(
|
|
292
|
+
TreeBuilder::DEFAULT.comment(text)
|
|
290
293
|
when :processing_instruction
|
|
291
|
-
TreeBuilder::DEFAULT.processing_instruction(
|
|
292
|
-
record[:text] || "")
|
|
294
|
+
TreeBuilder::DEFAULT.processing_instruction(qname, text || "")
|
|
293
295
|
end
|
|
294
296
|
|
|
295
|
-
frames.push([
|
|
297
|
+
frames.push([depth, node]) if node
|
|
296
298
|
end
|
|
297
299
|
|
|
298
300
|
top = frames.last
|
|
@@ -302,21 +304,24 @@ preserve_whitespace: false)
|
|
|
302
304
|
top[1]
|
|
303
305
|
end
|
|
304
306
|
|
|
305
|
-
def self.
|
|
307
|
+
def self.build_moxml_element_from_fields(qname, prefix, namespace_uri,
|
|
308
|
+
namespaces, attributes, depth,
|
|
309
|
+
frames, own_namespaces)
|
|
306
310
|
element = TreeBuilder::DEFAULT.element(
|
|
307
|
-
name:
|
|
308
|
-
prefix:
|
|
309
|
-
namespace_uri:
|
|
310
|
-
attributes:
|
|
311
|
+
name: qname,
|
|
312
|
+
prefix: prefix,
|
|
313
|
+
namespace_uri: namespace_uri,
|
|
314
|
+
attributes: attributes.each_slice(4).to_a,
|
|
311
315
|
)
|
|
312
316
|
|
|
313
317
|
# Adopt completed children: they pop in reverse order; reversing
|
|
314
318
|
# once is O(n) (unshift per child would be O(n^2) on wide trees).
|
|
315
319
|
children = []
|
|
316
|
-
children << frames.pop[1] while frames.any? && frames.last[0] >
|
|
320
|
+
children << frames.pop[1] while frames.any? && frames.last[0] > depth
|
|
317
321
|
children.reverse_each { |child| element.add_child(child) }
|
|
318
322
|
|
|
319
|
-
|
|
323
|
+
# Copy the declarations out of the reused buffer.
|
|
324
|
+
own_namespaces[element] = namespaces.each_slice(2).to_a
|
|
320
325
|
element
|
|
321
326
|
end
|
|
322
327
|
|
data/lib/canon/xml_backend.rb
CHANGED
|
@@ -10,13 +10,12 @@ module Canon
|
|
|
10
10
|
# leptris no HTML parser (see Canon::Html::NokogiriSupport).
|
|
11
11
|
#
|
|
12
12
|
# SSOT: moxml owns adapter preference (Moxml::Config prefers leptris
|
|
13
|
-
# when installed; see XmlParsing.moxml_adapter_name).
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# CANON_XML_BACKEND=moxml opts into the leptris DOM engine today.
|
|
13
|
+
# when installed; see XmlParsing.moxml_adapter_name). Both engines
|
|
14
|
+
# follow the resolved adapter: SAX since leptris#625/#99 were fixed,
|
|
15
|
+
# DOM since moxml#143's materialize_fields stream (zero-allocation
|
|
16
|
+
# flat buffers) made the conversion competitive. Conformance parity
|
|
17
|
+
# is complete (engine_parity_spec 12/12). CANON_XML_BACKEND forces
|
|
18
|
+
# either engine; the CI performance gate is the standing referee.
|
|
20
19
|
#
|
|
21
20
|
# HTML stays on Nokogiri on CRuby (Canon::Html::NokogiriSupport) and the
|
|
22
21
|
# pretty-printers keep the Nokogiri pipeline — pretty-printed bytes are
|
|
@@ -61,12 +60,11 @@ module Canon
|
|
|
61
60
|
def detect
|
|
62
61
|
return :moxml if RUBY_ENGINE == "opal"
|
|
63
62
|
|
|
64
|
-
#
|
|
65
|
-
# CI-gated
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
:nokogiri
|
|
63
|
+
# Both engines now run leptris: SAX since leptris#625/#99
|
|
64
|
+
# (CI-gated), DOM since moxml#143's zero-allocation
|
|
65
|
+
# materialize_fields stream made the conversion competitive.
|
|
66
|
+
# The CI performance gate is the standing referee.
|
|
67
|
+
XmlParsing.moxml_adapter_name == :nokogiri ? :nokogiri : :moxml
|
|
70
68
|
end
|
|
71
69
|
end
|
|
72
70
|
end
|