moxml 0.5.118 → 0.5.119

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: 60a08183c240700f3cde7675fb3428b47340f0dba11e723309c5afb09aa988bb
4
- data.tar.gz: 42e790020feb09861560717610f16f6e8996fb7435689eae1f989a05cb90ab0a
3
+ metadata.gz: 7a30730e871854c7b88fc3b6a3498b4f4d5504ac47caa2aabcc530f2bf0eec96
4
+ data.tar.gz: 8d4f301d7d100cab15cc55b4f0e3db36bc5e50916775adfd34f64b816546d466
5
5
  SHA512:
6
- metadata.gz: 4accde9025cb43cbe09661c68be8d31047f39339f035f2a80d895e3e8b03a786b7b0d492880a39d0f2f4b57b0209002e62cc79c7c71b3c4373091ceaac4481ee
7
- data.tar.gz: 203fb7db9d8e46a7a028218dda254367cc0cb1c8ac096b516102937874ba0f14b2bbe1f06cfcb413334567722d31f94f4e00fe2850e2c3a20f1334a3bfce5f70
6
+ metadata.gz: 4b61a839f7399e0b9e9236b1d921cfc161714b114d73da1b737a80c98795d8c88b96f8e85e71c3a71f58a090578b2ba6ffa4ec57cb9a6309cb53296bb000b277
7
+ data.tar.gz: b42fa624031b28da813039d441024be7766f8322fc54f247075b0c205cb79ec57052ababc789ab90f1c3b91b04a0ced4de85760af3178c1675aedd390fdd8046
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gemspec
9
9
  gem "benchmark"
10
10
  gem "benchmark-ips"
11
11
  gem "get_process_mem"
12
- gem "leptris", "~> 1.9.320"
12
+ gem "leptris", "~> 1.9.321"
13
13
  gem "libxml-ruby", ">= 5.0"
14
14
  gem "nokogiri", "~> 1.18"
15
15
  gem "openssl", "~> 3.0"
data/README.adoc CHANGED
@@ -119,7 +119,7 @@ carries the plan-ABI surface, the 1.9.290 XSLT-params and
119
119
  bulk-append faces, and the 1.9.292 engine deep-copy root install).
120
120
  |===
121
121
 
122
- NOTE: moxml's dev Gemfile pins `leptris ~> 1.9.320` (the tested pair; the gemspec itself has zero runtime dependencies). Consumers of the leptris adapter should run leptris 1.9.320+ — earlier engines carry silent wrong-answer plan-path defects (moxml#344); moxml gates degrade to the always-correct slower paths below it.
122
+ NOTE: moxml's dev Gemfile pins `leptris ~> 1.9.321` (the tested pair; the gemspec itself has zero runtime dependencies). Consumers of the leptris adapter should run leptris 1.9.320+ — earlier engines carry silent wrong-answer plan-path defects (moxml#344); moxml gates degrade to the always-correct slower paths below it.
123
123
  `ox ~> 2.14`, `libxml-ruby >= 5.0`, and the vendored oga fork — the CI
124
124
  matrix tests exactly those floors.
125
125
 
@@ -258,6 +258,20 @@ module Moxml
258
258
  raise Moxml::NotImplementedError, XSLT_UNSUPPORTED_MESSAGE
259
259
  end
260
260
 
261
+ # XSD validation (moxml XSD contract): engines without a
262
+ # validator raise; leptris gates on >= 1.9.321.0.
263
+ XSD_SUPPORTED = false
264
+
265
+ def xsd_compile(_schema_source)
266
+ raise Moxml::NotImplementedError,
267
+ "XSD validation requires an adapter with an XSD engine"
268
+ end
269
+
270
+ def xsd_validate(_xsd_handle, _native_document)
271
+ raise Moxml::NotImplementedError,
272
+ "XSD validation requires an adapter with an XSD engine"
273
+ end
274
+
261
275
  # Apply a compiled stylesheet; returns the engine's result
262
276
  # document, or nil when the output method cannot produce one
263
277
  # (text). @params is the flat quoted name/value list.
@@ -165,6 +165,18 @@ module Moxml
165
165
  # binding 1.9.313): the DSL accumulates markup in a plain
166
166
  # String and ONE native crossing (parse + attach) flushes the
167
167
  # whole subtree. See Adapter::Base#builder_face.
168
+ # XSD validation (leptris-ruby tier-1, #1075): the binding's
169
+ # Leptris::XML::XSD faces — >= 1.9.321.0 carries instance
170
+ # validation with accumulated errors (slices 3-4). Face probe
171
+ # pairs the gate (misrelease races — NATIVE_PLAN_STRUCTS
172
+ # lesson).
173
+ NATIVE_XSD =
174
+ Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.321.0") &&
175
+ defined?(::Leptris::XML::XSD) &&
176
+ ::Leptris::XML::FFI.respond_to?(:leptris_xsd_validate)
177
+
178
+ XSD_SUPPORTED = NATIVE_XSD
179
+
168
180
  NATIVE_BUILDER =
