leptris 1.9.418.0 → 1.9.419.0

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/TODO.perf/39-hot-c-reads-or-hydrated-walk.md +35 -0
  4. data/TODO.perf/40-nodeset-c-mint.md +10 -0
  5. data/TODO.perf/41-c-set-attribute-entry.md +11 -0
  6. data/ext/leptris/native/native.c +38 -0
  7. data/lib/leptris/vendor/aarch64-linux/libleptris.so +0 -0
  8. data/lib/leptris/vendor/aarch64-linux-musl/libleptris.so +0 -0
  9. data/lib/leptris/vendor/arm-linux/libleptris.so +0 -0
  10. data/lib/leptris/vendor/arm-linux-musl/libleptris.so +0 -0
  11. data/lib/leptris/vendor/arm64-darwin/libleptris.dylib +0 -0
  12. data/lib/leptris/vendor/ppc64le-linux/libleptris.so +0 -0
  13. data/lib/leptris/vendor/s390x-linux-musl/libleptris.so +0 -0
  14. data/lib/leptris/vendor/x86_64-darwin/libleptris.dylib +0 -0
  15. data/lib/leptris/vendor/x86_64-linux/libleptris.so +0 -0
  16. data/lib/leptris/vendor/x86_64-linux-musl/libleptris.so +0 -0
  17. data/lib/leptris/version.rb +1 -1
  18. data/vendor-src/README.md +1 -1
  19. data/vendor-src/libleptris/CHANGELOG.md +13 -0
  20. data/vendor-src/libleptris/CMakeLists.txt +1 -1
  21. data/vendor-src/libleptris/TODO.max-perf/15-c-face-vs-pugixml.md +73 -0
  22. data/vendor-src/libleptris/src/leptris/xsd/compile.c +56 -30
  23. data/vendor-src/libleptris/src/leptris/xsd/validate.c +72 -0
  24. data/vendor-src/libleptris/src/leptris/xsd/xsd_internal.h +3 -0
  25. data/vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014a-11.xsd +16 -0
  26. data/vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014a.xml +1 -0
  27. data/vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014a.xsd +16 -0
  28. data/vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014b.xml +1 -0
  29. data/vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014b.xsd +16 -0
  30. data/vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873.xsd +122 -0
  31. data/vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873_imp.xsd +15 -0
  32. data/vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873b.xml +3 -0
  33. data/vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873c.xml +3 -0
  34. data/vendor-src/libleptris/test/xsd/test_xsd_compile.cpp +95 -0
  35. data/vendor-src/libleptris/vcpkg.json +1 -1
  36. metadata +13 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 602afb776ae5cbc4da725de682f9b2ecaaa468203a7a08ebd282001c49abc5e1
4
- data.tar.gz: 2c76c6063b0256865991082653d8cda99aa6dac330ccdd4378f108c5d5511810
3
+ metadata.gz: af2b87b2aaec36ee96f0572566b19678f06da068a2bd8fac00b086585a69dbd3
4
+ data.tar.gz: f0be350c456f6097e500488ade498cd5a14454461f3cb7476c79a19e5d4b8e30
5
5
  SHA512:
6
- metadata.gz: 1e8e56d54bf1c223a62eef03612dab63d0bf1b44929ba3f8aa50f037738cc91f4e048593d1af87eeaa2421401e26e36bb3b891ec105a020d2d0c59fcd981e2ab
7
- data.tar.gz: f1b83a111189aa6b620d0bf60deb5e871fd1ea1e8122c7d87e052b39e348a8f59081b5cb9c95cb9248e46a18ed85e6e9ecf170dbf1800fe61f9509e5ab87fd03
6
+ metadata.gz: edb18348f5b49be7967e570f50b88a5038d6b3525734a4f8f8e86929546663c53b1b73386168f089c040fe7757906ba9174144469d5f88af032a3103911ba7cb
7
+ data.tar.gz: 91d9cc505d079ade08cd8b0c68bcee95b5f7f26413dd5a7b753acf3707662634a17f03cb79d03b9d1bad33412fe3657eb7632ecaa79a93fa8d92975c1c5fbbd4
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
8
8
  # Pin for `rake compile` and the platform-gem builds. Keep in lockstep
9
9
  # with .github/workflows/build.yml (which calls `rake compile`) and the
10
10
  # CHANGELOG when libleptris releases.
11
- LIBLEPTRIS_VERSION = "1.9.418"
11
+ LIBLEPTRIS_VERSION = "1.9.419"
12
12
  # Vendored alongside libleptris for fn:normalize-unicode (TODO
13
13
  # .restructure/20): built per platform with a RELOCATABLE @rpath
14
14
  # install name, loaded by ffi.rb before libleptris so the
