moxml 0.5.165 → 0.5.167

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.
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ # Processing model §Validation (normative): pinned here.
6
+ # #466 class 1: the engine's content-model matcher matches
7
+ # particles by exact name only, so a valid substitution-group
8
+ # member is rejected with "children do not match the content
9
+ # model". The Ruby-side dismissal drops such a finding only when
10
+ # the parent's content model is a pure sequence, the child
11
+ # sequence matches it position-for-position with every particle
12
+ # exactly-once, and a registered member realizes a position —
13
+ # any choice/all, cardinality violation, or unknown name keeps
14
+ # the engine's answer, so the dismissal can only remove false
15
+ # rejections, never create false acceptances.
16
+ RSpec.describe "Moxml::XSD substitution-group dismissal (#466)" do
17
+ %i[nokogiri leptris].each do |adapter_name|
18
+ describe "on #{adapter_name}" do
19
+ let(:ctx) { Moxml.new(adapter_name) }
20
+
21
+ before do
22
+ skip "#{adapter_name} requires an XSD-capable engine" unless
23
+ Moxml::XSD.supported?(ctx)
24
+ end
25
+
26
+ describe "member of a referenced head particle" do
27
+ let(:schema) do
28
+ ctx.xsd(<<~XSD)
29
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
30
+ xmlns:x="http://xsdtesting"
31
+ targetNamespace="http://xsdtesting"
32
+ elementFormDefault="qualified">
33
+ <xsd:element name="doc">
34
+ <xsd:complexType>
35
+ <xsd:sequence>
36
+ <xsd:element ref="x:elem1"/>
37
+ </xsd:sequence>
38
+ </xsd:complexType>
39
+ </xsd:element>
40
+ <xsd:element name="elem1" abstract="false"/>
41
+ <xsd:element name="elem2" substitutionGroup="x:elem1"/>
42
+ </xsd:schema>
43
+ XSD
44
+ end
45
+
46
+ it "accepts the member where the head is declared" do
47
+ doc = ctx.parse(
48
+ '<x:doc xmlns:x="http://xsdtesting"><x:elem2/></x:doc>',
49
+ )
50
+ expect(schema.valid?(doc)).to be(true)
51
+ end
52
+
53
+ it "accepts the head itself" do
54
+ doc = ctx.parse(
55
+ '<x:doc xmlns:x="http://xsdtesting"><x:elem1/></x:doc>',
56
+ )
57
+ expect(schema.valid?(doc)).to be(true)
58
+ end
59
+
60
+ it "rejects a stray non-member child" do
61
+ doc = ctx.parse(
62
+ '<x:doc xmlns:x="http://xsdtesting"><x:unknown/></x:doc>',
63
+ )
64
+ expect(schema.valid?(doc)).to be(false)
65
+ end
66
+ end
67
+
68
+ describe "member inside a nested sequence" do
69
+ let(:schema) do
70
+ ctx.xsd(<<~XSD)
71
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
72
+ xmlns:x="http://xsdtesting"
73
+ targetNamespace="http://xsdtesting"
74
+ elementFormDefault="qualified">
75
+ <xsd:element name="doc">
76
+ <xsd:complexType>
77
+ <xsd:sequence>
78
+ <xsd:element ref="x:mid"/>
79
+ </xsd:sequence>
80
+ </xsd:complexType>
81
+ </xsd:element>
82
+ <xsd:element name="mid">
83
+ <xsd:complexType>
84
+ <xsd:sequence>
85
+ <xsd:element ref="x:elem1"/>
86
+ </xsd:sequence>
87
+ </xsd:complexType>
88
+ </xsd:element>
89
+ <xsd:element name="elem1" abstract="false"/>
90
+ <xsd:element name="elem2" substitutionGroup="x:elem1"/>
91
+ </xsd:schema>
92
+ XSD
93
+ end
94
+
95
+ it "accepts the member at the inner position" do
96
+ doc = ctx.parse(
97
+ '<x:doc xmlns:x="http://xsdtesting">' \
98
+ "<x:mid><x:elem2/></x:mid></x:doc>",
99
+ )
100
+ expect(schema.valid?(doc)).to be(true)
101
+ end
102
+ end
103
+
104
+ describe "models the dismissal refuses" do
105
+ let(:schema) do
106
+ ctx.xsd(<<~XSD)
107
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
108
+ xmlns:x="http://xsdtesting"
109
+ targetNamespace="http://xsdtesting"
110
+ elementFormDefault="qualified">
111
+ <xsd:element name="doc">
112
+ <xsd:complexType>
113
+ <xsd:choice>
114
+ <xsd:element ref="x:elem1"/>
115
+ <xsd:element name="other"/>
116
+ </xsd:choice>
117
+ </xsd:complexType>
118
+ </xsd:element>
119
+ <xsd:element name="elem1" abstract="false"/>
120
+ <xsd:element name="elem2" substitutionGroup="x:elem1"/>
121
+ </xsd:schema>
122
+ XSD
123
+ end
124
+
125
+ it "keeps the engine's answer for a two-child choice match" do
126
+ # A choice takes one item; two children cannot be valid
127
+ # even though both names resolve — the flattened particle
128
+ # list is not a validity witness for non-sequences.
129
+ doc = ctx.parse(
130
+ '<x:doc xmlns:x="http://xsdtesting">' \
131
+ "<x:elem2/><x:other/></x:doc>",
132
+ )
133
+ expect(schema.valid?(doc)).to be(false)
134
+ end
135
+ end
136
+
137
+ describe "cardinality the dismissal refuses" do
138
+ let(:schema) do
139
+ ctx.xsd(<<~XSD)
140
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
141
+ xmlns:x="http://xsdtesting"
142
+ targetNamespace="http://xsdtesting"
143
+ elementFormDefault="qualified">
144
+ <xsd:element name="doc">
145
+ <xsd:complexType>
146
+ <xsd:sequence>
147
+ <xsd:element ref="x:elem1" minOccurs="2" maxOccurs="2"/>
148
+ </xsd:sequence>
149
+ </xsd:complexType>
150
+ </xsd:element>
151
+ <xsd:element name="elem1" abstract="false"/>
152
+ <xsd:element name="elem2" substitutionGroup="x:elem1"/>
153
+ </xsd:schema>
154
+ XSD
155
+ end
156
+
157
+ it "keeps the engine's answer below minOccurs" do
158
+ doc = ctx.parse(
159
+ '<x:doc xmlns:x="http://xsdtesting"><x:elem2/></x:doc>',
160
+ )
161
+ expect(schema.valid?(doc)).to be(false)
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -89,10 +89,18 @@ module ModelCoverage
89
89
  section: "Validation",