169
181
  defined?(::Leptris::XML::Builder) &&
170
182
  defined?(::Leptris::XML::Document) &&
@@ -218,6 +230,27 @@ module Moxml
218
230
  # (and on installs without the native layer — the constant
219
231
  # check short-circuits), a Node.wrap over the shared C
220
232
  # pointer for NativeNodes.
233
+ def xsd_compile(schema_source)
234
+ unless XSD_SUPPORTED
235
+ raise Moxml::NotImplementedError,
236
+ "XSD validation requires the leptris 1.9.321+ engine"
237
+ end
238
+
239
+ ::Leptris::XML::XSD.compile(schema_source)
240
+ end
241
+
242
+ def xsd_validate(xsd_handle, native_document)
243
+ # +xsd_handle+ is the binding's Leptris::XML::XSD::Schema;
244
+ # validate_errors takes the binding document and returns
245
+ # the engine's accumulated messages ([] = valid).
246
+ doc = if native_document.is_a?(::Leptris::XML::Document)
247
+ native_document
248
+ else
249
+ to_binding(native_document)
250
+ end
251
+ xsd_handle.validate_errors(doc)
252
+ end
253
+
221
254
  def builder_face(native_document)
222
255
  return nil unless NATIVE_BUILDER && NATIVE_READ_LAYER
223
256
 
data/lib/moxml/context.rb CHANGED
@@ -144,6 +144,18 @@ module Moxml
144
144
  # @return [Moxml::XSLT::Stylesheet]
145
145
  # @raise [Moxml::NotImplementedError] on adapters without an engine
146
146
  # @raise [Moxml::XsltError] on a malformed stylesheet
147
+ # Compile an XSD schema for validation (moxml XSD contract).
148
+ # Returns a Moxml::XSD::Schema; #validate/#valid? take a node or
149
+ # raw XML string. Adapters without an engine raise
150
+ # Moxml::NotImplementedError; Moxml::XSD.supported?(self)
151
+ # answers without raising.
152
+ #
153
+ # @raise [Moxml::NotImplementedError] on adapters without a validator
154
+ def xsd(schema_source)
155
+ handle = config.adapter.xsd_compile(schema_source.to_s)
156
+ Moxml::XSD::Schema.new(handle, self)
157
+ end
158
+
147
159
  def xslt(stylesheet)
148
160
  source = case stylesheet
149
161
  when Moxml::Document then stylesheet.to_xml
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.118"
4
+ VERSION = "0.5.119"
5
5
  end
data/lib/moxml/xsd.rb ADDED
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Moxml
4
+ # XSD validation. Implementation-agnostic over engines that ship
5
+ # an XSD validator (currently leptris, tier-1: named+typed
6
+ # top-level elements, one-level content-model descent, lexical
7
+ # builtin/simpleType checks — see docs/c14n for the sibling
8
+ # pattern).
9
+ #
10
+ # ctx = Moxml.new(:leptris)
11
+ # schema = ctx.xsd(<<~XSD)
12
+ # <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
13
+ # <xs:element name="note" type="t_note"/>
14
+ # <xs:complexType name="t_note">
15
+ # <xs:sequence>
16
+ # <xs:element name="to" type="xs:string"/>
17
+ # </xs:sequence>
18
+ # </xs:complexType>
19
+ # </xs:schema>
20
+ # XSD
21
+ # schema.valid?(doc) # => true/false
22
+ # schema.validate(doc) # => [] or ["1:0: ...", ...]
23
+ #
24
+ # Adapters without an engine raise Moxml::NotImplementedError at
25
+ # compile; Moxml::XSD.supported?(context) answers without
26
+ # raising. The tier-1 scope is the engine's: documents outside it
27
+ # validate laxly (see the binding's xsd_validate_spec).
28
+ module XSD
29
+ SUPPORTED_ADAPTERS = %i[leptris].freeze
30
+
31
+ class << self
32
+ # Whether the context's adapter ships an XSD validator.
33
+ # Answers without raising; compile raises
34
+ # Moxml::NotImplementedError regardless (the capability probe
35
+ # is advisory).
36
+ def supported?(context)
37
+ adapter = context.config.adapter
38
+ adapter.const_defined?(:XSD_SUPPORTED) &&
39
+ adapter.const_get(:XSD_SUPPORTED)
40
+ end
41
+ end
42
+
43
+ # A compiled schema (adapter-owned handle). Validation results
44
+ # are the engine's accumulated messages; [] means valid.
45
+ class Schema
46
+ def initialize(handle, context)
47
+ @handle = handle
48
+ @context = context
49
+ end
50
+
51
+ # Validate a node or raw XML string. Returns [] when valid.
52
+ def validate(node_or_xml)
53
+ doc = case node_or_xml
54
+ when Moxml::Document then node_or_xml
55
+ when Moxml::Node then node_or_xml.document
56
+ else @context.parse(node_or_xml.to_s)
57
+ end
58
+ @context.config.adapter.xsd_validate(@handle, doc.native)
59
+ end
60
+
61
+ def valid?(node_or_xml)
62
+ validate(node_or_xml).empty?
63
+ end
64
+ end
65
+ end
66
+ end
data/lib/moxml.rb CHANGED
@@ -101,6 +101,7 @@ module Moxml
101
101
  autoload :Signature, "moxml/signature"
