leptris 1.9.331.0 → 1.9.334.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/Rakefile +19 -1
- data/lib/leptris/vendor/aarch64-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/aarch64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/arm-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/arm-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/arm64-darwin/libleptris.dylib +0 -0
- data/lib/leptris/vendor/arm64-darwin/libutf8proc.3.dylib +0 -0
- data/lib/leptris/vendor/ppc64le-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/s390x-linux-musl/libleptris.so +0 -0
- data/lib/leptris/vendor/x86_64-darwin/libleptris.dylib +0 -0
- data/lib/leptris/vendor/x86_64-darwin/libutf8proc.3.dylib +0 -0
- data/lib/leptris/vendor/x86_64-linux/libleptris.so +0 -0
- data/lib/leptris/vendor/x86_64-linux-musl/libleptris.so +0 -0
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/cdata.rb +4 -0
- data/lib/leptris/xml/comment.rb +4 -0
- data/lib/leptris/xml/descriptor.rb +55 -0
- data/lib/leptris/xml/entity_reference.rb +4 -0
- data/lib/leptris/xml/ffi.rb +25 -0
- data/lib/leptris/xml/node.rb +1 -0
- data/lib/leptris/xml/processing_instruction.rb +4 -0
- data/lib/leptris/xml/text.rb +4 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +65 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/include/leptris/descriptor.h +30 -0
- data/vendor-src/libleptris/src/include/leptris.h +5 -0
- data/vendor-src/libleptris/src/leptris/descriptor/plan.c +144 -0
- data/vendor-src/libleptris/src/leptris/dom/element_modify.c +7 -0
- data/vendor-src/libleptris/src/leptris/xsd/compile.c +241 -4
- data/vendor-src/libleptris/src/leptris/xsd/content_model.c +50 -0
- data/vendor-src/libleptris/src/leptris/xsd/validate.c +190 -8
- data/vendor-src/libleptris/src/leptris/xsd/xsd_internal.h +34 -0
- data/vendor-src/libleptris/test/abi/test_descriptor.cpp +95 -0
- data/vendor-src/libleptris/test/xsd/test_xsd_compile.cpp +380 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +2 -2
|
@@ -36,11 +36,14 @@ struct leptris_xsd_schema {
|
|
|
36
36
|
XsdElementDecl* elements;
|
|
37
37
|
XsdCm* complex_types; /* name-carrying model roots */
|
|
38
38
|
XsdGroupDef* groups; /* top-level xs:group definitions */
|
|
39
|
+
XsdCm* default_open; /* xs:defaultOpenContent wildcard */
|
|
40
|
+
int default_oc_empty; /* appliesToEmpty="true" */
|
|
39
41
|
XsdAttrGroupDef* attr_groups;
|
|
40
42
|
XsdAttrDecl* top_attrs; /* top-level xs:attribute declarations */
|
|
41
43
|
XsdTypeAttrs* type_attrs;
|
|
42
44
|
XsdElementIcs* element_ics;
|
|
43
45
|
char* target_ns;
|
|
46
|
+
int version_11; /* xs:schema @version = "1.1" */
|
|
44
47
|
char* base_dir; /* schemaLocation resolution (file compile) */
|
|
45
48
|
int include_depth; /* include/import recursion guard */
|
|
46
49
|
void* validator; /* slice-4 parked error list */
|
|
@@ -76,10 +79,18 @@ static char* xsd_read_file(const char* path, size_t* out_len);
|
|
|
76
79
|
static XsdAttrDecl* xsd_copy_attr_rows(const XsdAttrDecl* src);
|
|
77
80
|
static void xsd_register_complex(struct leptris_xsd_schema* s,
|
|
78
81
|
XsdCm* root, XsdAttrDecl* attrs,
|
|
79
|
-
const char* name
|
|
82
|
+
const char* name,
|
|
83
|
+
char* any_attr_ns);
|
|
80
84
|
static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
|
|
81
85
|
LeptrisElement ct,
|
|
82
86
|
const char* name);
|
|
87
|
+
static XsdAssert* xsd_capture_assert(struct leptris_xsd_schema* s,
|
|
88
|
+
LeptrisElement e);
|
|
89
|
+
static XsdCm* xsd_capture_any(LeptrisElement any_child);
|
|
90
|
+
static char* xsd_capture_any_attr_ns(LeptrisElement container);
|
|
91
|
+
static void xsd_capture_alternatives(struct leptris_xsd_schema* s,
|
|
92
|
+
LeptrisElement decl_elem,
|
|
93
|
+
XsdElementDecl* d);
|
|
83
94
|
static XsdSimple* xsd_capture_simple(LeptrisElement st);
|
|
84
95
|
|
|
85
96
|
|
|
@@ -95,6 +106,15 @@ static XsdCm* xsd_cm_new(XsdCmKind kind) {
|
|
|
95
106
|
static void xsd_cm_free(XsdCm* cm) {
|
|
96
107
|
while (cm) {
|
|
97
108
|
XsdCm* next = cm->next;
|
|
109
|
+
XsdAssert* a = cm->asserts;
|
|
110
|
+
while (a) {
|
|
111
|
+
XsdAssert* an = a->next;
|
|
112
|
+
if (a->compiled) leptris_xquery_free(a->compiled);
|
|
113
|
+
free(a->test);
|
|
114
|
+
free(a);
|
|
115
|
+
a = an;
|
|
116
|
+
}
|
|
117
|
+
if (cm->oc_owned && cm->open_any) xsd_cm_free(cm->open_any);
|
|
98
118
|
xsd_cm_free(cm->first_child);
|
|
99
119
|
free(cm->name);
|
|
100
120
|
free(cm->type);
|
|
@@ -370,6 +390,9 @@ static XsdSimple* xsd_capture_simple(LeptrisElement st) {
|
|
|
370
390
|
simple->fraction_digits = val ? strtol(val, NULL, 10) : -1;
|
|
371
391
|
else if (strcmp(fl, "whiteSpace") == 0)
|
|
372
392
|
simple->whitespace = xsd_strdup(val);
|
|
393
|
+
else if (strcmp(fl, "assertion") == 0)
|
|
394
|
+
simple->assertion = xsd_strdup(
|
|
395
|
+
leptris_element_attribute(fe, "test"));
|
|
373
396
|
}
|
|
374
397
|
}
|
|
375
398
|
}
|
|
@@ -481,6 +504,7 @@ static int xsd_is_declaration(const char* local, const char* uri) {
|
|
|
481
504
|
static const char* names[] = {
|
|
482
505
|
"element", "attribute", "simpleType", "complexType",
|
|
483
506
|
"group", "attributeGroup", "notation", "include",
|
|
507
|
+
"defaultOpenContent",
|
|
484
508
|
"import", "redefine", NULL
|
|
485
509
|
};
|
|
486
510
|
for (int i = 0; names[i]; i++)
|
|
@@ -594,6 +618,10 @@ static LeptrisXsdSchema xsd_compile_impl(const char* xsd_text,
|
|
|
594
618
|
}
|
|
595
619
|
s->target_ns = xsd_strdup(
|
|
596
620
|
leptris_element_attribute(root, "targetNamespace"));
|
|
621
|
+
{
|
|
622
|
+
const char* ver = leptris_element_attribute(root, "version");
|
|
623
|
+
s->version_11 = (ver && strcmp(ver, "1.1") == 0);
|
|
624
|
+
}
|
|
597
625
|
|
|
598
626
|
const char* local = NULL;
|
|
599
627
|
const char* prefix = NULL;
|
|
@@ -692,6 +720,7 @@ static void xsd_capture_root(struct leptris_xsd_schema* s,
|
|
|
692
720
|
if (d) {
|
|
693
721
|
d->name = xsd_strdup(nm);
|
|
694
722
|
d->type = xsd_strdup(ty);
|
|
723
|
+
xsd_capture_alternatives(s, (LeptrisElement)n, d);
|
|
695
724
|
d->fixed = xsd_strdup(
|
|
696
725
|
leptris_element_attribute((LeptrisElement)n,
|
|
697
726
|
"fixed"));
|
|
@@ -730,6 +759,29 @@ static void xsd_capture_root(struct leptris_xsd_schema* s,
|
|
|
730
759
|
leptris_element_attribute((LeptrisElement)n, "name");
|
|
731
760
|
if (nm)
|
|
732
761
|
xsd_capture_complex_model(s, (LeptrisElement)n, nm);
|
|
762
|
+
} else if (strcmp(local, "defaultOpenContent") == 0 && uri &&
|
|
763
|
+
!strcmp(uri, XSD_NS)) {
|
|
764
|
+
if (s->version_11) {
|
|
765
|
+
const char* ape = leptris_element_attribute(
|
|
766
|
+
(LeptrisElement)n, "appliesToEmpty");
|
|
767
|
+
for (LeptrisNodeRef q = leptris_node_first_child(
|
|
768
|
+
leptris_element_as_node((LeptrisElement)n));
|
|
769
|
+
q && !s->default_open;
|
|
770
|
+
q = leptris_node_next_sibling(q)) {
|
|
771
|
+
if (leptris_node_get_type(q) !=
|
|
772
|
+
LEPTRIS_NODE_TYPE_ELEMENT)
|
|
773
|
+
continue;
|
|
774
|
+
LeptrisElement qe = (LeptrisElement)q;
|
|
775
|
+
const char* ql = NULL;
|
|
776
|
+
leptris_element_expanded_name(qe, &ql, NULL, NULL);
|
|
777
|
+
if (ql && strcmp(ql, "any") == 0)
|
|
778
|
+
s->default_open = xsd_capture_any(qe);
|
|
779
|
+
}
|
|
780
|
+
if (s->default_open)
|
|
781
|
+
s->default_oc_empty =
|
|
782
|
+
(ape && strcmp(ape, "true") == 0);
|
|
783
|
+
}
|
|
784
|
+
continue;
|
|
733
785
|
} else if (strcmp(local, "attribute") == 0 && uri && !strcmp(uri, XSD_NS)) {
|
|
734
786
|
const char* nm =
|
|
735
787
|
leptris_element_attribute((LeptrisElement)n, "name");
|
|
@@ -803,6 +855,8 @@ static void xsd_free_simple_one(XsdSimple* t) {
|
|
|
803
855
|
free(t->max_inclusive);
|
|
804
856
|
free(t->max_exclusive);
|
|
805
857
|
free(t->whitespace);
|
|
858
|
+
if (t->assertion_q) leptris_xquery_free(t->assertion_q);
|
|
859
|
+
free(t->assertion);
|
|
806
860
|
free(t->item_type);
|
|
807
861
|
xsd_free_simple_one(t->item_def);
|
|
808
862
|
for (size_t i = 0; i < t->member_count; i++) free(t->members[i]);
|
|
@@ -848,12 +902,22 @@ LEPTRIS_API void leptris_xsd_free(LeptrisXsdSchema schema) {
|
|
|
848
902
|
a = an;
|
|
849
903
|
}
|
|
850
904
|
free(ta->type_name);
|
|
905
|
+
free(ta->any_attr_ns);
|
|
851
906
|
free(ta);
|
|
852
907
|
ta = tn;
|
|
853
908
|
}
|
|
854
909
|
XsdElementDecl* d = s->elements;
|
|
855
910
|
while (d) {
|
|
856
911
|
XsdElementDecl* dn = d->next;
|
|
912
|
+
XsdAlternative* a = d->alternatives;
|
|
913
|
+
while (a) {
|
|
914
|
+
XsdAlternative* an = a->next;
|
|
915
|
+
if (a->compiled) leptris_xquery_free(a->compiled);
|
|
916
|
+
free(a->test);
|
|
917
|
+
free(a->type);
|
|
918
|
+
free(a);
|
|
919
|
+
a = an;
|
|
920
|
+
}
|
|
857
921
|
free(d->name);
|
|
858
922
|
free(d->type);
|
|
859
923
|
free(d->fixed);
|
|
@@ -894,6 +958,7 @@ LEPTRIS_API void leptris_xsd_free(LeptrisXsdSchema schema) {
|
|
|
894
958
|
free(g);
|
|
895
959
|
g = gn;
|
|
896
960
|
}
|
|
961
|
+
if (s->default_open) xsd_cm_free(s->default_open);
|
|
897
962
|
free(s->target_ns);
|
|
898
963
|
free(s->base_dir);
|
|
899
964
|
if (s->validator)
|
|
@@ -936,19 +1001,107 @@ static XsdCm* xsd_cm_copy_list(const XsdCm* head) {
|
|
|
936
1001
|
|
|
937
1002
|
static void xsd_register_complex(struct leptris_xsd_schema* s,
|
|
938
1003
|
XsdCm* root, XsdAttrDecl* attrs,
|
|
939
|
-
const char* name
|
|
1004
|
+
const char* name,
|
|
1005
|
+
char* any_attr_ns) {
|
|
940
1006
|
if (!root) return;
|
|
941
1007
|
root->name = xsd_strdup(name);
|
|
942
1008
|
root->next = s->complex_types;
|
|
943
1009
|
s->complex_types = root;
|
|
944
|
-
if (attrs) {
|
|
1010
|
+
if (attrs || any_attr_ns) {
|
|
945
1011
|
XsdTypeAttrs* ta = (XsdTypeAttrs*)calloc(1, sizeof(*ta));
|
|
946
1012
|
if (ta) {
|
|
947
1013
|
ta->type_name = xsd_strdup(name);
|
|
948
1014
|
ta->attrs = attrs;
|
|
1015
|
+
ta->any_attr_ns = any_attr_ns;
|
|
949
1016
|
ta->next = s->type_attrs;
|
|
950
1017
|
s->type_attrs = ta;
|
|
951
1018
|
}
|
|
1019
|
+
} else if (any_attr_ns) {
|
|
1020
|
+
free(any_attr_ns);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/* XSD 1.1: xs:alternative children of an element declaration. */
|
|
1025
|
+
static void xsd_capture_alternatives(struct leptris_xsd_schema* s,
|
|
1026
|
+
LeptrisElement decl_elem,
|
|
1027
|
+
XsdElementDecl* d) {
|
|
1028
|
+
if (!s->version_11) return;
|
|
1029
|
+
XsdAlternative* tail = NULL;
|
|
1030
|
+
for (LeptrisNodeRef n =
|
|
1031
|
+
leptris_node_first_child(leptris_element_as_node(decl_elem));
|
|
1032
|
+
n; n = leptris_node_next_sibling(n)) {
|
|
1033
|
+
if (leptris_node_get_type(n) != LEPTRIS_NODE_TYPE_ELEMENT)
|
|
1034
|
+
continue;
|
|
1035
|
+
LeptrisElement e = (LeptrisElement)n;
|
|
1036
|
+
const char* local = NULL;
|
|
1037
|
+
leptris_element_expanded_name(e, &local, NULL, NULL);
|
|
1038
|
+
if (!local || strcmp(local, "alternative") != 0) continue;
|
|
1039
|
+
const char* test = leptris_element_attribute(e, "test");
|
|
1040
|
+
const char* type = leptris_element_attribute(e, "type");
|
|
1041
|
+
if (!test || !type) continue;
|
|
1042
|
+
XsdAlternative* a = (XsdAlternative*)calloc(1, sizeof(*a));
|
|
1043
|
+
if (!a) continue;
|
|
1044
|
+
a->test = xsd_strdup(test);
|
|
1045
|
+
a->type = xsd_strdup(type);
|
|
1046
|
+
a->compiled = leptris_xquery_parse(test, strlen(test));
|
|
1047
|
+
if (tail)
|
|
1048
|
+
tail->next = a;
|
|
1049
|
+
else
|
|
1050
|
+
d->alternatives = a;
|
|
1051
|
+
tail = a;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
static XsdCm* xsd_capture_any(LeptrisElement any_child) {
|
|
1056
|
+
XsdCm* w = xsd_cm_new(XSD_CM_ANY);
|
|
1057
|
+
if (!w) return NULL;
|
|
1058
|
+
w->any_ns = xsd_strdup(
|
|
1059
|
+
leptris_element_attribute(any_child, "namespace"));
|
|
1060
|
+
const char* pc = leptris_element_attribute(any_child,
|
|
1061
|
+
"processContents");
|
|
1062
|
+
w->process_skip =
|
|
1063
|
+
(pc && (strcmp(pc, "skip") == 0 || strcmp(pc, "lax") == 0))
|
|
1064
|
+
? 1
|
|
1065
|
+
: 0;
|
|
1066
|
+
w->min = 0;
|
|
1067
|
+
w->max = -1;
|
|
1068
|
+
return w;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
static XsdAssert* xsd_capture_assert(struct leptris_xsd_schema* s,
|
|
1072
|
+
LeptrisElement e) {
|
|
1073
|
+
const char* test = leptris_element_attribute(e, "test");
|
|
1074
|
+
if (!test || !*test) return NULL;
|
|
1075
|
+
XsdAssert* a = (XsdAssert*)calloc(1, sizeof(*a));
|
|
1076
|
+
if (!a) return NULL;
|
|
1077
|
+
a->test = xsd_strdup(test);
|
|
1078
|
+
if (s->version_11) {
|
|
1079
|
+
a->compiled = leptris_xquery_parse(test, strlen(test));
|
|
1080
|
+
/* NULL = syntax error: evaluation reports the assertion
|
|
1081
|
+
* as failed (XSD 1.1: an error is a failure) */
|
|
1082
|
+
}
|
|
1083
|
+
return a;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/* Append every xs:assert child under `container` to the type. */
|
|
1087
|
+
static void xsd_capture_assert_children(
|
|
1088
|
+
struct leptris_xsd_schema* s, LeptrisElement container,
|
|
1089
|
+
XsdCm* root) {
|
|
1090
|
+
XsdAssert* tail = root->asserts;
|
|
1091
|
+
while (tail && tail->next) tail = tail->next;
|
|
1092
|
+
for (LeptrisNodeRef n =
|
|
1093
|
+
leptris_node_first_child(leptris_element_as_node(container));
|
|
1094
|
+
n; n = leptris_node_next_sibling(n)) {
|
|
1095
|
+
if (leptris_node_get_type(n) != LEPTRIS_NODE_TYPE_ELEMENT)
|
|
1096
|
+
continue;
|
|
1097
|
+
LeptrisElement e = (LeptrisElement)n;
|
|
1098
|
+
const char* local = NULL;
|
|
1099
|
+
leptris_element_expanded_name(e, &local, NULL, NULL);
|
|
1100
|
+
if (!local || strcmp(local, "assert") != 0) continue;
|
|
1101
|
+
XsdAssert* a = xsd_capture_assert(s, e);
|
|
1102
|
+
if (!a) continue;
|
|
1103
|
+
if (!root->asserts) root->asserts = a;
|
|
1104
|
+
tail = a;
|
|
952
1105
|
}
|
|
953
1106
|
}
|
|
954
1107
|
|
|
@@ -962,6 +1115,7 @@ static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
|
|
|
962
1115
|
XsdCm* root = xsd_cm_new(XSD_CM_SEQ); /* wrapper keeps the name */
|
|
963
1116
|
if (!root) return NULL;
|
|
964
1117
|
XsdAttrDecl* attrs = NULL;
|
|
1118
|
+
char* any_attr_ns = NULL;
|
|
965
1119
|
|
|
966
1120
|
for (LeptrisNodeRef n =
|
|
967
1121
|
leptris_node_first_child(leptris_element_as_node(ct));
|
|
@@ -1026,6 +1180,11 @@ static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
|
|
|
1026
1180
|
root->first_child = xsd_cm_parse(s, dq, NULL);
|
|
1027
1181
|
attrs = xsd_capture_attr_rows(s, dq, 0);
|
|
1028
1182
|
}
|
|
1183
|
+
/* XSD 1.1: asserts nested under the derivation */
|
|
1184
|
+
if (s->version_11)
|
|
1185
|
+
xsd_capture_assert_children(s, dq, root);
|
|
1186
|
+
if (!any_attr_ns)
|
|
1187
|
+
any_attr_ns = xsd_capture_any_attr_ns(dq);
|
|
1029
1188
|
}
|
|
1030
1189
|
} else if (strcmp(local, "simpleContent") == 0) {
|
|
1031
1190
|
for (LeptrisNodeRef q = leptris_node_first_child(
|
|
@@ -1092,7 +1251,52 @@ static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
|
|
|
1092
1251
|
* re-capturing would orphan those rows. */
|
|
1093
1252
|
root->first_child = xsd_cm_parse(s, ct, NULL);
|
|
1094
1253
|
if (!attrs) attrs = xsd_capture_attr_rows(s, ct, 0);
|
|
1254
|
+
if (!any_attr_ns) any_attr_ns = xsd_capture_any_attr_ns(ct);
|
|
1095
1255
|
}
|
|
1256
|
+
/* XSD 1.1: openContent on the type, else the schema default */
|
|
1257
|
+
if (s->version_11) {
|
|
1258
|
+
for (LeptrisNodeRef n =
|
|
1259
|
+
leptris_node_first_child(leptris_element_as_node(ct));
|
|
1260
|
+
n; n = leptris_node_next_sibling(n)) {
|
|
1261
|
+
if (leptris_node_get_type(n) != LEPTRIS_NODE_TYPE_ELEMENT)
|
|
1262
|
+
continue;
|
|
1263
|
+
LeptrisElement e = (LeptrisElement)n;
|
|
1264
|
+
const char* ocl = NULL;
|
|
1265
|
+
leptris_element_expanded_name(e, &ocl, NULL, NULL);
|
|
1266
|
+
if (!ocl || strcmp(ocl, "openContent") != 0) continue;
|
|
1267
|
+
const char* mode = leptris_element_attribute(e, "mode");
|
|
1268
|
+
for (LeptrisNodeRef q = leptris_node_first_child(
|
|
1269
|
+
leptris_element_as_node(e));
|
|
1270
|
+
q && !root->open_any;
|
|
1271
|
+
q = leptris_node_next_sibling(q)) {
|
|
1272
|
+
if (leptris_node_get_type(q) !=
|
|
1273
|
+
LEPTRIS_NODE_TYPE_ELEMENT)
|
|
1274
|
+
continue;
|
|
1275
|
+
LeptrisElement qe = (LeptrisElement)q;
|
|
1276
|
+
const char* ql = NULL;
|
|
1277
|
+
leptris_element_expanded_name(qe, &ql, NULL, NULL);
|
|
1278
|
+
if (ql && strcmp(ql, "any") == 0) {
|
|
1279
|
+
root->open_any = xsd_capture_any(qe);
|
|
1280
|
+
if (root->open_any) root->oc_owned = 1;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (mode && strcmp(mode, "suffix") == 0)
|
|
1284
|
+
root->oc_mode = 1;
|
|
1285
|
+
else if (mode && strcmp(mode, "interleave") == 0)
|
|
1286
|
+
root->oc_mode = 2;
|
|
1287
|
+
else
|
|
1288
|
+
root->oc_mode = 0;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
if (!root->oc_mode && s->default_open && root->first_child)
|
|
1292
|
+
root->oc_mode = 2;
|
|
1293
|
+
if (!root->oc_mode && s->default_open && !root->first_child &&
|
|
1294
|
+
s->default_oc_empty)
|
|
1295
|
+
root->oc_mode = 2;
|
|
1296
|
+
if (root->oc_mode == 2 && !root->open_any && s->default_open)
|
|
1297
|
+
root->open_any = s->default_open;
|
|
1298
|
+
/* XSD 1.1: direct xs:assert children of the complexType */
|
|
1299
|
+
if (s->version_11) xsd_capture_assert_children(s, ct, root);
|
|
1096
1300
|
/* the NFA and model walkers consume ONE root particle —
|
|
1097
1301
|
* a multi-particle model (derivation splices) normalizes
|
|
1098
1302
|
* under a sequence */
|
|
@@ -1103,7 +1307,19 @@ static XsdCm* xsd_capture_complex_model(struct leptris_xsd_schema* s,
|
|
|
1103
1307
|
root->first_child = seq;
|
|
1104
1308
|
}
|
|
1105
1309
|
}
|
|
1106
|
-
|
|
1310
|
+
/* open-content semantics ride the model root (the NFA builds
|
|
1311
|
+
* from ct->first_child, never the name wrapper) */
|
|
1312
|
+
if (root->first_child) {
|
|
1313
|
+
root->first_child->open_any = root->open_any;
|
|
1314
|
+
root->first_child->oc_mode = root->oc_mode;
|
|
1315
|
+
root->first_child->oc_owned = root->oc_owned;
|
|
1316
|
+
root->open_any = NULL;
|
|
1317
|
+
root->oc_owned = 0;
|
|
1318
|
+
} else if (root->open_any && root->oc_owned) {
|
|
1319
|
+
xsd_cm_free(root->open_any);
|
|
1320
|
+
root->open_any = NULL;
|
|
1321
|
+
}
|
|
1322
|
+
xsd_register_complex(s, root, attrs, name, any_attr_ns);
|
|
1107
1323
|
return root;
|
|
1108
1324
|
}
|
|
1109
1325
|
|
|
@@ -1124,6 +1340,10 @@ int xsd_is_substitute(struct leptris_xsd_schema* s,
|
|
|
1124
1340
|
return 0;
|
|
1125
1341
|
}
|
|
1126
1342
|
|
|
1343
|
+
int xsd_schema_version_11(struct leptris_xsd_schema* s) {
|
|
1344
|
+
return s ? s->version_11 : 0;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1127
1347
|
XsdGroupDef* xsd_find_group(struct leptris_xsd_schema* s,
|
|
1128
1348
|
const char* name) {
|
|
1129
1349
|
if (!s || !name) return NULL;
|
|
@@ -1265,6 +1485,23 @@ static XsdAttrDecl* xsd_capture_attr_rows(struct leptris_xsd_schema* s,
|
|
|
1265
1485
|
return head;
|
|
1266
1486
|
}
|
|
1267
1487
|
|
|
1488
|
+
/* One container's xs:anyAttribute grammar (NULL when absent). */
|
|
1489
|
+
static char* xsd_capture_any_attr_ns(LeptrisElement container) {
|
|
1490
|
+
for (LeptrisNodeRef ac = leptris_node_first_child(
|
|
1491
|
+
leptris_element_as_node(container));
|
|
1492
|
+
ac; ac = leptris_node_next_sibling(ac)) {
|
|
1493
|
+
if (leptris_node_get_type(ac) != LEPTRIS_NODE_TYPE_ELEMENT)
|
|
1494
|
+
continue;
|
|
1495
|
+
LeptrisElement ae = (LeptrisElement)ac;
|
|
1496
|
+
const char* al = NULL;
|
|
1497
|
+
leptris_element_expanded_name(ae, &al, NULL, NULL);
|
|
1498
|
+
if (al && strcmp(al, "anyAttribute") == 0)
|
|
1499
|
+
return xsd_strdup(
|
|
1500
|
+
leptris_element_attribute(ae, "namespace"));
|
|
1501
|
+
}
|
|
1502
|
+
return NULL;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1268
1505
|
LEPTRIS_API int leptris_xsd_builtin_valid(const char* builtin,
|
|
1269
1506
|
const char* lexical) {
|
|
1270
1507
|
extern int xsd_builtin_valid(const char* type, const char* v);
|
|
@@ -56,20 +56,35 @@ static void cm_build_occurrence(CmNfa* n, XsdCm* node,
|
|
|
56
56
|
/* chain the group children: first reads `from`, last writes `to`.
|
|
57
57
|
* xs:all is evaluated in sequence order for now (its order-free
|
|
58
58
|
* semantics arrive with slice 4's all-semantics pass). */
|
|
59
|
+
/* XSD 1.1 open content: a wildcard self-loop at a junction lets
|
|
60
|
+
* any-namespace elements (per the wildcard's grammar) consume a
|
|
61
|
+
* child without advancing the model. */
|
|
62
|
+
static void oc_loop(CmNfa* n, XsdCm* node, int state) {
|
|
63
|
+
if (!node->open_any || !node->oc_mode) return;
|
|
64
|
+
nfa_trans(n, state, 0, node->open_any, state);
|
|
65
|
+
}
|
|
66
|
+
|
|
59
67
|
static void cm_build_children(CmNfa* n, XsdCm* node, int from, int to) {
|
|
60
68
|
XsdCm* c = node->first_child;
|
|
61
69
|
if (!c) {
|
|
62
70
|
nfa_trans(n, from, -1, NULL, to);
|
|
63
71
|
return;
|
|
64
72
|
}
|
|
73
|
+
int interleave =
|
|
74
|
+
(node->open_any && node->oc_mode == 2) ? 1 : 0;
|
|
65
75
|
int cursor = from;
|
|
76
|
+
if (interleave) oc_loop(n, node, cursor);
|
|
66
77
|
while (c->next) {
|
|
67
78
|
int mid = nfa_state(n);
|
|
68
79
|
cm_build_occurrence(n, c, cursor, mid);
|
|
69
80
|
cursor = mid;
|
|
81
|
+
if (interleave) oc_loop(n, node, cursor);
|
|
70
82
|
c = c->next;
|
|
71
83
|
}
|
|
72
84
|
cm_build_occurrence(n, c, cursor, to);
|
|
85
|
+
/* suffix (and interleave) wildcards may follow the sequence */
|
|
86
|
+
if (node->open_any && node->oc_mode)
|
|
87
|
+
oc_loop(n, node, to);
|
|
73
88
|
}
|
|
74
89
|
|
|
75
90
|
static void cm_build(CmNfa* n, XsdCm* node, int from, int to) {
|
|
@@ -193,10 +208,45 @@ static void ss_close(StateSet* ss, CmNfa* n) {
|
|
|
193
208
|
}
|
|
194
209
|
}
|
|
195
210
|
|
|
211
|
+
/* XSD xs:all at the model root: order-free, each particle at
|
|
212
|
+
* most maxOccurs times, minOccurs floors — a counting check over
|
|
213
|
+
* the particle list (XSD 1.0 restricts xs:all to the model root,
|
|
214
|
+
* each child a particle, maxOccurs <= 1). */
|
|
215
|
+
static int all_root_valid(XsdCm* all, const char* target_ns,
|
|
216
|
+
const char* const* names,
|
|
217
|
+
const char* const* ns_uris, size_t count) {
|
|
218
|
+
for (XsdCm* p = all->first_child; p; p = p->next) {
|
|
219
|
+
size_t hits = 0;
|
|
220
|
+
for (size_t i = 0; i < count; i++) {
|
|
221
|
+
const char* uri = ns_uris ? ns_uris[i] : NULL;
|
|
222
|
+
if (p->name && strcmp(p->name, names[i]) == 0 &&
|
|
223
|
+
(!p->ns || (uri && strcmp(uri, p->ns) == 0)))
|
|
224
|
+
hits++;
|
|
225
|
+
}
|
|
226
|
+
if ((long)hits < p->min) return 0;
|
|
227
|
+
if (p->max >= 0 && (long)hits > p->max) return 0;
|
|
228
|
+
}
|
|
229
|
+
/* every instance child must belong to a particle */
|
|
230
|
+
for (size_t i = 0; i < count; i++) {
|
|
231
|
+
int matched = 0;
|
|
232
|
+
const char* uri = ns_uris ? ns_uris[i] : NULL;
|
|
233
|
+
for (XsdCm* p = all->first_child; p && !matched; p = p->next) {
|
|
234
|
+
if (p->name && strcmp(p->name, names[i]) == 0 &&
|
|
235
|
+
(!p->ns || (uri && strcmp(uri, p->ns) == 0)))
|
|
236
|
+
matched = 1;
|
|
237
|
+
}
|
|
238
|
+
if (!matched) return 0;
|
|
239
|
+
}
|
|
240
|
+
(void)target_ns;
|
|
241
|
+
return 1;
|
|
242
|
+
}
|
|
243
|
+
|
|
196
244
|
int xsd_content_valid(struct leptris_xsd_schema* s, XsdCm* model,
|
|
197
245
|
const char* target_ns, const char* const* names,
|
|
198
246
|
const char* const* ns_uris, size_t count) {
|
|
199
247
|
if (!model) return -1;
|
|
248
|
+
if (model->kind == XSD_CM_ALL && model->first_child)
|
|
249
|
+
return all_root_valid(model, target_ns, names, ns_uris, count);
|
|
200
250
|
CmNfa n;
|
|
201
251
|
memset(&n, 0, sizeof(n));
|
|
202
252
|
n.s = s;
|