leptris 1.9.390.3-aarch64-linux → 1.9.394.0-aarch64-linux
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 +4 -4
- data/Rakefile +1 -1
- data/lib/leptris/version.rb +1 -1
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +101 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/README.adoc +37 -0
- data/vendor-src/libleptris/src/include/leptris/types.h +52 -0
- data/vendor-src/libleptris/src/include/leptris.h +6 -0
- data/vendor-src/libleptris/src/leptris/core.c +31 -0
- data/vendor-src/libleptris/src/leptris/xpath/parser.c +11 -29
- data/vendor-src/libleptris/src/leptris/xsd/compile.c +121 -13
- data/vendor-src/libleptris/src/leptris/xsd/xsd_internal.h +9 -0
- data/vendor-src/libleptris/test/CMakeLists.txt +17 -0
- data/vendor-src/libleptris/test/abi/test_capabilities.cpp +112 -0
- data/vendor-src/libleptris/test/dom/test_entity_refs.cpp +111 -0
- data/vendor-src/libleptris/test/xsd/test_xsd_compile.cpp +323 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca834bfba520ffac47a4d7e2a45ba9fc298683a2e3f733dfa001c52a69caba7b
|
|
4
|
+
data.tar.gz: 4595a965a4e09df9fb53e582149f1d6e2d05e94f0144b9324e6da5ba83fdbfac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c4aaaa1c101bf275dc2a45df3ea19f90ff0aa29f4afd25d99fc96cae412036085fb53d4640f35127b128aaad9af43b73a2b426ecdc2e57502f7cfc2b7baf1197
|
|
7
|
+
data.tar.gz: eef6a971ac77c4c9fe5860af6a6563d98d6cef91c925da6ba57c9643208428b58855b9420fe49827b1a81f68f36d01166f006028dcce6d943a370643ce1e784a
|
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.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.394"
|
|
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
|
data/lib/leptris/version.rb
CHANGED
data/lib/libleptris.so
CHANGED
|
Binary file
|
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,106 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.394] - 2026-10-30
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **xs:override loads its base and replaces the overridden components
|
|
8
|
+
(leptris#1913, PR #1917).** `override` was absent from the
|
|
9
|
+
declaration gate and the include-family chase, so the base document
|
|
10
|
+
never loaded and the override body's nested declarations were never
|
|
11
|
+
captured — the compiled schema had an empty symbol space (decls=0,
|
|
12
|
+
every instance element "not declared"). Override now chases its
|
|
13
|
+
schemaLocation like include (same targetNamespace), then captures
|
|
14
|
+
its own declaration children as a pseudo-root AFTER the base so the
|
|
15
|
+
head-first lookup ladder sees the replacements; the attributeGroup
|
|
16
|
+
pre-pass honors a capture-force flag in that body, and the ref-check
|
|
17
|
+
declaration collector walks the override body too. Witness: base
|
|
18
|
+
`Doc` replaced by the override's `Doc` — `<doc><b>1</b></doc>`
|
|
19
|
+
validates, `<doc><a>x</a></doc>` is rejected.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## [1.9.393] - 2026-10-30
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- **Capability bit for entity-reference nodes (leptris#1904, PR #1915).**
|
|
28
|
+
`LEPTRIS_PARSE_KEEP_ENTITY_REFS` already parses references as
|
|
29
|
+
first-class `LEPTRIS_NODE_TYPE_ENTITY_REF` nodes — text segments
|
|
30
|
+
split around the five built-ins and custom named references
|
|
31
|
+
(numeric character references stay text, XML 1.0 §4.1) — but
|
|
32
|
+
nothing advertised it. `LEPTRIS_CAP_ENTITY_REF_NODES` lets a
|
|
33
|
+
binding probe once and parse with the flag instead of re-scanning
|
|
34
|
+
expanded text; a spec pins the DOM shape and the
|
|
35
|
+
string-value / serialization / XPath agreement.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- **XSD 1.1 was inert for every `vc:minVersion`-marked schema
|
|
40
|
+
(leptris#1910, leptris#1911, PR #1914).** The version detector
|
|
41
|
+
read only the root's plain `version` attribute; the W3C suite and
|
|
42
|
+
the binding ecosystem mark 1.1 with `vc:minVersion` in the
|
|
43
|
+
versioning namespace. With the capture gates off,
|
|
44
|
+
`xs:alternative` and `xs:assert` compiled to nothing —
|
|
45
|
+
conditional type assignment applied the declared base type's
|
|
46
|
+
model in both directions (false rejects and false accepts), and
|
|
47
|
+
asserts never attached to their types. The detector now honors
|
|
48
|
+
`version`, `vc:minVersion`, and a `vc:maxVersion="1.0"` pin, and
|
|
49
|
+
`xs:openContent` interleave/suffix semantics engage with it
|
|
50
|
+
(leptris#1912's repro validates clean).
|
|
51
|
+
- **Value-comparison keywords accept name-test operands
|
|
52
|
+
(`w le h`).** The XPath `eq/ne/lt/le/gt/ge` operators only read
|
|
53
|
+
as operators when the right operand opened with a scalar, paren,
|
|
54
|
+
variable, or function call — an `xs:assert test="w le h"` failed
|
|
55
|
+
to compile. Adjacent name tokens are never a valid path
|
|
56
|
+
continuation, so a bare name-test follower is unambiguously an
|
|
57
|
+
operand; every path start is now admitted.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## [1.9.392] - 2026-10-30
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- **Capability descriptor face (leptris#1905, PR #1908).**
|
|
66
|
+
`leptris_capabilities()` returns a versioned bitset of every face
|
|
67
|
+
this installed engine serves — the engine-side half of the
|
|
68
|
+
moxml#504 capability report. Bindings OR it with their own wrapper
|
|
69
|
+
knowledge instead of maintaining scattered version-gate
|
|
70
|
+
constants; build-conditional faces (DUCET collation, utf8proc,
|
|
71
|
+
iconv, AVX2) follow the same `LEPTRIS_HAS_*` macros that gate the
|
|
72
|
+
sources, so the descriptor cannot drift from the binary it ships
|
|
73
|
+
in. Contract: bits append, never reorder; the descriptor version
|
|
74
|
+
gates shape changes. The spec anchors every unconditional bit to
|
|
75
|
+
its real face symbol — a bit without a linked face fails the
|
|
76
|
+
build, not the assertion.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
## [1.9.391] - 2026-10-30
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- **XSD: resolve attributeGroup ref rows the pre-pass captured
|
|
85
|
+
before its imports (leptris-ruby#569, PR #1906).** The #1880
|
|
86
|
+
attributeGroup pre-pass captures each unit's group defs *before*
|
|
87
|
+
that unit's imports are chased, so an `<xs:attribute ref="r:embed"/>`
|
|
88
|
+
row whose declaration lives in a later-imported unit found no
|
|
89
|
+
global attribute and was silently dropped. Types were left
|
|
90
|
+
hole-punched (whole-instance validation then rejected `a:blip
|
|
91
|
+
@r:embed` with "not declared (strict)" on the OOXML `wml.xsd`
|
|
92
|
+
chain — clean on 1.9.368.1, regressed by the 386-390 wave) or
|
|
93
|
+
attribute-less, which skipped the strict attribute walk entirely
|
|
94
|
+
and false-validated foreign attributes. Unresolved ref rows are
|
|
95
|
+
now kept pending — with the ref's own `use=` override recorded —
|
|
96
|
+
and re-resolved against the merged top-level attribute table once
|
|
97
|
+
the whole capture has run; row copies carry the flag so referencing
|
|
98
|
+
types heal too. Witness: the real uniword `wml.xsd` (1826
|
|
99
|
+
declarations) compiles clean and a docx-style document with
|
|
100
|
+
`a:blip r:embed` validates 1.
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
3
104
|
## [1.9.390] - 2026-10-29
|
|
4
105
|
|
|
5
106
|
### Fixed
|
|
@@ -744,6 +744,43 @@ To pin enum values (bindings hard-code these):
|
|
|
744
744
|
ctest --test-dir build -R HeaderHygiene
|
|
745
745
|
----
|
|
746
746
|
|
|
747
|
+
=== Capability descriptor (one call: what does this engine serve?)
|
|
748
|
+
|
|
749
|
+
Bindings and embedders stop maintaining scattered version-gate
|
|
750
|
+
constants: one call returns a versioned bitset of every face this
|
|
751
|
+
installed engine serves. Build-conditional faces (Unicode
|
|
752
|
+
normalization, iconv, DUCET collation, AVX2) answer honestly for the
|
|
753
|
+
exact library you linked. New capabilities APPEND bits — the
|
|
754
|
+
descriptor version gates shape changes.
|
|
755
|
+
|
|
756
|
+
[source,c]
|
|
757
|
+
----
|
|
758
|
+
LeptrisCapabilities c = leptris_capabilities();
|
|
759
|
+
if (c.descriptor_version >= 1 && (c.caps & LEPTRIS_CAP_XSD)) {
|
|
760
|
+
/* xsd compile/validate faces are present */
|
|
761
|
+
}
|
|
762
|
+
----
|
|
763
|
+
|
|
764
|
+
Entity references: parsing with `LEPTRIS_PARSE_KEEP_ENTITY_REFS`
|
|
765
|
+
yields `LEPTRIS_NODE_TYPE_ENTITY_REF` nodes instead of pre-expanded
|
|
766
|
+
text — segments split around the five built-ins and custom named
|
|
767
|
+
references (numeric character references stay text, per XML 1.0
|
|
768
|
+
§4.1). String-value, serialization, and XPath all see the expanded
|
|
769
|
+
value. Probe `LEPTRIS_CAP_ENTITY_REF_NODES` before relying on the
|
|
770
|
+
mode.
|
|
771
|
+
|
|
772
|
+
The bits: `LEPTRIS_CAP_PARSE`, `LEPTRIS_CAP_DOM`, `LEPTRIS_CAP_XPATH`,
|
|
773
|
+
`LEPTRIS_CAP_XQUERY`, `LEPTRIS_CAP_DTD`, `LEPTRIS_CAP_SAX`,
|
|
774
|
+
`LEPTRIS_CAP_HTML`, `LEPTRIS_CAP_XINCLUDE`, `LEPTRIS_CAP_DIFF`,
|
|
775
|
+
`LEPTRIS_CAP_DIGEST`, `LEPTRIS_CAP_XSD`, `LEPTRIS_CAP_XSD_SET`,
|
|
776
|
+
`LEPTRIS_CAP_RELAXNG`, `LEPTRIS_CAP_SCHEMATRON`, `LEPTRIS_CAP_XSLT`,
|
|
777
|
+
`LEPTRIS_CAP_DESCRIPTOR`, `LEPTRIS_CAP_NS_SNAPSHOT_BULK`,
|
|
778
|
+
`LEPTRIS_CAP_CHILDREN_BATCH`, `LEPTRIS_CAP_NAME_COMPARE`,
|
|
779
|
+
`LEPTRIS_CAP_VERSION`, and the build-conditional
|
|
780
|
+
`LEPTRIS_CAP_COLLATION_DUCET`, `LEPTRIS_CAP_UNICODE_UTF8PROC`,
|
|
781
|
+
`LEPTRIS_CAP_ENCODING_ICONV`, `LEPTRIS_CAP_SIMD_AVX2`,
|
|
782
|
+
`LEPTRIS_CAP_ENTITY_REF_NODES`.
|
|
783
|
+
|
|
747
784
|
[#FFI]
|
|
748
785
|
== FFI design
|
|
749
786
|
|
|
@@ -447,6 +447,58 @@ typedef struct leptris_xpath_compiled* LeptrisXPathCompiled;
|
|
|
447
447
|
* compiled — apply it to any number of documents, from any threads. */
|
|
448
448
|
typedef struct leptris_xslt* LeptrisXslt;
|
|
449
449
|
|
|
450
|
+
/* ============================================================================
|
|
451
|
+
* Capability Descriptor (leptris#1905)
|
|
452
|
+
* ============================================================================ */
|
|
453
|
+
|
|
454
|
+
/* What this INSTALLED engine serves — one call, one versioned
|
|
455
|
+
* bitset. Contract: new capabilities APPEND bits; a bit is never
|
|
456
|
+
* removed, repurposed, or reordered — that is a descriptor-version
|
|
457
|
+
* bump. Build-conditional faces (utf8proc/iconv/DUCET/AVX2) answer
|
|
458
|
+
* honestly for the exact library a consumer linked. Bindings OR
|
|
459
|
+
* this with their own wrapper knowledge; consumers stop maintaining
|
|
460
|
+
* scattered version-gate constants. */
|
|
461
|
+
enum {
|
|
462
|
+
LEPTRIS_CAP_PARSE = 1ULL << 0,
|
|
463
|
+
LEPTRIS_CAP_DOM = 1ULL << 1,
|
|
464
|
+
LEPTRIS_CAP_XPATH = 1ULL << 2,
|
|
465
|
+
LEPTRIS_CAP_XQUERY = 1ULL << 3,
|
|
466
|
+
LEPTRIS_CAP_DTD = 1ULL << 4,
|
|
467
|
+
LEPTRIS_CAP_SAX = 1ULL << 5,
|
|
468
|
+
LEPTRIS_CAP_HTML = 1ULL << 6,
|
|
469
|
+
LEPTRIS_CAP_XINCLUDE = 1ULL << 7,
|
|
470
|
+
LEPTRIS_CAP_DIFF = 1ULL << 8,
|
|
471
|
+
LEPTRIS_CAP_DIGEST = 1ULL << 9,
|
|
472
|
+
LEPTRIS_CAP_XSD = 1ULL << 10,
|
|
473
|
+
LEPTRIS_CAP_XSD_SET = 1ULL << 11,
|
|
474
|
+
LEPTRIS_CAP_RELAXNG = 1ULL << 12,
|
|
475
|
+
LEPTRIS_CAP_SCHEMATRON = 1ULL << 13,
|
|
476
|
+
LEPTRIS_CAP_XSLT = 1ULL << 14,
|
|
477
|
+
LEPTRIS_CAP_DESCRIPTOR = 1ULL << 15,
|
|
478
|
+
LEPTRIS_CAP_NS_SNAPSHOT_BULK = 1ULL << 16,
|
|
479
|
+
LEPTRIS_CAP_CHILDREN_BATCH = 1ULL << 17,
|
|
480
|
+
LEPTRIS_CAP_NAME_COMPARE = 1ULL << 18,
|
|
481
|
+
LEPTRIS_CAP_VERSION = 1ULL << 19,
|
|
482
|
+
/* build-conditional */
|
|
483
|
+
LEPTRIS_CAP_COLLATION_DUCET = 1ULL << 20,
|
|
484
|
+
LEPTRIS_CAP_UNICODE_UTF8PROC = 1ULL << 21,
|
|
485
|
+
LEPTRIS_CAP_ENCODING_ICONV = 1ULL << 22,
|
|
486
|
+
LEPTRIS_CAP_SIMD_AVX2 = 1ULL << 23,
|
|
487
|
+
/* LEPTRIS_PARSE_KEEP_ENTITY_REFS yields entity references as
|
|
488
|
+
* first-class ENTITY_REF nodes (segments split around the five
|
|
489
|
+
* built-ins and custom named references; leptris#1904). */
|
|
490
|
+
LEPTRIS_CAP_ENTITY_REF_NODES = 1ULL << 24
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
/* Descriptor shape version: 1. Bump when the STRUCT changes or a
|
|
494
|
+
* bit is retired (never expected — bits append). */
|
|
495
|
+
#define LEPTRIS_CAPS_DESCRIPTOR_VERSION 1u
|
|
496
|
+
|
|
497
|
+
typedef struct leptris_capabilities {
|
|
498
|
+
unsigned long long caps;
|
|
499
|
+
unsigned descriptor_version;
|
|
500
|
+
} LeptrisCapabilities;
|
|
501
|
+
|
|
450
502
|
/* ============================================================================
|
|
451
503
|
* Memory Allocation Function Types
|
|
452
504
|
* ============================================================================ */
|
|
@@ -4230,6 +4230,12 @@ LEPTRIS_API const char* leptris_version(void);
|
|
|
4230
4230
|
*/
|
|
4231
4231
|
LEPTRIS_API void leptris_version_components(int* major, int* minor, int* patch);
|
|
4232
4232
|
|
|
4233
|
+
/* leptris#1905: the capability descriptor — what this installed
|
|
4234
|
+
* engine serves, as a versioned bitset (LEPTRIS_CAP_*). Query once
|
|
4235
|
+
* at attach; new capabilities append bits (the descriptor version
|
|
4236
|
+
* gates shape changes). Thread-safe: pure, allocation-free. */
|
|
4237
|
+
LEPTRIS_API LeptrisCapabilities leptris_capabilities(void);
|
|
4238
|
+
|
|
4233
4239
|
/**
|
|
4234
4240
|
* Release this thread's libleptris caches
|
|
4235
4241
|
*
|
|
@@ -72,6 +72,37 @@ LEPTRIS_API void leptris_version_components(int* major, int* minor, int* patch)
|
|
|
72
72
|
if (patch) *patch = LEPTRIS_VERSION_PATCH;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/* leptris#1905: the capability descriptor. Unconditional faces are
|
|
76
|
+
* always compiled into this library; the build-conditional bits
|
|
77
|
+
* follow the same macros the build system defines for the sources
|
|
78
|
+
* — the descriptor cannot drift from the binary it ships in. */
|
|
79
|
+
LEPTRIS_API LeptrisCapabilities leptris_capabilities(void) {
|
|
80
|
+
LeptrisCapabilities c;
|
|
81
|
+
c.caps = LEPTRIS_CAP_PARSE | LEPTRIS_CAP_DOM | LEPTRIS_CAP_XPATH |
|
|
82
|
+
LEPTRIS_CAP_XQUERY | LEPTRIS_CAP_DTD | LEPTRIS_CAP_SAX |
|
|
83
|
+
LEPTRIS_CAP_HTML | LEPTRIS_CAP_XINCLUDE | LEPTRIS_CAP_DIFF |
|
|
84
|
+
LEPTRIS_CAP_DIGEST | LEPTRIS_CAP_XSD | LEPTRIS_CAP_XSD_SET |
|
|
85
|
+
LEPTRIS_CAP_RELAXNG | LEPTRIS_CAP_SCHEMATRON |
|
|
86
|
+
LEPTRIS_CAP_XSLT | LEPTRIS_CAP_DESCRIPTOR |
|
|
87
|
+
LEPTRIS_CAP_NS_SNAPSHOT_BULK | LEPTRIS_CAP_CHILDREN_BATCH |
|
|
88
|
+
LEPTRIS_CAP_NAME_COMPARE | LEPTRIS_CAP_VERSION |
|
|
89
|
+
LEPTRIS_CAP_ENTITY_REF_NODES;
|
|
90
|
+
#if defined(LEPTRIS_HAS_DUCET)
|
|
91
|
+
c.caps |= LEPTRIS_CAP_COLLATION_DUCET;
|
|
92
|
+
#endif
|
|
93
|
+
#if defined(LEPTRIS_HAS_UTF8PROC)
|
|
94
|
+
c.caps |= LEPTRIS_CAP_UNICODE_UTF8PROC;
|
|
95
|
+
#endif
|
|
96
|
+
#if defined(LEPTRIS_HAS_ICONV)
|
|
97
|
+
c.caps |= LEPTRIS_CAP_ENCODING_ICONV;
|
|
98
|
+
#endif
|
|
99
|
+
#if defined(LEPTRIS_HAS_AVX2_BUILD)
|
|
100
|
+
c.caps |= LEPTRIS_CAP_SIMD_AVX2;
|
|
101
|
+
#endif
|
|
102
|
+
c.descriptor_version = LEPTRIS_CAPS_DESCRIPTOR_VERSION;
|
|
103
|
+
return c;
|
|
104
|
+
}
|
|
105
|
+
|
|
75
106
|
LEPTRIS_API void leptris_thread_cleanup(void) {
|
|
76
107
|
leptris_xpath_drain_thread_caches();
|
|
77
108
|
leptris_root_doc_drain_thread_caches();
|
|
@@ -643,44 +643,26 @@ static XPathASTNode* parse_string_concat_expr(XPathParser* parser) {
|
|
|
643
643
|
}
|
|
644
644
|
|
|
645
645
|
/* True when the token AFTER a bare value-comparison keyword may
|
|
646
|
-
* START an operand.
|
|
647
|
-
*
|
|
648
|
-
*
|
|
646
|
+
* START an operand. Scalars, parens, variables, and (leptris#1910)
|
|
647
|
+
* every path start: a bare NCName/QName is an element name test in
|
|
648
|
+
* operand position, and adjacent name tokens are never a valid
|
|
649
|
+
* path continuation, so the keyword reading is unambiguous
|
|
650
|
+
* (`w le h` in xs:assert/xs:alternative tests). */
|
|
649
651
|
static int kw_operand_boundary(XPathParser* parser, XPathToken* nx) {
|
|
652
|
+
(void)parser;
|
|
650
653
|
if (!nx) return 1;
|
|
651
654
|
switch (nx->type) {
|
|
652
655
|
case TOK_EOF: case TOK_RPAREN: case TOK_COMMA:
|
|
653
656
|
case TOK_RBRACE: case TOK_LBRACE: case TOK_NUMBER:
|
|
654
657
|
case TOK_STRING: case TOK_DOLLAR: case TOK_LPAREN:
|
|
655
658
|
case TOK_MINUS: case TOK_PLUS:
|
|
659
|
+
case TOK_SLASH: case TOK_DOUBLE_SLASH: case TOK_AT:
|
|
660
|
+
case TOK_DOT: case TOK_DOUBLE_DOT: case TOK_STAR:
|
|
656
661
|
return 1;
|
|
657
662
|
case TOK_QNAME:
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
/* unprefixed call: name '(' ... prefixed call:
|
|
662
|
-
* name ':' name '(' (the QT3 corpus writes fn:year-...). */
|
|
663
|
-
XPathToken* nnx =
|
|
664
|
-
parser->token_pos + 2 < parser->token_count
|
|
665
|
-
? &parser->tokens[parser->token_pos + 2]
|
|
666
|
-
: NULL;
|
|
667
|
-
if (nnx && nnx->type == TOK_LPAREN) return 1;
|
|
668
|
-
XPathToken* t3 =
|
|
669
|
-
parser->token_pos + 3 < parser->token_count
|
|
670
|
-
? &parser->tokens[parser->token_pos + 3]
|
|
671
|
-
: NULL;
|
|
672
|
-
XPathToken* t4 =
|
|
673
|
-
parser->token_pos + 4 < parser->token_count
|
|
674
|
-
? &parser->tokens[parser->token_pos + 4]
|
|
675
|
-
: NULL;
|
|
676
|
-
XPathToken* t5 =
|
|
677
|
-
parser->token_pos + 5 < parser->token_count
|
|
678
|
-
? &parser->tokens[parser->token_pos + 5]
|
|
679
|
-
: NULL;
|
|
680
|
-
return nnx && nnx->type == TOK_COLON && t3 &&
|
|
681
|
-
t3->type == TOK_NCNAME && t4 &&
|
|
682
|
-
t4->type == TOK_LPAREN && t5;
|
|
683
|
-
}
|
|
663
|
+
case TOK_NCNAME:
|
|
664
|
+
/* name test, function call, or prefixed call */
|
|
665
|
+
return 1;
|
|
684
666
|
default:
|
|
685
667
|
return 0;
|
|
686
668
|
}
|
|
@@ -51,7 +51,11 @@ struct leptris_xsd_schema {
|
|
|
51
51
|
char* target_ns;
|
|
52
52
|
int version_11; /* xs:schema @version = "1.1" */
|
|
53
53
|
char* base_dir; /* schemaLocation resolution (file compile) */
|
|
54
|
-
int include_depth;
|
|
54
|
+
int include_depth;
|
|
55
|
+
/* xs:override body capture replaces same-named components: the
|
|
56
|
+
* attributeGroup pre-pass must re-register defs the base
|
|
57
|
+
* already captured (leptris#1913). */
|
|
58
|
+
int capture_force; /* include/import recursion guard */
|
|
55
59
|
/* leptris#1644: already-captured schema units (canonical
|
|
56
60
|
* location per entry) — the include/import DAG is dense and
|
|
57
61
|
* cyclic; without this set every DAG path re-parses and
|
|
@@ -100,6 +104,7 @@ static void xsd_capture_root(struct leptris_xsd_schema* s,
|
|
|
100
104
|
LeptrisElement root);
|
|
101
105
|
static char* xsd_read_file(const char* path, size_t* out_len);
|
|
102
106
|
static XsdAttrDecl* xsd_copy_attr_rows(const XsdAttrDecl* src);
|
|
107
|
+
static void xsd_resolve_pending_attr_refs(struct leptris_xsd_schema* s);
|
|
103
108
|
static void xsd_register_complex(struct leptris_xsd_schema* s,
|
|
104
109
|
XsdCm* root, XsdAttrDecl* attrs,
|
|
105
110
|
const char* name, char* any_attr_ns,
|
|
@@ -678,7 +683,7 @@ static int xsd_is_declaration(const char* local, const char* uri) {
|
|
|
678
683
|
"element", "attribute", "simpleType", "complexType",
|
|
679
684
|
"group", "attributeGroup", "notation", "include",
|
|
680
685
|
"defaultOpenContent",
|
|
681
|
-
"import", "redefine", NULL
|
|
686
|
+
"import", "redefine", "override", NULL
|
|
682
687
|
};
|
|
683
688
|
for (int i = 0; names[i]; i++)
|
|
684
689
|
if (strcmp(local, names[i]) == 0) return 1;
|
|
@@ -1809,7 +1814,8 @@ static void xsd_collect_decls_doc(LeptrisElement root, const char* eff_tns,
|
|
|
1809
1814
|
if (!l || !u || strcmp(u, XSD_NS) != 0)
|
|
1810
1815
|
continue;
|
|
1811
1816
|
int is_inc = (strcmp(l, "include") == 0 ||
|
|
1812
|
-
strcmp(l, "redefine") == 0
|
|
1817
|
+
strcmp(l, "redefine") == 0 ||
|
|
1818
|
+
strcmp(l, "override") == 0);
|
|
1813
1819
|
int is_imp = (strcmp(l, "import") == 0);
|
|
1814
1820
|
if (!is_inc && !is_imp) continue;
|
|
1815
1821
|
const char* loc = leptris_element_attribute(c, "schemaLocation");
|
|
@@ -1852,6 +1858,13 @@ static void xsd_collect_decls_doc(LeptrisElement root, const char* eff_tns,
|
|
|
1852
1858
|
xsd_collect_decls_doc(subroot, eff, sub_base, decls, n, max,
|
|
1853
1859
|
claimed, nclaimed, cmax, depth + 1);
|
|
1854
1860
|
}
|
|
1861
|
+
/* leptris#1913: an xs:override body's declarations belong
|
|
1862
|
+
* to the symbol space too — walk the override element as a
|
|
1863
|
+
* pseudo-root (it has no include/import children of its
|
|
1864
|
+
* own). */
|
|
1865
|
+
if (strcmp(l, "override") == 0)
|
|
1866
|
+
xsd_collect_decls_doc(c, eff_tns, base_dir, decls, n, max,
|
|
1867
|
+
claimed, nclaimed, cmax, depth + 1);
|
|
1855
1868
|
leptris_document_free(sub);
|
|
1856
1869
|
}
|
|
1857
1870
|
}
|
|
@@ -1959,8 +1972,24 @@ static LeptrisXsdSchema xsd_compile_impl(const char* xsd_text,
|
|
|
1959
1972
|
s->target_ns = xsd_strdup(
|
|
1960
1973
|
leptris_element_attribute(root, "targetNamespace"));
|
|
1961
1974
|
{
|
|
1975
|
+
/* XSD 1.1 §4.3 schema versioning: the W3C suite and the
|
|
1976
|
+
* binding ecosystem mark 1.1 with vc:minVersion (the
|
|
1977
|
+
* versioning namespace); the plain version attribute is
|
|
1978
|
+
* the other legal spelling. vc:maxVersion below 1.1 pins
|
|
1979
|
+
* a 1.0 processor target regardless. leptris#1910/#1911:
|
|
1980
|
+
* reading only @version silently compiled asserts and
|
|
1981
|
+
* alternatives away for every vc-marked schema. */
|
|
1962
1982
|
const char* ver = leptris_element_attribute(root, "version");
|
|
1963
|
-
|
|
1983
|
+
const char* vmin = leptris_element_attribute_ns(
|
|
1984
|
+
root, "http://www.w3.org/2001/XMLSchema-versioning",
|
|
1985
|
+
"minVersion");
|
|
1986
|
+
const char* vmax = leptris_element_attribute_ns(
|
|
1987
|
+
root, "http://www.w3.org/2001/XMLSchema-versioning",
|
|
1988
|
+
"maxVersion");
|
|
1989
|
+
int is11 = (ver && strcmp(ver, "1.1") == 0) ||
|
|
1990
|
+
(vmin && strcmp(vmin, "1.1") == 0);
|
|
1991
|
+
if (vmax && strcmp(vmax, "1.0") == 0) is11 = 0;
|
|
1992
|
+
s->version_11 = is11;
|
|
1964
1993
|
}
|
|
1965
1994
|
|
|
1966
1995
|
const char* local = NULL;
|
|
@@ -2021,6 +2050,7 @@ static LeptrisXsdSchema xsd_compile_impl(const char* xsd_text,
|
|
|
2021
2050
|
|
|
2022
2051
|
xsd_capture_root(s, root);
|
|
2023
2052
|
xsd_resolve_extension_bases(s);
|
|
2053
|
+
xsd_resolve_pending_attr_refs(s);
|
|
2024
2054
|
|
|
2025
2055
|
leptris_document_free(doc);
|
|
2026
2056
|
return s;
|
|
@@ -2245,7 +2275,8 @@ static void xsd_capture_root(struct leptris_xsd_schema* s,
|
|
|
2245
2275
|
|
|
2246
2276
|
if (strcmp(local, "include") == 0 ||
|
|
2247
2277
|
strcmp(local, "import") == 0 ||
|
|
2248
|
-
strcmp(local, "redefine") == 0
|
|
2278
|
+
strcmp(local, "redefine") == 0 ||
|
|
2279
|
+
strcmp(local, "override") == 0) {
|
|
2249
2280
|
const char* loc = leptris_element_attribute(
|
|
2250
2281
|
(LeptrisElement)n, "schemaLocation");
|
|
2251
2282
|
if (loc && s->base_dir && s->include_depth < 16) {
|
|
@@ -2312,6 +2343,20 @@ static void xsd_capture_root(struct leptris_xsd_schema* s,
|
|
|
2312
2343
|
if (sub_ns) free(sub_ns);
|
|
2313
2344
|
s->target_ns = saved_ns;
|
|
2314
2345
|
}
|
|
2346
|
+
/* leptris#1913 (XSD 1.1 §I.4): the override
|
|
2347
|
+
* element's OWN declaration children
|
|
2348
|
+
* replace same-named components of the base
|
|
2349
|
+
* just captured — capture them AFTER the
|
|
2350
|
+
* base so the lookup ladder (head-first)
|
|
2351
|
+
* sees the replacements. */
|
|
2352
|
+
if (subroot && same_ns &&
|
|
2353
|
+
strcmp(local, "override") == 0) {
|
|
2354
|
+
s->include_depth++;
|
|
2355
|
+
s->capture_force = 1;
|
|
2356
|
+
xsd_capture_root(s, (LeptrisElement)n);
|
|
2357
|
+
s->capture_force = 0;
|
|
2358
|
+
s->include_depth--;
|
|
2359
|
+
}
|
|
2315
2360
|
leptris_document_free(sub);
|
|
2316
2361
|
}
|
|
2317
2362
|
free(text);
|
|
@@ -2446,7 +2491,8 @@ static void xsd_capture_root(struct leptris_xsd_schema* s,
|
|
|
2446
2491
|
XsdAttrGroupDef* seen = s->attr_groups;
|
|
2447
2492
|
for (; seen; seen = seen->next)
|
|
2448
2493
|
if (strcmp(seen->name, nm) == 0) break;
|
|
2449
|
-
if (!seen
|
|
2494
|
+
if (!seen || s->capture_force)
|
|
2495
|
+
xsd_capture_attr_group_def(s, (LeptrisElement)n, nm);
|
|
2450
2496
|
}
|
|
2451
2497
|
} else if (strcmp(local, "group") == 0 && uri && !strcmp(uri, XSD_NS)) {
|
|
2452
2498
|
const char* nm =
|
|
@@ -3109,6 +3155,7 @@ static XsdAttrDecl* xsd_copy_attr_rows(const XsdAttrDecl* src) {
|
|
|
3109
3155
|
d->type = xsd_strdup(src->type);
|
|
3110
3156
|
d->fixed = xsd_strdup(src->fixed);
|
|
3111
3157
|
d->required = src->required;
|
|
3158
|
+
d->pending_ref = src->pending_ref;
|
|
3112
3159
|
if (tail)
|
|
3113
3160
|
tail->next = d;
|
|
3114
3161
|
else
|
|
@@ -3118,6 +3165,51 @@ static XsdAttrDecl* xsd_copy_attr_rows(const XsdAttrDecl* src) {
|
|
|
3118
3165
|
return head;
|
|
3119
3166
|
}
|
|
3120
3167
|
|
|
3168
|
+
/* leptris-ruby#569: re-resolve the rows the #1880 attributeGroup
|
|
3169
|
+
* pre-pass captured before the import chase had registered the
|
|
3170
|
+
* referenced unit's top-level attributes. Idempotent; pending rows
|
|
3171
|
+
* that never resolve keep declaring their name (untyped) — the
|
|
3172
|
+
* compile-time ref check already rejects true danglers loudly. */
|
|
3173
|
+
#define XSD_PENDING_REF 1
|
|
3174
|
+
#define XSD_PENDING_USE 2
|
|
3175
|
+
static void xsd_resolve_pending_attr_refs(struct leptris_xsd_schema* s) {
|
|
3176
|
+
if (!s) return;
|
|
3177
|
+
int progressed = 1;
|
|
3178
|
+
while (progressed) {
|
|
3179
|
+
progressed = 0;
|
|
3180
|
+
for (XsdAttrGroupDef* g = s->attr_groups; g; g = g->next)
|
|
3181
|
+
for (XsdAttrDecl* a = g->attrs; a; a = a->next) {
|
|
3182
|
+
if (!(a->pending_ref & XSD_PENDING_REF) || !a->name)
|
|
3183
|
+
continue;
|
|
3184
|
+
const XsdAttrDecl* src = xsd_find_top_attr(s, a->name);
|
|
3185
|
+
if (!src) continue;
|
|
3186
|
+
free(a->type);
|
|
3187
|
+
free(a->fixed);
|
|
3188
|
+
a->type = xsd_strdup(src->type);
|
|
3189
|
+
a->fixed = xsd_strdup(src->fixed);
|
|
3190
|
+
if (!(a->pending_ref & XSD_PENDING_USE))
|
|
3191
|
+
a->required = src->required;
|
|
3192
|
+
a->pending_ref &= ~XSD_PENDING_REF;
|
|
3193
|
+
progressed = 1;
|
|
3194
|
+
}
|
|
3195
|
+
for (XsdTypeAttrs* t = s->type_attrs; t; t = t->next)
|
|
3196
|
+
for (XsdAttrDecl* a = t->attrs; a; a = a->next) {
|
|
3197
|
+
if (!(a->pending_ref & XSD_PENDING_REF) || !a->name)
|
|
3198
|
+
continue;
|
|
3199
|
+
const XsdAttrDecl* src = xsd_find_top_attr(s, a->name);
|
|
3200
|
+
if (!src) continue;
|
|
3201
|
+
free(a->type);
|
|
3202
|
+
free(a->fixed);
|
|
3203
|
+
a->type = xsd_strdup(src->type);
|
|
3204
|
+
a->fixed = xsd_strdup(src->fixed);
|
|
3205
|
+
if (!(a->pending_ref & XSD_PENDING_USE))
|
|
3206
|
+
a->required = src->required;
|
|
3207
|
+
a->pending_ref &= ~XSD_PENDING_REF;
|
|
3208
|
+
progressed = 1;
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3121
3213
|
/* Capture the attribute rows of a complexType or attributeGroup:
|
|
3122
3214
|
* named rows, inline anonymous simpleTypes (synthesized slots),
|
|
3123
3215
|
* refs to top-level attributes, and attributeGroup refs. */
|
|
@@ -3185,16 +3277,31 @@ static XsdAttrDecl* xsd_capture_attr_rows(struct leptris_xsd_schema* s,
|
|
|
3185
3277
|
leptris_element_attribute(ae, "ref"));
|
|
3186
3278
|
const XsdAttrDecl* src =
|
|
3187
3279
|
ref ? xsd_find_top_attr(s, ref) : NULL;
|
|
3188
|
-
if (!src) {
|
|
3280
|
+
if (!src && !ref) {
|
|
3189
3281
|
free(d);
|
|
3190
3282
|
continue;
|
|
3191
3283
|
}
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3284
|
+
if (!src) {
|
|
3285
|
+
/* leptris-ruby#569: the #1880 pre-pass captures
|
|
3286
|
+
* attributeGroup defs BEFORE the import chase
|
|
3287
|
+
* registers the referenced unit's globals — an
|
|
3288
|
+
* unresolved ref used to be silently DROPPED
|
|
3289
|
+
* here, hole-punching the type's rows (a:blip
|
|
3290
|
+
* @r:embed "not declared (strict)") or leaving
|
|
3291
|
+
* the type attribute-less so the strict walk
|
|
3292
|
+
* never ran. Keep the row pending; the
|
|
3293
|
+
* post-capture fixup resolves it. */
|
|
3294
|
+
d->name = xsd_strdup(xsd_local_name(ref));
|
|
3295
|
+
d->pending_ref = use ? 3 : 1;
|
|
3296
|
+
d->required = (use && strcmp(use, "required") == 0);
|
|
3297
|
+
} else {
|
|
3298
|
+
d->name = xsd_strdup(src->name);
|
|
3299
|
+
d->type = xsd_strdup(src->type);
|
|
3300
|
+
d->fixed = xsd_strdup(src->fixed);
|
|
3301
|
+
d->required = use
|
|
3302
|
+
? (strcmp(use, "required") == 0)
|
|
3303
|
+
: src->required;
|
|
3304
|
+
}
|
|
3198
3305
|
}
|
|
3199
3306
|
if (tail)
|
|
3200
3307
|
tail->next = d;
|
|
@@ -3802,5 +3909,6 @@ LEPTRIS_API LeptrisXsdSchema leptris_xsd_compile_set(
|
|
|
3802
3909
|
s->base_dir = saved;
|
|
3803
3910
|
}
|
|
3804
3911
|
xsd_resolve_extension_bases(s);
|
|
3912
|
+
xsd_resolve_pending_attr_refs(s);
|
|
3805
3913
|
return s;
|
|
3806
3914
|
}
|
|
@@ -197,6 +197,15 @@ typedef struct xsd_attr_decl {
|
|
|
197
197
|
char* type; /* builtin ref or local simpleType name (NULL=anySimple) */
|
|
198
198
|
char* fixed; /* #FIXED value: present values must string-equal it */
|
|
199
199
|
int required;
|
|
200
|
+
/* leptris-ruby#569: the row came from <xs:attribute ref=.../>
|
|
201
|
+
* whose global declaration was not yet captured (the #1880
|
|
202
|
+
* attributeGroup pre-pass runs before the import chase). The
|
|
203
|
+
* row is kept — never silently dropped — and xsd_compile_impl
|
|
204
|
+
* re-resolves it once the full merged capture has run
|
|
205
|
+
* (xsd_resolve_pending_attr_refs). bit 0 = ref unresolved,
|
|
206
|
+
* bit 1 = the ref carried its own use= (it overrides the
|
|
207
|
+
* declaration's). */
|
|
208
|
+
int pending_ref;
|
|
200
209
|
struct xsd_attr_decl* next;
|
|
201
210
|
} XsdAttrDecl;
|
|
202
211
|
|
|
@@ -120,11 +120,28 @@ leptris_add_test(test_large_docs parser/test_large_documents.cpp)
|
|
|
120
120
|
leptris_add_test(test_encoding parser/test_encoding.cpp)
|
|
121
121
|
leptris_add_test(test_dom dom/test_dom.cpp)
|
|
122
122
|
leptris_add_test(test_element_children dom/test_element_children.cpp)
|
|
123
|
+
leptris_add_test(test_entity_refs dom/test_entity_refs.cpp)
|
|
123
124
|
leptris_add_test(test_namespace_cache dom/test_namespace_cache.cpp)
|
|
124
125
|
leptris_add_test(test_map_lifecycle dom/test_map_lifecycle.cpp)
|
|
125
126
|
leptris_add_test(test_simd_count parser/test_simd_count.cpp)
|
|
126
127
|
leptris_add_test(test_ws_shape parser/test_whitespace_shape.cpp)
|
|
127
128
|
leptris_add_test(test_descriptor abi/test_descriptor.cpp)
|
|
129
|
+
leptris_add_test(test_capabilities abi/test_capabilities.cpp)
|
|
130
|
+
# The capability descriptor's build-conditional bits follow the
|
|
131
|
+
# engine's PUBLIC macros, which do not flow through the object
|
|
132
|
+
# aggregation (same mirror as test_qt3 below).
|
|
133
|
+
if(LEPTRIS_ENABLE_DUCET)
|
|
134
|
+
target_compile_definitions(test_capabilities PRIVATE LEPTRIS_HAS_DUCET=1)
|
|
135
|
+
endif()
|
|
136
|
+
if(LEPTRIS_ENABLE_UTF8PROC)
|
|
137
|
+
target_compile_definitions(test_capabilities PRIVATE LEPTRIS_HAS_UTF8PROC=1)
|
|
138
|
+
endif()
|
|
139
|
+
if(LEPTRIS_ENABLE_ICONV)
|
|
140
|
+
target_compile_definitions(test_capabilities PRIVATE LEPTRIS_HAS_ICONV=1)
|
|
141
|
+
endif()
|
|
142
|
+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|AMD64|i[3-6]86)")
|
|
143
|
+
target_compile_definitions(test_capabilities PRIVATE LEPTRIS_HAS_AVX2_BUILD=1)
|
|
144
|
+
endif()
|
|
128
145
|
leptris_add_test(test_document_children dom/test_document_children.cpp)
|
|
129
146
|
leptris_add_test(test_vtable dom/test_vtable.cpp)
|
|
130
147
|
leptris_add_test(test_node_surface_parity dom/test_node_surface_parity.cpp)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// leptris#1905: one call answering what this installed engine
|
|
2
|
+
// serves. The descriptor is a versioned bitset — new capabilities
|
|
3
|
+
// APPEND bits, never reorder or repack (a reorder bumps
|
|
4
|
+
// LEPTRIS_CAPS_DESCRIPTOR_VERSION).
|
|
5
|
+
#include <leptris.h>
|
|
6
|
+
#include <leptris/descriptor.h>
|
|
7
|
+
#include <leptris/dtd.h>
|
|
8
|
+
#include <leptris/html.h>
|
|
9
|
+
#include <leptris/sax/sax.h>
|
|
10
|
+
#include <leptris/xpath/xpath.h>
|
|
11
|
+
#include <leptris/xquery/xquery.h>
|
|
12
|
+
|
|
13
|
+
#include <gtest/gtest.h>
|
|
14
|
+
|
|
15
|
+
// Anchor law: each unconditional bit's face symbol is REFERENCED
|
|
16
|
+
// here — a descriptor bit without a real, linked face fails the
|
|
17
|
+
// BUILD of this test, not just the assertion.
|
|
18
|
+
namespace caps_anchors {
|
|
19
|
+
void* const kParse = (void*)&leptris_parse_string;
|
|
20
|
+
void* const kDom = (void*)&leptris_document_root;
|
|
21
|
+
void* const kXpath = (void*)&leptris_xpath_eval;
|
|
22
|
+
void* const kXquery = (void*)&leptris_xquery_eval;
|
|
23
|
+
void* const kDtd = (void*)&leptris_dtd_parse;
|
|
24
|
+
void* const kSax = (void*)&leptris_sax_parse;
|
|
25
|
+
void* const kHtml = (void*)&leptris_parse_html_string;
|
|
26
|
+
void* const kXinclude = (void*)&leptris_xinclude_process;
|
|
27
|
+
void* const kDiff = (void*)&leptris_diff;
|
|
28
|
+
void* const kDigest = (void*)&leptris_node_digest;
|
|
29
|
+
void* const kXsd = (void*)&leptris_xsd_compile;
|
|
30
|
+
void* const kXsdSet = (void*)&leptris_xsd_compile_set;
|
|
31
|
+
void* const kRelaxng = (void*)&leptris_rng_parse;
|
|
32
|
+
void* const kSchematron = (void*)&leptris_schematron_parse;
|
|
33
|
+
void* const kXslt = (void*)&leptris_xslt_parse;
|
|
34
|
+
void* const kDescriptor = (void*)&leptris_plan_result_build_packed;
|
|
35
|
+
void* const kNsSnapshot = (void*)&leptris_element_namespace_declarations_snapshot;
|
|
36
|
+
void* const kChildrenBatch = (void*)&leptris_element_children_batch;
|
|
37
|
+
void* const kNameCompare = (void*)&leptris_node_name_compare;
|
|
38
|
+
void* const kVersion = (void*)&leptris_version;
|
|
39
|
+
void* const kEntityRefs = (void*)&leptris_entity_ref_node_name;
|
|
40
|
+
} // namespace caps_anchors
|
|
41
|
+
|
|
42
|
+
TEST(LeptrisCapabilities, DescriptorVersionIsCurrent) {
|
|
43
|
+
LeptrisCapabilities c = leptris_capabilities();
|
|
44
|
+
EXPECT_EQ(c.descriptor_version, LEPTRIS_CAPS_DESCRIPTOR_VERSION);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
TEST(LeptrisCapabilities, UnconditionalFacesAreSet) {
|
|
48
|
+
LeptrisCapabilities c = leptris_capabilities();
|
|
49
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_PARSE, 0ULL);
|
|
50
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_DOM, 0ULL);
|
|
51
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_XPATH, 0ULL);
|
|
52
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_XQUERY, 0ULL);
|
|
53
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_DTD, 0ULL);
|
|
54
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_SAX, 0ULL);
|
|
55
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_HTML, 0ULL);
|
|
56
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_XINCLUDE, 0ULL);
|
|
57
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_DIFF, 0ULL);
|
|
58
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_DIGEST, 0ULL);
|
|
59
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_XSD, 0ULL);
|
|
60
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_XSD_SET, 0ULL);
|
|
61
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_RELAXNG, 0ULL);
|
|
62
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_SCHEMATRON, 0ULL);
|
|
63
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_XSLT, 0ULL);
|
|
64
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_DESCRIPTOR, 0ULL);
|
|
65
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_NS_SNAPSHOT_BULK, 0ULL);
|
|
66
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_CHILDREN_BATCH, 0ULL);
|
|
67
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_NAME_COMPARE, 0ULL);
|
|
68
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_VERSION, 0ULL);
|
|
69
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_ENTITY_REF_NODES, 0ULL);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
TEST(LeptrisCapabilities, BuildConditionalBitsMatchTheBuild) {
|
|
73
|
+
LeptrisCapabilities c = leptris_capabilities();
|
|
74
|
+
#if defined(LEPTRIS_HAS_DUCET)
|
|
75
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_COLLATION_DUCET, 0ULL);
|
|
76
|
+
#else
|
|
77
|
+
EXPECT_EQ(c.caps & LEPTRIS_CAP_COLLATION_DUCET, 0ULL);
|
|
78
|
+
#endif
|
|
79
|
+
#if defined(LEPTRIS_HAS_UTF8PROC)
|
|
80
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_UNICODE_UTF8PROC, 0ULL);
|
|
81
|
+
#else
|
|
82
|
+
EXPECT_EQ(c.caps & LEPTRIS_CAP_UNICODE_UTF8PROC, 0ULL);
|
|
83
|
+
#endif
|
|
84
|
+
#if defined(LEPTRIS_HAS_ICONV)
|
|
85
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_ENCODING_ICONV, 0ULL);
|
|
86
|
+
#else
|
|
87
|
+
EXPECT_EQ(c.caps & LEPTRIS_CAP_ENCODING_ICONV, 0ULL);
|
|
88
|
+
#endif
|
|
89
|
+
#if defined(LEPTRIS_HAS_AVX2_BUILD)
|
|
90
|
+
EXPECT_NE(c.caps & LEPTRIS_CAP_SIMD_AVX2, 0ULL);
|
|
91
|
+
#else
|
|
92
|
+
EXPECT_EQ(c.caps & LEPTRIS_CAP_SIMD_AVX2, 0ULL);
|
|
93
|
+
#endif
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
TEST(LeptrisCapabilities, NoUnknownBits) {
|
|
97
|
+
LeptrisCapabilities c = leptris_capabilities();
|
|
98
|
+
constexpr unsigned long long kKnown =
|
|
99
|
+
LEPTRIS_CAP_PARSE | LEPTRIS_CAP_DOM | LEPTRIS_CAP_XPATH |
|
|
100
|
+
LEPTRIS_CAP_XQUERY | LEPTRIS_CAP_DTD | LEPTRIS_CAP_SAX |
|
|
101
|
+
LEPTRIS_CAP_HTML | LEPTRIS_CAP_XINCLUDE | LEPTRIS_CAP_DIFF |
|
|
102
|
+
LEPTRIS_CAP_DIGEST | LEPTRIS_CAP_XSD | LEPTRIS_CAP_XSD_SET |
|
|
103
|
+
LEPTRIS_CAP_RELAXNG | LEPTRIS_CAP_SCHEMATRON | LEPTRIS_CAP_XSLT |
|
|
104
|
+
LEPTRIS_CAP_DESCRIPTOR | LEPTRIS_CAP_NS_SNAPSHOT_BULK |
|
|
105
|
+
LEPTRIS_CAP_CHILDREN_BATCH | LEPTRIS_CAP_NAME_COMPARE |
|
|
106
|
+
LEPTRIS_CAP_VERSION | LEPTRIS_CAP_COLLATION_DUCET |
|
|
107
|
+
LEPTRIS_CAP_UNICODE_UTF8PROC | LEPTRIS_CAP_ENCODING_ICONV |
|
|
108
|
+
LEPTRIS_CAP_SIMD_AVX2 | LEPTRIS_CAP_ENTITY_REF_NODES;
|
|
109
|
+
EXPECT_EQ(c.caps & ~kKnown, 0ULL)
|
|
110
|
+
<< "an unknown bit is set — the descriptor grew without "
|
|
111
|
+
"bumping LEPTRIS_CAPS_DESCRIPTOR_VERSION";
|
|
112
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// leptris#1904: LEPTRIS_PARSE_KEEP_ENTITY_REFS yields entity
|
|
2
|
+
// references as FIRST-CLASS nodes — segments split around the five
|
|
3
|
+
// built-ins and custom named references, numeric character
|
|
4
|
+
// references folded into text (they are character references, not
|
|
5
|
+
// entity references, per XML 1.0 §4.1). The DOM the binding
|
|
6
|
+
// consumes: text / entity-ref / text / ... with string-value,
|
|
7
|
+
// serialization, and XPath walking the expanded value.
|
|
8
|
+
#include <gtest/gtest.h>
|
|
9
|
+
#include <leptris.h>
|
|
10
|
+
#include <cstring>
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <vector>
|
|
13
|
+
|
|
14
|
+
namespace {
|
|
15
|
+
|
|
16
|
+
struct ChildInfo {
|
|
17
|
+
int type;
|
|
18
|
+
std::string text;
|
|
19
|
+
std::string name;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
std::vector<ChildInfo> children_of(LeptrisElement e) {
|
|
23
|
+
std::vector<ChildInfo> rows;
|
|
24
|
+
for (LeptrisNodeRef c = leptris_node_first_child(
|
|
25
|
+
leptris_element_as_node(e));
|
|
26
|
+
c; c = leptris_node_next_sibling(c)) {
|
|
27
|
+
ChildInfo row;
|
|
28
|
+
row.type = (int)leptris_node_get_type(c);
|
|
29
|
+
if (row.type == LEPTRIS_NODE_TYPE_TEXT)
|
|
30
|
+
row.text = leptris_text_node_get_content(c);
|
|
31
|
+
if (row.type == LEPTRIS_NODE_TYPE_ENTITY_REF)
|
|
32
|
+
row.name = leptris_entity_ref_node_name(c);
|
|
33
|
+
rows.push_back(row);
|
|
34
|
+
}
|
|
35
|
+
return rows;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
} // namespace
|
|
39
|
+
|
|
40
|
+
TEST(EntityRefNodes, BuiltinsBecomeNodes) {
|
|
41
|
+
const char* xml = "<a>x&y<z>w</a>";
|
|
42
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
43
|
+
LeptrisDocument doc = leptris_parse_string_flags(
|
|
44
|
+
xml, strlen(xml), LEPTRIS_PARSE_KEEP_ENTITY_REFS, &st);
|
|
45
|
+
ASSERT_NE(doc, (LeptrisDocument)0);
|
|
46
|
+
LeptrisElement a = leptris_document_root(doc);
|
|
47
|
+
std::vector<ChildInfo> kids = children_of(a);
|
|
48
|
+
ASSERT_EQ(kids.size(), 7u);
|
|
49
|
+
EXPECT_EQ(kids[0].type, (int)LEPTRIS_NODE_TYPE_TEXT);
|
|
50
|
+
EXPECT_EQ(kids[0].text, "x");
|
|
51
|
+
EXPECT_EQ(kids[1].type, (int)LEPTRIS_NODE_TYPE_ENTITY_REF);
|
|
52
|
+
EXPECT_EQ(kids[1].name, "amp");
|
|
53
|
+
EXPECT_EQ(kids[2].text, "y");
|
|
54
|
+
EXPECT_EQ(kids[3].name, "lt");
|
|
55
|
+
EXPECT_EQ(kids[4].text, "z");
|
|
56
|
+
EXPECT_EQ(kids[5].name, "gt");
|
|
57
|
+
EXPECT_EQ(kids[6].text, "w");
|
|
58
|
+
leptris_document_free(doc);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
TEST(EntityRefNodes, NumericCharacterRefsStayText) {
|
|
62
|
+
/* XML 1.0 §4.1: character references are NOT entity references. */
|
|
63
|
+
const char* xml = "<a>AB</a>";
|
|
64
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
65
|
+
LeptrisDocument doc = leptris_parse_string_flags(
|
|
66
|
+
xml, strlen(xml), LEPTRIS_PARSE_KEEP_ENTITY_REFS, &st);
|
|
67
|
+
ASSERT_NE(doc, (LeptrisDocument)0);
|
|
68
|
+
LeptrisElement a = leptris_document_root(doc);
|
|
69
|
+
std::vector<ChildInfo> kids = children_of(a);
|
|
70
|
+
ASSERT_EQ(kids.size(), 1u);
|
|
71
|
+
EXPECT_EQ(kids[0].type, (int)LEPTRIS_NODE_TYPE_TEXT);
|
|
72
|
+
EXPECT_EQ(kids[0].text, "AB");
|
|
73
|
+
leptris_document_free(doc);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
TEST(EntityRefNodes, StringValueSerializationAndXPathAgree) {
|
|
77
|
+
const char* xml = "<a>x&y<z</a>";
|
|
78
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
79
|
+
LeptrisDocument doc = leptris_parse_string_flags(
|
|
80
|
+
xml, strlen(xml), LEPTRIS_PARSE_KEEP_ENTITY_REFS, &st);
|
|
81
|
+
ASSERT_NE(doc, (LeptrisDocument)0);
|
|
82
|
+
LeptrisElement a = leptris_document_root(doc);
|
|
83
|
+
EXPECT_STREQ(leptris_element_text(a), "x&y<z");
|
|
84
|
+
char* ser = leptris_document_serialize(doc, NULL);
|
|
85
|
+
ASSERT_NE(ser, nullptr);
|
|
86
|
+
EXPECT_STREQ(ser, "<a>x&y<z</a>");
|
|
87
|
+
leptris_free_string(ser);
|
|
88
|
+
LeptrisXPathResult r = leptris_xpath_eval(doc, NULL, "string(/a)");
|
|
89
|
+
ASSERT_NE(r, nullptr);
|
|
90
|
+
char* sv = leptris_xpath_result_string(r);
|
|
91
|
+
EXPECT_STREQ(sv, "x&y<z");
|
|
92
|
+
leptris_free_string(sv);
|
|
93
|
+
leptris_xpath_result_free(r);
|
|
94
|
+
leptris_document_free(doc);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
TEST(EntityRefNodes, CustomNamedRefsAreNodes) {
|
|
98
|
+
const char* xml =
|
|
99
|
+
"<!DOCTYPE r [<!ENTITY foo \"x\">]><r>a&foo;b</r>";
|
|
100
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
101
|
+
LeptrisDocument doc = leptris_parse_string_flags(
|
|
102
|
+
xml, strlen(xml), LEPTRIS_PARSE_KEEP_ENTITY_REFS, &st);
|
|
103
|
+
ASSERT_NE(doc, (LeptrisDocument)0);
|
|
104
|
+
LeptrisElement r = leptris_document_root(doc);
|
|
105
|
+
std::vector<ChildInfo> kids = children_of(r);
|
|
106
|
+
ASSERT_EQ(kids.size(), 3u);
|
|
107
|
+
EXPECT_EQ(kids[1].type, (int)LEPTRIS_NODE_TYPE_ENTITY_REF);
|
|
108
|
+
EXPECT_EQ(kids[1].name, "foo");
|
|
109
|
+
EXPECT_STREQ(leptris_element_text(r), "axb");
|
|
110
|
+
leptris_document_free(doc);
|
|
111
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <gtest/gtest.h>
|
|
8
8
|
|
|
9
9
|
#include <cstdio>
|
|
10
|
+
#include <fstream>
|
|
10
11
|
#include <cstring>
|
|
11
12
|
#include <string>
|
|
12
13
|
#include <algorithm>
|
|
@@ -3680,3 +3681,325 @@ TEST(XsdContent, Issue1894ReproStaysUnderCapAndCorrect) {
|
|
|
3680
3681
|
EXPECT_EQ(leptris_xsd_error_count(s), 0u);
|
|
3681
3682
|
leptris_xsd_free(s);
|
|
3682
3683
|
}
|
|
3684
|
+
|
|
3685
|
+
|
|
3686
|
+
/* leptris-ruby#569 family: cross-namespace references into an
|
|
3687
|
+
* IMPORTED unit. The importing schema must declare xmlns="urn:a"
|
|
3688
|
+
* as the DEFAULT namespace — unprefixed ref QNames resolve to
|
|
3689
|
+
* no-namespace otherwise (spec behavior, the #1901 repro lesson). */
|
|
3690
|
+
TEST(XsdCrossNs, AttributeRefIntoImportedUnitResolves) {
|
|
3691
|
+
const char* rel =
|
|
3692
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3693
|
+
" targetNamespace=\"urn:r\" elementFormDefault=\"qualified\">"
|
|
3694
|
+
"<xs:simpleType name=\"ST_RelId\">"
|
|
3695
|
+
"<xs:restriction base=\"xs:string\"/></xs:simpleType>"
|
|
3696
|
+
"<xs:attribute name=\"embed\" type=\"ST_RelId\"/>"
|
|
3697
|
+
"</xs:schema>";
|
|
3698
|
+
const char* main =
|
|
3699
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3700
|
+
" xmlns:r=\"urn:r\" xmlns=\"urn:a\" targetNamespace=\"urn:a\""
|
|
3701
|
+
" elementFormDefault=\"qualified\">"
|
|
3702
|
+
"<xs:import namespace=\"urn:r\" schemaLocation=\"blip_repro_rel.xsd\"/>"
|
|
3703
|
+
"<xs:attributeGroup name=\"AG_Blob\">"
|
|
3704
|
+
"<xs:attribute ref=\"r:embed\" use=\"optional\"/>"
|
|
3705
|
+
"</xs:attributeGroup>"
|
|
3706
|
+
"<xs:complexType name=\"CT_Blip\">"
|
|
3707
|
+
"<xs:sequence><xs:element name=\"e\" type=\"xs:string\""
|
|
3708
|
+
" minOccurs=\"0\"/></xs:sequence>"
|
|
3709
|
+
"<xs:attributeGroup ref=\"AG_Blob\"/>"
|
|
3710
|
+
"</xs:complexType>"
|
|
3711
|
+
"<xs:element name=\"blip\" type=\"CT_Blip\"/>"
|
|
3712
|
+
"</xs:schema>";
|
|
3713
|
+
|
|
3714
|
+
const char* dir = std::getenv("TMPDIR");
|
|
3715
|
+
std::string base = dir ? dir : "/tmp";
|
|
3716
|
+
std::string rel_path = base + "/blip_repro_rel.xsd";
|
|
3717
|
+
std::string main_path = base + "/blip_repro_main.xsd";
|
|
3718
|
+
{
|
|
3719
|
+
std::ofstream f(rel_path);
|
|
3720
|
+
f << rel;
|
|
3721
|
+
}
|
|
3722
|
+
{
|
|
3723
|
+
std::ofstream f(main_path);
|
|
3724
|
+
f << main;
|
|
3725
|
+
}
|
|
3726
|
+
const char* paths[2] = {rel_path.c_str(), main_path.c_str()};
|
|
3727
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3728
|
+
LeptrisXsdSchema s =
|
|
3729
|
+
leptris_xsd_compile_set(paths, 2, &st);
|
|
3730
|
+
if (st != LEPTRIS_OK || s == (LeptrisXsdSchema)0) {
|
|
3731
|
+
const char* err = s ? leptris_xsd_error(s) : "(no handle)";
|
|
3732
|
+
GTEST_FAIL() << "compile_set failed st=" << (int)st
|
|
3733
|
+
<< " err=" << (err ? err : "(null)");
|
|
3734
|
+
}
|
|
3735
|
+
|
|
3736
|
+
EXPECT_EQ(validate_compiled(s,
|
|
3737
|
+
"<a:blip xmlns:a=\"urn:a\" xmlns:r=\"urn:r\""
|
|
3738
|
+
" r:embed=\"rId2\"><e>x</e></a:blip>"),
|
|
3739
|
+
1)
|
|
3740
|
+
<< "cross-unit attribute ref must resolve: "
|
|
3741
|
+
<< leptris_xsd_error(s);
|
|
3742
|
+
std::remove(rel_path.c_str());
|
|
3743
|
+
std::remove(main_path.c_str());
|
|
3744
|
+
leptris_xsd_free(s);
|
|
3745
|
+
}
|
|
3746
|
+
|
|
3747
|
+
/* Same shape through the single-document import chase. */
|
|
3748
|
+
TEST(XsdCrossNs, SingleDocImportChaseResolves) {
|
|
3749
|
+
const char* rel =
|
|
3750
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3751
|
+
" targetNamespace=\"urn:r\" elementFormDefault=\"qualified\">"
|
|
3752
|
+
"<xs:simpleType name=\"ST_RelId\">"
|
|
3753
|
+
"<xs:restriction base=\"xs:string\"/></xs:simpleType>"
|
|
3754
|
+
"<xs:attribute name=\"embed\" type=\"ST_RelId\"/>"
|
|
3755
|
+
"</xs:schema>";
|
|
3756
|
+
const char* main =
|
|
3757
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3758
|
+
" xmlns:r=\"urn:r\" xmlns=\"urn:a\" targetNamespace=\"urn:a\""
|
|
3759
|
+
" elementFormDefault=\"qualified\">"
|
|
3760
|
+
"<xs:import namespace=\"urn:r\""
|
|
3761
|
+
" schemaLocation=\"blip_repro_rel.xsd\"/>"
|
|
3762
|
+
"<xs:attributeGroup name=\"AG_Blob\">"
|
|
3763
|
+
"<xs:attribute ref=\"r:embed\" use=\"optional\"/>"
|
|
3764
|
+
"</xs:attributeGroup>"
|
|
3765
|
+
"<xs:complexType name=\"CT_Blip\">"
|
|
3766
|
+
"<xs:sequence><xs:element name=\"e\" type=\"xs:string\""
|
|
3767
|
+
" minOccurs=\"0\"/></xs:sequence>"
|
|
3768
|
+
"<xs:attributeGroup ref=\"AG_Blob\"/>"
|
|
3769
|
+
"</xs:complexType>"
|
|
3770
|
+
"<xs:element name=\"blip\" type=\"CT_Blip\"/>"
|
|
3771
|
+
"</xs:schema>";
|
|
3772
|
+
|
|
3773
|
+
const char* dir = std::getenv("TMPDIR");
|
|
3774
|
+
std::string base = dir ? dir : "/tmp";
|
|
3775
|
+
std::string rel_path = base + "/blip_repro_rel.xsd";
|
|
3776
|
+
std::string main_path = base + "/blip_repro_main.xsd";
|
|
3777
|
+
{
|
|
3778
|
+
std::ofstream f(rel_path);
|
|
3779
|
+
f << rel;
|
|
3780
|
+
}
|
|
3781
|
+
{
|
|
3782
|
+
std::ofstream f(main_path);
|
|
3783
|
+
f << main;
|
|
3784
|
+
}
|
|
3785
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3786
|
+
LeptrisXsdSchema s =
|
|
3787
|
+
leptris_xsd_compile_file(main_path.c_str(), &st);
|
|
3788
|
+
if (st != LEPTRIS_OK || s == (LeptrisXsdSchema)0) {
|
|
3789
|
+
const char* err = s ? leptris_xsd_error(s) : "(no handle)";
|
|
3790
|
+
GTEST_FAIL() << "single-doc compile failed st=" << (int)st
|
|
3791
|
+
<< " err=" << (err ? err : "(null)");
|
|
3792
|
+
}
|
|
3793
|
+
|
|
3794
|
+
EXPECT_EQ(validate_compiled(s,
|
|
3795
|
+
"<a:blip xmlns:a=\"urn:a\" xmlns:r=\"urn:r\""
|
|
3796
|
+
" r:embed=\"rId2\"><e>x</e></a:blip>"),
|
|
3797
|
+
1)
|
|
3798
|
+
<< "import-chase attribute ref must resolve: "
|
|
3799
|
+
<< leptris_xsd_error(s);
|
|
3800
|
+
std::remove(rel_path.c_str());
|
|
3801
|
+
std::remove(main_path.c_str());
|
|
3802
|
+
leptris_xsd_free(s);
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
/* The #569 regression itself: the #1880 attributeGroup pre-pass
|
|
3806
|
+
* captured AG_Blob and resolved its <xs:attribute ref="r:embed"/>
|
|
3807
|
+
* row BEFORE the import chase registered the referenced unit's
|
|
3808
|
+
* r:embed — the row used to be silently dropped, so whole-instance
|
|
3809
|
+
* validation then rejected every a:blip @r:embed ("not declared
|
|
3810
|
+
* (strict)") on the real DrawingML chain. The row must survive as
|
|
3811
|
+
* pending and resolve once the full capture has run. */
|
|
3812
|
+
TEST(XsdCrossNs, AttrGroupRefRowResolvedAfterImportChase) {
|
|
3813
|
+
const char* rel =
|
|
3814
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3815
|
+
" targetNamespace=\"urn:r\" elementFormDefault=\"qualified\">"
|
|
3816
|
+
"<xs:attribute name=\"embed\" type=\"xs:string\"/>"
|
|
3817
|
+
"</xs:schema>";
|
|
3818
|
+
const char* main =
|
|
3819
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3820
|
+
" xmlns:r=\"urn:r\" xmlns=\"urn:a\" targetNamespace=\"urn:a\""
|
|
3821
|
+
" elementFormDefault=\"qualified\">"
|
|
3822
|
+
"<xs:import namespace=\"urn:r\" schemaLocation=\"ag569_rel.xsd\"/>"
|
|
3823
|
+
"<xs:attributeGroup name=\"AG_Blob\">"
|
|
3824
|
+
"<xs:attribute ref=\"r:embed\"/>"
|
|
3825
|
+
"</xs:attributeGroup>"
|
|
3826
|
+
"<xs:complexType name=\"CT_Blip\">"
|
|
3827
|
+
"<xs:sequence><xs:element name=\"e\" type=\"xs:string\""
|
|
3828
|
+
" minOccurs=\"0\"/></xs:sequence>"
|
|
3829
|
+
"<xs:attributeGroup ref=\"AG_Blob\"/>"
|
|
3830
|
+
"</xs:complexType>"
|
|
3831
|
+
"<xs:element name=\"blip\" type=\"CT_Blip\"/>"
|
|
3832
|
+
"</xs:schema>";
|
|
3833
|
+
|
|
3834
|
+
const char* dir = std::getenv("TMPDIR");
|
|
3835
|
+
std::string base = dir ? dir : "/tmp";
|
|
3836
|
+
std::string rel_path = base + "/ag569_rel.xsd";
|
|
3837
|
+
std::string main_path = base + "/ag569_main.xsd";
|
|
3838
|
+
{
|
|
3839
|
+
std::ofstream f(rel_path);
|
|
3840
|
+
f << rel;
|
|
3841
|
+
}
|
|
3842
|
+
{
|
|
3843
|
+
std::ofstream f(main_path);
|
|
3844
|
+
f << main;
|
|
3845
|
+
}
|
|
3846
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3847
|
+
LeptrisXsdSchema s =
|
|
3848
|
+
leptris_xsd_compile_file(main_path.c_str(), &st);
|
|
3849
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3850
|
+
const char* err = leptris_xsd_error(s);
|
|
3851
|
+
ASSERT_EQ(st, LEPTRIS_OK)
|
|
3852
|
+
<< "compile failed: " << (err ? err : "(null)");
|
|
3853
|
+
|
|
3854
|
+
EXPECT_EQ(validate_compiled(s,
|
|
3855
|
+
"<a:blip xmlns:a=\"urn:a\" xmlns:r=\"urn:r\""
|
|
3856
|
+
" r:embed=\"rId2\"><e>x</e></a:blip>"),
|
|
3857
|
+
1)
|
|
3858
|
+
<< "pre-pass ref row must resolve after the import chase: "
|
|
3859
|
+
<< leptris_xsd_error(s);
|
|
3860
|
+
std::remove(rel_path.c_str());
|
|
3861
|
+
std::remove(main_path.c_str());
|
|
3862
|
+
leptris_xsd_free(s);
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
/* leptris-ruby#569: compiling the REAL wml.xsd (ISO transitional,
|
|
3866
|
+
* 790 element decls, import chain to the drawing units) must yield
|
|
3867
|
+
* a cleanly compiled schema — a missing import file poisons the
|
|
3868
|
+
* graph (the '{mce}Ignorable' class), and the merged capture must
|
|
3869
|
+
* carry every unit. The schema set is bundled at $BLIP_CHAIN_DIR
|
|
3870
|
+
* in dev; CI skips when the fixture is absent so the suite stays
|
|
3871
|
+
* hermetic. */
|
|
3872
|
+
TEST(XsdCrossNs, RealWmlChainCompilesDeclarations) {
|
|
3873
|
+
const char* dir = std::getenv("BLIP_CHAIN_DIR");
|
|
3874
|
+
if (!dir || *dir == '\0') {
|
|
3875
|
+
GTEST_SKIP() << "BLIP_CHAIN_DIR not set";
|
|
3876
|
+
}
|
|
3877
|
+
std::string wml = std::string(dir) + "/wml.xsd";
|
|
3878
|
+
std::ifstream f(wml);
|
|
3879
|
+
ASSERT_TRUE(f.good()) << wml;
|
|
3880
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3881
|
+
LeptrisXsdSchema s = leptris_xsd_compile_file(wml.c_str(), &st);
|
|
3882
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3883
|
+
const char* err = leptris_xsd_error(s);
|
|
3884
|
+
EXPECT_EQ(st, LEPTRIS_OK)
|
|
3885
|
+
<< "compile status " << (int)st
|
|
3886
|
+
<< " decls=" << leptris_xsd_declaration_count(s)
|
|
3887
|
+
<< " err=" << (err ? err : "(clean)");
|
|
3888
|
+
leptris_xsd_free(s);
|
|
3889
|
+
}
|
|
3890
|
+
|
|
3891
|
+
/* leptris#1911: vc:minVersion="1.1" marks the schema as XSD 1.1
|
|
3892
|
+
* (the W3C suite and moxml both use the versioning namespace; the
|
|
3893
|
+
* plain version attribute is the other legal spelling). The
|
|
3894
|
+
* alternative's test selects the type — validation must run the
|
|
3895
|
+
* SELECTED type's content model, in both directions. */
|
|
3896
|
+
TEST(Xsd11Gate, CtaSelectsAlternativeType) {
|
|
3897
|
+
const char xsd[] =
|
|
3898
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3899
|
+
" vc:minVersion=\"1.1\""
|
|
3900
|
+
" xmlns:vc=\"http://www.w3.org/2001/XMLSchema-versioning\">"
|
|
3901
|
+
"<xs:element name=\"shape\" type=\"Shape\">"
|
|
3902
|
+
"<xs:alternative test=\"@kind='circle'\" type=\"Circle\"/>"
|
|
3903
|
+
"</xs:element>"
|
|
3904
|
+
"<xs:complexType name=\"Shape\" abstract=\"true\">"
|
|
3905
|
+
"<xs:attribute name=\"kind\" type=\"xs:string\"/>"
|
|
3906
|
+
"</xs:complexType>"
|
|
3907
|
+
"<xs:complexType name=\"Circle\">"
|
|
3908
|
+
"<xs:complexContent><xs:extension base=\"Shape\">"
|
|
3909
|
+
"<xs:sequence><xs:element name=\"r\" type=\"xs:integer\"/>"
|
|
3910
|
+
"</xs:sequence></xs:extension></xs:complexContent>"
|
|
3911
|
+
"</xs:complexType></xs:schema>";
|
|
3912
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3913
|
+
LeptrisXsdSchema s = leptris_xsd_compile(xsd, strlen(xsd), &st);
|
|
3914
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3915
|
+
ASSERT_EQ(st, LEPTRIS_OK) << leptris_xsd_error(s);
|
|
3916
|
+
EXPECT_STREQ(leptris_xsd_version(s), "1.1")
|
|
3917
|
+
<< "vc:minVersion must gate the 1.1 feature set";
|
|
3918
|
+
EXPECT_EQ(validate_compiled(s,
|
|
3919
|
+
"<shape kind=\"circle\"><r>4</r></shape>"),
|
|
3920
|
+
1)
|
|
3921
|
+
<< "the selected Circle type admits <r>: "
|
|
3922
|
+
<< leptris_xsd_error(s);
|
|
3923
|
+
EXPECT_EQ(validate_compiled(s, "<shape kind=\"circle\"/>"), 0)
|
|
3924
|
+
<< "the selected Circle type REQUIRES <r>";
|
|
3925
|
+
leptris_xsd_free(s);
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
/* leptris#1910: an xs:assert in a vc:minVersion="1.1" schema must
|
|
3929
|
+
* be evaluated — a violating instance produces an assertion row. */
|
|
3930
|
+
TEST(Xsd11Gate, AssertIsEvaluated) {
|
|
3931
|
+
const char xsd[] =
|
|
3932
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3933
|
+
" vc:minVersion=\"1.1\""
|
|
3934
|
+
" xmlns:vc=\"http://www.w3.org/2001/XMLSchema-versioning\">"
|
|
3935
|
+
"<xs:element name=\"size\">"
|
|
3936
|
+
"<xs:complexType><xs:sequence>"
|
|
3937
|
+
"<xs:element name=\"w\" type=\"xs:integer\"/>"
|
|
3938
|
+
"<xs:element name=\"h\" type=\"xs:integer\"/>"
|
|
3939
|
+
"</xs:sequence><xs:assert test=\"w le h\"/></xs:complexType>"
|
|
3940
|
+
"</xs:element></xs:schema>";
|
|
3941
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3942
|
+
LeptrisXsdSchema s = leptris_xsd_compile(xsd, strlen(xsd), &st);
|
|
3943
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3944
|
+
ASSERT_EQ(st, LEPTRIS_OK) << leptris_xsd_error(s);
|
|
3945
|
+
EXPECT_EQ(validate_compiled(s, "<size><w>3</w><h>5</h></size>"), 1)
|
|
3946
|
+
<< "satisfying assert must stay valid: "
|
|
3947
|
+
<< leptris_xsd_error(s);
|
|
3948
|
+
EXPECT_EQ(validate_compiled(s, "<size><w>9</w><h>5</h></size>"), 0)
|
|
3949
|
+
<< "violating assert must produce a finding";
|
|
3950
|
+
leptris_xsd_free(s);
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
/* leptris#1913: xs:override (XSD 1.1 Structures §I.4) — the base
|
|
3954
|
+
* document's declarations load (xs:override is an include-family
|
|
3955
|
+
* chase), then the override body's same-named declarations REPLACE
|
|
3956
|
+
* them. Previously override was absent from the chase condition:
|
|
3957
|
+
* the base never loaded and the body's nested declarations were
|
|
3958
|
+
* never captured — an empty symbol space (decls=0). */
|
|
3959
|
+
TEST(Xsd11Gate, OverrideLoadsBaseAndReplacesComponents) {
|
|
3960
|
+
const char* base =
|
|
3961
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3962
|
+
" targetNamespace=\"urn:b\" xmlns=\"urn:b\""
|
|
3963
|
+
" elementFormDefault=\"qualified\">"
|
|
3964
|
+
"<xs:element name=\"doc\" type=\"Doc\"/>"
|
|
3965
|
+
"<xs:complexType name=\"Doc\">"
|
|
3966
|
+
"<xs:sequence><xs:element name=\"a\" type=\"xs:string\"/>"
|
|
3967
|
+
"</xs:sequence></xs:complexType></xs:schema>";
|
|
3968
|
+
const char* ovr =
|
|
3969
|
+
"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
|
|
3970
|
+
" targetNamespace=\"urn:b\" xmlns=\"urn:b\""
|
|
3971
|
+
" elementFormDefault=\"qualified\" vc:minVersion=\"1.1\""
|
|
3972
|
+
" xmlns:vc=\"http://www.w3.org/2001/XMLSchema-versioning\">"
|
|
3973
|
+
"<xs:override schemaLocation=\"ovr1913_base.xsd\">"
|
|
3974
|
+
"<xs:complexType name=\"Doc\">"
|
|
3975
|
+
"<xs:sequence><xs:element name=\"b\" type=\"xs:integer\"/>"
|
|
3976
|
+
"</xs:sequence></xs:complexType>"
|
|
3977
|
+
"</xs:override></xs:schema>";
|
|
3978
|
+
const char* dir = std::getenv("TMPDIR");
|
|
3979
|
+
std::string tmp = dir ? dir : "/tmp";
|
|
3980
|
+
std::string base_path = tmp + "/ovr1913_base.xsd";
|
|
3981
|
+
std::string ovr_path = tmp + "/ovr1913_ovr.xsd";
|
|
3982
|
+
{
|
|
3983
|
+
std::ofstream f(base_path);
|
|
3984
|
+
f << base;
|
|
3985
|
+
}
|
|
3986
|
+
{
|
|
3987
|
+
std::ofstream f(ovr_path);
|
|
3988
|
+
f << ovr;
|
|
3989
|
+
}
|
|
3990
|
+
LeptrisStatus st = LEPTRIS_OK;
|
|
3991
|
+
LeptrisXsdSchema s = leptris_xsd_compile_file(ovr_path.c_str(), &st);
|
|
3992
|
+
ASSERT_NE(s, (LeptrisXsdSchema)0);
|
|
3993
|
+
ASSERT_EQ(st, LEPTRIS_OK) << leptris_xsd_error(s);
|
|
3994
|
+
EXPECT_GT(leptris_xsd_declaration_count(s), 0u)
|
|
3995
|
+
<< "override must not produce an empty symbol space";
|
|
3996
|
+
EXPECT_EQ(validate_compiled(s, "<doc xmlns=\"urn:b\"><b>1</b></doc>"),
|
|
3997
|
+
1)
|
|
3998
|
+
<< "the overridden Doc admits <b>: " << leptris_xsd_error(s);
|
|
3999
|
+
EXPECT_EQ(validate_compiled(s, "<doc xmlns=\"urn:b\"><a>x</a></doc>"),
|
|
4000
|
+
0)
|
|
4001
|
+
<< "the overridden Doc no longer admits <a>";
|
|
4002
|
+
std::remove(base_path.c_str());
|
|
4003
|
+
std::remove(ovr_path.c_str());
|
|
4004
|
+
leptris_xsd_free(s);
|
|
4005
|
+
}
|
|
@@ -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.
|
|
4
|
+
"version": "1.9.394",
|
|
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,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: leptris
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.394.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|
|
@@ -744,6 +744,7 @@ files:
|
|
|
744
744
|
- vendor-src/libleptris/src/man/libleptris.5.adoc
|
|
745
745
|
- vendor-src/libleptris/test/CMakeLists.txt
|
|
746
746
|
- vendor-src/libleptris/test/README.md
|
|
747
|
+
- vendor-src/libleptris/test/abi/test_capabilities.cpp
|
|
747
748
|
- vendor-src/libleptris/test/abi/test_descriptor.cpp
|
|
748
749
|
- vendor-src/libleptris/test/abi/test_doctype_api.cpp
|
|
749
750
|
- vendor-src/libleptris/test/abi/test_dom_deep_copy.cpp
|
|
@@ -782,6 +783,7 @@ files:
|
|
|
782
783
|
- vendor-src/libleptris/test/dom/test_document_children.cpp
|
|
783
784
|
- vendor-src/libleptris/test/dom/test_dom.cpp
|
|
784
785
|
- vendor-src/libleptris/test/dom/test_element_children.cpp
|
|
786
|
+
- vendor-src/libleptris/test/dom/test_entity_refs.cpp
|
|
785
787
|
- vendor-src/libleptris/test/dom/test_map_lifecycle.cpp
|
|
786
788
|
- vendor-src/libleptris/test/dom/test_namespace_cache.cpp
|
|
787
789
|
- vendor-src/libleptris/test/dom/test_node_surface_parity.cpp
|