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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 769900ed7676cee2de32bcb98a390616a5284bec301789ab95af7bc3d7384971
4
- data.tar.gz: 9bd2bcb7eda50b2d4246ec8caea424971e291c00cbc6789e14c18c9f1ed61b7f
3
+ metadata.gz: ded5a4e91431d2dc0aa52f5ed3a013dafe8ff9dc5dbcb3490a4793c2e50882bc
4
+ data.tar.gz: 132da396e0ecb742951521cfcc12f04e1a250bd81607d8f0b9a00db1c926712f
5
5
  SHA512:
6
- metadata.gz: bc5ad58955107e459f8432084c9a049d4217ac9b56a9a378969d14b88bcf8ac7cf582cfa9db899adb116ff5a1e4c88e93153eb9ef5d61066f3d6144045ccd359
7
- data.tar.gz: 1f8b0344a42afbf5c3c8b59e43fa72e322a8700ecc2d39c1450c14f1cbed31c2b81b910ce34f8b20f422792b8e92ddfff0ad967d3fc61f6301722b836dd6f242
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: DIGEST_SUPPORTED && engine_serves?(: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
- native_other = other.is_a?(::Leptris::XML::NativeNode)
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
- value = if NATIVE_READ_LAYER && element.is_a?(NN)
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
- return to_binding(node).target if NATIVE_READ_LAYER && node.is_a?(NN)
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
- return nil unless DIGEST_SUPPORTED
2392
- if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
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 NATIVE_READ_LAYER && element.is_a?(NN)
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) && ATTR_RESULT_NATIVE
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, NATIVE_SAX_RECORDS):
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 = NATIVE_SAX_RECORDS ? ::Leptris::XML::SAX::Records.open(xml_string) : nil
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 #452 rule index reads this document only; a document
241
- # that composes others (include/import/redefine/override)
242
- # turns the strict re-checks off (#510) — included parts stay
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.6.3"
4
+ VERSION = "0.6.4"
5
5
  end