moxml 0.6.3 → 0.6.4
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/docs/_pages/divergences.adoc +31 -0
- data/lib/moxml/adapter/leptris.rb +216 -21
- data/lib/moxml/context.rb +4 -5
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/xsd.rb +436 -2
- data/spec/moxml/adapter/leptris_children_address_spec.rb +171 -0
- data/spec/moxml/adapter/leptris_spec.rb +0 -6
- data/spec/moxml/xsd_composed_spec.rb +183 -0
- metadata +4 -3
- data/spec/moxml/adapter/leptris_children_columnar_spec.rb +0 -146
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ded5a4e91431d2dc0aa52f5ed3a013dafe8ff9dc5dbcb3490a4793c2e50882bc
|
|
4
|
+
data.tar.gz: 132da396e0ecb742951521cfcc12f04e1a250bd81607d8f0b9a00db1c926712f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df4fc2b129067c6ae6a7571abd150dcc53851e71a234cc11513842bddc45e4534502a983bd61c952ba8db8b54f85beefb9dc01dc4893e5df9155482ea2119758
|
|
7
|
+
data.tar.gz: 5703c216bd7bfd25da921e8c3b9f0dc9e87df3112cd644809a4564c1903007687611f1d734a8515b3477b8f75b6133eeb62ce0196a3d7ba6a4f3c1522448fb02
|
|
@@ -156,3 +156,34 @@ before leptris#1866's fix (the fix itself is not the cause); not a
|
|
|
156
156
|
regression of the fix. Noted in
|
|
157
157
|
`spec/moxml/adapter/leptris_crossdoc_replace_spec.rb`.
|
|
158
158
|
|===
|
|
159
|
+
|
|
160
|
+
| D-23
|
|
161
|
+
| leptris (XSD engine lane, before 1.9.409)
|
|
162
|
+
| Strict wildcard/anyAttribute admission consulted only the head
|
|
163
|
+
unit's declaration table, so items declared in a NON-head unit of a
|
|
164
|
+
composition (xsi:schemaLocation hint documents) got "not declared
|
|
165
|
+
(strict)" rows. The facade owns the composition: Schema#validate
|
|
166
|
+
resolves the instance's hints against the schema path, walks the
|
|
167
|
+
schema graph (include/import/redefine) for the unit closure, and
|
|
168
|
+
dismisses refutable rows — global declarations AND group members
|
|
169
|
+
(moxml#528; group admission this entry's companion). RESOLVED
|
|
170
|
+
engine-side by leptris/leptris#1964 (v1.9.409, namespace-aware
|
|
171
|
+
particle typing): the 16-case W3C set (attgD019-034, attgC035-038,
|
|
172
|
+
addB114) answers VALID through the facade. Verified through the
|
|
173
|
+
lutaml-xsd conformance runner (locations registration
|
|
174
|
+
lutaml/lutaml-xsd#234); pinned in `spec/moxml/xsd_composed_spec.rb`.
|
|
175
|
+
|
|
176
|
+
| D-24
|
|
177
|
+
| leptris (XSD engine lane, 1.9.409+)
|
|
178
|
+
| The 1.9.409 namespace-aware particle typing regresses the W3C
|
|
179
|
+
schG2 composition (A imports no-ns B; expected valid): the engine
|
|
180
|
+
types the no-namespace `<e1>` variant's children against ns-a's
|
|
181
|
+
same-name declarations, so the lane answers INVALID where the model
|
|
182
|
+
says VALID. v1.9.410 (leptris/leptris#1976) fixed the element
|
|
183
|
+
resolution — the false lexical rows for the import-RESOLVED compile
|
|
184
|
+
remain: the child-typing branch still resolves the no-ns `e1`'s
|
|
185
|
+
`<a1>` against ns-a's `ct-A`, tracked upstream as
|
|
186
|
+
leptris/leptris#1979. Until it lands the lexical rows pass through
|
|
187
|
+
the facade untouched (they are not admission rows and are never
|
|
188
|
+
dismissable).
|
|
189
|
+
|===
|
|
@@ -80,6 +80,28 @@ module Moxml
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
# The address-native lane's native (leptris-ruby#587/#589/#591):
|
|
84
|
+
# a node as (binding document, raw C address, parent-reported
|
|
85
|
+
# kind). Plain Ruby — one allocation per node, no TypedData
|
|
86
|
+
# wrap, no binding identity-cache crossing. Reads resolve
|
|
87
|
+
# through the address-keyed C faces; writes bridge through
|
|
88
|
+
# #to_binding (address + document answer the bridge's
|
|
89
|
+
# questions). The per-document token cache (#address_native)
|
|
90
|
+
# hands the SAME token back per address while the document is
|
|
91
|
+
# unmutated, so wrapper identity rides the context registry
|
|
92
|
+
# unchanged. +kind+ is the children_addrs integer (0 element,
|
|
93
|
+
# 1 text, 2 comment, 3 cdata, 4 pi) — VISIT_NODE_TYPES'
|
|
94
|
+
# order.
|
|
95
|
+
class AddressNode
|
|
96
|
+
attr_reader :document, :address, :kind
|
|
97
|
+
|
|
98
|
+
def initialize(document, address, kind)
|
|
99
|
+
@document = document
|
|
100
|
+
@address = address
|
|
101
|
+
@kind = kind
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
83
105
|
if Gem::Version.new(::Leptris::VERSION.to_s) <
|
|
84
106
|
Gem::Version.new(MINIMUM_BINDING_VERSION)
|
|
85
107
|
raise Moxml::AdapterError.new(
|
|
@@ -96,12 +118,10 @@ module Moxml
|
|
|
96
118
|
# Attribute-node xpath results carry proper wrappers since
|
|
97
119
|
# 1.9.105 (leptris-ruby#153: ResultAttr with name/value);
|
|
98
120
|
# before that the native gate routed them to the Ruby engine.
|
|
99
|
-
ATTR_RESULT_NATIVE = true
|
|
100
121
|
|
|
101
122
|
# leptris_node_digest shipped in bindings 1.9.99 (libleptris
|
|
102
123
|
# 1.9.99, engine #869): on-demand Merkle subtree hash, zero
|
|
103
124
|
# cost when unused. Below it, Node#digest answers nil.
|
|
104
|
-
DIGEST_SUPPORTED = true
|
|
105
125
|
|
|
106
126
|
# 1.9.163.7 added the XPath seams (TODO.perf/15+16):
|
|
107
127
|
# Searchable#at_xpath materializes nodeset entry 0 and frees
|
|
@@ -186,6 +206,20 @@ module Moxml
|
|
|
186
206
|
defined?(::Leptris::XML::Native) &&
|
|
187
207
|
::Leptris::XML::Native.respond_to?(:walk_columnar)
|
|
188
208
|
|
|
209
|
+
# The address-keyed shadow faces (leptris-ruby#587/#589/#591):
|
|
210
|
+
# children_addrs(parent) => [addrs, kinds] accepts a raw
|
|
211
|
+
# address Integer, and the fast_* read faces (name, element
|
|
212
|
+
# text, comment/cdata/pi payloads) read by address. The
|
|
213
|
+
# address-native lane mints a plain AddressNode per node
|
|
214
|
+
# instead of the TypedData wrap + identity-cache crossing the
|
|
215
|
+
# columnar lane pays in C. Face-probed, not version-gated.
|
|
216
|
+
ADDRESS_NATIVE =
|
|
217
|
+
defined?(::Leptris::XML::Native) &&
|
|
218
|
+
::Leptris::XML::Native.respond_to?(:children_addrs) &&
|
|
219
|
+
::Leptris::XML::Native.respond_to?(:walk_addresses) &&
|
|
220
|
+
::Leptris::XML::Native.respond_to?(:fast_name) &&
|
|
221
|
+
::Leptris::XML::Native.respond_to?(:fast_text_content)
|
|
222
|
+
|
|
189
223
|
# 1.9.163.2's native layer returns UTF-8, unfrozen strings
|
|
190
224
|
# (1.9.162.x answered ASCII-8BIT — the reads retagged with a
|
|
191
225
|
# dup+force_encoding per call).
|
|
@@ -240,7 +274,6 @@ module Moxml
|
|
|
240
274
|
# 1.9.181 (lockstep): Node#source_position — {line, col_start,
|
|
241
275
|
# col_end} from the engine's source-position API (upstream
|
|
242
276
|
# #1124); created nodes report zeros.
|
|
243
|
-
NATIVE_SOURCE_POSITION = true
|
|
244
277
|
|
|
245
278
|
# Entity-reference preservation (leptris-ruby#212 / upstream
|
|
246
279
|
# #1094): 1.9.177 ships ParseOptions.keep_entity_refs plus
|
|
@@ -268,7 +301,6 @@ module Moxml
|
|
|
268
301
|
# so the gate names the first release where the drain is
|
|
269
302
|
# CORRECT, not merely present. Dev floor pins ~> 1.9.238;
|
|
270
303
|
# older bindings take the callback Parser below.
|
|
271
|
-
NATIVE_SAX_RECORDS = true
|
|
272
304
|
|
|
273
305
|
# Document#absorb (engine #1548): one call transfers a source
|
|
274
306
|
# document's pool ownership into the destination, so
|
|
@@ -429,7 +461,7 @@ module Moxml
|
|
|
429
461
|
native_bulk_fixed: !NATIVE_BULK_FIXED.nil?,
|
|
430
462
|
native_plan_structs: NATIVE_PLAN_STRUCTS,
|
|
431
463
|
native_plan_typed: NATIVE_PLAN_TYPED,
|
|
432
|
-
digest:
|
|
464
|
+
digest: engine_serves?(:digest),
|
|
433
465
|
xsd: XSD_SUPPORTED && engine_serves?(:xsd),
|
|
434
466
|
relaxng: RELAXNG_SUPPORTED && engine_serves?(:relaxng),
|
|
435
467
|
xslt: XSLT_SUPPORTED && engine_serves?(:xslt),
|
|
@@ -664,12 +696,13 @@ module Moxml
|
|
|
664
696
|
|
|
665
697
|
def to_binding(node)
|
|
666
698
|
return node unless NATIVE_READ_LAYER &&
|
|
667
|
-
node.is_a?(::Leptris::XML::NativeNode)
|
|
699
|
+
(node.is_a?(::Leptris::XML::NativeNode) ||
|
|
700
|
+
node.is_a?(AddressNode))
|
|
668
701
|
|
|
669
702
|
bridged = @binding_of[node]
|
|
670
703
|
return bridged if bridged
|
|
671
704
|
|
|
672
|
-
doc = doc_for(node)
|
|
705
|
+
doc = node.is_a?(AddressNode) ? node.document : doc_for(node)
|
|
673
706
|
ptr = ::FFI::Pointer.new(node.address)
|
|
674
707
|
bridged = ::Leptris::XML::Node.wrap(ptr, doc)
|
|
675
708
|
@binding_of = fresh_node_registry if @binding_of.size >= BINDING_OF_CAP
|
|
@@ -918,6 +951,15 @@ module Moxml
|
|
|
918
951
|
# already-minted wrappers, so the adapter crossing
|
|
919
952
|
# (bind_call + to_a + keep-refs probe) drops out, and
|
|
920
953
|
# entity-marker documents take super for the split.
|
|
954
|
+
# NOTE (address-lane verdict, #531): the token arm was
|
|
955
|
+
# tried HERE and measured — tokens cannot serve the
|
|
956
|
+
# wrapper walk without breaking the klass-propagating
|
|
957
|
+
# identity contract (children vs element_children mint
|
|
958
|
+
# different wrapper classes for the same C node) and the
|
|
959
|
+
# wrapper lifecycle (tokens pin the binding document, so
|
|
960
|
+
# dropped documents stop releasing wrappers). The C-side
|
|
961
|
+
# klass-injected native cache is the walk lane; the
|
|
962
|
+
# address faces serve direct adapter consumers.
|
|
921
963
|
if NN.method_defined?(:children_read)
|
|
922
964
|
module ChildReads
|
|
923
965
|
def children
|
|
@@ -1093,8 +1135,10 @@ module Moxml
|
|
|
1093
1135
|
end
|
|
1094
1136
|
|
|
1095
1137
|
if NATIVE_READ_LAYER
|
|
1096
|
-
native_one = one.is_a?(::Leptris::XML::NativeNode)
|
|
1097
|
-
|
|
1138
|
+
native_one = one.is_a?(::Leptris::XML::NativeNode) ||
|
|
1139
|
+
one.is_a?(AddressNode)
|
|
1140
|
+
native_other = other.is_a?(::Leptris::XML::NativeNode) ||
|
|
1141
|
+
other.is_a?(AddressNode)
|
|
1098
1142
|
if native_one || native_other
|
|
1099
1143
|
address_one = native_one ? one.address : one.c_ptr.address
|
|
1100
1144
|
address_other = native_other ? other.address : other.c_ptr.address
|
|
@@ -1109,6 +1153,9 @@ module Moxml
|
|
|
1109
1153
|
# to the root (C-bound reads) and look the doc up in the
|
|
1110
1154
|
# root registry. Detached subtrees answer nil.
|
|
1111
1155
|
def doc_for(node)
|
|
1156
|
+
# Address tokens carry their document (set at mint).
|
|
1157
|
+
return node.document if node.is_a?(AddressNode)
|
|
1158
|
+
|
|
1112
1159
|
# The 1.9.163.5 native layer exposes the owning document
|
|
1113
1160
|
# directly; the root climb serves older bindings.
|
|
1114
1161
|
return NN_DOCUMENT.bind_call(node) if NATIVE_MUTATIONS_COHERENT
|
|
@@ -1572,8 +1619,13 @@ module Moxml
|
|
|
1572
1619
|
def bare_attr_value(element, name)
|
|
1573
1620
|
# Exact-name C read: bare names target no-namespace
|
|
1574
1621
|
# attributes (the documented contract — a bare "y" never
|
|
1575
|
-
# resolves a "p:y" sibling).
|
|
1576
|
-
|
|
1622
|
+
# resolves a "p:y" sibling). Address tokens take the
|
|
1623
|
+
# address-keyed attribute face.
|
|
1624
|
+
value = if element.is_a?(AddressNode)
|
|
1625
|
+
::Leptris::XML::Native.fast_attribute(
|
|
1626
|
+
element.address, name.to_s
|
|
1627
|
+
)
|
|
1628
|
+
elsif NATIVE_READ_LAYER && element.is_a?(NN)
|
|
1577
1629
|
NN_ATTRIBUTE.bind_call(element, name.to_s)
|
|
1578
1630
|
else
|
|
1579
1631
|
element[name.to_s]
|
|
@@ -2326,7 +2378,10 @@ module Moxml
|
|
|
2326
2378
|
end
|
|
2327
2379
|
|
|
2328
2380
|
def processing_instruction_target(node)
|
|
2329
|
-
|
|
2381
|
+
if NATIVE_READ_LAYER &&
|
|
2382
|
+
(node.is_a?(NN) || node.is_a?(AddressNode))
|
|
2383
|
+
return to_binding(node).target
|
|
2384
|
+
end
|
|
2330
2385
|
|
|
2331
2386
|
node.target
|
|
2332
2387
|
end
|
|
@@ -2344,6 +2399,12 @@ module Moxml
|
|
|
2344
2399
|
# complete on the snapshot itself.
|
|
2345
2400
|
return :attribute if node.is_a?(SnapshotAttribute)
|
|
2346
2401
|
|
|
2402
|
+
# Address tokens carry the parent-reported WS kind.
|
|
2403
|
+
if node.is_a?(AddressNode)
|
|
2404
|
+
mapped = VISIT_NODE_TYPES[node.kind]
|
|
2405
|
+
return mapped if mapped
|
|
2406
|
+
end
|
|
2407
|
+
|
|
2347
2408
|
if node.is_a?(::Leptris::XML::Node) &&
|
|
2348
2409
|
node.instance_variable_defined?(:@node_type)
|
|
2349
2410
|
kind = node.instance_variable_get(:@node_type)
|
|
@@ -2388,8 +2449,9 @@ module Moxml
|
|
|
2388
2449
|
# wrappers (declarations, doctypes, entity markers) and the
|
|
2389
2450
|
# lightweight Attr triples answer nil.
|
|
2390
2451
|
def digest(node, drop_ws_text: false)
|
|
2391
|
-
|
|
2392
|
-
|
|
2452
|
+
if NATIVE_READ_LAYER &&
|
|
2453
|
+
(node.is_a?(::Leptris::XML::NativeNode) ||
|
|
2454
|
+
node.is_a?(AddressNode))
|
|
2393
2455
|
return to_binding(node).digest(drop_ws: drop_ws_text)
|
|
2394
2456
|
end
|
|
2395
2457
|
return nil unless node.is_a?(::Leptris::XML::Node) &&
|
|
@@ -2401,6 +2463,18 @@ module Moxml
|
|
|
2401
2463
|
def node_name(node)
|
|
2402
2464
|
return node.root_name if node.is_a?(::Leptris::XML::DocType)
|
|
2403
2465
|
|
|
2466
|
+
# Address tokens: the fast_name face is element-only (nil
|
|
2467
|
+
# otherwise); PIs answer their target.
|
|
2468
|
+
if node.is_a?(AddressNode)
|
|
2469
|
+
if node.kind == 4
|
|
2470
|
+
return ::Leptris::XML::Native.fast_pi_target(
|
|
2471
|
+
node.address,
|
|
2472
|
+
).to_s
|
|
2473
|
+
end
|
|
2474
|
+
|
|
2475
|
+
return ::Leptris::XML::Native.fast_name(node.address).to_s
|
|
2476
|
+
end
|
|
2477
|
+
|
|
2404
2478
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
2405
2479
|
# PIs expose no name through the native layer.
|
|
2406
2480
|
return to_binding(node).target.to_s if NN_NODE_TYPE.bind_call(node) == :pi
|
|
@@ -2475,7 +2549,30 @@ module Moxml
|
|
|
2475
2549
|
return to_binding(node).children.to_a
|
|
2476
2550
|
end
|
|
2477
2551
|
|
|
2552
|
+
# Address tokens: element receivers take the token arm;
|
|
2553
|
+
# terminal kinds answer [] through the case chain below.
|
|
2554
|
+
if NATIVE_READ_LAYER && node.is_a?(AddressNode)
|
|
2555
|
+
doc = node.document
|
|
2556
|
+
return address_children(doc, node) if doc && node.kind.zero?
|
|
2557
|
+
|
|
2558
|
+
return []
|
|
2559
|
+
end
|
|
2560
|
+
|
|
2478
2561
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
2562
|
+
# The address-native arm outranks the columnar lane: the
|
|
2563
|
+
# same child lists, but the tokens are plain
|
|
2564
|
+
# (document, address, kind) AddressNodes — the columnar
|
|
2565
|
+
# crossing mints a TypedData wrap + identity-cache write
|
|
2566
|
+
# per node in C, this arm allocates one plain token per
|
|
2567
|
+
# node in Ruby (ADDRESS_NATIVE above). Element receivers
|
|
2568
|
+
# only: their children's kinds are the WS enum the token
|
|
2569
|
+
# carries; document receivers keep the assembly path
|
|
2570
|
+
# (declaration/doctype kinds are outside the enum).
|
|
2571
|
+
if ADDRESS_NATIVE && !entity_bearing && element_native?(node)
|
|
2572
|
+
doc = doc_for(node)
|
|
2573
|
+
return address_children(doc, node) if doc
|
|
2574
|
+
end
|
|
2575
|
+
|
|
2479
2576
|
# Bulk C children through moxml's own scratch (see
|
|
2480
2577
|
# NATIVE_READ_LAYER note above). Entity-marker documents
|
|
2481
2578
|
# bridge each child for the marker split — the
|
|
@@ -2539,15 +2636,67 @@ module Moxml
|
|
|
2539
2636
|
CustomizedLeptris::EntityReference, CustomizedLeptris::TextSegment,
|
|
2540
2637
|
# Terminal node kinds pay an FFI round trip for an empty
|
|
2541
2638
|
# list; unfiltered recursions visit every text node.
|
|
2639
|
+
# Address tokens of the terminal kinds (text, comment,
|
|
2640
|
+
# cdata, pi) have no children either.
|
|
2542
2641
|
::Leptris::XML::Text, ::Leptris::XML::Comment,
|
|
2543
2642
|
::Leptris::XML::CDATA, ::Leptris::XML::ProcessingInstruction,
|
|
2544
|
-
::Leptris::XML::Attr
|
|
2643
|
+
::Leptris::XML::Attr, AddressNode
|
|
2545
2644
|
[]
|
|
2546
2645
|
else
|
|
2547
2646
|
node.children.to_a
|
|
2548
2647
|
end
|
|
2549
2648
|
end
|
|
2550
2649
|
|
|
2650
|
+
# The address-native arm's child list: one children_addrs
|
|
2651
|
+
# crossing, one token per child (ADDRESS_NATIVES cache for
|
|
2652
|
+
# identity stability).
|
|
2653
|
+
ADDRESS_NATIVES = :address_natives
|
|
2654
|
+
|
|
2655
|
+
def address_children(doc, node)
|
|
2656
|
+
addrs, kinds = ::Leptris::XML::Native.children_addrs(
|
|
2657
|
+
node.is_a?(AddressNode) ? node.address : node,
|
|
2658
|
+
)
|
|
2659
|
+
children = Array.new(addrs.size)
|
|
2660
|
+
i = 0
|
|
2661
|
+
while i < addrs.size
|
|
2662
|
+
children[i] = address_native(doc, addrs[i], kinds[i])
|
|
2663
|
+
i += 1
|
|
2664
|
+
end
|
|
2665
|
+
children
|
|
2666
|
+
end
|
|
2667
|
+
|
|
2668
|
+
# One address token per (document version, address): the
|
|
2669
|
+
# context registry keys wrapper identity on the token, so a
|
|
2670
|
+
# stable token per address keeps the children[0].equal?
|
|
2671
|
+
# semantics across traversals. The document version stamps
|
|
2672
|
+
# the map — any mutation invalidates wholesale, the same
|
|
2673
|
+
# discipline as the columnar map and the binding's own
|
|
2674
|
+
# children memo.
|
|
2675
|
+
ADDRESS_NATIVES_CAP = 1_048_576
|
|
2676
|
+
|
|
2677
|
+
def address_native(doc, address, kind)
|
|
2678
|
+
pair = attachments.get(doc, ADDRESS_NATIVES)
|
|
2679
|
+
unless pair.is_a?(Array) && pair[0] == doc.version
|
|
2680
|
+
pair = [doc.version, {}]
|
|
2681
|
+
attachments.set(doc, ADDRESS_NATIVES, pair)
|
|
2682
|
+
end
|
|
2683
|
+
map = pair[1]
|
|
2684
|
+
map.clear if map.size >= ADDRESS_NATIVES_CAP
|
|
2685
|
+
token = map[address]
|
|
2686
|
+
return token if token
|
|
2687
|
+
|
|
2688
|
+
token = AddressNode.new(doc, address, kind)
|
|
2689
|
+
map[address] = token
|
|
2690
|
+
token
|
|
2691
|
+
end
|
|
2692
|
+
|
|
2693
|
+
# Element-ness of a native receiver, for the address arm's
|
|
2694
|
+
# gate (one kind read; the token lane answers from the
|
|
2695
|
+
# parent-reported kind without a crossing).
|
|
2696
|
+
def element_native?(node)
|
|
2697
|
+
NN_NODE_TYPE.bind_call(node) == :element
|
|
2698
|
+
end
|
|
2699
|
+
|
|
2551
2700
|
# Map hit for a primed node (see COLUMNAR_WALK). Served dup'd so
|
|
2552
2701
|
# no consumer can mutate the cached list in place.
|
|
2553
2702
|
def columnar_children_hit(node)
|
|
@@ -2737,6 +2886,24 @@ module Moxml
|
|
|
2737
2886
|
def root_parent(node)
|
|
2738
2887
|
return node.document if node.is_a?(::Leptris::XML::DocType)
|
|
2739
2888
|
|
|
2889
|
+
# Address tokens carry no parent face: bridge once, then
|
|
2890
|
+
# answer through the binding parent — as a document-cache
|
|
2891
|
+
# twin so the answer stays in the native representation.
|
|
2892
|
+
# The binding reports the root element and document-level
|
|
2893
|
+
# parts parentless; the moxml contract roots them at the
|
|
2894
|
+
# document (same rule as the binding arm below).
|
|
2895
|
+
if node.is_a?(AddressNode)
|
|
2896
|
+
doc = node.document
|
|
2897
|
+
bound = to_binding(node)
|
|
2898
|
+
parent = bound&.parent
|
|
2899
|
+
return native_twin(doc, parent) if parent
|
|
2900
|
+
|
|
2901
|
+
return doc if doc && (doc.root&.c_address == node.address ||
|
|
2902
|
+
bound.is_a?(::Leptris::XML::ProcessingInstruction))
|
|
2903
|
+
|
|
2904
|
+
return nil
|
|
2905
|
+
end
|
|
2906
|
+
|
|
2740
2907
|
parent = node.parent
|
|
2741
2908
|
return parent if parent
|
|
2742
2909
|
|
|
@@ -2750,6 +2917,8 @@ module Moxml
|
|
|
2750
2917
|
end
|
|
2751
2918
|
|
|
2752
2919
|
def next_sibling(node)
|
|
2920
|
+
return next_sibling(to_binding(node)) if node.is_a?(AddressNode)
|
|
2921
|
+
|
|
2753
2922
|
return NN_NEXT_SIBLING.bind_call(node) if NATIVE_READ_LAYER &&
|
|
2754
2923
|
node.is_a?(::Leptris::XML::NativeNode)
|
|
2755
2924
|
|
|
@@ -2766,6 +2935,8 @@ module Moxml
|
|
|
2766
2935
|
end
|
|
2767
2936
|
|
|
2768
2937
|
def document(node)
|
|
2938
|
+
return node.document if node.is_a?(AddressNode)
|
|
2939
|
+
|
|
2769
2940
|
return doc_for(node) if NATIVE_READ_LAYER &&
|
|
2770
2941
|
node.is_a?(::Leptris::XML::NativeNode)
|
|
2771
2942
|
|
|
@@ -2792,8 +2963,6 @@ module Moxml
|
|
|
2792
2963
|
end
|
|
2793
2964
|
|
|
2794
2965
|
def source_position(node)
|
|
2795
|
-
return nil unless NATIVE_SOURCE_POSITION
|
|
2796
|
-
|
|
2797
2966
|
to_binding(node).source_position
|
|
2798
2967
|
end
|
|
2799
2968
|
|
|
@@ -2919,7 +3088,9 @@ module Moxml
|
|
|
2919
3088
|
end
|
|
2920
3089
|
|
|
2921
3090
|
def attr_packet_target(element)
|
|
2922
|
-
if
|
|
3091
|
+
if element.is_a?(AddressNode)
|
|
3092
|
+
[element.document, element.address]
|
|
3093
|
+
elsif NATIVE_READ_LAYER && element.is_a?(NN)
|
|
2923
3094
|
[NN_DOCUMENT.bind_call(element), element.address]
|
|
2924
3095
|
elsif element.respond_to?(:c_address)
|
|
2925
3096
|
[element.document, element.c_address]
|
|
@@ -3738,6 +3909,22 @@ module Moxml
|
|
|
3738
3909
|
end
|
|
3739
3910
|
|
|
3740
3911
|
def text_content(node)
|
|
3912
|
+
# Address tokens dispatch the same kind table the native
|
|
3913
|
+
# layer's #content uses (elements aggregate via
|
|
3914
|
+
# fast_element_text; text/comment/cdata/pi carry their
|
|
3915
|
+
# payload faces).
|
|
3916
|
+
if node.is_a?(AddressNode)
|
|
3917
|
+
native = ::Leptris::XML::Native
|
|
3918
|
+
content = case node.kind
|
|
3919
|
+
when 0 then native.fast_element_text(node.address)
|
|
3920
|
+
when 1 then native.fast_text_content(node.address)
|
|
3921
|
+
when 2 then native.fast_comment_content(node.address)
|
|
3922
|
+
when 3 then native.fast_cdata_content(node.address)
|
|
3923
|
+
when 4 then native.fast_pi_data(node.address)
|
|
3924
|
+
end
|
|
3925
|
+
return content.to_s
|
|
3926
|
+
end
|
|
3927
|
+
|
|
3741
3928
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
3742
3929
|
content = NN_CONTENT.bind_call(node)
|
|
3743
3930
|
return content if NATIVE_STRINGS_UTF8
|
|
@@ -3833,6 +4020,10 @@ module Moxml
|
|
|
3833
4020
|
end
|
|
3834
4021
|
|
|
3835
4022
|
def cdata_content(node)
|
|
4023
|
+
if node.is_a?(AddressNode)
|
|
4024
|
+
return ::Leptris::XML::Native.fast_cdata_content(node.address)
|
|
4025
|
+
end
|
|
4026
|
+
|
|
3836
4027
|
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
3837
4028
|
|
|
3838
4029
|
node.content
|
|
@@ -3844,6 +4035,10 @@ module Moxml
|
|
|
3844
4035
|
end
|
|
3845
4036
|
|
|
3846
4037
|
def comment_content(node)
|
|
4038
|
+
if node.is_a?(AddressNode)
|
|
4039
|
+
return ::Leptris::XML::Native.fast_comment_content(node.address)
|
|
4040
|
+
end
|
|
4041
|
+
|
|
3847
4042
|
if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
3848
4043
|
content = NN_CONTENT.bind_call(node)
|
|
3849
4044
|
# NativeNode#content answers nil for comment-kind nodes
|
|
@@ -4220,7 +4415,7 @@ module Moxml
|
|
|
4220
4415
|
# (leptris-ruby#153: ResultAttr wrappers with name/value);
|
|
4221
4416
|
# older bindings returned generic Node wrappers whose
|
|
4222
4417
|
# #name raised, so the Ruby engine owned them.
|
|
4223
|
-
next true if selects_attribute_results?(ast)
|
|
4418
|
+
next true if selects_attribute_results?(ast)
|
|
4224
4419
|
|
|
4225
4420
|
!selects_attribute_results?(ast)
|
|
4226
4421
|
end
|
|
@@ -4331,14 +4526,14 @@ module Moxml
|
|
|
4331
4526
|
def sax_parse(xml, handler)
|
|
4332
4527
|
bridge = LeptrisSAXBridge.new(handler)
|
|
4333
4528
|
xml_string = xml.is_a?(IO) || xml.is_a?(::StringIO) ? xml.read : xml.to_s
|
|
4334
|
-
# Bulk record drain (leptris#1298
|
|
4529
|
+
# Bulk record drain (leptris#1298):
|
|
4335
4530
|
# one crossing per document. The handler decides the shape
|
|
4336
4531
|
# polymorphically — Handler#on_sax_records answers
|
|
4337
4532
|
# :unhandled, so classic handlers get the exact callback
|
|
4338
4533
|
# stream replayed from the table; hot loops override and
|
|
4339
4534
|
# walk the records (nil table = outside the drain subset
|
|
4340
4535
|
# or pre-1.9.238 binding — callback path).
|
|
4341
|
-
table =
|
|
4536
|
+
table = ::Leptris::XML::SAX::Records.open(xml_string)
|
|
4342
4537
|
if table
|
|
4343
4538
|
begin
|
|
4344
4539
|
return if handler.on_sax_records(table) != :unhandled
|
data/lib/moxml/context.rb
CHANGED
|
@@ -237,14 +237,13 @@ module Moxml
|
|
|
237
237
|
# Compile an XSD schema from a file path — <xs:include href>
|
|
238
238
|
# resolves relative to the file's directory (the engine
|
|
239
239
|
# resolves it; reading the file into #xsd would lose that).
|
|
240
|
-
# The
|
|
241
|
-
#
|
|
242
|
-
#
|
|
243
|
-
# engine-validated and the index can only under-report.
|
|
240
|
+
# The path is kept on the Schema (moxml#522): #validate resolves
|
|
241
|
+
# the instance's xsi:schemaLocation hints against it and unions
|
|
242
|
+
# the hinted documents into the compiled set.
|
|
244
243
|
def xsd_file(path)
|
|
245
244
|
handle = config.adapter.xsd_compile_file(path.to_s)
|
|
246
245
|
source = File.read(path.to_s)
|
|
247
|
-
Moxml::XSD::Schema.new(handle, self, source)
|
|
246
|
+
Moxml::XSD::Schema.new(handle, self, source, path: path.to_s)
|
|
248
247
|
end
|
|
249
248
|
|
|
250
249
|
# Compile a SET of schema documents (paths) into one schema:
|
data/lib/moxml/version.rb
CHANGED