moxml 0.5.176 → 0.5.177

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: b00ba396700e1ee797651d8db90cc283733f062021e05d8c807c751a07442414
4
- data.tar.gz: f0f35b75c740842a6bb4a21c0fde3b944e5994c2935a1de0e57b6671d02eb2fe
3
+ metadata.gz: 021a0d5d25cfe9e12a0a29968649a0801d0379e30b4f6aefe349d86a8959149b
4
+ data.tar.gz: 197a8e2c303f7fa1e29e7f25b8d64502d6c3d3179ca342af4b02dda168e7fa89
5
5
  SHA512:
6
- metadata.gz: 8302fa56d49d9e6965559bf2be0db79afc61b5d6696cbe34aa5f6ff07381af94261b2988f858d76d5625cb7796b84c70999a6e899e7d5b5c61cdd58134dba462
7
- data.tar.gz: 349a9bf1e50540698ee21572f29c93db127d206bca9ab622fed3c989ed601af0109181b9b107ac06c27f17432cf98402ab2118d3ba6f8b0976b8ee7542fd74d8
6
+ metadata.gz: cddcf3bb2b304e5d78779cba12b3f57514b783336642a8e40ca7d8894ba47485ef6ffff114b9f8a1430e6b9669067c86f4de2bbd53aac6d18ed8ffef52828d5f
7
+ data.tar.gz: 6d88eb872c4a876d9f387af3e006eb8247935ff58f70c6d3249d6b3afba7809e3485c117fbeaa3dc61103ab9858997b98c230efc870e0dac0a914971bb20e49e
data/lib/moxml/context.rb CHANGED
@@ -214,9 +214,10 @@ module Moxml
214
214
  # Compile an XSD schema from a file path — <xs:include href>
215
215
  # resolves relative to the file's directory (the engine
216
216
  # resolves it; reading the file into #xsd would lose that).
217
- # The #452 rule index reads this document only; included
218
- # schema parts stay engine-validated (the index can only
219
- # under-report).
217
+ # The #452 rule index reads this document only; a document
218
+ # that composes others (include/import/redefine/override)
219
+ # turns the strict re-checks off (#510) — included parts stay
220
+ # engine-validated and the index can only under-report.
220
221
  def xsd_file(path)
221
222
  handle = config.adapter.xsd_compile_file(path.to_s)
222
223
  source = File.read(path.to_s)
@@ -229,7 +230,10 @@ module Moxml
229
230
  # types) are visible to the head's content models — the
230
231
  # single-document faces cannot see them (#483 item 4). The
231
232
  # Schema's #version / SchemaRules index read the HEAD document
232
- # (the first path); engine-set semantics cover the rest.
233
+ # (the first path); engine-set semantics cover the rest. A set
234
+ # is composition-shaped by contract, so the strict re-checks
235
+ # stay off (#510): the index under-reports instead of
236
+ # false-reporting components that live in a member.
233
237
  # Adapters without a set-capable engine raise
234
238
  # Moxml::NotImplementedError.
235
239
  def xsd_set(*paths)
@@ -238,7 +242,7 @@ module Moxml
238
242
 
239
243
  handle = config.adapter.xsd_compile_set(paths.map(&:to_s))
240
244
  source = File.read(paths.first.to_s)
241
- Moxml::XSD::Schema.new(handle, self, source)
245
+ Moxml::XSD::Schema.new(handle, self, source, self_contained: false)
242
246
  end
243
247
 
244
248
  # Compile a RELAX NG schema from source or from a file path (the
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.5.176"
4
+ VERSION = "0.5.177"
5
5
  end
@@ -197,7 +197,7 @@ module Moxml
197
197
  :attribute_default, :elements,
198
198
  :attributes, :contents, :version,
199
199
  :element_patterns, :attribute_patterns,
200
- :substitution_members)
200
+ :substitution_members, :self_contained)
201
201
 
202
202
  # Resolves a QName token against an element's in-scope
203
203
  # bindings. node.namespaces is adapter-divergent (some
@@ -338,7 +338,7 @@ module Moxml
338
338
  # Index one schema document. Returns nil when the source
339
339
  # cannot be indexed — the engine's answer then stands alone
340
340
  # (today's behavior).
341
- def index(schema_source, context)
341
+ def index(schema_source, context, self_contained: nil)
342
342
  root = context.parse(schema_source).root
343
343
  return nil unless root&.name == "schema"
344
344
 
@@ -346,7 +346,8 @@ module Moxml
346
346
  root["targetNamespace"].to_s,
347
347
  root["elementFormDefault"] == "qualified",
348
348
  root["attributeFormDefault"] == "qualified",
349
- {}, {}, {}, schema_version(root), {}, {}, {}
349
+ {}, {}, {}, schema_version(root), {}, {}, {},
350
+ self_contained.nil? ? composition_free?(root) : self_contained
350
351
  )
351
352
  child_elements(root).each do |decl|
352
353
  case decl.name
@@ -360,6 +361,24 @@ module Moxml
360
361
  nil
361
362
  end
362
363
 
364
+ COMPOSITION_ELEMENTS = %w[include import redefine override].freeze
365
+
366
+ # A schema document that composes other documents
367
+ # (include/import/redefine/override) declares only part of
368
+ # the compiled declaration surface in its own source — the
369
+ # engine resolves the members, and a strict re-check run
370
+ # against this index alone would answer "not declared" for
371
+ # components that live in a member (#510): a false report,
372
+ # which the one-directional contract forbids. Composition
373
+ # therefore turns the strict re-checks off — the index
374
+ # under-reports instead. Schema sets (xsd_set) are always
375
+ # composition-shaped: any member may carry declarations.
376
+ def composition_free?(root)
377
+ child_elements(root).none? do |decl|
378
+ COMPOSITION_ELEMENTS.include?(decl.name)
379
+ end
380
+ end
381
+
363
382
  # The effective schema version declared at the root