102
102
  autoload :C14n, "moxml/c14n"
103
103
  autoload :XSLT, "moxml/xslt"
104
+ autoload :XSD, "moxml/xsd"
104
105
 
105
106
  # Error hierarchy — each subclass autoloads from the same file
106
107
  autoload :Error, "moxml/error"
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ # Moxml::XSD contract (leptris tier-1 faces): compile + validate
6
+ # with accumulated errors; unsupported adapters raise
7
+ # NotImplementedError at compile.
8
+ RSpec.describe Moxml::XSD do
9
+ let(:ctx) { Moxml.new(:leptris) }
10
+ let(:schema_text) do
11
+ <<~XSD
12
+ <?xml version="1.0"?>
13
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
14
+ <xs:element name="note" type="t_note"/>
15
+ <xs:complexType name="t_note">
16
+ <xs:sequence>
17
+ <xs:element name="to" type="xs:string"/>
18
+ </xs:sequence>
19
+ </xs:complexType>
20
+ </xs:schema>
21
+ XSD
22
+ end
23
+
24
+ it "reports supported? on the leptris adapter" do
25
+ skip "leptris adapter unavailable" unless
26
+ Moxml::Adapter::Leptris::XSD_SUPPORTED
27
+
28
+ expect(described_class.supported?(ctx)).to be(true)
29
+ end
30
+
31
+ context "when the adapter ships a validator" do
32
+ before do
33
+ skip "leptris 1.9.321+ engine required" unless
34
+ Moxml::Adapter::Leptris::XSD_SUPPORTED
35
+ end
36
+
37
+ it "compiles and validates a good document" do
38
+ schema = ctx.xsd(schema_text)
39
+ doc = ctx.parse("<note><to>You</to></note>")
40
+ expect(schema.valid?(doc)).to be(true)
41
+ expect(schema.validate(doc)).to eq([])
42
+ end
43
+
44
+ it "returns accumulated messages for an invalid document" do
45
+ schema = ctx.xsd(schema_text)
46
+ errors = schema.validate("<note><wrong/></note>")
47
+ expect(errors).not_to be_empty
48
+ end
49
+
50
+ it "validates raw XML strings and nodes" do
51
+ schema = ctx.xsd(schema_text)
52
+ doc = ctx.parse("<note><to>x</to></note>")
53
+ expect(schema.valid?(doc.root)).to be(true)
54
+ expect(schema.valid?("<note><to>x</to></note>")).to be(true)
55
+ expect(schema.valid?("<note><wrong/></note>")).to be(false)
56
+ end
57
+
58
+ it "derives XSD_SUPPORTED from the engine face gate" do
59
+ # The capability flag must not outrun the engine faces: a
60
+ # misreleased lockstep (NATIVE_PLAN_STRUCTS lesson) would arm
61
+ # compile against missing functions.
62
+ expect(Moxml::Adapter::Leptris::XSD_SUPPORTED)
63
+ .to eq(Moxml::Adapter::Leptris::NATIVE_XSD)
64
+ end
65
+ end
66
+ 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.118
4
+ version: 0.5.119
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -297,6 +297,7 @@ files:
297
297
  - lib/moxml/xpath/parser.rb
298
298
  - lib/moxml/xpath/ruby/generator.rb
299
299
  - lib/moxml/xpath/ruby/node.rb
300
+ - lib/moxml/xsd.rb
300
301
  - lib/moxml/xslt.rb
301
302
  - lib/moxml/xslt/stylesheet.rb
302
303
  - moxml.gemspec
@@ -569,6 +570,7 @@ files:
569
570
  - spec/moxml/xpath/union_spec.rb
570
571
  - spec/moxml/xpath_capabilities_spec.rb
571
572
  - spec/moxml/xpath_spec.rb
573
+ - spec/moxml/xsd_spec.rb
572
574
  - spec/moxml/xslt/stylesheet_spec.rb
573
575
  - spec/performance/README.md
574
576
  - spec/performance/benchmark_spec.rb