@@ -0,0 +1,35 @@
1
+ # 39 — Hot reads: C-defined parameterized readers, or the hydrated columnar walk
2
+
3
+ Status: QUEUED (leptris-ruby#622, ask 1)
4
+
5
+ Source: the moxml-on-leptris facade's structural-row losses, all at
6
+ the per-read/per-mint Ruby floor. Facade reads sit at ~331ns because
7
+ every read is an `UnboundMethod#bind_call` (one Ruby frame). The
8
+ proven budgets (TODO.perf/32, clean host): native `[]` 71ns, binding
9
+ memo seam ~160ns. The 2x-reads finish line needs the last Ruby frame
10
+ gone. Two acceptable shapes — the owner picks:
11
+
12
+ - **(a)** a binding-side C API that defines hot instance methods on
13
+ arbitrary receiver classes, operating on the receiver's TypedData
14
+ struct — the shape #204's closure sketched ("C-defined hot methods
15
+ parameterized by subclass"). moxml's Identity classes (subclass
16
+ NativeNode, klass-injected via `NativeNode.from`) get C
17
+ `[]`/`name`/`content`/`attribute` readers; the platform matrix
18
+ stays on the leptris dependency (moxml remains pure-Ruby).
19
+ - **(b)** extend `walk_columnar` (TODO.perf/32's face) to a
20
+ **hydrated** walk: the same single crossing returns, per row, the
21
+ flat attr packet + text content alongside names/handles/depths.
22
+ The consumer pipeline (walk + attribute + text reads) then pays
23
+ zero per-read calls — the reads ride the walk crossing.
24
+
25
+ Unlocks: walk+read (warm) 0.67x, walk+read (cold) 0.37x, children
26
+ recursion (cold) 0.46x of raw nokogiri.
27
+
28
+ ## Evidence
29
+
30
+ - lutaml/moxml scoreboard baseline (v0.5.166-era, clean host,
31
+ interleaved A/B per the published protocol).
32
+ - TODO.perf/32's clean-host floor table: `[]` 71ns native / 160ns
33
+ binding seam.
34
+ - leptris-ruby#527's verdict: the engine line is flat — the cold-row
35
+ cost is binding/facade, not an engine regression.
@@ -0,0 +1,10 @@
1
+ # 40 — NodeSet.from_result: klass-injected result materialization
2
+
3
+ Status: QUEUED (leptris-ruby#622, ask 2 — the #204 ask, refiled)
4
+
5
+ `xpath_result_rows_bulk` crosses once but still mints wrappers in a
6
+ Ruby loop (~1.4us/query ask from #204). Mint the result rows in C
7
+ with klass injection so consumers receive their wrapper classes
8
+ directly.
9
+
10
+ Unlocks: xpath `//field` (each) 0.59x of raw nokogiri.
@@ -0,0 +1,11 @@
1
+ # 41 — C set-attribute entry (the write floor)
2
+
3
+ Status: QUEUED (leptris-ruby#622, ask 3)
4
+
5
+ `set_binding_text` landed (adopted behind a face probe); attribute-set
6
+ has no C entry — post-build `set_attribute` pays the binding-layer
7
+ crossing per attribute. `add_element_full` (TODO.sota/04) covers
8
+ build-time attrs only.
9
+
10
+ Unlocks: mutation-heavy/builder lanes (the build add_element row is
11
+ at 0.975x and rides on this for the post-hoc shape).
@@ -1681,6 +1681,42 @@ static VALUE nn_set_root(VALUE klass, VALUE document, VALUE element)
1681
1681
  return element;
1682
1682
  }
1683
1683
 
1684
+ /* TODO.perf/39(a) (leptris-ruby#622 ask 1): hot readers
1685
+ * parameterized by subclass. Consumers whose wrapper classes SUBCLASS
1686
+ * NativeNode (klass injection, #340) shadow these C methods with
1687
+ * included Ruby modules — every shadowed read pays an
1688
+ * UnboundMethod#bind_call frame (~the whole difference between the
1689
+ * facade's ~331ns reads and the binding's ~160ns seam). This entry
1690
+ * defines the SAME C functions (same bodies, same walk-memos, same
1691
+ * TypedData type) DIRECTLY on the consumer's subclass, so lookup
1692
+ * answers in C with no module shadow in the chain.
1693
+ *
1694
+ * The consumer decides which classes get the hot surface: a
1695
+ * per-document klass map (#340) can route entity-bearing documents
1696
+ * to contract classes and clean documents to hot classes, keeping
1697
+ * any Ruby-side value post-processing exactly where it is still
1698
+ * needed.
1699
+ *
1700
+ * Re-defining a method that already exists on the class replaces it
1701
+ * (Ruby semantics); calling twice is harmless. The class must be the
1702
+ * consumer's NativeNode subclass or NativeNode itself — a non-
1703
+ * TypedData class would crash on first read, so the type is checked
1704
+ * here against the registry. */
1705
+ static VALUE nf_define_hot_readers(VALUE self, VALUE klass)
1706
+ {
1707
+ (void)self;
1708
+ if (!RB_TYPE_P(klass, T_CLASS))
1709
+ rb_raise(rb_eTypeError, "expected a class");
1710
+ if (klass != c_native_node &&
1711
+ rb_class_inherited_p(klass, c_native_node) != Qtrue)
1712
+ rb_raise(rb_eTypeError,
1713
+ "the class must subclass Leptris::XML::NativeNode");
1714
+ rb_define_method(klass, "name", nn_name, 0);
1715
+ rb_define_method(klass, "content", nn_content, 0);
1716
+ rb_define_method(klass, "attribute", nn_attribute, 1);
1717
+ return Qtrue;
1718
+ }
1719
+
1684
1720
  /* NativeNode surface completion (TODO.perf/05): bulk attribute
1685
1721
  * hash (name => value, one C walk, no per-attr Ruby frames) and
1686
1722
  * the position readers. */
@@ -4350,6 +4386,8 @@ static void leptris_native_setup(void)
4350
4386
  nf_append_binding_child, 3);
4351
4387
  rb_define_module_function(m_native, "set_binding_attribute",
4352
4388
  nf_set_binding_attribute, 4);
4389
+ rb_define_module_function(m_native, "define_hot_readers",
4390
+ nf_define_hot_readers, 1);
4353
4391
  rb_define_module_function(m_native, "insert_binding_child",
4354
4392
  nf_insert_binding_child, 4);
4355
4393
  rb_define_module_function(m_native, "at_xpath_first",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.418.0"
4
+ VERSION = "1.9.419.0"
5
5
  end
data/vendor-src/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Sources vendored in this gem (recompile rights; the ruby
2
2
  variant builds them at install via extconf.rb):
3
3
 
4
- - libleptris v1.9.418
4
+ - libleptris v1.9.419
5
5
  - utf8proc v2.11.0
6
6
 
7
7
  Rebuild by hand:
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.9.419] - 2026-11-12
4
+ ### Fixed
5
+
6
+ - **xsd: wildcards ride attributeGroup refs across units** (leptris-rs#72, W3C wildZ013b/c). The #1964 deep capture left two holes: the extension branch still scanned shallow, so a wildcard living inside a REFERENCED attributeGroup under the extension element was invisible (strict admission rejected attributes the composed union admits); and a wildcard found in a group from ANOTHER unit (a namespace-less import) resolved against the CONSUMING schema's targetNamespace instead of its declaring unit's — `##other` flipped meaning across the boundary and the union collapsed to admitting only half the instance's attribute namespaces. The capture now follows refs in the extension branch and carries the declaring group's own unit tns (absent for the import).
7
+
8
+ - **xsd: a bare `<xs:anyAttribute />` is a live ##any wildcard** (leptris-rs#73, W3C attZ014a/b). Absent @namespace means ##any (the moxml#460 posture) — the capture mapped it to NULL, an invisible wildcard, so wildcard-admitted attributes fell to strict rejection for the wrong reason. With admission live, XSD 1.0's one-ID-per-element rule fires: an element assessed with more than one ID-typed attribute (declared rows AND wildcard-admitted names whose global declaration is ID-derived) is invalid; XSD 1.1 lifted the constraint and reads the same shape valid. The rule is version-gated (`xsd_schema_version_11`).
9
+
10
+ ## Tests
11
+
12
+ - wildZ013b/c + attZ014a/b fixtures vendored from w3c/xsdtests (msData/wildcards, msData/attribute); attZ014a also pinned under `@version="1.1"` (valid). Falsified: an always-false ID test failed exactly the two 1.0 pins and passed the 1.1 reading.
13
+
14
+
15
+
3
16
  ## [1.9.418] - 2026-11-12
4
17
  ## Fixed
5
18
 
@@ -3,7 +3,7 @@
3
3
  cmake_minimum_required(VERSION 3.20)
4
4
 
5
5
  project(leptris
6
- VERSION 1.9.418
6
+ VERSION 1.9.419
7
7
  DESCRIPTION "Fast XML parser and XPath evaluator in pure C"
8
8
  LANGUAGES C CXX
9
9
  )
@@ -405,3 +405,76 @@ the loop-body surgery slice — it inherits the region-wrap probe
405
405
 
406
406
  RANKED CUT #1 therefore moves to the loop-surgery slice with the
407
407
  scan-merge as its first step. Nothing ships from the kernel alone.
408
+
409
+ ## Track D addendum 9 — the inline text-scan cut REJECTED by CI (PR #2018, closed)
410
+
411
+ The ranked-#1 cut (inline 32-byte scalar prefix scan for short text
412
+ runs, kernel for the remainder) went through the full gate: round 1
413
+ caught the restart-at-run-start flaw (the kernel rescanned the
414
+ scalar prefix — every leg regressed), round 2 fixed that (kernel
415
+ from the prefix end) and STILL regressed on all three legs vs the
416
+ A3d baselines (macos -39-46%, ubuntu-arm -26-27%, ubuntu-x86 -37-45%
417
+ vs its AVX2 run). Cause: the bench-class run lengths (33-64B) sit
418
+ exactly where the cut loses — 32 branchy scalar bytes plus a kernel
419
+ pass over a 1-32B remainder exceeds the kernel alone, and runs
420
+ <=32B are too few in these shapes to carry it.
421
+
422
+ THE MISSING DATUM: the run-length distribution of the real fixtures
423
+ and the scoreboard corpus. The next session's opening instrument =
424
+ a run-length histogram (one counting pass per fixture, reusable),
425
+ which decides whether the scan-merge has a paying window at all —
426
+ and at what threshold. Until then the kernel stands unchanged; the
427
+ PR closed with the full data (three legs, two rounds, CI artifacts).
428
+
429
+ ## Track D addendum 10 — the scan-merge slice CLOSED (PR #2020, closed unmerged)
430
+
431
+ The 64-byte window (histogram-driven) went through the full gate and
432
+ regressed WORSE than the 32-byte attempt: macos -45/-39/-46%, arm
433
+ -32/-32/-29%, x86 -53/-53/-50% (vs the AVX2 run) — even for runs
434
+ fully inside the window. THE VERDICT: the branchy scalar loop
435
+ (~3-5 ops/byte) loses to the SIMD kernel (~1 op/byte) at every run
436
+ length on every platform; the kernel's per-run fixed cost is small
437
+ next to its per-byte advantage. The scan-merge slice is structurally
438
+ dead — two windows, two full CI runs, one consistent verdict.
439
+
440
+ THE TEXT-ROW LEVER REDIRECTS to the kernel's own per-byte
441
+ throughput: the text_scan_run NEON kernel processes ~1 byte/op
442
+ while pugixml's scanner sustains 2.1-2.7 GB/s — the Track A scanner
443
+ class. The next concrete candidate: process 32B chunks (NEON
444
+ registers ×2) per iteration instead of 16B, halving the reduction
445
+ frequency; and the parser's text-branch call overhead already
446
+ measures separably (the scalar wrapper at 2.2%).
447
+
448
+ The histogram instrument (probe/run-histogram) remains in the repo
449
+ history on probe/run-histogram; both rejected cut branches carry
450
+ their full data.
451
+
452
+ ## Track D addendum 11 — the 32B kernel window measured-NEGATIVE (PR #2022, closed unmerged)
453
+
454
+ The addendum-10 candidate (NEON text_scan_run at 32B windows — two
455
+ uint8x16 registers, term masks OR-combined before ONE vmaxvq, halving
456
+ the horizontal-reduction frequency) passed the full CI suite but the
457
+ CI split was poisoned by fleet variance (x86 +31% on code the diff
458
+ does not touch). The decisive instrument was a same-machine
459
+ interleaved A/B on Apple silicon (Release+LTO, 3 rounds ABBA, pugixml
460
+ side flat ~2370/1800 MB/s across rounds — machine verified stable):
461
+
462
+ | shape | 16B (main) | 32B (PR) | delta |
463
+ |-------|-----------|----------|-------|
464
+ | 1.5MB | ~1341 MB/s | ~1144 MB/s | −15% |
465
+ | 5MB | ~1332 MB/s | ~1135 MB/s | −15% |
466
+ | 13MB | ~1029 MB/s | ~913 MB/s | −11% |
467
+
468
+ THE INVARIANT: horizontal-reduction frequency is NOT the binding term
469
+ in text_scan_run on M-series. The accumulator chain is — two extra
470
+ cmpeq+orr per register per window lengthen the dependency chain and
471
+ raise live-register pressure (9+ Q registers) without removing any
472
+ real per-byte work. Widening the window cannot pay; the kernel's
473
+ per-byte op count is already minimal for its contract (first-term
474
+ scan + f1/f2 seen-flags).
475
+
476
+ TEXT-ROW STATUS after three measured closures (scan-merge 32B,
477
+ scan-merge 64B, kernel-width 32B): the kernel is at its floor. The
478
+ remaining text-row gap to pugixml is the parser's text-branch call
479
+ overhead (the scalar wrapper measures separably at 2.2% — the only
480
+ untried lever in this class), not the kernel.
@@ -128,9 +128,9 @@ static char* xsd_capture_unit_tns(LeptrisElement e);
128
128
  static void xsd_resolve_qname(LeptrisElement e, const char* qname,
129
129
  char* uri, size_t urisz, char* local,
130
130
  size_t localsz);
131
- static char* xsd_capture_any_attr_ns(LeptrisElement container);
132
131
  static char* xsd_capture_any_attr_ns_deep(
133
- struct leptris_xsd_schema* s, LeptrisElement container, int depth);
132
+ struct leptris_xsd_schema* s, LeptrisElement container, int depth,
133
+ char** out_unit);
134
134
  static char* xsd_capture_any_attr_not_qname(LeptrisElement container);
135
135
 
136
136
  /* #1626: prefixed QName refs (type="w:CT_Border") resolve by local
@@ -3257,13 +3257,26 @@ static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
3257
3257
  /* XSD 1.1: asserts nested under the derivation */
3258
3258
  if (s->version_11)
3259
3259
  xsd_capture_assert_children(s, dq, root);
3260
- if (!any_attr_ns)
3260
+ if (!any_attr_ns) {
3261
3261
  if (!any_attr_unit_ns)
3262
3262
  any_attr_unit_ns = xsd_capture_unit_tns(dq);
3263
- any_attr_ns = xsd_capture_any_attr_ns(dq);
3263
+ /* leptris-rs#72: the extension's wildcard rides
3264
+ * attributeGroup refs too — the shallow scan
3265
+ * misses attgD019/wildZ013 shapes. Cross-unit
3266
+ * found-groups carry their own tns. */
3267
+ char* deep_unit = NULL;
3268
+ any_attr_ns = xsd_capture_any_attr_ns_deep(
3269
+ s, dq, 0, &deep_unit);
3270
+ if (any_attr_ns && deep_unit) {
3271
+ free(any_attr_unit_ns);
3272
+ any_attr_unit_ns = deep_unit;
3273
+ } else {
3274
+ free(deep_unit);
3275
+ }
3264
3276
  if (!any_attr_not_qname)
3265
3277
  any_attr_not_qname =
3266
3278
  xsd_capture_any_attr_not_qname(dq);
3279
+ }
3267
3280
  }