90
90
  pin: "spec/moxml/xsd_version_spec.rb",
91
91
  },
92
+ "validation engine metadata" => {
93
+ section: "Validation",
94
+ pin: "spec/moxml/xsd_engine_meta_spec.rb",
95
+ },
92
96
  "validation regex dismissal" => {
93
97
  section: "Validation",
94
98
  pin: "spec/moxml/xsd_regex_spec.rb",
95
99
  },
100
+ "validation substitution dismissal" => {
101
+ section: "Validation",
102
+ pin: "spec/moxml/xsd_substitution_spec.rb",
103
+ },
96
104
  "loud capability contracts" => {
97
105
  section: "Errors and loud degradation",
98
106
  pin: "spec/consistency/loud_degradation_spec.rb",
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.165
4
+ version: 0.5.167
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-10-26 00:00:00.000000000 Z
11
+ date: 2026-10-28 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
@@ -486,11 +486,13 @@ files:
486
486
  - spec/moxml/adapter/leptris_binding_cap_spec.rb
487
487
  - spec/moxml/adapter/leptris_children_columnar_spec.rb
488
488
  - spec/moxml/adapter/leptris_contract_reads_spec.rb
489
+ - spec/moxml/adapter/leptris_crossdoc_replace_spec.rb
489
490
  - spec/moxml/adapter/leptris_detached_text_spec.rb
490
491
  - spec/moxml/adapter/leptris_doc_parts_spec.rb
491
492
  - spec/moxml/adapter/leptris_document_children_older_binding_spec.rb
492
493
  - spec/moxml/adapter/leptris_document_declaration_spec.rb
493
494
  - spec/moxml/adapter/leptris_inbody_comment_spec.rb
495
+ - spec/moxml/adapter/leptris_native_parent_axis_spec.rb
494
496
  - spec/moxml/adapter/leptris_parse_lint_spec.rb
495
497
  - spec/moxml/adapter/leptris_parse_skips_spec.rb
496
498
  - spec/moxml/adapter/leptris_record_driver_spec.rb
@@ -629,11 +631,13 @@ files:
629
631
  - spec/moxml/xpath/union_spec.rb
630
632
  - spec/moxml/xpath_capabilities_spec.rb
631
633
  - spec/moxml/xpath_spec.rb
634
+ - spec/moxml/xsd_engine_meta_spec.rb
632
635
  - spec/moxml/xsd_error_contract_spec.rb
633
636
  - spec/moxml/xsd_handle_mismatch_spec.rb
634
637
  - spec/moxml/xsd_regex_spec.rb
635
638
  - spec/moxml/xsd_release_spec.rb
636
639
  - spec/moxml/xsd_spec.rb
640
+ - spec/moxml/xsd_substitution_spec.rb
637
641
  - spec/moxml/xsd_underdetection_spec.rb
638
642
  - spec/moxml/xsd_version_spec.rb
639
643
  - spec/moxml/xslt/stylesheet_spec.rb