364
383
  # (#460 item 2): vc:minVersion="1.1" on <xs:schema> scopes
365
384
  # the document to 1.1 semantics; anything else reports
@@ -606,12 +625,18 @@ module Moxml
606
625
  model = index.contents[root_qname]
607
626
  findings = []
608
627
  findings << nil_finding(root, declaration) if declaration
609
- findings.concat(attribute_findings(root, model, index))
610
- if model
628
+ # The strict wildcard/attribute re-checks answer "not
629
+ # declared" against this index's declaration sets — they
630
+ # vouch only when the index saw the whole declaration
631
+ # surface (no composition, #510).
632
+ if model && index.self_contained
611
633
  child_elements(root).each do |child|
612
634
  findings.concat(child_findings(child, model, index))
613
635
  end
614
636
  end
637
+ if index.self_contained
638
+ findings.concat(attribute_findings(root, model, index))
639
+ end
615
640
  findings.compact
616
641
  end
617
642
 
data/lib/moxml/xsd.rb CHANGED
@@ -96,11 +96,15 @@ module Moxml
96
96
  "schema released (deterministic drop); compile a new one"
97
97
  end
98
98
 
99
- def initialize(handle, context, schema_source = nil)
99
+ def initialize(handle, context, schema_source = nil,
100
+ self_contained: nil)
100
101
  @handle = handle
101
102
  @context = context
102
103
  @rules_index =
103
- schema_source && SchemaRules.index(schema_source, context)
104
+ if schema_source
105
+ SchemaRules.index(schema_source, context,
106
+ self_contained: self_contained)
107
+ end
104
108
  assert_adapter_matches_handle!
105
109
  end
106
110
 
@@ -82,6 +82,84 @@ RSpec.describe "Schema-set compilation" do
82
82
  end
83
83
  end
84
84
 
85
+ # #510: the strict re-check answers "not declared" against the
86
+ # head document's own declaration index; composition (a set, or a
87
+ # single document carrying include/import/redefine/override)
88
+ # means declarations may live in a member the index never saw —
89
+ # the re-check must stay silent (under-report, never
90
+ # false-report) and let the engine's set-wide answer stand.
91
+ describe "strict re-check across composed schemas (#510)" do
92
+ def write_wildcard_set(dir)
93
+ File.write(File.join(dir, "headw.xsd"), <<~XSD)
94
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
95
+ xmlns="urn:W" targetNamespace="urn:W">
96
+ <xs:import namespace="urn:D" schemaLocation="decl.xsd"/>
97
+ <xs:element name="foo">
98
+ <xs:complexType>
99
+ <xs:sequence>
100
+ <xs:any namespace="##other" processContents="strict"/>
101
+ </xs:sequence>
102
+ </xs:complexType>
103
+ </xs:element>
104
+ </xs:schema>
105
+ XSD
106
+ File.write(File.join(dir, "decl.xsd"), <<~XSD)
107
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
108
+ xmlns="urn:D" targetNamespace="urn:D">
109
+ <xs:element name="bar" type="xs:string"/>
110
+ </xs:schema>
111
+ XSD
112
+ [File.join(dir, "headw.xsd"), File.join(dir, "decl.xsd")]
113
+ end
114
+
115
+ def wildcard_instance
116
+ '<foo xmlns="urn:W" xmlns:d="urn:D"><d:bar>hi</d:bar></foo>'
117
+ end
118
+
119
+ it "does not false-report a member-declared admission on a set" do
120
+ skip "requires the leptris compile_set face (binding 1.9.386.0+)" unless
121
+ set_capable?
122
+
123
+ Dir.mktmpdir do |dir|
124
+ paths = write_wildcard_set(dir)
125
+ schema = ctx.xsd_set(*paths)
126
+ expect(schema.validate(wildcard_instance)).to be_empty
127
+ end
128
+ end
129
+
130
+ it "does not false-report on a single composing document" do
131
+ Dir.mktmpdir do |dir|
132
+ write_wildcard_set(dir)
133
+ schema = ctx.xsd_file(File.join(dir, "headw.xsd"))
134
+ expect(schema.validate(wildcard_instance)).to be_empty
135
+ end
136
+ end
137
+
138
+ it "keeps the re-check on a self-contained schema" do
139
+ Dir.mktmpdir do |dir|
140
+ path = File.join(dir, "solo.xsd")
141
+ File.write(path, <<~XSD)
142
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
143
+ xmlns="urn:S" targetNamespace="urn:S">
144
+ <xs:element name="solo">
145
+ <xs:complexType>
146
+ <xs:sequence>
147
+ <xs:any namespace="##other" processContents="strict"/>
148
+ </xs:sequence>
149
+ </xs:complexType>
150
+ </xs:element>
151
+ </xs:schema>
152
+ XSD
153
+ schema = ctx.xsd_file(path)
154
+ errors = schema.validate(
155
+ '<solo xmlns="urn:S"><u:x xmlns:u="urn:U"/></solo>',
156
+ )
157
+ expect(errors.first.message)
158
+ .to include("matches a strict wildcard but is not declared")
159
+ end
160
+ end
161
+ end
162
+
85
163
  it "raises on an empty set" do
86
164
  expect { ctx.xsd_set }.to raise_error(ArgumentError)
87
165
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.176
4
+ version: 0.5.177
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.