3268
3281
  } else if (strcmp(local, "simpleContent") == 0) {
3269
3282
  for (LeptrisNodeRef q = leptris_node_first_child(
@@ -3344,8 +3357,19 @@ static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
3344
3357
  if (!attrs) attrs = xsd_capture_attr_rows(s, ct, 0);
3345
3358
  if (!any_attr_unit_ns)
3346
3359
  any_attr_unit_ns = xsd_capture_unit_tns(ct);
3347
- if (!any_attr_ns)
3348
- any_attr_ns = xsd_capture_any_attr_ns_deep(s, ct, 0);
3360
+ if (!any_attr_ns) {
3361
+ char* deep_unit = NULL;
3362
+ any_attr_ns = xsd_capture_any_attr_ns_deep(s, ct, 0,
3363
+ &deep_unit);
3364
+ if (any_attr_ns && deep_unit) {
3365
+ /* the wildcard lives in a REFERENCED group from
3366
+ * another unit — its declaring tns wins */
3367
+ free(any_attr_unit_ns);
3368
+ any_attr_unit_ns = deep_unit;
3369
+ } else {
3370
+ free(deep_unit);
3371
+ }
3372
+ }
3349
3373
  if (!any_attr_not_qname)
3350
3374
  any_attr_not_qname = xsd_capture_any_attr_not_qname(ct);
3351
3375
  }
@@ -3455,7 +3479,9 @@ XsdGroupDef* xsd_find_group(struct leptris_xsd_schema* s,
3455
3479
  return NULL;
3456
3480
  }
3457
3481
 
3458
- static const XsdAttrDecl* xsd_find_top_attr(
3482
+ /* leptris-rs#73: the global attribute declaration for a local name
3483
+ * (the ID-count pass resolves wildcard-admitted names against it). */
3484
+ const XsdAttrDecl* xsd_find_top_attr(
3459
3485
  struct leptris_xsd_schema* s, const char* name) {
3460
3486
  if (!s || !name) return NULL;
3461
3487
  for (XsdAttrDecl* a = s->top_attrs; a; a = a->next)
@@ -3686,7 +3712,7 @@ static char* xsd_capture_unit_tns(LeptrisElement e) {
3686
3712
  * (depth-bounded); the group's OWN element is the walk root. */
3687
3713
  static char* xsd_capture_any_attr_ns_deep(
3688
3714
  struct leptris_xsd_schema* s, LeptrisElement container,
3689
- int depth) {
3715
+ int depth, char** out_unit) {
3690
3716
  if (depth > 8) return NULL;
3691
3717
  for (LeptrisNodeRef ac = leptris_node_first_child(
3692
3718
  leptris_element_as_node(container));
@@ -3697,9 +3723,14 @@ static char* xsd_capture_any_attr_ns_deep(
3697
3723
  const char* al = NULL, *au = NULL;
3698
3724
  leptris_element_expanded_name(ae, &al, NULL, &au);
3699
3725
  if (!al || (au && strcmp(au, XSD_NS) != 0)) continue;
3700
- if (strcmp(al, "anyAttribute") == 0)
3701
- return xsd_strdup(
3702
- leptris_element_attribute(ae, "namespace"));
3726
+ if (strcmp(al, "anyAttribute") == 0) {
3727
+ /* leptris-rs#73: absent @namespace means ##any — a
3728
+ * bare <xs:anyAttribute /> is a live wildcard, not an
3729
+ * invisible one. */
3730
+ const char* ns =
3731
+ leptris_element_attribute(ae, "namespace");
3732
+ return xsd_strdup(ns ? ns : "##any");
3733
+ }
3703
3734
  if (strcmp(al, "attributeGroup") == 0) {
3704
3735
  const char* ref = xsd_local_name(
3705
3736
  leptris_element_attribute(ae, "ref"));
@@ -3708,31 +3739,26 @@ static char* xsd_capture_any_attr_ns_deep(
3708
3739
  for (; g; g = g->next)
3709
3740
  if (strcmp(g->name, ref) == 0) break;
3710
3741
  if (g && g->elem) {
3711
- char* r = xsd_capture_any_attr_ns_deep(s, g->elem,
3712
- depth + 1);
3713
- if (r) return r;
3742
+ char* inner_unit = NULL;
3743
+ char* r = xsd_capture_any_attr_ns_deep(
3744
+ s, g->elem, depth + 1, &inner_unit);
3745
+ if (r) {
3746
+ /* leptris-rs#72: the wildcard resolves against
3747
+ * its DECLARING unit's tns — the group's own
3748
+ * unit ("" for a namespace-less import), which
3749
+ * may differ from the consuming type's. */
3750
+ if (out_unit)
3751
+ *out_unit = inner_unit
3752
+ ? inner_unit
3753
+ : xsd_capture_unit_tns(g->elem);
3754
+ return r;
3755
+ }
3714
3756
  }
3715
3757
  }
3716
3758
  }
3717
3759
  return NULL;
3718
3760
  }
3719
3761
 
3720
- static char* xsd_capture_any_attr_ns(LeptrisElement container) {
3721
- for (LeptrisNodeRef ac = leptris_node_first_child(
3722
- leptris_element_as_node(container));
3723
- ac; ac = leptris_node_next_sibling(ac)) {
3724
- if (leptris_node_get_type(ac) != LEPTRIS_NODE_TYPE_ELEMENT)
3725
- continue;
3726
- LeptrisElement ae = (LeptrisElement)ac;
3727
- const char* al = NULL;
3728
- leptris_element_expanded_name(ae, &al, NULL, NULL);
3729
- if (al && strcmp(al, "anyAttribute") == 0)
3730
- return xsd_strdup(
3731
- leptris_element_attribute(ae, "namespace"));
3732
- }
3733
- return NULL;
3734
- }
3735
-
3736
3762
  /* moxml#460: the anyAttribute's XSD 1.1 @notQName (same walk as the
3737
3763
  * namespace capture). NULL when absent. */
3738
3764
  static char* xsd_capture_any_attr_not_qname(LeptrisElement container) {
@@ -832,6 +832,11 @@ static int attr_fixed_matches(struct leptris_xsd_schema* s,
832
832
  return strcmp(norm_v, norm_f) == 0;
833
833
  }
834
834
 
835
+ /* leptris-rs#73: xs:ID itself or a user simpleType whose restriction
836
+ * chain roots at xs:ID. */
837
+ static int attr_type_is_id(struct leptris_xsd_schema* s,
838
+ const char* type);
839
+
835
840
  static void validate_attributes(struct xsd_validator* v,
836
841
  struct leptris_xsd_schema* s,
837
842
  LeptrisElement elem,
@@ -962,6 +967,73 @@ static void validate_attributes(struct xsd_validator* v,
962
967
  verrf_atk(v, elem, "attribute-use", local, "attribute", local,
963
968
  "not declared (strict)");
964
969
  }
970
+ /* leptris-rs#73 (W3C attZ014, XSD 1.0): an element assessed with
971
+ * more than one ID-typed attribute is invalid — declared rows
972
+ * AND wildcard-admitted attributes whose GLOBAL declaration is
973
+ * ID-derived both count. 1.1 lifted the constraint. */
974
+ if (!xsd_schema_version_11(s)) {
975
+ int id_count = 0;
976
+ for (XsdAttrDecl* a = ta->attrs; a; a = a->next)
977
+ if (attr_type_is_id(s, a->type)) id_count++;
978
+ for (LeptrisAttribute at = leptris_element_first_attribute(elem);
979
+ at && id_count < 2; at = leptris_attribute_next(at)) {
980
+ const char* qn = leptris_attribute_get_name(at);
981
+ if (!qn || strncmp(qn, "xmlns", 5) == 0) continue;
982
+ const char* colon = strchr(qn, ':');
983
+ const char* local = colon ? colon + 1 : qn;
984
+ int declared = 0;
985
+ for (XsdAttrDecl* a = ta->attrs; a && !declared; a = a->next)
986
+ if (strcmp(a->name, local) == 0 ||
987
+ strcmp(a->name, qn) == 0)
988
+ declared = 1;
989
+ if (declared) continue;
990
+ const char* auri = leptris_attribute_namespace_uri(at);
991
+ if (auri && strcmp(auri,
992
+ "http://www.w3.org/2001/XMLSchema-instance")
993
+ == 0)
994
+ continue;
995
+ if (ta->any_attr_not_qname &&
996
+ attr_not_qname_hits(ta->any_attr_not_qname, s, local))
997
+ continue;
998
+ int admitted =
999
+ ((ta->any_attr_ns || ta->any_attr_not_qname) &&
1000
+ any_attr_matches(ta->any_attr_ns, auri,
1001
+ ta->any_attr_unit_ns
1002
+ ? ta->any_attr_unit_ns
1003
+ : xsd_target_ns(s))) ||
1004
+ (ta->any_attr_base_ns &&
1005
+ any_attr_matches(ta->any_attr_base_ns, auri,
1006
+ ta->any_attr_base_unit_ns
1007
+ ? ta->any_attr_base_unit_ns
1008
+ : xsd_target_ns(s)));
1009
+ if (!admitted) continue;
1010
+ const XsdAttrDecl* g =
1011
+ xsd_find_top_attr(s, local);
1012
+ if (g && attr_type_is_id(s, g->type)) id_count++;
1013
+ }
1014
+ if (id_count > 1)
1015
+ verrf_atk(v, elem, "attribute-use", "ID", "attribute",
1016
+ "ID",
1017
+ "more than one ID-typed attribute (XSD 1.0 "
1018
+ "one-ID-per-element)");
1019
+ }
1020
+ }
1021
+
1022
+ /* leptris-rs#73: xs:ID itself or a user simpleType whose restriction
1023
+ * chain roots at xs:ID. */
1024
+ static int attr_type_is_id(struct leptris_xsd_schema* s,
1025
+ const char* type) {
1026
+ if (!type) return 0;
1027
+ if (strcmp(type, "xs:ID") == 0 || strcmp(type, "xsd:ID") == 0)
1028
+ return 1;
1029
+ const XsdSimple* st = xsd_find_simple_ns_pub(s, type, NULL);
1030
+ for (int hops = 0; st && st->base && hops < 8; hops++) {
1031
+ if (strcmp(st->base, "xs:ID") == 0 ||
1032
+ strcmp(st->base, "xsd:ID") == 0)
1033
+ return 1;
1034
+ st = xsd_find_simple_pub(s, st->base);
1035
+ }
1036
+ return 0;
965
1037
  }
966
1038
 
967
1039
  static void validate_element(struct xsd_validator* v,
@@ -87,6 +87,9 @@ int xsd_element_name_defined(struct leptris_xsd_schema* s,
87
87
  const char* local, const char* uri);
88
88
  int xsd_attr_name_defined(struct leptris_xsd_schema* s,
89
89
  const char* local);
90
+ struct xsd_attr_decl;
91
+ const struct xsd_attr_decl* xsd_find_top_attr(
92
+ struct leptris_xsd_schema* s, const char* local);
90
93
 
91
94
  /* One validation finding (slice 4). text is malloc'd; kind and
92
95
  * component are BORROWED (static names / schema-owned component
@@ -0,0 +1,16 @@
1
+ <xsd:schema version="1.1" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
2
+ <xsd:complexType name="base">
3
+ <xsd:attribute name="att1" type="xsd:string"/>
4
+ <xsd:attribute name="att2" type="xsd:string"/>
5
+ <xsd:anyAttribute />
6
+ </xsd:complexType>
7
+
8
+ <xsd:simpleType name="st">
9
+ <xsd:restriction base="xsd:ID"/>
10
+ </xsd:simpleType>
11
+
12
+ <xsd:element name="doc" type="base" />
13
+
14
+ <xsd:attribute name="a" type="xsd:ID"/>
15
+ <xsd:attribute name="b" type="st"/>
16
+ </xsd:schema>
@@ -0,0 +1 @@
1
+ <doc att1="a" att2="a" a="a" b="b"/>
@@ -0,0 +1,16 @@
1
+ <xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
2
+ <xsd:complexType name="base">
3
+ <xsd:attribute name="att1" type="xsd:string"/>
4
+ <xsd:attribute name="att2" type="xsd:string"/>
5
+ <xsd:anyAttribute />
6
+ </xsd:complexType>
7
+
8
+ <xsd:simpleType name="st">
9
+ <xsd:restriction base="xsd:ID"/>
10
+ </xsd:simpleType>
11
+
12
+ <xsd:element name="doc" type="base" />
13
+
14
+ <xsd:attribute name="a" type="xsd:ID"/>
15
+ <xsd:attribute name="b" type="st"/>
16
+ </xsd:schema>
@@ -0,0 +1 @@
1
+ <doc att1="a" att2="a" b="b"/>
@@ -0,0 +1,16 @@
1
+ <xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
2
+ <xsd:complexType name="base">
3
+ <xsd:attribute name="att1" type="xsd:string"/>
4
+ <xsd:attribute name="att2" type="xsd:ID"/>
5
+ <xsd:anyAttribute />
6
+ </xsd:complexType>
7
+
8
+ <xsd:simpleType name="st">
9
+ <xsd:restriction base="xsd:ID"/>
10
+ </xsd:simpleType>
11
+
12
+ <xsd:element name="doc" type="base" />
13
+
14
+ <xsd:attribute name="a" type="xsd:ID"/>
15
+ <xsd:attribute name="b" type="st"/>
16
+ </xsd:schema>
@@ -0,0 +1,122 @@
1
+ <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="a" xmlns:a="a" xmlns:b="b">
2
+ <xs:import schemaLocation="test328873_imp.xsd"/>
3
+
4
+ <xs:element name="doc" type="a:derived"/>
5
+ <xs:element name="sub" type="a:derived2" />
6
+ <xs:element name="sub2" type="a:derived3" />
7
+ <xs:element name="sub3" type="a:derived4" />
8
+ <xs:element name="sub4" type="a:derived5" />
9
+ <xs:element name="sub5" type="a:intersection1" />
10
+ <xs:element name="sub6" type="a:intersection2" />
11
+ <xs:complexType name="base">
12
+ <xs:sequence>
13
+ <xs:element name="sub" type="a:derived2" minOccurs="0"/>
14
+ <xs:element name="sub2" type="a:derived3" minOccurs="0"/>
15
+ <xs:element name="sub3" type="a:derived4" minOccurs="0"/>
16
+ <xs:element name="sub4" type="a:derived5" minOccurs="0"/>
17
+ <xs:element name="sub5" type="a:intersection1" minOccurs="0"/>
18
+ <xs:element name="sub6" type="a:intersection2" minOccurs="0"/>
19
+ </xs:sequence>
20
+ <xs:attributeGroup ref="a:attG-a1"/>
21
+ </xs:complexType>
22
+
23
+ <xs:complexType name="derived">
24
+ <xs:complexContent>
25
+ <xs:extension base="a:base">
26
+ <xs:sequence />
27
+ <xs:attributeGroup ref="a:attG-a2"/>
28
+ </xs:extension>
29
+ </xs:complexContent>
30
+ </xs:complexType>
31
+
32
+ <xs:complexType name="base2">
33
+ <xs:sequence />
34
+ <xs:attributeGroup ref="a:attG1-54"/>
35
+ </xs:complexType>
36
+
37
+ <xs:complexType name="derived2">
38
+ <xs:complexContent>
39
+ <xs:extension base="a:base2">
40
+ <xs:sequence />
41
+ <xs:attributeGroup ref="a:attG2-54"/>
42
+ </xs:extension>
43
+ </xs:complexContent>
44
+ </xs:complexType>
45
+
46
+ <xs:complexType name="base3">
47
+ <xs:sequence />
48
+ <xs:attributeGroup ref="a:attG1-51"/>
49
+ </xs:complexType>
50
+
51
+ <xs:complexType name="derived3">
52
+ <xs:complexContent>
53
+ <xs:extension base="a:base3">
54
+ <xs:sequence />
55
+ <xs:attributeGroup ref="a:attG2-51"/>
56
+ </xs:extension>
57
+ </xs:complexContent>
58
+ </xs:complexType>
59
+
60
+ <xs:complexType name="base4">
61
+ <xs:sequence />
62
+ <xs:attributeGroup ref="attG1-61"/>
63
+ </xs:complexType>
64
+
65
+ <xs:complexType name="derived4">
66
+ <xs:complexContent>
67
+ <xs:extension base="a:base4">
68
+ <xs:sequence />
69
+ <xs:attributeGroup ref="attG2-61"/> <!-- resultant wildcard is any -->
70
+ </xs:extension>
71
+ </xs:complexContent>
72
+ </xs:complexType>
73
+
74
+ <xs:complexType name="derived5">
75
+ <xs:complexContent>
76
+ <xs:extension base="a:base4">
77
+ <xs:sequence />
78
+ <xs:attributeGroup ref="attG3-61"/> <!-- resultant wildcard is not(absent) -->
79
+ </xs:extension>
80
+ </xs:complexContent>
81
+ </xs:complexType>
82
+
83
+ <xs:complexType name="intersection1">
84
+ <xs:attributeGroup ref="a:attG-a1"/>
85
+ <xs:attributeGroup ref="a:attG2-3"/> <!-- resultant wildcard is set(b, c) -->
86
+ </xs:complexType>
87
+
88
+ <xs:complexType name="intersection2">
89
+ <xs:attributeGroup ref="a:attG-a1"/>
90
+ <xs:attributeGroup ref="attG1-61"/> <!-- resultant wildcard is not(a) -->
91
+ </xs:complexType>
92
+
93
+ <xs:attribute name="attA"/>
94
+ <xs:attributeGroup name="attG-a1">
95
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
96
+ </xs:attributeGroup>
97
+
98
+ <xs:attributeGroup name="attG2-3">
99
+ <xs:anyAttribute namespace="##local b c" processContents="lax"/>
100
+ </xs:attributeGroup>
101
+
102
+ <xs:attributeGroup name="attG-a2">
103
+ <xs:anyAttribute namespace="##targetNamespace b c" processContents="lax"/>
104
+ </xs:attributeGroup>
105
+
106
+ <xs:attributeGroup name="attG1-54">
107
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
108
+ </xs:attributeGroup>
109
+
110
+ <xs:attributeGroup name="attG2-54">
111
+ <xs:anyAttribute namespace="b c" processContents="lax"/>
112
+ </xs:attributeGroup>
113
+
114
+ <xs:attributeGroup name="attG1-51">
115
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
116
+ </xs:attributeGroup>
117
+
118
+ <xs:attributeGroup name="attG2-51">
119
+ <xs:anyAttribute namespace="##targetNamespace ##local b c" processContents="lax"/>
120
+ </xs:attributeGroup>
121
+
122
+ </xs:schema>
@@ -0,0 +1,15 @@
1
+ <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
2
+
3
+ <xs:attributeGroup name="attG1-61">
4
+ <xs:anyAttribute namespace="##other" processContents="lax"/> <!-- not(absent) -->
5
+ </xs:attributeGroup>
6
+
7
+ <xs:attributeGroup name="attG2-61">
8
+ <xs:anyAttribute namespace="##local b c" processContents="lax"/>
9
+ </xs:attributeGroup>
10
+
11
+ <xs:attributeGroup name="attG3-61">
12
+ <xs:anyAttribute namespace="b c" processContents="lax"/>
13
+ </xs:attributeGroup>
14
+
15
+ </xs:schema>
@@ -0,0 +1,3 @@
1
+ <a:sub2 a:att1="abc" att2="bc" b:att3="foo" x:att4="val" att="a" xmlns:a="a" xmlns:b="b" xmlns:x="x"/> <!-- resultant wildcard is ##any -->
2
+
3
+
@@ -0,0 +1,3 @@
1
+ <a:sub3 a:att1="abc" att2="bc" b:att3="foo" x:att4="val" att="a" xmlns:a="a" xmlns:b="b" xmlns:x="x"/> <!-- resultant wildcard is ##any -->
2
+
3
+
@@ -1331,6 +1331,101 @@ TEST(XsdValidate, SchG2RoundtripUnitAAlone) {
1331
1331
  leptris_xsd_free(s);
1332
1332
  }
1333
1333
 
1334
+ // leptris-rs#72 (W3C wildZ013b, msData/wildcards, expected VALID):
1335
+ // the extension's wildcard lives inside a REFERENCED attributeGroup
1336
+ // (attG2-51 under the extension element) — the deep capture must
1337
+ // ride group refs in the extension branch too. The composed union
1338
+ // (base ##other ∪ extension ##targetNamespace ##local b c) admits
1339
+ // all five instance attribute namespaces.
1340
+ TEST(XsdValidate, WildZ013bExtensionGroupRefWildcardValid) {
1341
+ LeptrisStatus st = LEPTRIS_OK;
1342
+ LeptrisXsdSchema s = leptris_xsd_compile_file(
1343
+ LEPTRIS_XSD_CASES_DIR "/wildZ013-set/test328873.xsd", &st);
1344
+ ASSERT_NE(s, (LeptrisXsdSchema)0) << "status " << (int)st;
1345
+ LeptrisDocument d = leptris_parse_file(
1346
+ LEPTRIS_XSD_CASES_DIR "/wildZ013-set/test328873b.xml", &st);
1347
+ ASSERT_NE(d, nullptr) << "status " << (int)st;
1348
+ EXPECT_EQ(leptris_xsd_validate(s, d), 1)
1349
+ << leptris_xsd_error_at(s, 0);
1350
+ for (size_t i = 0; i < leptris_xsd_error_count(s); i++)
1351
+ ADD_FAILURE() << leptris_xsd_error_at(s, i);
1352
+ leptris_document_free(d);
1353
+ leptris_xsd_free(s);
1354
+ }
1355
+
1356
+ // leptris-rs#72 (W3C wildZ013c): BOTH wildcards live in the
1357
+ // namespace-less IMPORT (attG1-61/attG2-61). Each resolves against
1358
+ // its DECLARING unit's tns (absent), not the consuming schema's —
1359
+ // ##other@absent ∪ {absent, b, c}@absent = ##any.
1360
+ TEST(XsdValidate, WildZ013cCrossUnitImportUnionValid) {
1361
+ LeptrisStatus st = LEPTRIS_OK;
1362
+ LeptrisXsdSchema s = leptris_xsd_compile_file(
1363
+ LEPTRIS_XSD_CASES_DIR "/wildZ013-set/test328873.xsd", &st);
1364
+ ASSERT_NE(s, (LeptrisXsdSchema)0) << "status " << (int)st;
1365
+ LeptrisDocument d = leptris_parse_file(
1366
+ LEPTRIS_XSD_CASES_DIR "/wildZ013-set/test328873c.xml", &st);
1367
+ ASSERT_NE(d, nullptr) << "status " << (int)st;
1368
+ EXPECT_EQ(leptris_xsd_validate(s, d), 1)
1369
+ << leptris_xsd_error_at(s, 0);
1370
+ for (size_t i = 0; i < leptris_xsd_error_count(s); i++)
1371
+ ADD_FAILURE() << leptris_xsd_error_at(s, i);
1372
+ leptris_document_free(d);
1373
+ leptris_xsd_free(s);
1374
+ }
1375
+
1376
+ // leptris-rs#73 (W3C attZ014a, version-contested): <xs:anyAttribute />
1377
+ // without @namespace is a LIVE ##any (absent @namespace means ##any,
1378
+ // the moxml#460 posture) — a and b admit through it and resolve
1379
+ // against their global ID-typed declarations. XSD 1.0's
1380
+ // one-ID-per-element rule then makes the instance INVALID (two
1381
+ // ID-typed attributes on one element); XSD 1.1 lifted the rule.
1382
+ TEST(XsdValidate, AttZ014aIdCountInvalid10) {
1383
+ LeptrisStatus st = LEPTRIS_OK;
1384
+ LeptrisXsdSchema s = leptris_xsd_compile_file(
1385
+ LEPTRIS_XSD_CASES_DIR "/attZ014-set/attZ014a.xsd", &st);
1386
+ ASSERT_NE(s, (LeptrisXsdSchema)0) << "status " << (int)st;
1387
+ LeptrisDocument d = leptris_parse_file(
1388
+ LEPTRIS_XSD_CASES_DIR "/attZ014-set/attZ014a.xml", &st);
1389
+ ASSERT_NE(d, nullptr) << "status " << (int)st;
1390
+ EXPECT_EQ(leptris_xsd_validate(s, d), 0);
1391
+ leptris_document_free(d);
1392
+ leptris_xsd_free(s);
1393
+ }
1394
+
1395
+ // leptris-rs#73 (attZ014b): the declared att2 row is xs:ID and the
1396
+ // wildcard-admitted b resolves to a global restriction of xs:ID —
1397
+ // still two ID-typed attributes on the element. INVALID in 1.0.
1398
+ TEST(XsdValidate, AttZ014bDeclaredAndAdmittedIdInvalid10) {
1399
+ LeptrisStatus st = LEPTRIS_OK;
1400
+ LeptrisXsdSchema s = leptris_xsd_compile_file(
1401
+ LEPTRIS_XSD_CASES_DIR "/attZ014-set/attZ014b.xsd", &st);
1402
+ ASSERT_NE(s, (LeptrisXsdSchema)0) << "status " << (int)st;
1403
+ LeptrisDocument d = leptris_parse_file(
1404
+ LEPTRIS_XSD_CASES_DIR "/attZ014-set/attZ014b.xml", &st);
1405
+ ASSERT_NE(d, nullptr) << "status " << (int)st;
1406
+ EXPECT_EQ(leptris_xsd_validate(s, d), 0);
1407
+ leptris_document_free(d);
1408
+ leptris_xsd_free(s);
1409
+ }
1410
+
1411
+ // leptris-rs#73 (1.1 reading): the same shape under @version="1.1"
1412
+ // is VALID — 1.1 lifted the one-ID-per-element constraint.
1413
+ TEST(XsdValidate, AttZ014aVersion11ReadingIsValid) {
1414
+ LeptrisStatus st = LEPTRIS_OK;
1415
+ LeptrisXsdSchema s = leptris_xsd_compile_file(
1416
+ LEPTRIS_XSD_CASES_DIR "/attZ014-set/attZ014a-11.xsd", &st);
1417
+ ASSERT_NE(s, (LeptrisXsdSchema)0) << "status " << (int)st;
1418
+ LeptrisDocument d = leptris_parse_file(
1419
+ LEPTRIS_XSD_CASES_DIR "/attZ014-set/attZ014a.xml", &st);
1420
+ ASSERT_NE(d, nullptr) << "status " << (int)st;
1421
+ EXPECT_EQ(leptris_xsd_validate(s, d), 1)
1422
+ << leptris_xsd_error_at(s, 0);
1423
+ for (size_t i = 0; i < leptris_xsd_error_count(s); i++)
1424
+ ADD_FAILURE() << leptris_xsd_error_at(s, i);
1425
+ leptris_document_free(d);
1426
+ leptris_xsd_free(s);
1427
+ }
1428
+
1334
1429
  TEST(XsdValidate, ValidDocumentPasses) {
1335
1430
  EXPECT_EQ(validate_doc(k_v_schema,
1336
1431
  "<rows version=\"2\" status=\"ok\">"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
3
3
  "name": "leptris",
4
- "version": "1.9.418",
4
+ "version": "1.9.419",
5
5
  "description": "High-performance XML parser and XPath 1.0 engine in C (libleptris)",
6
6
  "homepage": "https://github.com/leptris/leptris",
7
7
  "license": "MIT",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.418.0
4
+ version: 1.9.419.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -109,6 +109,9 @@ files:
109
109
  - TODO.perf/36-raise-in-c-serializer-encoding.md
110
110
  - TODO.perf/37-document-lazy-pointer.md
111
111
  - TODO.perf/38-bulk-walk-and-bench-gate.md
112
+ - TODO.perf/39-hot-c-reads-or-hydrated-walk.md
113
+ - TODO.perf/40-nodeset-c-mint.md
114
+ - TODO.perf/41-c-set-attribute-entry.md
112
115
  - TODO.restructure/01-constraint-compliance-audit.md
113
116
  - TODO.restructure/02-deep-copy-seam.md
114
117
  - TODO.restructure/03-evaluation-context-seam.md
@@ -1282,6 +1285,11 @@ files:
1282
1285
  - vendor-src/libleptris/test/xsd/libxml2-cases/anyAttr.importB.1_0.xsd
1283
1286
  - vendor-src/libleptris/test/xsd/libxml2-cases/anyAttr1_0.xml
1284
1287
  - vendor-src/libleptris/test/xsd/libxml2-cases/anyAttr1_0.xsd
1288
+ - vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014a-11.xsd
1289
+ - vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014a.xml
1290
+ - vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014a.xsd
1291
+ - vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014b.xml
1292
+ - vendor-src/libleptris/test/xsd/libxml2-cases/attZ014-set/attZ014b.xsd
1285
1293
  - vendor-src/libleptris/test/xsd/libxml2-cases/attgD019-set/attgD019.xsd
1286
1294
  - vendor-src/libleptris/test/xsd/libxml2-cases/attgD019-set/attgD019a.xsd
1287
1295
  - vendor-src/libleptris/test/xsd/libxml2-cases/attr0_0.xml
@@ -1627,6 +1635,10 @@ files:
1627
1635
  - vendor-src/libleptris/test/xsd/libxml2-cases/vdv-first5_0.xml
1628
1636
  - vendor-src/libleptris/test/xsd/libxml2-cases/vdv-first5_0.xsd
1629
1637
  - vendor-src/libleptris/test/xsd/libxml2-cases/vdv-simpleTypes.xsd
1638
+ - vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873.xsd
1639
+ - vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873_imp.xsd
1640
+ - vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873b.xml
1641
+ - vendor-src/libleptris/test/xsd/libxml2-cases/wildZ013-set/test328873c.xml
1630
1642
  - vendor-src/libleptris/test/xsd/libxml2-cases/xml.xsd
1631
1643
  - vendor-src/libleptris/test/xsd/libxml2-cases/xns_type_refs/main.xsd
1632
1644
  - vendor-src/libleptris/test/xsd/libxml2-cases/xns_type_refs/root.xsd