uss-xsd-engine 0.2.0 → 0.2.2
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.
- package/README.md +15 -71
- package/dist/uss-xsd-engine.esm.js +640 -22
- package/dist/uss-xsd-engine.standalone.js +640 -22
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* uss-xsd-engine v0.2.
|
|
2
|
+
* uss-xsd-engine v0.2.2
|
|
3
3
|
* (c) 2026 Bernard Mumble
|
|
4
4
|
* MIT License
|
|
5
5
|
*/
|
|
@@ -96,6 +96,8 @@ var UssXsdEngine = (() => {
|
|
|
96
96
|
XML_KEY_NULL_VIOLATION: "XML_KEY_NULL_VIOLATION",
|
|
97
97
|
XML_KEYREF_VIOLATION: "XML_KEYREF_VIOLATION",
|
|
98
98
|
XML_UNIQUE_VIOLATION: "XML_UNIQUE_VIOLATION",
|
|
99
|
+
XML_ANY_STRICT_VALIDATION_FAILED: "XML_ANY_STRICT_VALIDATION_FAILED",
|
|
100
|
+
XML_ANYATTRIBUTE_STRICT_VALIDATION_FAILED: "XML_ANYATTRIBUTE_STRICT_VALIDATION_FAILED",
|
|
99
101
|
XML_PATTERN_MISMATCH: "XML_PATTERN_MISMATCH",
|
|
100
102
|
XML_LENGTH_MISMATCH: "XML_LENGTH_MISMATCH",
|
|
101
103
|
XML_MIN_LENGTH_VIOLATION: "XML_MIN_LENGTH_VIOLATION",
|
|
@@ -122,10 +124,15 @@ var UssXsdEngine = (() => {
|
|
|
122
124
|
XSD_RESTRICTION_NOT_SUBSET: "XSD_RESTRICTION_NOT_SUBSET",
|
|
123
125
|
XSD_RESTRICTION_OCCURS_WIDENED: "XSD_RESTRICTION_OCCURS_WIDENED",
|
|
124
126
|
XSD_RESTRICTION_ATTRIBUTE_WIDENED: "XSD_RESTRICTION_ATTRIBUTE_WIDENED",
|
|
127
|
+
XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE: "XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
|
|
128
|
+
XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE: "XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
|
|
129
|
+
XSD_RESTRICTION_WILDCARD_INCOMPATIBLE: "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
|
|
125
130
|
XSD_INCLUDE_NOT_PROVIDED: "XSD_INCLUDE_NOT_PROVIDED",
|
|
126
131
|
XSD_IMPORT_NOT_PROVIDED: "XSD_IMPORT_NOT_PROVIDED",
|
|
127
132
|
XSD_INCLUDE_NAMESPACE_MISMATCH: "XSD_INCLUDE_NAMESPACE_MISMATCH",
|
|
128
|
-
XSD_IMPORT_NAMESPACE_MISMATCH: "XSD_IMPORT_NAMESPACE_MISMATCH"
|
|
133
|
+
XSD_IMPORT_NAMESPACE_MISMATCH: "XSD_IMPORT_NAMESPACE_MISMATCH",
|
|
134
|
+
XSD_REDEFINE_NAMESPACE_MISMATCH: "XSD_REDEFINE_NAMESPACE_MISMATCH",
|
|
135
|
+
REDEFINE_INVALID_OVERRIDE: "REDEFINE_INVALID_OVERRIDE"
|
|
129
136
|
};
|
|
130
137
|
|
|
131
138
|
// src/parser/parseXsd.js
|
|
@@ -178,6 +185,7 @@ var UssXsdEngine = (() => {
|
|
|
178
185
|
targetNamespace: null,
|
|
179
186
|
elementFormDefault: null,
|
|
180
187
|
attributeFormDefault: null,
|
|
188
|
+
schemaVersion: null,
|
|
181
189
|
namespaces: {
|
|
182
190
|
default: null,
|
|
183
191
|
prefixes: /* @__PURE__ */ Object.create(null)
|
|
@@ -193,7 +201,8 @@ var UssXsdEngine = (() => {
|
|
|
193
201
|
documents: [],
|
|
194
202
|
externalRefs: {
|
|
195
203
|
includes: [],
|
|
196
|
-
imports: []
|
|
204
|
+
imports: [],
|
|
205
|
+
redefines: []
|
|
197
206
|
},
|
|
198
207
|
importedSchemas: [],
|
|
199
208
|
roots: [],
|
|
@@ -226,6 +235,16 @@ var UssXsdEngine = (() => {
|
|
|
226
235
|
}
|
|
227
236
|
return null;
|
|
228
237
|
}
|
|
238
|
+
function createAnnotation({
|
|
239
|
+
documentation = null,
|
|
240
|
+
appinfo = null
|
|
241
|
+
} = {}) {
|
|
242
|
+
return {
|
|
243
|
+
kind: "annotation",
|
|
244
|
+
documentation,
|
|
245
|
+
appinfo
|
|
246
|
+
};
|
|
247
|
+
}
|
|
229
248
|
function createElementDecl({
|
|
230
249
|
name = null,
|
|
231
250
|
qName = null,
|
|
@@ -239,6 +258,7 @@ var UssXsdEngine = (() => {
|
|
|
239
258
|
fixedValue = null,
|
|
240
259
|
nillable = false,
|
|
241
260
|
identityConstraints = [],
|
|
261
|
+
annotation = null,
|
|
242
262
|
line = null,
|
|
243
263
|
column = null,
|
|
244
264
|
path = null
|
|
@@ -257,6 +277,7 @@ var UssXsdEngine = (() => {
|
|
|
257
277
|
fixedValue,
|
|
258
278
|
nillable,
|
|
259
279
|
identityConstraints,
|
|
280
|
+
annotation,
|
|
260
281
|
line,
|
|
261
282
|
column,
|
|
262
283
|
path
|
|
@@ -272,6 +293,7 @@ var UssXsdEngine = (() => {
|
|
|
272
293
|
use = null,
|
|
273
294
|
defaultValue = null,
|
|
274
295
|
fixedValue = null,
|
|
296
|
+
annotation = null,
|
|
275
297
|
line = null,
|
|
276
298
|
column = null,
|
|
277
299
|
path = null
|
|
@@ -287,6 +309,7 @@ var UssXsdEngine = (() => {
|
|
|
287
309
|
use,
|
|
288
310
|
defaultValue,
|
|
289
311
|
fixedValue,
|
|
312
|
+
annotation,
|
|
290
313
|
line,
|
|
291
314
|
column,
|
|
292
315
|
path
|
|
@@ -303,6 +326,7 @@ var UssXsdEngine = (() => {
|
|
|
303
326
|
mixed = false,
|
|
304
327
|
abstract = false,
|
|
305
328
|
identityConstraints = [],
|
|
329
|
+
annotation = null,
|
|
306
330
|
line = null,
|
|
307
331
|
column = null,
|
|
308
332
|
path = null
|
|
@@ -319,6 +343,7 @@ var UssXsdEngine = (() => {
|
|
|
319
343
|
mixed,
|
|
320
344
|
abstract,
|
|
321
345
|
identityConstraints,
|
|
346
|
+
annotation,
|
|
322
347
|
line,
|
|
323
348
|
column,
|
|
324
349
|
path
|
|
@@ -331,6 +356,7 @@ var UssXsdEngine = (() => {
|
|
|
331
356
|
baseTypeName = null,
|
|
332
357
|
facets = {},
|
|
333
358
|
enumerations = [],
|
|
359
|
+
annotation = null,
|
|
334
360
|
line = null,
|
|
335
361
|
column = null,
|
|
336
362
|
path = null
|
|
@@ -343,6 +369,7 @@ var UssXsdEngine = (() => {
|
|
|
343
369
|
baseTypeName,
|
|
344
370
|
facets,
|
|
345
371
|
enumerations,
|
|
372
|
+
annotation,
|
|
346
373
|
line,
|
|
347
374
|
column,
|
|
348
375
|
path
|
|
@@ -390,6 +417,7 @@ var UssXsdEngine = (() => {
|
|
|
390
417
|
}
|
|
391
418
|
function createAttributeGroupRef({
|
|
392
419
|
refName,
|
|
420
|
+
use = null,
|
|
393
421
|
line = null,
|
|
394
422
|
column = null,
|
|
395
423
|
path = null
|
|
@@ -397,6 +425,7 @@ var UssXsdEngine = (() => {
|
|
|
397
425
|
return {
|
|
398
426
|
kind: "attributeGroupRef",
|
|
399
427
|
refName,
|
|
428
|
+
use,
|
|
400
429
|
line,
|
|
401
430
|
column,
|
|
402
431
|
path
|
|
@@ -507,9 +536,11 @@ var UssXsdEngine = (() => {
|
|
|
507
536
|
}
|
|
508
537
|
function createAnyNode({
|
|
509
538
|
namespace = null,
|
|
510
|
-
processContents =
|
|
539
|
+
processContents = "strict",
|
|
511
540
|
minOccurs = 1,
|
|
512
541
|
maxOccurs = 1,
|
|
542
|
+
notNamespace = [],
|
|
543
|
+
notQName = [],
|
|
513
544
|
line = null,
|
|
514
545
|
column = null,
|
|
515
546
|
path = null
|
|
@@ -517,9 +548,31 @@ var UssXsdEngine = (() => {
|
|
|
517
548
|
return {
|
|
518
549
|
kind: "any",
|
|
519
550
|
namespace,
|
|
520
|
-
processContents,
|
|
551
|
+
processContents: processContents || "strict",
|
|
521
552
|
minOccurs,
|
|
522
553
|
maxOccurs,
|
|
554
|
+
notNamespace,
|
|
555
|
+
notQName,
|
|
556
|
+
line,
|
|
557
|
+
column,
|
|
558
|
+
path
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
function createAnyAttributeNode({
|
|
562
|
+
namespace = null,
|
|
563
|
+
processContents = "strict",
|
|
564
|
+
notNamespace = [],
|
|
565
|
+
notQName = [],
|
|
566
|
+
line = null,
|
|
567
|
+
column = null,
|
|
568
|
+
path = null
|
|
569
|
+
} = {}) {
|
|
570
|
+
return {
|
|
571
|
+
kind: "anyAttribute",
|
|
572
|
+
namespace,
|
|
573
|
+
processContents: processContents || "strict",
|
|
574
|
+
notNamespace,
|
|
575
|
+
notQName,
|
|
523
576
|
line,
|
|
524
577
|
column,
|
|
525
578
|
path
|
|
@@ -844,9 +897,6 @@ var UssXsdEngine = (() => {
|
|
|
844
897
|
|
|
845
898
|
// src/parser/buildSchemaModel.js
|
|
846
899
|
var UNSUPPORTED_NODE_FEATURES = /* @__PURE__ */ new Set([
|
|
847
|
-
"any",
|
|
848
|
-
"anyAttribute",
|
|
849
|
-
"redefine",
|
|
850
900
|
"notation"
|
|
851
901
|
]);
|
|
852
902
|
function elementChildren(node) {
|
|
@@ -867,6 +917,8 @@ var UssXsdEngine = (() => {
|
|
|
867
917
|
schema.externalRefs.includes.push(entry);
|
|
868
918
|
} else if (kind === "import") {
|
|
869
919
|
schema.externalRefs.imports.push(entry);
|
|
920
|
+
} else if (kind === "redefine") {
|
|
921
|
+
schema.externalRefs.redefines.push(entry);
|
|
870
922
|
}
|
|
871
923
|
}
|
|
872
924
|
function mergeGlobalsIntoSchema(targetSchema, sourceSchema, issues, createDuplicateIssue) {
|
|
@@ -907,6 +959,9 @@ var UssXsdEngine = (() => {
|
|
|
907
959
|
targetSchema.externalRefs.imports.push(
|
|
908
960
|
...sourceSchema.externalRefs.imports || []
|
|
909
961
|
);
|
|
962
|
+
targetSchema.externalRefs.redefines.push(
|
|
963
|
+
...sourceSchema.externalRefs.redefines || []
|
|
964
|
+
);
|
|
910
965
|
targetSchema.importedSchemas.push(...sourceSchema.importedSchemas || []);
|
|
911
966
|
targetSchema.identityConstraints.push(
|
|
912
967
|
...sourceSchema.identityConstraints || []
|
|
@@ -1180,6 +1235,42 @@ var UssXsdEngine = (() => {
|
|
|
1180
1235
|
}
|
|
1181
1236
|
return { facets, enumerations };
|
|
1182
1237
|
}
|
|
1238
|
+
function parseAnnotation(node) {
|
|
1239
|
+
if (!node || node.localName !== "annotation") {
|
|
1240
|
+
return null;
|
|
1241
|
+
}
|
|
1242
|
+
const children = Array.from(node.children || []).filter(
|
|
1243
|
+
(child) => child.nodeType === 1
|
|
1244
|
+
);
|
|
1245
|
+
let documentation = null;
|
|
1246
|
+
let appinfo = null;
|
|
1247
|
+
for (const child of children) {
|
|
1248
|
+
if (child.localName === "documentation") {
|
|
1249
|
+
const lang = child.getAttribute("xml:lang") || null;
|
|
1250
|
+
const source = child.getAttribute("source") || null;
|
|
1251
|
+
const text = (child.textContent || "").trim();
|
|
1252
|
+
documentation = {
|
|
1253
|
+
text,
|
|
1254
|
+
lang,
|
|
1255
|
+
source
|
|
1256
|
+
};
|
|
1257
|
+
} else if (child.localName === "appinfo") {
|
|
1258
|
+
const source = child.getAttribute("source") || null;
|
|
1259
|
+
const text = (child.textContent || "").trim();
|
|
1260
|
+
appinfo = {
|
|
1261
|
+
text,
|
|
1262
|
+
source
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
if (!documentation && !appinfo) {
|
|
1267
|
+
return null;
|
|
1268
|
+
}
|
|
1269
|
+
return createAnnotation({
|
|
1270
|
+
documentation,
|
|
1271
|
+
appinfo
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1183
1274
|
function parseSimpleType(node, xsdText, lineStarts, parentPath, schema, issues) {
|
|
1184
1275
|
const path = buildPath(parentPath, node);
|
|
1185
1276
|
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
@@ -1187,7 +1278,12 @@ var UssXsdEngine = (() => {
|
|
|
1187
1278
|
let baseTypeName = null;
|
|
1188
1279
|
let facets = {};
|
|
1189
1280
|
let enumerations = [];
|
|
1190
|
-
const
|
|
1281
|
+
const children = elementChildren(node);
|
|
1282
|
+
const annotationNode = children.find(
|
|
1283
|
+
(child) => child.localName === "annotation"
|
|
1284
|
+
);
|
|
1285
|
+
const annotation = parseAnnotation(annotationNode);
|
|
1286
|
+
const restriction = children.find(
|
|
1191
1287
|
(child) => child.localName === "restriction"
|
|
1192
1288
|
);
|
|
1193
1289
|
if (restriction) {
|
|
@@ -1214,6 +1310,7 @@ var UssXsdEngine = (() => {
|
|
|
1214
1310
|
baseTypeName,
|
|
1215
1311
|
facets,
|
|
1216
1312
|
enumerations,
|
|
1313
|
+
annotation,
|
|
1217
1314
|
line: loc.line,
|
|
1218
1315
|
column: loc.column,
|
|
1219
1316
|
path
|
|
@@ -1223,7 +1320,12 @@ var UssXsdEngine = (() => {
|
|
|
1223
1320
|
const path = buildPath(parentPath, node);
|
|
1224
1321
|
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
1225
1322
|
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1226
|
-
const
|
|
1323
|
+
const children = elementChildren(node);
|
|
1324
|
+
const annotationNode = children.find(
|
|
1325
|
+
(child) => child.localName === "annotation"
|
|
1326
|
+
);
|
|
1327
|
+
const annotation = parseAnnotation(annotationNode);
|
|
1328
|
+
const inlineSimpleTypeNode = children.find(
|
|
1227
1329
|
(child) => child.localName === "simpleType"
|
|
1228
1330
|
);
|
|
1229
1331
|
const inlineType = inlineSimpleTypeNode ? parseSimpleType(
|
|
@@ -1246,6 +1348,7 @@ var UssXsdEngine = (() => {
|
|
|
1246
1348
|
use: normalizeUse(node.getAttribute("use")),
|
|
1247
1349
|
defaultValue: node.getAttribute("default"),
|
|
1248
1350
|
fixedValue: node.getAttribute("fixed"),
|
|
1351
|
+
annotation,
|
|
1249
1352
|
line: loc.line,
|
|
1250
1353
|
column: loc.column,
|
|
1251
1354
|
path
|
|
@@ -1257,6 +1360,7 @@ var UssXsdEngine = (() => {
|
|
|
1257
1360
|
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1258
1361
|
return createAttributeGroupRef({
|
|
1259
1362
|
refName: node.getAttribute("ref"),
|
|
1363
|
+
use: normalizeUse(node.getAttribute("use")),
|
|
1260
1364
|
line: loc.line,
|
|
1261
1365
|
column: loc.column,
|
|
1262
1366
|
path
|
|
@@ -1280,6 +1384,10 @@ var UssXsdEngine = (() => {
|
|
|
1280
1384
|
issues
|
|
1281
1385
|
)
|
|
1282
1386
|
);
|
|
1387
|
+
} else if (child.localName === "anyAttribute") {
|
|
1388
|
+
attributes.push(
|
|
1389
|
+
parseAnyAttribute(child, xsdText, lineStarts, parentPath, schema, issues)
|
|
1390
|
+
);
|
|
1283
1391
|
}
|
|
1284
1392
|
}
|
|
1285
1393
|
return attributes;
|
|
@@ -1290,6 +1398,10 @@ var UssXsdEngine = (() => {
|
|
|
1290
1398
|
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1291
1399
|
let inlineType = null;
|
|
1292
1400
|
const children = elementChildren(node);
|
|
1401
|
+
const annotationNode = children.find(
|
|
1402
|
+
(child) => child.localName === "annotation"
|
|
1403
|
+
);
|
|
1404
|
+
const annotation = parseAnnotation(annotationNode);
|
|
1293
1405
|
const inlineComplexTypeNode = children.find(
|
|
1294
1406
|
(child) => child.localName === "complexType"
|
|
1295
1407
|
);
|
|
@@ -1345,6 +1457,7 @@ var UssXsdEngine = (() => {
|
|
|
1345
1457
|
fixedValue: node.getAttribute("fixed"),
|
|
1346
1458
|
nillable: node.getAttribute("nillable") === "true",
|
|
1347
1459
|
identityConstraints,
|
|
1460
|
+
annotation,
|
|
1348
1461
|
line: loc.line,
|
|
1349
1462
|
column: loc.column,
|
|
1350
1463
|
path
|
|
@@ -1363,15 +1476,58 @@ var UssXsdEngine = (() => {
|
|
|
1363
1476
|
path
|
|
1364
1477
|
});
|
|
1365
1478
|
}
|
|
1479
|
+
function parseWildcardNamespace(namespaceStr) {
|
|
1480
|
+
if (!namespaceStr) return null;
|
|
1481
|
+
const trimmed = namespaceStr.trim();
|
|
1482
|
+
if (!trimmed) return null;
|
|
1483
|
+
if (trimmed.includes(" ")) {
|
|
1484
|
+
return trimmed.split(/\s+/).filter((ns) => ns);
|
|
1485
|
+
}
|
|
1486
|
+
return trimmed;
|
|
1487
|
+
}
|
|
1488
|
+
function parseNotNamespace(notNamespaceStr) {
|
|
1489
|
+
if (!notNamespaceStr) return [];
|
|
1490
|
+
const trimmed = notNamespaceStr.trim();
|
|
1491
|
+
if (!trimmed) return [];
|
|
1492
|
+
if (trimmed.includes(" ")) {
|
|
1493
|
+
return trimmed.split(/\s+/).filter((ns) => ns);
|
|
1494
|
+
}
|
|
1495
|
+
return [trimmed];
|
|
1496
|
+
}
|
|
1497
|
+
function parseNotQName(notQNameStr) {
|
|
1498
|
+
if (!notQNameStr) return [];
|
|
1499
|
+
const trimmed = notQNameStr.trim();
|
|
1500
|
+
if (!trimmed) return [];
|
|
1501
|
+
if (trimmed.includes(" ")) {
|
|
1502
|
+
return trimmed.split(/\s+/).filter((qn) => qn);
|
|
1503
|
+
}
|
|
1504
|
+
return [trimmed];
|
|
1505
|
+
}
|
|
1366
1506
|
function parseAny(node, xsdText, lineStarts, parentPath, schema, issues) {
|
|
1367
1507
|
const path = buildPath(parentPath, node);
|
|
1368
1508
|
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
1369
1509
|
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1370
1510
|
return createAnyNode({
|
|
1371
|
-
namespace: node.getAttribute("namespace"),
|
|
1511
|
+
namespace: parseWildcardNamespace(node.getAttribute("namespace")),
|
|
1372
1512
|
processContents: node.getAttribute("processContents"),
|
|
1373
1513
|
minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
|
|
1374
1514
|
maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
|
|
1515
|
+
notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
|
|
1516
|
+
notQName: parseNotQName(node.getAttribute("notQName")),
|
|
1517
|
+
line: loc.line,
|
|
1518
|
+
column: loc.column,
|
|
1519
|
+
path
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1522
|
+
function parseAnyAttribute(node, xsdText, lineStarts, parentPath, schema, issues) {
|
|
1523
|
+
const path = buildPath(parentPath, node);
|
|
1524
|
+
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
1525
|
+
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1526
|
+
return createAnyAttributeNode({
|
|
1527
|
+
namespace: parseWildcardNamespace(node.getAttribute("namespace")),
|
|
1528
|
+
processContents: node.getAttribute("processContents"),
|
|
1529
|
+
notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
|
|
1530
|
+
notQName: parseNotQName(node.getAttribute("notQName")),
|
|
1375
1531
|
line: loc.line,
|
|
1376
1532
|
column: loc.column,
|
|
1377
1533
|
path
|
|
@@ -1562,6 +1718,10 @@ var UssXsdEngine = (() => {
|
|
|
1562
1718
|
let contentModel = "complex";
|
|
1563
1719
|
const children = elementChildren(node);
|
|
1564
1720
|
const namespaceUri4 = schema.targetNamespace || null;
|
|
1721
|
+
const annotationNode = children.find(
|
|
1722
|
+
(child) => child.localName === "annotation"
|
|
1723
|
+
);
|
|
1724
|
+
const annotation = parseAnnotation(annotationNode);
|
|
1565
1725
|
const identityConstraints = children.filter(
|
|
1566
1726
|
(child) => ["key", "keyref", "unique"].includes(child.localName)
|
|
1567
1727
|
).map(
|
|
@@ -1647,6 +1807,7 @@ var UssXsdEngine = (() => {
|
|
|
1647
1807
|
mixed: node.getAttribute("mixed") === "true",
|
|
1648
1808
|
abstract: node.getAttribute("abstract") === "true",
|
|
1649
1809
|
identityConstraints,
|
|
1810
|
+
annotation,
|
|
1650
1811
|
line: loc.line,
|
|
1651
1812
|
column: loc.column,
|
|
1652
1813
|
path
|
|
@@ -1716,6 +1877,63 @@ var UssXsdEngine = (() => {
|
|
|
1716
1877
|
}
|
|
1717
1878
|
return (declaredNs || null) === (importedNs || null);
|
|
1718
1879
|
}
|
|
1880
|
+
function isRedefineNamespaceCompatible(hostSchema, redefinedSchema) {
|
|
1881
|
+
const hostNs = hostSchema?.targetNamespace || null;
|
|
1882
|
+
const redefinedNs = redefinedSchema?.targetNamespace || null;
|
|
1883
|
+
return hostNs === redefinedNs;
|
|
1884
|
+
}
|
|
1885
|
+
function mergeRedefinesIntoSchema(targetSchema, sourceSchema, issues, createDuplicateIssue) {
|
|
1886
|
+
const buckets = [
|
|
1887
|
+
["complexTypes", "DUPLICATE_GLOBAL_COMPLEX_TYPE"],
|
|
1888
|
+
["simpleTypes", "DUPLICATE_GLOBAL_SIMPLE_TYPE"],
|
|
1889
|
+
["groups", "DUPLICATE_GLOBAL_GROUP"],
|
|
1890
|
+
["attributeGroups", "DUPLICATE_GLOBAL_ATTRIBUTE_GROUP"]
|
|
1891
|
+
];
|
|
1892
|
+
for (const [bucketName, _duplicateCode] of buckets) {
|
|
1893
|
+
for (const [key, decl] of Object.entries(
|
|
1894
|
+
sourceSchema.globals[bucketName] || {}
|
|
1895
|
+
)) {
|
|
1896
|
+
if (targetSchema.globals[bucketName][key]) {
|
|
1897
|
+
targetSchema.globals[bucketName][key] = {
|
|
1898
|
+
...decl,
|
|
1899
|
+
redefined: true,
|
|
1900
|
+
originalDefinition: targetSchema.globals[bucketName][key]
|
|
1901
|
+
};
|
|
1902
|
+
} else {
|
|
1903
|
+
issues.push(
|
|
1904
|
+
createIssue({
|
|
1905
|
+
code: ISSUE_CODES.REDEFINE_INVALID_OVERRIDE,
|
|
1906
|
+
severity: "error",
|
|
1907
|
+
message: `xs:redefine attempts to override ${bucketName.slice(0, -1)} '${decl.name}' which does not exist in the base schema.`,
|
|
1908
|
+
line: decl.line,
|
|
1909
|
+
column: decl.column,
|
|
1910
|
+
path: decl.path,
|
|
1911
|
+
source: "xsd",
|
|
1912
|
+
nodeKind: decl.kind,
|
|
1913
|
+
name: decl.name,
|
|
1914
|
+
details: { declarationName: decl.name }
|
|
1915
|
+
})
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
targetSchema.references.types.push(...sourceSchema.references.types || []);
|
|
1921
|
+
targetSchema.references.baseTypes.push(
|
|
1922
|
+
...sourceSchema.references.baseTypes || []
|
|
1923
|
+
);
|
|
1924
|
+
targetSchema.references.groupRefs.push(
|
|
1925
|
+
...sourceSchema.references.groupRefs || []
|
|
1926
|
+
);
|
|
1927
|
+
targetSchema.references.attributeGroupRefs.push(
|
|
1928
|
+
...sourceSchema.references.attributeGroupRefs || []
|
|
1929
|
+
);
|
|
1930
|
+
for (const feature of sourceSchema.usedFeatures || []) {
|
|
1931
|
+
targetSchema.usedFeatures.add(feature);
|
|
1932
|
+
}
|
|
1933
|
+
targetSchema.unsupportedFeatures.push(
|
|
1934
|
+
...sourceSchema.unsupportedFeatures || []
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1719
1937
|
function normalizeSchemaPath(value) {
|
|
1720
1938
|
if (!value || typeof value !== "string") return null;
|
|
1721
1939
|
const trimmed = value.trim();
|
|
@@ -1794,24 +2012,24 @@ var UssXsdEngine = (() => {
|
|
|
1794
2012
|
}
|
|
1795
2013
|
}
|
|
1796
2014
|
if (ref?.kind === "import" && ref.namespace) {
|
|
1797
|
-
const
|
|
2015
|
+
const namespaceMatches2 = entries.filter((entry) => {
|
|
1798
2016
|
const declaredTargetNamespace = getDeclaredTargetNamespaceFromText(
|
|
1799
2017
|
entry.text
|
|
1800
2018
|
);
|
|
1801
2019
|
return (declaredTargetNamespace || null) === (ref.namespace || null);
|
|
1802
2020
|
});
|
|
1803
|
-
if (
|
|
2021
|
+
if (namespaceMatches2.length === 1) {
|
|
1804
2022
|
return {
|
|
1805
2023
|
kind: "namespace",
|
|
1806
|
-
entry:
|
|
1807
|
-
matches:
|
|
2024
|
+
entry: namespaceMatches2[0],
|
|
2025
|
+
matches: namespaceMatches2
|
|
1808
2026
|
};
|
|
1809
2027
|
}
|
|
1810
|
-
if (
|
|
2028
|
+
if (namespaceMatches2.length > 1) {
|
|
1811
2029
|
return {
|
|
1812
2030
|
kind: "ambiguous-namespace",
|
|
1813
2031
|
entry: null,
|
|
1814
|
-
matches:
|
|
2032
|
+
matches: namespaceMatches2
|
|
1815
2033
|
};
|
|
1816
2034
|
}
|
|
1817
2035
|
}
|
|
@@ -1841,6 +2059,7 @@ var UssXsdEngine = (() => {
|
|
|
1841
2059
|
schema.targetNamespace = getEffectiveTargetNamespace(schemaRoot, options);
|
|
1842
2060
|
schema.elementFormDefault = schemaRoot.getAttribute("elementFormDefault");
|
|
1843
2061
|
schema.attributeFormDefault = schemaRoot.getAttribute("attributeFormDefault");
|
|
2062
|
+
schema.schemaVersion = schemaRoot.getAttribute("version");
|
|
1844
2063
|
extractNamespaces(schemaRoot, schema);
|
|
1845
2064
|
const rootPath = "/schema";
|
|
1846
2065
|
const rootLoc = locateNodeInSource(xsdText, lineStarts, schemaRoot);
|
|
@@ -1993,6 +2212,13 @@ var UssXsdEngine = (() => {
|
|
|
1993
2212
|
recordExternalRef(schema, "import", child, path, loc);
|
|
1994
2213
|
break;
|
|
1995
2214
|
}
|
|
2215
|
+
case "redefine": {
|
|
2216
|
+
const path = buildPath(rootPath, child);
|
|
2217
|
+
const loc = locateNodeInSource(xsdText, lineStarts, child);
|
|
2218
|
+
collectNodeDiagnostics(schema, issues, child, path, loc);
|
|
2219
|
+
recordExternalRef(schema, "redefine", child, path, loc);
|
|
2220
|
+
break;
|
|
2221
|
+
}
|
|
1996
2222
|
default: {
|
|
1997
2223
|
const path = buildPath(rootPath, child);
|
|
1998
2224
|
const loc = locateNodeInSource(xsdText, lineStarts, child);
|
|
@@ -2017,7 +2243,8 @@ var UssXsdEngine = (() => {
|
|
|
2017
2243
|
const visited = options._visitedExternalSchemas || /* @__PURE__ */ new Set();
|
|
2018
2244
|
const includes = schema.externalRefs.includes || [];
|
|
2019
2245
|
const imports = schema.externalRefs.imports || [];
|
|
2020
|
-
|
|
2246
|
+
const redefines = schema.externalRefs.redefines || [];
|
|
2247
|
+
for (const ref of [...includes, ...imports, ...redefines]) {
|
|
2021
2248
|
if (!ref.schemaLocation) continue;
|
|
2022
2249
|
const resolution = resolveExternalDocument(ref, externalDocuments);
|
|
2023
2250
|
if (resolution.kind === "ambiguous-namespace") {
|
|
@@ -2144,6 +2371,34 @@ var UssXsdEngine = (() => {
|
|
|
2144
2371
|
} else {
|
|
2145
2372
|
schema.importedSchemas.push(externalBuild.schema);
|
|
2146
2373
|
}
|
|
2374
|
+
} else if (ref.kind === "redefine") {
|
|
2375
|
+
if (!isRedefineNamespaceCompatible(schema, externalBuild.schema)) {
|
|
2376
|
+
issues.push(
|
|
2377
|
+
createIssue({
|
|
2378
|
+
code: ISSUE_CODES.XSD_REDEFINE_NAMESPACE_MISMATCH,
|
|
2379
|
+
severity: "error",
|
|
2380
|
+
message: `xs:redefine namespace mismatch. Host targetNamespace is '${schema.targetNamespace || ""}', redefined schema targetNamespace is '${externalBuild.schema.targetNamespace || ""}'.`,
|
|
2381
|
+
line: ref.line,
|
|
2382
|
+
column: ref.column,
|
|
2383
|
+
path: ref.path,
|
|
2384
|
+
source: "xsd",
|
|
2385
|
+
nodeKind: "redefine",
|
|
2386
|
+
details: {
|
|
2387
|
+
schemaLocation: ref.schemaLocation,
|
|
2388
|
+
resolvedSchemaKey,
|
|
2389
|
+
hostTargetNamespace: schema.targetNamespace || null,
|
|
2390
|
+
redefinedTargetNamespace: externalBuild.schema.targetNamespace || null
|
|
2391
|
+
}
|
|
2392
|
+
})
|
|
2393
|
+
);
|
|
2394
|
+
} else {
|
|
2395
|
+
mergeRedefinesIntoSchema(
|
|
2396
|
+
schema,
|
|
2397
|
+
externalBuild.schema,
|
|
2398
|
+
issues,
|
|
2399
|
+
createDuplicateIssue
|
|
2400
|
+
);
|
|
2401
|
+
}
|
|
2147
2402
|
}
|
|
2148
2403
|
}
|
|
2149
2404
|
issues.push(...externalBuild.issues || []);
|
|
@@ -2428,6 +2683,115 @@ var UssXsdEngine = (() => {
|
|
|
2428
2683
|
}
|
|
2429
2684
|
}
|
|
2430
2685
|
}
|
|
2686
|
+
function checkWildcardRestriction(schema, derivedType, baseType, issues) {
|
|
2687
|
+
const derivedContent = getEffectiveContent(schema, derivedType);
|
|
2688
|
+
const baseContent = getEffectiveContent(schema, baseType);
|
|
2689
|
+
const derivedWildcards = [];
|
|
2690
|
+
const baseWildcards = [];
|
|
2691
|
+
function collectWildcards(node, arr) {
|
|
2692
|
+
if (!node) return;
|
|
2693
|
+
if (node.kind === "any") {
|
|
2694
|
+
arr.push(node);
|
|
2695
|
+
return;
|
|
2696
|
+
}
|
|
2697
|
+
if (node.children) {
|
|
2698
|
+
for (const child of asArray(node.children)) {
|
|
2699
|
+
collectWildcards(child, arr);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
collectWildcards(derivedContent, derivedWildcards);
|
|
2704
|
+
collectWildcards(baseContent, baseWildcards);
|
|
2705
|
+
if (derivedWildcards.length > 0 && baseWildcards.length === 0) {
|
|
2706
|
+
issues.push(
|
|
2707
|
+
buildRestrictionIssue(
|
|
2708
|
+
"XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
|
|
2709
|
+
`Restricted type introduces wildcard elements that base type does not have.`,
|
|
2710
|
+
derivedType
|
|
2711
|
+
)
|
|
2712
|
+
);
|
|
2713
|
+
}
|
|
2714
|
+
const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
|
|
2715
|
+
const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
|
|
2716
|
+
const derivedHasAnyAttribute = derivedAttrs.some((a) => a?.kind === "anyAttribute");
|
|
2717
|
+
const baseHasAnyAttribute = baseAttrs.some((a) => a?.kind === "anyAttribute");
|
|
2718
|
+
if (derivedHasAnyAttribute && !baseHasAnyAttribute) {
|
|
2719
|
+
issues.push(
|
|
2720
|
+
buildRestrictionIssue(
|
|
2721
|
+
"XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
|
|
2722
|
+
`Restricted type introduces anyAttribute that base type does not have.`,
|
|
2723
|
+
derivedType
|
|
2724
|
+
)
|
|
2725
|
+
);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
function checkOccurrenceCompatibility(derived, base, name) {
|
|
2729
|
+
const dMin = typeof derived.minOccurs === "number" ? derived.minOccurs : 1;
|
|
2730
|
+
const bMin = typeof base.minOccurs === "number" ? base.minOccurs : 1;
|
|
2731
|
+
const dMax = maxToNumber(derived.maxOccurs ?? 1);
|
|
2732
|
+
const bMax = maxToNumber(base.maxOccurs ?? 1);
|
|
2733
|
+
return dMin >= bMin && dMax <= bMax;
|
|
2734
|
+
}
|
|
2735
|
+
function checkComplexContentRestriction(schema, derivedType, baseType, issues) {
|
|
2736
|
+
const derivedContent = getEffectiveContent(schema, derivedType);
|
|
2737
|
+
const baseContent = getEffectiveContent(schema, baseType);
|
|
2738
|
+
if (!derivedContent || !baseContent) return;
|
|
2739
|
+
const derivedFlat = flattenContent(derivedContent, []);
|
|
2740
|
+
const baseFlat = flattenContent(baseContent, []);
|
|
2741
|
+
const baseMap = new Map(baseFlat.map((item) => [item.name, item]));
|
|
2742
|
+
for (const item of derivedFlat) {
|
|
2743
|
+
const baseItem = baseMap.get(item.name);
|
|
2744
|
+
if (!baseItem) {
|
|
2745
|
+
issues.push(
|
|
2746
|
+
buildRestrictionIssue(
|
|
2747
|
+
"XSD_RESTRICTION_NOT_SUBSET",
|
|
2748
|
+
`Restricted type contains element '${item.name}' not in base type.`,
|
|
2749
|
+
item
|
|
2750
|
+
)
|
|
2751
|
+
);
|
|
2752
|
+
continue;
|
|
2753
|
+
}
|
|
2754
|
+
if (!checkOccurrenceCompatibility(item, baseItem, item.name)) {
|
|
2755
|
+
issues.push(
|
|
2756
|
+
buildRestrictionIssue(
|
|
2757
|
+
"XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
|
|
2758
|
+
`Restricted type has incompatible occurrence constraints for '${item.name}'.`,
|
|
2759
|
+
item
|
|
2760
|
+
)
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
function checkSimpleContentRestriction(schema, derivedType, baseType, issues) {
|
|
2766
|
+
if (baseType.contentModel !== "simple") {
|
|
2767
|
+
issues.push(
|
|
2768
|
+
buildRestrictionIssue(
|
|
2769
|
+
"XSD_RESTRICTION_NOT_SUBSET",
|
|
2770
|
+
`SimpleContent restriction requires base type to have simple content.`,
|
|
2771
|
+
derivedType
|
|
2772
|
+
)
|
|
2773
|
+
);
|
|
2774
|
+
}
|
|
2775
|
+
const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
|
|
2776
|
+
const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
|
|
2777
|
+
const baseAttrMap = new Map(
|
|
2778
|
+
baseAttrs.filter((attr) => attr?.kind === "attribute").map((attr) => [localDeclName(attr), attr])
|
|
2779
|
+
);
|
|
2780
|
+
for (const attr of derivedAttrs) {
|
|
2781
|
+
if (attr?.kind !== "attribute") continue;
|
|
2782
|
+
const name = localDeclName(attr);
|
|
2783
|
+
const baseAttr = baseAttrMap.get(name);
|
|
2784
|
+
if (!baseAttr && !baseAttrs.some((a) => a?.kind === "anyAttribute")) {
|
|
2785
|
+
issues.push(
|
|
2786
|
+
buildRestrictionIssue(
|
|
2787
|
+
"XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
|
|
2788
|
+
`SimpleContent restricted type adds attribute '${name}' not in base type.`,
|
|
2789
|
+
attr
|
|
2790
|
+
)
|
|
2791
|
+
);
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2431
2795
|
function runRestrictionDiagnostics(schema) {
|
|
2432
2796
|
const issues = [];
|
|
2433
2797
|
for (const complexType of Object.values(schema.globals.complexTypes || {})) {
|
|
@@ -2437,6 +2801,12 @@ var UssXsdEngine = (() => {
|
|
|
2437
2801
|
if (!baseType) continue;
|
|
2438
2802
|
checkRestrictedContentSubset(schema, complexType, baseType, issues);
|
|
2439
2803
|
checkRestrictedAttributes(schema, complexType, baseType, issues);
|
|
2804
|
+
checkWildcardRestriction(schema, complexType, baseType, issues);
|
|
2805
|
+
if (complexType.contentModel === "complex" && baseType.contentModel === "complex") {
|
|
2806
|
+
checkComplexContentRestriction(schema, complexType, baseType, issues);
|
|
2807
|
+
} else if (complexType.contentModel === "simple" && baseType.contentModel === "simple") {
|
|
2808
|
+
checkSimpleContentRestriction(schema, complexType, baseType, issues);
|
|
2809
|
+
}
|
|
2440
2810
|
}
|
|
2441
2811
|
return issues;
|
|
2442
2812
|
}
|
|
@@ -2763,6 +3133,130 @@ var UssXsdEngine = (() => {
|
|
|
2763
3133
|
return issues;
|
|
2764
3134
|
}
|
|
2765
3135
|
|
|
3136
|
+
// src/diagnostics/schemaWildcardDiagnostics.js
|
|
3137
|
+
function validateWildcardNamespace(namespace, path) {
|
|
3138
|
+
if (!namespace) return null;
|
|
3139
|
+
const trimmed = namespace.trim();
|
|
3140
|
+
if (!trimmed) return null;
|
|
3141
|
+
const parts = trimmed.split(/\s+/);
|
|
3142
|
+
for (const part of parts) {
|
|
3143
|
+
if (part === "##any" || part === "##other" || part === "##targetNamespace") {
|
|
3144
|
+
continue;
|
|
3145
|
+
}
|
|
3146
|
+
if (!part.includes(":") && part !== "") {
|
|
3147
|
+
return createIssue({
|
|
3148
|
+
code: "INVALID_WILDCARD_NAMESPACE",
|
|
3149
|
+
severity: "warning",
|
|
3150
|
+
message: `Invalid namespace in wildcard constraint: '${part}'. Expected ##any, ##other, ##targetNamespace, or a valid namespace URI.`,
|
|
3151
|
+
path
|
|
3152
|
+
});
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
return null;
|
|
3156
|
+
}
|
|
3157
|
+
function validateProcessContents(processContents, path) {
|
|
3158
|
+
if (!processContents) return null;
|
|
3159
|
+
const trimmed = processContents.trim();
|
|
3160
|
+
if (trimmed === "strict" || trimmed === "lax" || trimmed === "skip") {
|
|
3161
|
+
return null;
|
|
3162
|
+
}
|
|
3163
|
+
return createIssue({
|
|
3164
|
+
code: "INVALID_PROCESS_CONTENTS",
|
|
3165
|
+
severity: "error",
|
|
3166
|
+
message: `Invalid processContents value: '${processContents}'. Must be 'strict', 'lax', or 'skip'.`,
|
|
3167
|
+
path
|
|
3168
|
+
});
|
|
3169
|
+
}
|
|
3170
|
+
function validateSingleWildcard(wildcardNode, nodeName) {
|
|
3171
|
+
const issues = [];
|
|
3172
|
+
const nsIssue = validateWildcardNamespace(wildcardNode.namespace, wildcardNode.path);
|
|
3173
|
+
if (nsIssue) {
|
|
3174
|
+
issues.push(nsIssue);
|
|
3175
|
+
}
|
|
3176
|
+
const pcIssue = validateProcessContents(wildcardNode.processContents, wildcardNode.path);
|
|
3177
|
+
if (pcIssue) {
|
|
3178
|
+
issues.push(pcIssue);
|
|
3179
|
+
}
|
|
3180
|
+
if (wildcardNode.notNamespace && wildcardNode.notNamespace.length > 0) {
|
|
3181
|
+
if (wildcardNode.namespace !== "##other" && wildcardNode.namespace !== "##targetNamespace") {
|
|
3182
|
+
issues.push(
|
|
3183
|
+
createIssue({
|
|
3184
|
+
code: "INVALID_NOT_NAMESPACE_USAGE",
|
|
3185
|
+
severity: "warning",
|
|
3186
|
+
message: `notNamespace is only meaningful with ##other or ##targetNamespace namespace constraint.`,
|
|
3187
|
+
path: wildcardNode.path
|
|
3188
|
+
})
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
if (wildcardNode.notQName && wildcardNode.notQName.length > 0) {
|
|
3193
|
+
for (const qname of wildcardNode.notQName) {
|
|
3194
|
+
if (!qname || qname.trim() === "") {
|
|
3195
|
+
issues.push(
|
|
3196
|
+
createIssue({
|
|
3197
|
+
code: "INVALID_NOT_QNAME",
|
|
3198
|
+
severity: "warning",
|
|
3199
|
+
message: `Empty QName in notQName constraint.`,
|
|
3200
|
+
path: wildcardNode.path
|
|
3201
|
+
})
|
|
3202
|
+
);
|
|
3203
|
+
break;
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
return issues;
|
|
3208
|
+
}
|
|
3209
|
+
function findWildcardsInContent(node, wildcards) {
|
|
3210
|
+
if (!node) return;
|
|
3211
|
+
if (node.kind === "any" || node.kind === "anyAttribute") {
|
|
3212
|
+
wildcards.push(node);
|
|
3213
|
+
return;
|
|
3214
|
+
}
|
|
3215
|
+
if (node.children && Array.isArray(node.children)) {
|
|
3216
|
+
for (const child of node.children) {
|
|
3217
|
+
findWildcardsInContent(child, wildcards);
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
function findWildcardsInAttributes(attributes, wildcards) {
|
|
3222
|
+
if (!attributes || !Array.isArray(attributes)) return;
|
|
3223
|
+
for (const attr of attributes) {
|
|
3224
|
+
if (attr.kind === "anyAttribute") {
|
|
3225
|
+
wildcards.push(attr);
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
function runWildcardDiagnostics(schema) {
|
|
3230
|
+
const issues = [];
|
|
3231
|
+
const wildcards = [];
|
|
3232
|
+
for (const elem of Object.values(schema.globals.elements || {})) {
|
|
3233
|
+
if (elem.inlineType?.content) {
|
|
3234
|
+
findWildcardsInContent(elem.inlineType.content, wildcards);
|
|
3235
|
+
}
|
|
3236
|
+
if (elem.inlineType?.attributes) {
|
|
3237
|
+
findWildcardsInAttributes(elem.inlineType.attributes, wildcards);
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
for (const complexType of Object.values(schema.globals.complexTypes || {})) {
|
|
3241
|
+
if (complexType.content) {
|
|
3242
|
+
findWildcardsInContent(complexType.content, wildcards);
|
|
3243
|
+
}
|
|
3244
|
+
if (complexType.attributes) {
|
|
3245
|
+
findWildcardsInAttributes(complexType.attributes, wildcards);
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
for (const group of Object.values(schema.globals.groups || {})) {
|
|
3249
|
+
if (group.content) {
|
|
3250
|
+
findWildcardsInContent(group.content, wildcards);
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
for (const wildcard of wildcards) {
|
|
3254
|
+
const wildcardIssues = validateSingleWildcard(wildcard, wildcard.kind);
|
|
3255
|
+
issues.push(...wildcardIssues);
|
|
3256
|
+
}
|
|
3257
|
+
return issues;
|
|
3258
|
+
}
|
|
3259
|
+
|
|
2766
3260
|
// src/diagnostics/schemaDiagnostics.js
|
|
2767
3261
|
function buildStats(schema) {
|
|
2768
3262
|
return {
|
|
@@ -2937,6 +3431,8 @@ var UssXsdEngine = (() => {
|
|
|
2937
3431
|
const identityIssues = runIdentityConstraintDiagnostics(schema);
|
|
2938
3432
|
issues.push(...identityIssues);
|
|
2939
3433
|
emitUnsupportedFeatureWarnings(schema, issues, options);
|
|
3434
|
+
const wildcardIssues = runWildcardDiagnostics(schema);
|
|
3435
|
+
issues.push(...wildcardIssues);
|
|
2940
3436
|
const facetIssues = runFacetDiagnostics(schema, options);
|
|
2941
3437
|
issues.push(...facetIssues);
|
|
2942
3438
|
const restrictionIssues = runRestrictionDiagnostics(schema);
|
|
@@ -2957,7 +3453,7 @@ var UssXsdEngine = (() => {
|
|
|
2957
3453
|
}
|
|
2958
3454
|
|
|
2959
3455
|
// src/version.js
|
|
2960
|
-
var ENGINE_VERSION = "v0.2.
|
|
3456
|
+
var ENGINE_VERSION = "v0.2.2";
|
|
2961
3457
|
|
|
2962
3458
|
// src/utils/result.js
|
|
2963
3459
|
function summarizeIssues(issues = []) {
|
|
@@ -3845,6 +4341,24 @@ var UssXsdEngine = (() => {
|
|
|
3845
4341
|
function buildComplexTypeContent(schema, complexTypeDecl, options, state) {
|
|
3846
4342
|
const content = getEffectiveContent(schema, complexTypeDecl);
|
|
3847
4343
|
const attributes = getEffectiveAttributes(schema, complexTypeDecl);
|
|
4344
|
+
if (state.currentDepth >= options.maxDepth) {
|
|
4345
|
+
return {
|
|
4346
|
+
attributes: buildAttributesObject(schema, attributes, options, state),
|
|
4347
|
+
children: []
|
|
4348
|
+
};
|
|
4349
|
+
}
|
|
4350
|
+
const typeKey = complexTypeDecl.name || complexTypeDecl.qName;
|
|
4351
|
+
if (typeKey && state.visitedTypes.has(typeKey)) {
|
|
4352
|
+
return {
|
|
4353
|
+
attributes: buildAttributesObject(schema, attributes, options, state),
|
|
4354
|
+
children: []
|
|
4355
|
+
};
|
|
4356
|
+
}
|
|
4357
|
+
if (typeKey) {
|
|
4358
|
+
state.visitedTypes.add(typeKey);
|
|
4359
|
+
}
|
|
4360
|
+
const previousDepth = state.currentDepth;
|
|
4361
|
+
state.currentDepth += 1;
|
|
3848
4362
|
let children = content ? buildNodesFromContent(schema, content, options, state) : [];
|
|
3849
4363
|
if (options.mode === "minimal" && children.length === 0 && content) {
|
|
3850
4364
|
children = buildRepresentativeNodesFromContent(
|
|
@@ -3854,6 +4368,10 @@ var UssXsdEngine = (() => {
|
|
|
3854
4368
|
state
|
|
3855
4369
|
);
|
|
3856
4370
|
}
|
|
4371
|
+
state.currentDepth = previousDepth;
|
|
4372
|
+
if (typeKey) {
|
|
4373
|
+
state.visitedTypes.delete(typeKey);
|
|
4374
|
+
}
|
|
3857
4375
|
return {
|
|
3858
4376
|
attributes: buildAttributesObject(schema, attributes, options, state),
|
|
3859
4377
|
children
|
|
@@ -3932,7 +4450,10 @@ var UssXsdEngine = (() => {
|
|
|
3932
4450
|
function generateXmlFromSchema(schema, options = {}, helpers = {}) {
|
|
3933
4451
|
const normalizedOptions = {
|
|
3934
4452
|
mode: options.mode === "full" ? "full" : "minimal",
|
|
3935
|
-
includeOptionalAttributes: options.includeOptionalAttributes === true
|
|
4453
|
+
includeOptionalAttributes: options.includeOptionalAttributes === true,
|
|
4454
|
+
maxDepth: options.maxDepth ?? 3,
|
|
4455
|
+
maxChoiceBranches: options.maxChoiceBranches ?? 1,
|
|
4456
|
+
expandRepeatingElements: options.expandRepeatingElements ?? 2
|
|
3936
4457
|
};
|
|
3937
4458
|
const root = selectRoot(schema, options);
|
|
3938
4459
|
if (!root) {
|
|
@@ -3945,7 +4466,9 @@ var UssXsdEngine = (() => {
|
|
|
3945
4466
|
const state = {
|
|
3946
4467
|
resolveAttributeGroup: helpers.resolveAttributeGroup,
|
|
3947
4468
|
targetPrefix: options.targetPrefix || "tns",
|
|
3948
|
-
nsContext
|
|
4469
|
+
nsContext,
|
|
4470
|
+
visitedTypes: /* @__PURE__ */ new Set(),
|
|
4471
|
+
currentDepth: 0
|
|
3949
4472
|
};
|
|
3950
4473
|
const [rootNode] = buildElementInstances(
|
|
3951
4474
|
schema,
|
|
@@ -4048,6 +4571,80 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4048
4571
|
});
|
|
4049
4572
|
}
|
|
4050
4573
|
|
|
4574
|
+
// src/validation/wildcardValidator.js
|
|
4575
|
+
function namespaceMatches(elementNamespace, wildcardNamespace, targetNamespace) {
|
|
4576
|
+
if (!wildcardNamespace) return true;
|
|
4577
|
+
if (wildcardNamespace === "##any") return true;
|
|
4578
|
+
if (wildcardNamespace === "##targetNamespace") {
|
|
4579
|
+
return elementNamespace === targetNamespace;
|
|
4580
|
+
}
|
|
4581
|
+
if (wildcardNamespace === "##other") {
|
|
4582
|
+
return elementNamespace !== targetNamespace;
|
|
4583
|
+
}
|
|
4584
|
+
if (Array.isArray(wildcardNamespace)) {
|
|
4585
|
+
return wildcardNamespace.includes(elementNamespace);
|
|
4586
|
+
}
|
|
4587
|
+
return elementNamespace === wildcardNamespace;
|
|
4588
|
+
}
|
|
4589
|
+
function isExcludedByNotNamespace(elementNamespace, notNamespace) {
|
|
4590
|
+
if (!notNamespace || notNamespace.length === 0) return false;
|
|
4591
|
+
return notNamespace.includes(elementNamespace);
|
|
4592
|
+
}
|
|
4593
|
+
function isExcludedByNotQName(qName, notQName) {
|
|
4594
|
+
if (!notQName || notQName.length === 0) return false;
|
|
4595
|
+
return notQName.includes(qName);
|
|
4596
|
+
}
|
|
4597
|
+
function buildQName(localName4, namespaceUri4) {
|
|
4598
|
+
if (!namespaceUri4 || namespaceUri4 === "") {
|
|
4599
|
+
return localName4;
|
|
4600
|
+
}
|
|
4601
|
+
return `{${namespaceUri4}}${localName4}`;
|
|
4602
|
+
}
|
|
4603
|
+
function elementMatchesWildcard(elementLocalName, elementNamespace, wildcardNode, targetNamespace) {
|
|
4604
|
+
if (!wildcardNode || wildcardNode.kind !== "any") {
|
|
4605
|
+
return false;
|
|
4606
|
+
}
|
|
4607
|
+
if (!namespaceMatches(elementNamespace, wildcardNode.namespace, targetNamespace)) {
|
|
4608
|
+
return false;
|
|
4609
|
+
}
|
|
4610
|
+
if (isExcludedByNotNamespace(elementNamespace, wildcardNode.notNamespace)) {
|
|
4611
|
+
return false;
|
|
4612
|
+
}
|
|
4613
|
+
const qName = buildQName(elementLocalName, elementNamespace);
|
|
4614
|
+
if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
|
|
4615
|
+
return false;
|
|
4616
|
+
}
|
|
4617
|
+
return true;
|
|
4618
|
+
}
|
|
4619
|
+
function attributeMatchesWildcard(attrLocalName, attrNamespace, wildcardNode, targetNamespace) {
|
|
4620
|
+
if (!wildcardNode || wildcardNode.kind !== "anyAttribute") {
|
|
4621
|
+
return false;
|
|
4622
|
+
}
|
|
4623
|
+
if (!namespaceMatches(attrNamespace, wildcardNode.namespace, targetNamespace)) {
|
|
4624
|
+
return false;
|
|
4625
|
+
}
|
|
4626
|
+
if (isExcludedByNotNamespace(attrNamespace, wildcardNode.notNamespace)) {
|
|
4627
|
+
return false;
|
|
4628
|
+
}
|
|
4629
|
+
const qName = buildQName(attrLocalName, attrNamespace);
|
|
4630
|
+
if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
|
|
4631
|
+
return false;
|
|
4632
|
+
}
|
|
4633
|
+
return true;
|
|
4634
|
+
}
|
|
4635
|
+
function normalizeProcessContents(processContents) {
|
|
4636
|
+
if (processContents === "lax" || processContents === "skip") {
|
|
4637
|
+
return processContents;
|
|
4638
|
+
}
|
|
4639
|
+
return "strict";
|
|
4640
|
+
}
|
|
4641
|
+
function isStrictWildcardValidation(processContents) {
|
|
4642
|
+
return normalizeProcessContents(processContents) === "strict";
|
|
4643
|
+
}
|
|
4644
|
+
function shouldSkipWildcardValidation(processContents) {
|
|
4645
|
+
return normalizeProcessContents(processContents) === "skip";
|
|
4646
|
+
}
|
|
4647
|
+
|
|
4051
4648
|
// src/validation/structureValidator.js
|
|
4052
4649
|
function elementChildren2(xmlNode) {
|
|
4053
4650
|
return Array.from(xmlNode?.children || []).filter((child) => child.nodeType === 1);
|
|
@@ -4117,6 +4714,7 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4117
4714
|
function validateAttributes(xmlNode, attributes, context) {
|
|
4118
4715
|
const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts, validateAttributeValue: validateAttributeValue2 } = context;
|
|
4119
4716
|
const allowed = /* @__PURE__ */ new Map();
|
|
4717
|
+
let anyAttributeWildcard = null;
|
|
4120
4718
|
for (const attr of attributes || []) {
|
|
4121
4719
|
if (!attr) continue;
|
|
4122
4720
|
if (attr.kind === "attribute") {
|
|
@@ -4128,6 +4726,8 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4128
4726
|
const group = context.resolveAttributeGroup?.(attr.refName);
|
|
4129
4727
|
if (!group) continue;
|
|
4130
4728
|
validateAttributes(xmlNode, group.attributes || [], context);
|
|
4729
|
+
} else if (attr.kind === "anyAttribute") {
|
|
4730
|
+
anyAttributeWildcard = attr;
|
|
4131
4731
|
}
|
|
4132
4732
|
}
|
|
4133
4733
|
for (const attrDecl of allowed.values()) {
|
|
@@ -4173,6 +4773,15 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4173
4773
|
continue;
|
|
4174
4774
|
}
|
|
4175
4775
|
if (!allowed.has(attr.name)) {
|
|
4776
|
+
if (anyAttributeWildcard) {
|
|
4777
|
+
const attrLocalName = attr.localName || attr.name.split(":")[1] || attr.name;
|
|
4778
|
+
const attrNamespace = attr.namespaceURI || null;
|
|
4779
|
+
if (attributeMatchesWildcard(attrLocalName, attrNamespace, anyAttributeWildcard, schema.targetNamespace)) {
|
|
4780
|
+
if (!shouldSkipWildcardValidation(anyAttributeWildcard.processContents)) {
|
|
4781
|
+
}
|
|
4782
|
+
continue;
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4176
4785
|
issues.push(
|
|
4177
4786
|
createIssue2({
|
|
4178
4787
|
code: ISSUE_CODES2.XML_UNEXPECTED_ATTRIBUTE,
|
|
@@ -4590,7 +5199,16 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4590
5199
|
return validateAll(children, startIndex, modelNode, context, pathParts, silent);
|
|
4591
5200
|
case "any":
|
|
4592
5201
|
if (startIndex < children.length) {
|
|
4593
|
-
|
|
5202
|
+
const childNode = children[startIndex];
|
|
5203
|
+
const childLocalName = localName(childNode);
|
|
5204
|
+
const childNamespace = namespaceUri(childNode);
|
|
5205
|
+
if (elementMatchesWildcard(childLocalName, childNamespace, modelNode, context.schema.targetNamespace)) {
|
|
5206
|
+
if (isStrictWildcardValidation(modelNode.processContents)) {
|
|
5207
|
+
validateElementDecl(childNode, { name: childLocalName, typeName: null }, context, [...pathParts, childLocalName]);
|
|
5208
|
+
} else if (!shouldSkipWildcardValidation(modelNode.processContents)) {
|
|
5209
|
+
}
|
|
5210
|
+
return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
|
|
5211
|
+
}
|
|
4594
5212
|
}
|
|
4595
5213
|
return { nextIndex: startIndex, matched: true, matchedAny: false };
|
|
4596
5214
|
default:
|