moxml 0.5.80 → 0.5.81
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/Gemfile +1 -1
- data/lib/moxml/adapter/leptris/sax_record_replay.rb +60 -0
- data/lib/moxml/adapter/leptris.rb +32 -3
- data/lib/moxml/cdata.rb +5 -0
- data/lib/moxml/comment.rb +5 -0
- data/lib/moxml/sax/handler.rb +15 -0
- data/lib/moxml/text.rb +8 -0
- data/lib/moxml/version.rb +1 -1
- data/spec/consistency/eol_normalization_spec.rb +91 -0
- data/spec/consistency/round_trip_spec.rb +16 -8
- data/spec/moxml/adapter/leptris_sax_records_spec.rb +87 -0
- data/spec/moxml/text_spec.rb +17 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 957697bcb855cea040ac0d8b2f202a7cd8fd230482137602fcf7d50fc2712ebb
|
|
4
|
+
data.tar.gz: 22815ac3e9920a8939b0076f3b4222a154e0420d4fe1a21d9b7e56bd9b0818b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 422b076bb191e01b27693af02a66d4e985f574dbcc49451c9af395c1905f9cabfdb2faf0e1b15303a5444c17a8fba98e70e5bea7d5c61f1f152d9fa09a550329
|
|
7
|
+
data.tar.gz: 2d75b66d322414ea8c99b79fe1ed78c7aa758b90b7f5b7f56a685e9f861bca12d6f641803aa04ced575a812677a085619bd40ee435963b035cdbe005a36d1b55
|
data/Gemfile
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Moxml
|
|
4
|
+
module Adapter
|
|
5
|
+
class Leptris
|
|
6
|
+
# Replays the engine's bulk SAX record table (leptris#1298) to
|
|
7
|
+
# the bridge protocol. One drain crossing replaces the
|
|
8
|
+
# per-event recorder replay; the only String materializations
|
|
9
|
+
# left are the name/value/text data the handler actually
|
|
10
|
+
# consumes. End events reconstruct from the records' parent
|
|
11
|
+
# indices with a name-carrying stack — pre-order records make
|
|
12
|
+
# a parent mismatch the exact close boundary, and
|
|
13
|
+
# self-closing elements pop at their next sibling, matching
|
|
14
|
+
# the callback engine's event stream.
|
|
15
|
+
#
|
|
16
|
+
# @private
|
|
17
|
+
class SaxRecordReplay
|
|
18
|
+
KIND_ELEMENT = ::Leptris::XML::SAX::Records::KIND_ELEMENT
|
|
19
|
+
|
|
20
|
+
def initialize(bridge)
|
|
21
|
+
@bridge = bridge
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def run(table)
|
|
25
|
+
@bridge.start_document
|
|
26
|
+
idx_stack = []
|
|
27
|
+
name_stack = []
|
|
28
|
+
count = table.count
|
|
29
|
+
i = 0
|
|
30
|
+
while i < count
|
|
31
|
+
while !idx_stack.empty? && table.parent(i) != idx_stack.last
|
|
32
|
+
idx_stack.pop
|
|
33
|
+
@bridge.end_element(name_stack.pop)
|
|
34
|
+
end
|
|
35
|
+
if table.kind(i) == KIND_ELEMENT
|
|
36
|
+
name = table.view(i)
|
|
37
|
+
pairs = []
|
|
38
|
+
k = table.attr_first(i)
|
|
39
|
+
last = k + table.attr_count_of(i)
|
|
40
|
+
while k < last
|
|
41
|
+
v = table.attr_value(k)
|
|
42
|
+
pairs << [table.attr_name(k),
|
|
43
|
+
table.attr_value_has_ws?(k) ? v.tr("\t\n\r", " ") : v]
|
|
44
|
+
k += 1
|
|
45
|
+
end
|
|
46
|
+
@bridge.start_element(name, pairs)
|
|
47
|
+
idx_stack << i
|
|
48
|
+
name_stack << name
|
|
49
|
+
else
|
|
50
|
+
@bridge.characters(table.view(i))
|
|
51
|
+
end
|
|
52
|
+
i += 1
|
|
53
|
+
end
|
|
54
|
+
@bridge.end_element(name_stack.pop) until name_stack.empty?
|
|
55
|
+
@bridge.end_document
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -130,6 +130,15 @@ module Moxml
|
|
|
130
130
|
defined?(::Leptris::XML::NativeNode) &&
|
|
131
131
|
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.163.2")
|
|
132
132
|
|
|
133
|
+
# Bulk SAX record drain (leptris#1298): leptris_sax_records_parse
|
|
134
|
+
# + Leptris::XML::SAX::Records — one crossing per document,
|
|
135
|
+
# handlers replay or walk the table. Ships in the binding ride
|
|
136
|
+
# 1.9.240.0 (1.9.239.0 predates the walker — the gate must name
|
|
137
|
+
# the carrying release, not the engine surface). Dev floor pins
|
|
138
|
+
# ~> 1.9.238; older bindings take the callback Parser below.
|
|
139
|
+
NATIVE_SAX_RECORDS =
|
|
140
|
+
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.240")
|
|
141
|
+
|
|
133
142
|
# Defined unconditionally: the body self-guards, and call
|
|
134
143
|
# sites must never depend on the layer having loaded
|
|
135
144
|
# (issue #217 — binding-only installs crashed on the
|
|
@@ -522,6 +531,7 @@ module Moxml
|
|
|
522
531
|
autoload :Materialize, "moxml/adapter/leptris/materialize"
|
|
523
532
|
autoload :Serialize, "moxml/adapter/leptris/serialize"
|
|
524
533
|
autoload :LeptrisSAXBridge, "moxml/adapter/leptris/sax_bridge"
|
|
534
|
+
autoload :SaxRecordReplay, "moxml/adapter/leptris/sax_record_replay"
|
|
525
535
|
extend Serialize
|
|
526
536
|
extend DocumentParts
|
|
527
537
|
extend Markers
|
|
@@ -1501,7 +1511,8 @@ module Moxml
|
|
|
1501
1511
|
|
|
1502
1512
|
flat = attrs.flatten
|
|
1503
1513
|
addr = ::Leptris::XML::Native.create_element_with_attrs(
|
|
1504
|
-
doc.c_address, binding_parent.c_address, name.to_s, flat
|
|
1514
|
+
doc.c_address, binding_parent.c_address, name.to_s, flat
|
|
1515
|
+
)
|
|
1505
1516
|
return nil if addr.nil? || addr.zero?
|
|
1506
1517
|
|
|
1507
1518
|
# The binding's own wrap produces the proper binding
|
|
@@ -1510,7 +1521,7 @@ module Moxml
|
|
|
1510
1521
|
# included — the SAME native, so the wrapper identity
|
|
1511
1522
|
# holds across later traversals.
|
|
1512
1523
|
canonical_native(doc,
|
|
1513
|
-
|
|
1524
|
+
::Leptris::XML::Node.wrap(::FFI::Pointer.new(addr), doc))
|
|
1514
1525
|
end
|
|
1515
1526
|
|
|
1516
1527
|
def attributes(element)
|
|
@@ -2114,7 +2125,25 @@ module Moxml
|
|
|
2114
2125
|
def sax_parse(xml, handler)
|
|
2115
2126
|
bridge = LeptrisSAXBridge.new(handler)
|
|
2116
2127
|
xml_string = xml.is_a?(IO) || xml.is_a?(::StringIO) ? xml.read : xml.to_s
|
|
2117
|
-
|
|
2128
|
+
# Bulk record drain (leptris#1298, NATIVE_SAX_RECORDS):
|
|
2129
|
+
# one crossing per document. The handler decides the shape
|
|
2130
|
+
# polymorphically — Handler#on_sax_records answers
|
|
2131
|
+
# :unhandled, so classic handlers get the exact callback
|
|
2132
|
+
# stream replayed from the table; hot loops override and
|
|
2133
|
+
# walk the records (nil table = outside the drain subset
|
|
2134
|
+
# or pre-1.9.238 binding — callback path).
|
|
2135
|
+
table = NATIVE_SAX_RECORDS ? ::Leptris::XML::SAX::Records.open(xml_string) : nil
|
|
2136
|
+
if table
|
|
2137
|
+
begin
|
|
2138
|
+
return if handler.on_sax_records(table) != :unhandled
|
|
2139
|
+
|
|
2140
|
+
SaxRecordReplay.new(bridge).run(table)
|
|
2141
|
+
ensure
|
|
2142
|
+
table.free
|
|
2143
|
+
end
|
|
2144
|
+
else
|
|
2145
|
+
::Leptris::XML::SAX::Parser.new(bridge).parse(xml_string)
|
|
2146
|
+
end
|
|
2118
2147
|
rescue ::Leptris::XML::ParseError, ::Leptris::XML::Error => e
|
|
2119
2148
|
handler.on_error(Moxml::ParseError.new(e.message))
|
|
2120
2149
|
end
|
data/lib/moxml/cdata.rb
CHANGED
data/lib/moxml/comment.rb
CHANGED
data/lib/moxml/sax/handler.rb
CHANGED
|
@@ -108,6 +108,21 @@ module Moxml
|
|
|
108
108
|
def on_warning(message)
|
|
109
109
|
# Override in subclass if needed
|
|
110
110
|
end
|
|
111
|
+
|
|
112
|
+
# Bulk SAX record surface (leptris#1298, leptris adapter only).
|
|
113
|
+
# On bindings with the drain the adapter hands the WHOLE
|
|
114
|
+
# document as a Leptris::XML::SAX::Records table — one crossing,
|
|
115
|
+
# no per-event marshaling; hot loops walk the records and
|
|
116
|
+
# materialize only what they consume (this default answers
|
|
117
|
+
# :unhandled, and the adapter replays the classic callback
|
|
118
|
+
# stream from the table instead — the events are identical).
|
|
119
|
+
#
|
|
120
|
+
# @param table [Leptris::XML::SAX::Records] record table, valid
|
|
121
|
+
# only during the call
|
|
122
|
+
# @return [Object] anything but :unhandled claims the table
|
|
123
|
+
def on_sax_records(_table)
|
|
124
|
+
:unhandled
|
|
125
|
+
end
|
|
111
126
|
end
|
|
112
127
|
end
|
|
113
128
|
end
|
data/lib/moxml/text.rb
CHANGED
|
@@ -21,5 +21,13 @@ module Moxml
|
|
|
21
21
|
def to_s
|
|
22
22
|
content
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
# Node#text's base returns "" for non-element nodes; a text
|
|
26
|
+
# node's text IS its content (leptris's Reads layer already
|
|
27
|
+
# answered content here — the wrapper contract now matches on
|
|
28
|
+
# every adapter).
|
|
29
|
+
def text
|
|
30
|
+
content
|
|
31
|
+
end
|
|
24
32
|
end
|
|
25
33
|
end
|
data/lib/moxml/version.rb
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
# XML 1.0 §2.11 End-of-Line Handling: literal CRLF and lone CR
|
|
6
|
+
# normalize to LF in parsed character data, before tokenization —
|
|
7
|
+
# so CDATA content normalizes too, while character references
|
|
8
|
+
# ( ) sit OUTSIDE the rule and must survive as CR. Attribute
|
|
9
|
+
# values normalize EOL first, then §3.3.3 maps the break to a
|
|
10
|
+
# space (libxml2 parity: "x\r\ny" -> "x y").
|
|
11
|
+
#
|
|
12
|
+
# Adapter status (verified 2026-09-25):
|
|
13
|
+
# nokogiri/libxml - conform on all three surfaces
|
|
14
|
+
# rexml - text/cdata conform; attrs EOL-only ("x\ny")
|
|
15
|
+
# ox - text/cdata conform; attrs raw;
|
|
16
|
+
# over-normalized to \n (upstream)
|
|
17
|
+
# oga - preserves raw CR everywhere (upstream)
|
|
18
|
+
# leptris - fixed in engine 1.9.240 (leptris#1355,
|
|
19
|
+
# leptris-ruby#326); skipped below until the
|
|
20
|
+
# binding release vending that engine rides
|
|
21
|
+
# (gate: binding 1.9.240).
|
|
22
|
+
RSpec.describe "XML line-ending normalization" do
|
|
23
|
+
ADAPTERS = %i[leptris nokogiri ox oga rexml libxml].freeze # rubocop:disable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
|
|
24
|
+
|
|
25
|
+
def with_adapter(name)
|
|
26
|
+
ctx = Moxml.new(name)
|
|
27
|
+
yield ctx
|
|
28
|
+
rescue LoadError
|
|
29
|
+
skip "adapter #{name} unavailable"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def leptris_fixed?(name)
|
|
33
|
+
return true unless name == :leptris
|
|
34
|
+
|
|
35
|
+
defined?(Leptris::VERSION) &&
|
|
36
|
+
Gem::Version.new(Leptris::VERSION) >= Gem::Version.new("1.9.240")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "normalizes CRLF and lone CR to LF in text content" do
|
|
40
|
+
ADAPTERS.each do |name|
|
|
41
|
+
next unless leptris_fixed?(name)
|
|
42
|
+
|
|
43
|
+
skip "oga preserves raw CR (upstream)" if name == :oga
|
|
44
|
+
|
|
45
|
+
with_adapter(name) do |ctx|
|
|
46
|
+
text = ctx.parse("<r>a\r\nb\rc</r>").root.children.first
|
|
47
|
+
expect(text.content).to eq("a\nb\nc"), "#{name}: #{text.content.inspect}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "normalizes EOL inside CDATA content" do
|
|
53
|
+
ADAPTERS.each do |name|
|
|
54
|
+
next unless leptris_fixed?(name)
|
|
55
|
+
|
|
56
|
+
skip "oga preserves raw CR (upstream)" if name == :oga
|
|
57
|
+
|
|
58
|
+
with_adapter(name) do |ctx|
|
|
59
|
+
cdata = ctx.parse("<r><![CDATA[a\r\nb]]></r>").root.children.first
|
|
60
|
+
expect(cdata.content).to eq("a\nb"), "#{name}: #{cdata.content.inspect}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "preserves CR from character references" do
|
|
66
|
+
ADAPTERS.each do |name|
|
|
67
|
+
next unless leptris_fixed?(name)
|
|
68
|
+
|
|
69
|
+
skip "ox collapses to LF (upstream)" if name == :ox
|
|
70
|
+
skip "oga preserves raw CR (upstream)" if name == :oga
|
|
71
|
+
|
|
72
|
+
with_adapter(name) do |ctx|
|
|
73
|
+
text = ctx.parse("<r>a b</r>").root.children.first
|
|
74
|
+
expect(text.content).to eq("a\rb"), "#{name}: #{text.content.inspect}"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "collapses attribute CRLF to a single space (libxml2 parity)" do
|
|
80
|
+
conforming = %i[nokogiri libxml leptris]
|
|
81
|
+
conforming.each do |name|
|
|
82
|
+
next unless leptris_fixed?(name)
|
|
83
|
+
|
|
84
|
+
with_adapter(name) do |ctx|
|
|
85
|
+
root = ctx.parse("<r a=\"x\r\ny\" b=\"x\ty\"/>").root
|
|
86
|
+
expect(root["a"]).to eq("x y"), "#{name}: attr CRLF #{root['a'].inspect}"
|
|
87
|
+
expect(root["b"]).to eq("x y"), "#{name}: attr tab #{root['b'].inspect}"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -295,16 +295,24 @@ def normalize_type_attribute(name, value)
|
|
|
295
295
|
end
|
|
296
296
|
end
|
|
297
297
|
|
|
298
|
-
def test_element_content(
|
|
299
|
-
return nil unless
|
|
298
|
+
def test_element_content(node)
|
|
299
|
+
return nil unless node
|
|
300
|
+
|
|
301
|
+
# :text_content holds a Text node (from //text()) — Text#text now
|
|
302
|
+
# returns real content on every adapter, so this branch actually
|
|
303
|
+
# fires. Text nodes have no name/attributes/children.
|
|
304
|
+
unless node.is_a?(Moxml::Element)
|
|
305
|
+
return { name: nil, attributes: {}, text: node.text.to_s.strip,
|
|
306
|
+
namespace: nil, children_count: 0, xpath: [] }
|
|
307
|
+
end
|
|
300
308
|
|
|
301
309
|
{
|
|
302
|
-
name:
|
|
303
|
-
attributes: universal_attributes(
|
|
304
|
-
text:
|
|
305
|
-
namespace:
|
|
306
|
-
children_count:
|
|
307
|
-
xpath:
|
|
310
|
+
name: node.name,
|
|
311
|
+
attributes: universal_attributes(node),
|
|
312
|
+
text: node.text.to_s.strip,
|
|
313
|
+
namespace: node.namespace&.uri,
|
|
314
|
+
children_count: node.children.size,
|
|
315
|
+
xpath: node.xpath("//*"),
|
|
308
316
|
}
|
|
309
317
|
end
|
|
310
318
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
# Bulk SAX record drain (leptris#1298): on bindings carrying
|
|
6
|
+
# Leptris::XML::SAX::Records the leptris adapter drains the document
|
|
7
|
+
# in one crossing. Classic handlers must receive the SAME event
|
|
8
|
+
# stream the callback Recorder produces (the replay reconstructs end
|
|
9
|
+
# events from the records' parent indices), handlers overriding
|
|
10
|
+
# on_sax_records claim the raw table instead, and raw attribute
|
|
11
|
+
# whitespace is normalized (3.3.3) exactly where the callback path
|
|
12
|
+
# normalizes it.
|
|
13
|
+
module SaxDrainHandlers
|
|
14
|
+
class EventCollector < Moxml::SAX::Handler
|
|
15
|
+
attr_reader :events
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
super
|
|
19
|
+
@events = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def on_start_document
|
|
23
|
+
@events << [:start_document]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def on_end_document
|
|
27
|
+
@events << [:end_document]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def on_start_element(name, attributes = {}, _namespaces = {})
|
|
31
|
+
@events << [:start, name, attributes]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def on_end_element(name)
|
|
35
|
+
@events << [:end, name]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def on_characters(text)
|
|
39
|
+
@events << [:chars, text]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class TableClaimant < Moxml::SAX::Handler
|
|
44
|
+
attr_reader :tables
|
|
45
|
+
|
|
46
|
+
def initialize
|
|
47
|
+
super
|
|
48
|
+
@tables = []
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def on_sax_records(table)
|
|
52
|
+
@tables << table
|
|
53
|
+
:claimed
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
RSpec.describe "leptris SAX record drain", if: defined?(Leptris::XML::SAX::Records) do
|
|
59
|
+
let(:context) { Moxml.new(:leptris) }
|
|
60
|
+
let(:xml) do
|
|
61
|
+
'<r a="x y" xmlns="urn:default"><item n="1">t1</item>' \
|
|
62
|
+
'<item n="2">t2<b>k</b></item><last/></r>'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "replays the callback event stream through the drain" do
|
|
66
|
+
drain_events = SaxDrainHandlers::EventCollector.new
|
|
67
|
+
context.sax_parse(xml, drain_events)
|
|
68
|
+
|
|
69
|
+
callback_events = SaxDrainHandlers::EventCollector.new
|
|
70
|
+
bridge = Moxml::Adapter::Leptris::LeptrisSAXBridge.new(callback_events)
|
|
71
|
+
Leptris::XML::SAX::Parser.new(bridge).parse(xml)
|
|
72
|
+
|
|
73
|
+
expect(drain_events.events).to eq(callback_events.events)
|
|
74
|
+
expect(drain_events.events.first).to eq([:start_document])
|
|
75
|
+
expect(drain_events.events).to include([:start, "item", { "n" => "1" }])
|
|
76
|
+
expect(drain_events.events).to include([:chars, "t2"])
|
|
77
|
+
expect(drain_events.events.last).to eq([:end_document])
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "hands claimed tables to handlers that opt in" do
|
|
81
|
+
claimant = SaxDrainHandlers::TableClaimant.new
|
|
82
|
+
context.sax_parse("<r><a>n</a></r>", claimant)
|
|
83
|
+
|
|
84
|
+
expect(claimant.tables.size).to eq(1)
|
|
85
|
+
expect(claimant.tables.first.count).to eq(3)
|
|
86
|
+
end
|
|
87
|
+
end
|
data/spec/moxml/text_spec.rb
CHANGED
|
@@ -14,6 +14,23 @@ RSpec.describe Moxml::Text do
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
describe "#text" do
|
|
18
|
+
it "matches content on a text node" do
|
|
19
|
+
text = doc.root.children.first
|
|
20
|
+
expect(text.text).to eq("plain text")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "is consistent across adapters" do
|
|
24
|
+
Moxml::Adapter::AVAILABLE_ADAPTERS.each do |adapter_name|
|
|
25
|
+
ctx = Moxml.new(adapter_name)
|
|
26
|
+
d = ctx.parse("<root>hello world</root>")
|
|
27
|
+
text = d.root.children.first
|
|
28
|
+
expect(text.text).to eq("hello world"),
|
|
29
|
+
"Text#text for #{adapter_name} adapter"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
17
34
|
describe "#to_xml" do
|
|
18
35
|
it "returns XML representation" do
|
|
19
36
|
text = doc.root.children.first
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: moxml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.81
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
14
|
Moxml is a unified XML manipulation library that provides a common API
|
|
@@ -160,6 +160,7 @@ files:
|
|
|
160
160
|
- lib/moxml/adapter/leptris/markers.rb
|
|
161
161
|
- lib/moxml/adapter/leptris/materialize.rb
|
|
162
162
|
- lib/moxml/adapter/leptris/sax_bridge.rb
|
|
163
|
+
- lib/moxml/adapter/leptris/sax_record_replay.rb
|
|
163
164
|
- lib/moxml/adapter/leptris/serialize.rb
|
|
164
165
|
- lib/moxml/adapter/libxml.rb
|
|
165
166
|
- lib/moxml/adapter/libxml/entity_ref_registry.rb
|
|
@@ -300,6 +301,7 @@ files:
|
|
|
300
301
|
- sig/moxml.rbs
|
|
301
302
|
- spec/consistency/README.md
|
|
302
303
|
- spec/consistency/adapter_parity_spec.rb
|
|
304
|
+
- spec/consistency/eol_normalization_spec.rb
|
|
303
305
|
- spec/consistency/round_trip_spec.rb
|
|
304
306
|
- spec/examples/README.md
|
|
305
307
|
- spec/examples/attribute_examples_spec.rb
|
|
@@ -435,6 +437,7 @@ files:
|
|
|
435
437
|
- spec/moxml/adapter/entity_restoration_spec.rb
|
|
436
438
|
- spec/moxml/adapter/headed_ox_spec.rb
|
|
437
439
|
- spec/moxml/adapter/leptris_doc_parts_spec.rb
|
|
440
|
+
- spec/moxml/adapter/leptris_sax_records_spec.rb
|
|
438
441
|
- spec/moxml/adapter/leptris_spec.rb
|
|
439
442
|
- spec/moxml/adapter/libxml_internals_spec.rb
|
|
440
443
|
- spec/moxml/adapter/libxml_spec.rb
|