uss-xsd-engine 0.1.1 → 0.2.1
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 +1325 -116
- package/dist/uss-xsd-engine.standalone.js +1325 -116
- package/package.json +71 -70
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* uss-xsd-engine v0.
|
|
2
|
+
* uss-xsd-engine v0.2.1
|
|
3
3
|
* (c) 2026 Bernard Mumble
|
|
4
4
|
* MIT License
|
|
5
5
|
*/
|
|
@@ -72,6 +72,10 @@ var UssXsdEngine = (() => {
|
|
|
72
72
|
UNKNOWN_GROUP: "UNKNOWN_GROUP",
|
|
73
73
|
UNKNOWN_ATTRIBUTE_GROUP: "UNKNOWN_ATTRIBUTE_GROUP",
|
|
74
74
|
MISSING_BASE_TYPE: "MISSING_BASE_TYPE",
|
|
75
|
+
INVALID_CONSTRAINT_SELECTOR: "INVALID_CONSTRAINT_SELECTOR",
|
|
76
|
+
INVALID_CONSTRAINT_FIELD: "INVALID_CONSTRAINT_FIELD",
|
|
77
|
+
UNKNOWN_KEY_REFERENCE: "UNKNOWN_KEY_REFERENCE",
|
|
78
|
+
DUPLICATE_CONSTRAINT_NAME: "DUPLICATE_CONSTRAINT_NAME",
|
|
75
79
|
UNSUPPORTED_FEATURE: "UNSUPPORTED_FEATURE",
|
|
76
80
|
INVALID_OCCURS_RANGE: "INVALID_OCCURS_RANGE",
|
|
77
81
|
INVALID_DEFAULT_FIXED_COMBINATION: "INVALID_DEFAULT_FIXED_COMBINATION",
|
|
@@ -88,6 +92,12 @@ var UssXsdEngine = (() => {
|
|
|
88
92
|
XML_VALUE_INVALID: "XML_VALUE_INVALID",
|
|
89
93
|
XML_ENUMERATION_MISMATCH: "XML_ENUMERATION_MISMATCH",
|
|
90
94
|
XML_VALUE_REQUIRED: "XML_VALUE_REQUIRED",
|
|
95
|
+
XML_KEY_VIOLATION: "XML_KEY_VIOLATION",
|
|
96
|
+
XML_KEY_NULL_VIOLATION: "XML_KEY_NULL_VIOLATION",
|
|
97
|
+
XML_KEYREF_VIOLATION: "XML_KEYREF_VIOLATION",
|
|
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",
|
|
91
101
|
XML_PATTERN_MISMATCH: "XML_PATTERN_MISMATCH",
|
|
92
102
|
XML_LENGTH_MISMATCH: "XML_LENGTH_MISMATCH",
|
|
93
103
|
XML_MIN_LENGTH_VIOLATION: "XML_MIN_LENGTH_VIOLATION",
|
|
@@ -114,6 +124,9 @@ var UssXsdEngine = (() => {
|
|
|
114
124
|
XSD_RESTRICTION_NOT_SUBSET: "XSD_RESTRICTION_NOT_SUBSET",
|
|
115
125
|
XSD_RESTRICTION_OCCURS_WIDENED: "XSD_RESTRICTION_OCCURS_WIDENED",
|
|
116
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",
|
|
117
130
|
XSD_INCLUDE_NOT_PROVIDED: "XSD_INCLUDE_NOT_PROVIDED",
|
|
118
131
|
XSD_IMPORT_NOT_PROVIDED: "XSD_IMPORT_NOT_PROVIDED",
|
|
119
132
|
XSD_INCLUDE_NAMESPACE_MISMATCH: "XSD_INCLUDE_NAMESPACE_MISMATCH",
|
|
@@ -189,6 +202,7 @@ var UssXsdEngine = (() => {
|
|
|
189
202
|
},
|
|
190
203
|
importedSchemas: [],
|
|
191
204
|
roots: [],
|
|
205
|
+
identityConstraints: [],
|
|
192
206
|
references: {
|
|
193
207
|
types: [],
|
|
194
208
|
refs: [],
|
|
@@ -220,7 +234,7 @@ var UssXsdEngine = (() => {
|
|
|
220
234
|
function createElementDecl({
|
|
221
235
|
name = null,
|
|
222
236
|
qName = null,
|
|
223
|
-
namespaceUri:
|
|
237
|
+
namespaceUri: namespaceUri4 = null,
|
|
224
238
|
typeName = null,
|
|
225
239
|
refName = null,
|
|
226
240
|
inlineType = null,
|
|
@@ -229,6 +243,7 @@ var UssXsdEngine = (() => {
|
|
|
229
243
|
defaultValue = null,
|
|
230
244
|
fixedValue = null,
|
|
231
245
|
nillable = false,
|
|
246
|
+
identityConstraints = [],
|
|
232
247
|
line = null,
|
|
233
248
|
column = null,
|
|
234
249
|
path = null
|
|
@@ -237,7 +252,7 @@ var UssXsdEngine = (() => {
|
|
|
237
252
|
kind: "element",
|
|
238
253
|
name,
|
|
239
254
|
qName,
|
|
240
|
-
namespaceUri:
|
|
255
|
+
namespaceUri: namespaceUri4,
|
|
241
256
|
typeName,
|
|
242
257
|
refName,
|
|
243
258
|
inlineType,
|
|
@@ -246,6 +261,7 @@ var UssXsdEngine = (() => {
|
|
|
246
261
|
defaultValue,
|
|
247
262
|
fixedValue,
|
|
248
263
|
nillable,
|
|
264
|
+
identityConstraints,
|
|
249
265
|
line,
|
|
250
266
|
column,
|
|
251
267
|
path
|
|
@@ -254,7 +270,7 @@ var UssXsdEngine = (() => {
|
|
|
254
270
|
function createAttributeDecl({
|
|
255
271
|
name = null,
|
|
256
272
|
qName = null,
|
|
257
|
-
namespaceUri:
|
|
273
|
+
namespaceUri: namespaceUri4 = null,
|
|
258
274
|
typeName = null,
|
|
259
275
|
refName = null,
|
|
260
276
|
inlineType = null,
|
|
@@ -269,7 +285,7 @@ var UssXsdEngine = (() => {
|
|
|
269
285
|
kind: "attribute",
|
|
270
286
|
name,
|
|
271
287
|
qName,
|
|
272
|
-
namespaceUri:
|
|
288
|
+
namespaceUri: namespaceUri4,
|
|
273
289
|
typeName,
|
|
274
290
|
refName,
|
|
275
291
|
inlineType,
|
|
@@ -284,13 +300,14 @@ var UssXsdEngine = (() => {
|
|
|
284
300
|
function createComplexTypeDecl({
|
|
285
301
|
name = null,
|
|
286
302
|
qName = null,
|
|
287
|
-
namespaceUri:
|
|
303
|
+
namespaceUri: namespaceUri4 = null,
|
|
288
304
|
content = null,
|
|
289
305
|
attributes = [],
|
|
290
306
|
derivation = { kind: null, baseTypeName: null },
|
|
291
307
|
contentModel = "complex",
|
|
292
308
|
mixed = false,
|
|
293
309
|
abstract = false,
|
|
310
|
+
identityConstraints = [],
|
|
294
311
|
line = null,
|
|
295
312
|
column = null,
|
|
296
313
|
path = null
|
|
@@ -299,13 +316,14 @@ var UssXsdEngine = (() => {
|
|
|
299
316
|
kind: "complexType",
|
|
300
317
|
name,
|
|
301
318
|
qName,
|
|
302
|
-
namespaceUri:
|
|
319
|
+
namespaceUri: namespaceUri4,
|
|
303
320
|
content,
|
|
304
321
|
attributes,
|
|
305
322
|
derivation,
|
|
306
323
|
contentModel,
|
|
307
324
|
mixed,
|
|
308
325
|
abstract,
|
|
326
|
+
identityConstraints,
|
|
309
327
|
line,
|
|
310
328
|
column,
|
|
311
329
|
path
|
|
@@ -314,7 +332,7 @@ var UssXsdEngine = (() => {
|
|
|
314
332
|
function createSimpleTypeDecl({
|
|
315
333
|
name = null,
|
|
316
334
|
qName = null,
|
|
317
|
-
namespaceUri:
|
|
335
|
+
namespaceUri: namespaceUri4 = null,
|
|
318
336
|
baseTypeName = null,
|
|
319
337
|
facets = {},
|
|
320
338
|
enumerations = [],
|
|
@@ -326,7 +344,7 @@ var UssXsdEngine = (() => {
|
|
|
326
344
|
kind: "simpleType",
|
|
327
345
|
name,
|
|
328
346
|
qName,
|
|
329
|
-
namespaceUri:
|
|
347
|
+
namespaceUri: namespaceUri4,
|
|
330
348
|
baseTypeName,
|
|
331
349
|
facets,
|
|
332
350
|
enumerations,
|
|
@@ -338,7 +356,7 @@ var UssXsdEngine = (() => {
|
|
|
338
356
|
function createGroupDecl({
|
|
339
357
|
name,
|
|
340
358
|
qName = null,
|
|
341
|
-
namespaceUri:
|
|
359
|
+
namespaceUri: namespaceUri4 = null,
|
|
342
360
|
content = null,
|
|
343
361
|
line = null,
|
|
344
362
|
column = null,
|
|
@@ -348,7 +366,7 @@ var UssXsdEngine = (() => {
|
|
|
348
366
|
kind: "group",
|
|
349
367
|
name,
|
|
350
368
|
qName,
|
|
351
|
-
namespaceUri:
|
|
369
|
+
namespaceUri: namespaceUri4,
|
|
352
370
|
content,
|
|
353
371
|
line,
|
|
354
372
|
column,
|
|
@@ -358,7 +376,7 @@ var UssXsdEngine = (() => {
|
|
|
358
376
|
function createAttributeGroupDecl({
|
|
359
377
|
name,
|
|
360
378
|
qName = null,
|
|
361
|
-
namespaceUri:
|
|
379
|
+
namespaceUri: namespaceUri4 = null,
|
|
362
380
|
attributes = [],
|
|
363
381
|
line = null,
|
|
364
382
|
column = null,
|
|
@@ -368,7 +386,7 @@ var UssXsdEngine = (() => {
|
|
|
368
386
|
kind: "attributeGroup",
|
|
369
387
|
name,
|
|
370
388
|
qName,
|
|
371
|
-
namespaceUri:
|
|
389
|
+
namespaceUri: namespaceUri4,
|
|
372
390
|
attributes,
|
|
373
391
|
line,
|
|
374
392
|
column,
|
|
@@ -389,6 +407,37 @@ var UssXsdEngine = (() => {
|
|
|
389
407
|
path
|
|
390
408
|
};
|
|
391
409
|
}
|
|
410
|
+
function createIdentityConstraint({
|
|
411
|
+
kind = null,
|
|
412
|
+
name = null,
|
|
413
|
+
qName = null,
|
|
414
|
+
namespaceUri: namespaceUri4 = null,
|
|
415
|
+
selector = null,
|
|
416
|
+
fields = [],
|
|
417
|
+
refer = null,
|
|
418
|
+
ownerName = null,
|
|
419
|
+
ownerNamespaceUri = null,
|
|
420
|
+
ownerPath = null,
|
|
421
|
+
line = null,
|
|
422
|
+
column = null,
|
|
423
|
+
path = null
|
|
424
|
+
} = {}) {
|
|
425
|
+
return {
|
|
426
|
+
kind,
|
|
427
|
+
name,
|
|
428
|
+
qName,
|
|
429
|
+
namespaceUri: namespaceUri4,
|
|
430
|
+
selector,
|
|
431
|
+
fields,
|
|
432
|
+
refer,
|
|
433
|
+
ownerName,
|
|
434
|
+
ownerNamespaceUri,
|
|
435
|
+
ownerPath,
|
|
436
|
+
line,
|
|
437
|
+
column,
|
|
438
|
+
path
|
|
439
|
+
};
|
|
440
|
+
}
|
|
392
441
|
function createSequenceNode({
|
|
393
442
|
children = [],
|
|
394
443
|
minOccurs = 1,
|
|
@@ -463,9 +512,11 @@ var UssXsdEngine = (() => {
|
|
|
463
512
|
}
|
|
464
513
|
function createAnyNode({
|
|
465
514
|
namespace = null,
|
|
466
|
-
processContents =
|
|
515
|
+
processContents = "strict",
|
|
467
516
|
minOccurs = 1,
|
|
468
517
|
maxOccurs = 1,
|
|
518
|
+
notNamespace = [],
|
|
519
|
+
notQName = [],
|
|
469
520
|
line = null,
|
|
470
521
|
column = null,
|
|
471
522
|
path = null
|
|
@@ -473,9 +524,31 @@ var UssXsdEngine = (() => {
|
|
|
473
524
|
return {
|
|
474
525
|
kind: "any",
|
|
475
526
|
namespace,
|
|
476
|
-
processContents,
|
|
527
|
+
processContents: processContents || "strict",
|
|
477
528
|
minOccurs,
|
|
478
529
|
maxOccurs,
|
|
530
|
+
notNamespace,
|
|
531
|
+
notQName,
|
|
532
|
+
line,
|
|
533
|
+
column,
|
|
534
|
+
path
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function createAnyAttributeNode({
|
|
538
|
+
namespace = null,
|
|
539
|
+
processContents = "strict",
|
|
540
|
+
notNamespace = [],
|
|
541
|
+
notQName = [],
|
|
542
|
+
line = null,
|
|
543
|
+
column = null,
|
|
544
|
+
path = null
|
|
545
|
+
} = {}) {
|
|
546
|
+
return {
|
|
547
|
+
kind: "anyAttribute",
|
|
548
|
+
namespace,
|
|
549
|
+
processContents: processContents || "strict",
|
|
550
|
+
notNamespace,
|
|
551
|
+
notQName,
|
|
479
552
|
line,
|
|
480
553
|
column,
|
|
481
554
|
path
|
|
@@ -560,8 +633,8 @@ var UssXsdEngine = (() => {
|
|
|
560
633
|
namespaceUri: resolveNamespaceUri(schema, parsed.prefix)
|
|
561
634
|
};
|
|
562
635
|
}
|
|
563
|
-
function makeLookupKey(
|
|
564
|
-
return `${
|
|
636
|
+
function makeLookupKey(namespaceUri4, localName4) {
|
|
637
|
+
return `${namespaceUri4 || ""}::${localName4 || ""}`;
|
|
565
638
|
}
|
|
566
639
|
function isBuiltinType(typeName, schema = null) {
|
|
567
640
|
const q = parseQName(typeName);
|
|
@@ -577,41 +650,41 @@ var UssXsdEngine = (() => {
|
|
|
577
650
|
function getLocalName(name) {
|
|
578
651
|
return parseQName(name).localName;
|
|
579
652
|
}
|
|
580
|
-
function lookupBucketByNamespace(bucket,
|
|
581
|
-
if (!bucket || !
|
|
582
|
-
return bucket[makeLookupKey(
|
|
653
|
+
function lookupBucketByNamespace(bucket, namespaceUri4, localName4) {
|
|
654
|
+
if (!bucket || !localName4) return null;
|
|
655
|
+
return bucket[makeLookupKey(namespaceUri4, localName4)] || null;
|
|
583
656
|
}
|
|
584
|
-
function lookupInSchemaBucket(bucketName, schema,
|
|
585
|
-
return lookupBucketByNamespace(schema?.globals?.[bucketName],
|
|
657
|
+
function lookupInSchemaBucket(bucketName, schema, namespaceUri4, localName4) {
|
|
658
|
+
return lookupBucketByNamespace(schema?.globals?.[bucketName], namespaceUri4, localName4);
|
|
586
659
|
}
|
|
587
|
-
function lookupInImportedSchemas(bucketName, schema,
|
|
588
|
-
if (!schema || !
|
|
660
|
+
function lookupInImportedSchemas(bucketName, schema, namespaceUri4, localName4, visited = /* @__PURE__ */ new Set()) {
|
|
661
|
+
if (!schema || !namespaceUri4) return null;
|
|
589
662
|
if (visited.has(schema)) return null;
|
|
590
663
|
visited.add(schema);
|
|
591
664
|
for (const importedSchema of schema.importedSchemas || []) {
|
|
592
665
|
if (!importedSchema) continue;
|
|
593
|
-
if ((importedSchema.targetNamespace || null) ===
|
|
666
|
+
if ((importedSchema.targetNamespace || null) === namespaceUri4) {
|
|
594
667
|
const direct = lookupInSchemaBucket(
|
|
595
668
|
bucketName,
|
|
596
669
|
importedSchema,
|
|
597
|
-
|
|
598
|
-
|
|
670
|
+
namespaceUri4,
|
|
671
|
+
localName4
|
|
599
672
|
);
|
|
600
673
|
if (direct) return direct;
|
|
601
674
|
}
|
|
602
675
|
const nested = lookupInImportedSchemas(
|
|
603
676
|
bucketName,
|
|
604
677
|
importedSchema,
|
|
605
|
-
|
|
606
|
-
|
|
678
|
+
namespaceUri4,
|
|
679
|
+
localName4,
|
|
607
680
|
visited
|
|
608
681
|
);
|
|
609
682
|
if (nested) return nested;
|
|
610
683
|
}
|
|
611
684
|
return null;
|
|
612
685
|
}
|
|
613
|
-
function lookupInImportedSchemasForUnprefixed(bucketName, schema,
|
|
614
|
-
if (!schema || !
|
|
686
|
+
function lookupInImportedSchemasForUnprefixed(bucketName, schema, localName4, visited = /* @__PURE__ */ new Set()) {
|
|
687
|
+
if (!schema || !localName4) return null;
|
|
615
688
|
if (visited.has(schema)) return null;
|
|
616
689
|
visited.add(schema);
|
|
617
690
|
const targetNs = schema.targetNamespace || null;
|
|
@@ -623,14 +696,14 @@ var UssXsdEngine = (() => {
|
|
|
623
696
|
bucketName,
|
|
624
697
|
importedSchema,
|
|
625
698
|
importedNs,
|
|
626
|
-
|
|
699
|
+
localName4
|
|
627
700
|
);
|
|
628
701
|
if (direct) return direct;
|
|
629
702
|
}
|
|
630
703
|
const nested = lookupInImportedSchemasForUnprefixed(
|
|
631
704
|
bucketName,
|
|
632
705
|
importedSchema,
|
|
633
|
-
|
|
706
|
+
localName4,
|
|
634
707
|
visited
|
|
635
708
|
);
|
|
636
709
|
if (nested) return nested;
|
|
@@ -641,24 +714,24 @@ var UssXsdEngine = (() => {
|
|
|
641
714
|
if (!schema || !name) return null;
|
|
642
715
|
const parsed = parseQName(name);
|
|
643
716
|
const resolved = resolveQName(schema, name);
|
|
644
|
-
const
|
|
645
|
-
if (!
|
|
717
|
+
const localName4 = resolved.localName;
|
|
718
|
+
if (!localName4) return null;
|
|
646
719
|
if (parsed.prefix) {
|
|
647
720
|
const direct = lookupInSchemaBucket(
|
|
648
721
|
bucketName,
|
|
649
722
|
schema,
|
|
650
723
|
resolved.namespaceUri,
|
|
651
|
-
|
|
724
|
+
localName4
|
|
652
725
|
);
|
|
653
726
|
if (direct) return direct;
|
|
654
727
|
return lookupInImportedSchemas(
|
|
655
728
|
bucketName,
|
|
656
729
|
schema,
|
|
657
730
|
resolved.namespaceUri,
|
|
658
|
-
|
|
731
|
+
localName4
|
|
659
732
|
);
|
|
660
733
|
}
|
|
661
|
-
const noNamespace = lookupInSchemaBucket(bucketName, schema, null,
|
|
734
|
+
const noNamespace = lookupInSchemaBucket(bucketName, schema, null, localName4);
|
|
662
735
|
if (noNamespace) return noNamespace;
|
|
663
736
|
const sameSchemaNs = schema.targetNamespace || null;
|
|
664
737
|
if (sameSchemaNs !== null) {
|
|
@@ -666,13 +739,13 @@ var UssXsdEngine = (() => {
|
|
|
666
739
|
bucketName,
|
|
667
740
|
schema,
|
|
668
741
|
sameSchemaNs,
|
|
669
|
-
|
|
742
|
+
localName4
|
|
670
743
|
);
|
|
671
744
|
if (hostNamespaceDecl) return hostNamespaceDecl;
|
|
672
745
|
const importedSameNamespaceDecl = lookupInImportedSchemasForUnprefixed(
|
|
673
746
|
bucketName,
|
|
674
747
|
schema,
|
|
675
|
-
|
|
748
|
+
localName4
|
|
676
749
|
);
|
|
677
750
|
if (importedSameNamespaceDecl) return importedSameNamespaceDecl;
|
|
678
751
|
}
|
|
@@ -800,11 +873,6 @@ var UssXsdEngine = (() => {
|
|
|
800
873
|
|
|
801
874
|
// src/parser/buildSchemaModel.js
|
|
802
875
|
var UNSUPPORTED_NODE_FEATURES = /* @__PURE__ */ new Set([
|
|
803
|
-
"key",
|
|
804
|
-
"keyref",
|
|
805
|
-
"unique",
|
|
806
|
-
"any",
|
|
807
|
-
"anyAttribute",
|
|
808
876
|
"redefine",
|
|
809
877
|
"notation"
|
|
810
878
|
]);
|
|
@@ -867,6 +935,9 @@ var UssXsdEngine = (() => {
|
|
|
867
935
|
...sourceSchema.externalRefs.imports || []
|
|
868
936
|
);
|
|
869
937
|
targetSchema.importedSchemas.push(...sourceSchema.importedSchemas || []);
|
|
938
|
+
targetSchema.identityConstraints.push(
|
|
939
|
+
...sourceSchema.identityConstraints || []
|
|
940
|
+
);
|
|
870
941
|
for (const feature of sourceSchema.usedFeatures || []) {
|
|
871
942
|
targetSchema.usedFeatures.add(feature);
|
|
872
943
|
}
|
|
@@ -919,17 +990,17 @@ var UssXsdEngine = (() => {
|
|
|
919
990
|
}
|
|
920
991
|
function locateNodeInSource(xsdText, lineStarts, node) {
|
|
921
992
|
if (!xsdText || !node) return { line: null, column: null };
|
|
922
|
-
const
|
|
993
|
+
const localName4 = node.localName;
|
|
923
994
|
const name = node.getAttribute("name");
|
|
924
995
|
const ref = node.getAttribute("ref");
|
|
925
996
|
const base = node.getAttribute("base");
|
|
926
997
|
const type = node.getAttribute("type");
|
|
927
998
|
const candidates = [
|
|
928
|
-
name ? `<(?:[\\w.-]+:)?${escapeRegExp(
|
|
929
|
-
ref ? `<(?:[\\w.-]+:)?${escapeRegExp(
|
|
930
|
-
base ? `<(?:[\\w.-]+:)?${escapeRegExp(
|
|
931
|
-
type ? `<(?:[\\w.-]+:)?${escapeRegExp(
|
|
932
|
-
`<(?:[\\w.-]+:)?${escapeRegExp(
|
|
999
|
+
name ? `<(?:[\\w.-]+:)?${escapeRegExp(localName4)}\\b[^>]*\\bname=(["'])${escapeRegExp(name)}\\1` : null,
|
|
1000
|
+
ref ? `<(?:[\\w.-]+:)?${escapeRegExp(localName4)}\\b[^>]*\\bref=(["'])${escapeRegExp(ref)}\\1` : null,
|
|
1001
|
+
base ? `<(?:[\\w.-]+:)?${escapeRegExp(localName4)}\\b[^>]*\\bbase=(["'])${escapeRegExp(base)}\\1` : null,
|
|
1002
|
+
type ? `<(?:[\\w.-]+:)?${escapeRegExp(localName4)}\\b[^>]*\\btype=(["'])${escapeRegExp(type)}\\1` : null,
|
|
1003
|
+
`<(?:[\\w.-]+:)?${escapeRegExp(localName4)}\\b`
|
|
933
1004
|
].filter(Boolean);
|
|
934
1005
|
for (const pattern of candidates) {
|
|
935
1006
|
const regex = new RegExp(pattern, "m");
|
|
@@ -952,9 +1023,9 @@ var UssXsdEngine = (() => {
|
|
|
952
1023
|
return `${parentPath}/${kind}${qualifier}`;
|
|
953
1024
|
}
|
|
954
1025
|
function registerGlobal(schema, issues, bucketName, duplicateCode, decl) {
|
|
955
|
-
const
|
|
956
|
-
if (!
|
|
957
|
-
const key = makeLookupKey(decl.namespaceUri,
|
|
1026
|
+
const localName4 = stripNamespacePrefix(decl.name);
|
|
1027
|
+
if (!localName4) return;
|
|
1028
|
+
const key = makeLookupKey(decl.namespaceUri, localName4);
|
|
958
1029
|
if (schema.globals[bucketName][key]) {
|
|
959
1030
|
issues.push(
|
|
960
1031
|
createIssue({
|
|
@@ -981,15 +1052,15 @@ var UssXsdEngine = (() => {
|
|
|
981
1052
|
schema.unsupportedFeatures.push(feature);
|
|
982
1053
|
}
|
|
983
1054
|
function collectNodeDiagnostics(schema, issues, node, path, loc) {
|
|
984
|
-
const
|
|
985
|
-
schema.usedFeatures.add(
|
|
986
|
-
if (UNSUPPORTED_NODE_FEATURES.has(
|
|
1055
|
+
const localName4 = node.localName;
|
|
1056
|
+
schema.usedFeatures.add(localName4);
|
|
1057
|
+
if (UNSUPPORTED_NODE_FEATURES.has(localName4)) {
|
|
987
1058
|
collectUnsupportedFeature(schema, {
|
|
988
|
-
feature: `xs:${
|
|
1059
|
+
feature: `xs:${localName4}`,
|
|
989
1060
|
line: loc.line,
|
|
990
1061
|
column: loc.column,
|
|
991
1062
|
path,
|
|
992
|
-
nodeKind:
|
|
1063
|
+
nodeKind: localName4,
|
|
993
1064
|
name: node.getAttribute("name") || null
|
|
994
1065
|
});
|
|
995
1066
|
}
|
|
@@ -999,7 +1070,7 @@ var UssXsdEngine = (() => {
|
|
|
999
1070
|
line: loc.line,
|
|
1000
1071
|
column: loc.column,
|
|
1001
1072
|
path,
|
|
1002
|
-
nodeKind:
|
|
1073
|
+
nodeKind: localName4,
|
|
1003
1074
|
name: node.getAttribute("name") || null
|
|
1004
1075
|
});
|
|
1005
1076
|
}
|
|
@@ -1009,47 +1080,47 @@ var UssXsdEngine = (() => {
|
|
|
1009
1080
|
line: loc.line,
|
|
1010
1081
|
column: loc.column,
|
|
1011
1082
|
path,
|
|
1012
|
-
nodeKind:
|
|
1083
|
+
nodeKind: localName4,
|
|
1013
1084
|
name: node.getAttribute("name") || node.getAttribute("ref") || null
|
|
1014
1085
|
});
|
|
1015
1086
|
}
|
|
1016
|
-
if ((
|
|
1087
|
+
if ((localName4 === "element" || localName4 === "attribute") && node.hasAttribute("ref")) {
|
|
1017
1088
|
collectReference(schema, "refs", {
|
|
1018
1089
|
refName: node.getAttribute("ref"),
|
|
1019
1090
|
line: loc.line,
|
|
1020
1091
|
column: loc.column,
|
|
1021
1092
|
path,
|
|
1022
|
-
nodeKind:
|
|
1093
|
+
nodeKind: localName4,
|
|
1023
1094
|
name: node.getAttribute("name") || null
|
|
1024
1095
|
});
|
|
1025
1096
|
}
|
|
1026
|
-
if ((
|
|
1097
|
+
if ((localName4 === "extension" || localName4 === "restriction") && node.hasAttribute("base")) {
|
|
1027
1098
|
collectReference(schema, "baseTypes", {
|
|
1028
1099
|
baseTypeName: node.getAttribute("base"),
|
|
1029
1100
|
line: loc.line,
|
|
1030
1101
|
column: loc.column,
|
|
1031
1102
|
path,
|
|
1032
|
-
nodeKind:
|
|
1103
|
+
nodeKind: localName4,
|
|
1033
1104
|
name: node.getAttribute("name") || null
|
|
1034
1105
|
});
|
|
1035
1106
|
}
|
|
1036
|
-
if (
|
|
1107
|
+
if (localName4 === "group" && node.hasAttribute("ref")) {
|
|
1037
1108
|
collectReference(schema, "groupRefs", {
|
|
1038
1109
|
refName: node.getAttribute("ref"),
|
|
1039
1110
|
line: loc.line,
|
|
1040
1111
|
column: loc.column,
|
|
1041
1112
|
path,
|
|
1042
|
-
nodeKind:
|
|
1113
|
+
nodeKind: localName4,
|
|
1043
1114
|
name: node.getAttribute("name") || null
|
|
1044
1115
|
});
|
|
1045
1116
|
}
|
|
1046
|
-
if (
|
|
1117
|
+
if (localName4 === "attributeGroup" && node.hasAttribute("ref")) {
|
|
1047
1118
|
collectReference(schema, "attributeGroupRefs", {
|
|
1048
1119
|
refName: node.getAttribute("ref"),
|
|
1049
1120
|
line: loc.line,
|
|
1050
1121
|
column: loc.column,
|
|
1051
1122
|
path,
|
|
1052
|
-
nodeKind:
|
|
1123
|
+
nodeKind: localName4,
|
|
1053
1124
|
name: node.getAttribute("name") || null
|
|
1054
1125
|
});
|
|
1055
1126
|
}
|
|
@@ -1065,13 +1136,13 @@ var UssXsdEngine = (() => {
|
|
|
1065
1136
|
column: loc.column,
|
|
1066
1137
|
path,
|
|
1067
1138
|
source: "xsd",
|
|
1068
|
-
nodeKind:
|
|
1139
|
+
nodeKind: localName4,
|
|
1069
1140
|
name: node.getAttribute("name") || null,
|
|
1070
1141
|
details: { minOccurs, maxOccurs }
|
|
1071
1142
|
})
|
|
1072
1143
|
);
|
|
1073
1144
|
}
|
|
1074
|
-
if ((
|
|
1145
|
+
if ((localName4 === "element" || localName4 === "attribute") && node.hasAttribute("default") && node.hasAttribute("fixed")) {
|
|
1075
1146
|
issues.push(
|
|
1076
1147
|
createIssue({
|
|
1077
1148
|
code: ISSUE_CODES.INVALID_DEFAULT_FIXED_COMBINATION,
|
|
@@ -1081,7 +1152,7 @@ var UssXsdEngine = (() => {
|
|
|
1081
1152
|
column: loc.column,
|
|
1082
1153
|
path,
|
|
1083
1154
|
source: "xsd",
|
|
1084
|
-
nodeKind:
|
|
1155
|
+
nodeKind: localName4,
|
|
1085
1156
|
name: node.getAttribute("name") || node.getAttribute("ref") || null,
|
|
1086
1157
|
details: {
|
|
1087
1158
|
defaultValue: node.getAttribute("default"),
|
|
@@ -1162,11 +1233,11 @@ var UssXsdEngine = (() => {
|
|
|
1162
1233
|
enumerations = parsed.enumerations;
|
|
1163
1234
|
}
|
|
1164
1235
|
const qName = node.getAttribute("name");
|
|
1165
|
-
const
|
|
1236
|
+
const namespaceUri4 = schema.targetNamespace || null;
|
|
1166
1237
|
return createSimpleTypeDecl({
|
|
1167
1238
|
name: qName ? parseQName(qName).localName : null,
|
|
1168
1239
|
qName,
|
|
1169
|
-
namespaceUri:
|
|
1240
|
+
namespaceUri: namespaceUri4,
|
|
1170
1241
|
baseTypeName,
|
|
1171
1242
|
facets,
|
|
1172
1243
|
enumerations,
|
|
@@ -1191,11 +1262,11 @@ var UssXsdEngine = (() => {
|
|
|
1191
1262
|
issues
|
|
1192
1263
|
) : null;
|
|
1193
1264
|
const qName = node.getAttribute("name");
|
|
1194
|
-
const
|
|
1265
|
+
const namespaceUri4 = getDeclarationNamespaceUri(schema, node, "attribute");
|
|
1195
1266
|
return createAttributeDecl({
|
|
1196
1267
|
name: qName ? parseQName(qName).localName : null,
|
|
1197
1268
|
qName,
|
|
1198
|
-
namespaceUri:
|
|
1269
|
+
namespaceUri: namespaceUri4,
|
|
1199
1270
|
typeName: node.getAttribute("type"),
|
|
1200
1271
|
refName: node.getAttribute("ref"),
|
|
1201
1272
|
inlineType,
|
|
@@ -1236,6 +1307,10 @@ var UssXsdEngine = (() => {
|
|
|
1236
1307
|
issues
|
|
1237
1308
|
)
|
|
1238
1309
|
);
|
|
1310
|
+
} else if (child.localName === "anyAttribute") {
|
|
1311
|
+
attributes.push(
|
|
1312
|
+
parseAnyAttribute(child, xsdText, lineStarts, parentPath, schema, issues)
|
|
1313
|
+
);
|
|
1239
1314
|
}
|
|
1240
1315
|
}
|
|
1241
1316
|
return attributes;
|
|
@@ -1272,11 +1347,26 @@ var UssXsdEngine = (() => {
|
|
|
1272
1347
|
);
|
|
1273
1348
|
}
|
|
1274
1349
|
const qName = node.getAttribute("name");
|
|
1275
|
-
const
|
|
1350
|
+
const namespaceUri4 = getDeclarationNamespaceUri(schema, node, "element");
|
|
1351
|
+
const identityConstraints = children.filter(
|
|
1352
|
+
(child) => ["key", "keyref", "unique"].includes(child.localName)
|
|
1353
|
+
).map(
|
|
1354
|
+
(child) => parseIdentityConstraint(
|
|
1355
|
+
child,
|
|
1356
|
+
xsdText,
|
|
1357
|
+
lineStarts,
|
|
1358
|
+
path,
|
|
1359
|
+
schema,
|
|
1360
|
+
issues,
|
|
1361
|
+
qName ? parseQName(qName).localName : null,
|
|
1362
|
+
namespaceUri4,
|
|
1363
|
+
path
|
|
1364
|
+
)
|
|
1365
|
+
);
|
|
1276
1366
|
return createElementDecl({
|
|
1277
1367
|
name: qName ? parseQName(qName).localName : null,
|
|
1278
1368
|
qName,
|
|
1279
|
-
namespaceUri:
|
|
1369
|
+
namespaceUri: namespaceUri4,
|
|
1280
1370
|
typeName: node.getAttribute("type"),
|
|
1281
1371
|
refName: node.getAttribute("ref"),
|
|
1282
1372
|
inlineType,
|
|
@@ -1285,6 +1375,7 @@ var UssXsdEngine = (() => {
|
|
|
1285
1375
|
defaultValue: node.getAttribute("default"),
|
|
1286
1376
|
fixedValue: node.getAttribute("fixed"),
|
|
1287
1377
|
nillable: node.getAttribute("nillable") === "true",
|
|
1378
|
+
identityConstraints,
|
|
1288
1379
|
line: loc.line,
|
|
1289
1380
|
column: loc.column,
|
|
1290
1381
|
path
|
|
@@ -1303,20 +1394,101 @@ var UssXsdEngine = (() => {
|
|
|
1303
1394
|
path
|
|
1304
1395
|
});
|
|
1305
1396
|
}
|
|
1397
|
+
function parseWildcardNamespace(namespaceStr) {
|
|
1398
|
+
if (!namespaceStr) return null;
|
|
1399
|
+
const trimmed = namespaceStr.trim();
|
|
1400
|
+
if (!trimmed) return null;
|
|
1401
|
+
if (trimmed.includes(" ")) {
|
|
1402
|
+
return trimmed.split(/\s+/).filter((ns) => ns);
|
|
1403
|
+
}
|
|
1404
|
+
return trimmed;
|
|
1405
|
+
}
|
|
1406
|
+
function parseNotNamespace(notNamespaceStr) {
|
|
1407
|
+
if (!notNamespaceStr) return [];
|
|
1408
|
+
const trimmed = notNamespaceStr.trim();
|
|
1409
|
+
if (!trimmed) return [];
|
|
1410
|
+
if (trimmed.includes(" ")) {
|
|
1411
|
+
return trimmed.split(/\s+/).filter((ns) => ns);
|
|
1412
|
+
}
|
|
1413
|
+
return [trimmed];
|
|
1414
|
+
}
|
|
1415
|
+
function parseNotQName(notQNameStr) {
|
|
1416
|
+
if (!notQNameStr) return [];
|
|
1417
|
+
const trimmed = notQNameStr.trim();
|
|
1418
|
+
if (!trimmed) return [];
|
|
1419
|
+
if (trimmed.includes(" ")) {
|
|
1420
|
+
return trimmed.split(/\s+/).filter((qn) => qn);
|
|
1421
|
+
}
|
|
1422
|
+
return [trimmed];
|
|
1423
|
+
}
|
|
1306
1424
|
function parseAny(node, xsdText, lineStarts, parentPath, schema, issues) {
|
|
1307
1425
|
const path = buildPath(parentPath, node);
|
|
1308
1426
|
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
1309
1427
|
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1310
1428
|
return createAnyNode({
|
|
1311
|
-
namespace: node.getAttribute("namespace"),
|
|
1429
|
+
namespace: parseWildcardNamespace(node.getAttribute("namespace")),
|
|
1312
1430
|
processContents: node.getAttribute("processContents"),
|
|
1313
1431
|
minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
|
|
1314
1432
|
maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
|
|
1433
|
+
notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
|
|
1434
|
+
notQName: parseNotQName(node.getAttribute("notQName")),
|
|
1315
1435
|
line: loc.line,
|
|
1316
1436
|
column: loc.column,
|
|
1317
1437
|
path
|
|
1318
1438
|
});
|
|
1319
1439
|
}
|
|
1440
|
+
function parseAnyAttribute(node, xsdText, lineStarts, parentPath, schema, issues) {
|
|
1441
|
+
const path = buildPath(parentPath, node);
|
|
1442
|
+
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
1443
|
+
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1444
|
+
return createAnyAttributeNode({
|
|
1445
|
+
namespace: parseWildcardNamespace(node.getAttribute("namespace")),
|
|
1446
|
+
processContents: node.getAttribute("processContents"),
|
|
1447
|
+
notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
|
|
1448
|
+
notQName: parseNotQName(node.getAttribute("notQName")),
|
|
1449
|
+
line: loc.line,
|
|
1450
|
+
column: loc.column,
|
|
1451
|
+
path
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
function parseIdentityConstraint(node, xsdText, lineStarts, parentPath, schema, issues, ownerName, ownerNamespaceUri, ownerPath) {
|
|
1455
|
+
const path = buildPath(parentPath, node);
|
|
1456
|
+
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
1457
|
+
collectNodeDiagnostics(schema, issues, node, path, loc);
|
|
1458
|
+
const selectorNode = elementChildren(node).find(
|
|
1459
|
+
(child) => child.localName === "selector"
|
|
1460
|
+
);
|
|
1461
|
+
const selector = selectorNode ? {
|
|
1462
|
+
xpath: selectorNode.getAttribute("xpath"),
|
|
1463
|
+
path: buildPath(path, selectorNode)
|
|
1464
|
+
} : null;
|
|
1465
|
+
const fields = elementChildren(node).filter((child) => child.localName === "field").map((child) => ({
|
|
1466
|
+
xpath: child.getAttribute("xpath"),
|
|
1467
|
+
line: locateNodeInSource(xsdText, lineStarts, child).line,
|
|
1468
|
+
column: locateNodeInSource(xsdText, lineStarts, child).column,
|
|
1469
|
+
path: buildPath(path, child)
|
|
1470
|
+
})).filter((field) => field.xpath != null);
|
|
1471
|
+
const qName = node.getAttribute("name");
|
|
1472
|
+
const name = qName ? parseQName(qName).localName : null;
|
|
1473
|
+
const namespaceUri4 = ownerNamespaceUri || schema.targetNamespace || null;
|
|
1474
|
+
const constraint = createIdentityConstraint({
|
|
1475
|
+
kind: node.localName,
|
|
1476
|
+
name,
|
|
1477
|
+
qName,
|
|
1478
|
+
namespaceUri: namespaceUri4,
|
|
1479
|
+
selector,
|
|
1480
|
+
fields,
|
|
1481
|
+
refer: node.getAttribute("refer"),
|
|
1482
|
+
ownerName,
|
|
1483
|
+
ownerNamespaceUri,
|
|
1484
|
+
ownerPath,
|
|
1485
|
+
line: loc.line,
|
|
1486
|
+
column: loc.column,
|
|
1487
|
+
path
|
|
1488
|
+
});
|
|
1489
|
+
schema.identityConstraints.push(constraint);
|
|
1490
|
+
return constraint;
|
|
1491
|
+
}
|
|
1320
1492
|
function parseContentNode(node, xsdText, lineStarts, parentPath, schema, issues) {
|
|
1321
1493
|
const path = buildPath(parentPath, node);
|
|
1322
1494
|
const loc = locateNodeInSource(xsdText, lineStarts, node);
|
|
@@ -1463,6 +1635,22 @@ var UssXsdEngine = (() => {
|
|
|
1463
1635
|
let derivation = { kind: null, baseTypeName: null };
|
|
1464
1636
|
let contentModel = "complex";
|
|
1465
1637
|
const children = elementChildren(node);
|
|
1638
|
+
const namespaceUri4 = schema.targetNamespace || null;
|
|
1639
|
+
const identityConstraints = children.filter(
|
|
1640
|
+
(child) => ["key", "keyref", "unique"].includes(child.localName)
|
|
1641
|
+
).map(
|
|
1642
|
+
(child) => parseIdentityConstraint(
|
|
1643
|
+
child,
|
|
1644
|
+
xsdText,
|
|
1645
|
+
lineStarts,
|
|
1646
|
+
path,
|
|
1647
|
+
schema,
|
|
1648
|
+
issues,
|
|
1649
|
+
null,
|
|
1650
|
+
namespaceUri4,
|
|
1651
|
+
path
|
|
1652
|
+
)
|
|
1653
|
+
);
|
|
1466
1654
|
const directContentNode = children.find(
|
|
1467
1655
|
(child) => ["sequence", "choice", "all", "group", "element", "any"].includes(
|
|
1468
1656
|
child.localName
|
|
@@ -1522,17 +1710,17 @@ var UssXsdEngine = (() => {
|
|
|
1522
1710
|
);
|
|
1523
1711
|
}
|
|
1524
1712
|
const qName = node.getAttribute("name");
|
|
1525
|
-
const namespaceUri3 = schema.targetNamespace || null;
|
|
1526
1713
|
return createComplexTypeDecl({
|
|
1527
1714
|
name: qName ? parseQName(qName).localName : null,
|
|
1528
1715
|
qName,
|
|
1529
|
-
namespaceUri:
|
|
1716
|
+
namespaceUri: namespaceUri4,
|
|
1530
1717
|
content,
|
|
1531
1718
|
attributes,
|
|
1532
1719
|
derivation,
|
|
1533
1720
|
contentModel,
|
|
1534
1721
|
mixed: node.getAttribute("mixed") === "true",
|
|
1535
1722
|
abstract: node.getAttribute("abstract") === "true",
|
|
1723
|
+
identityConstraints,
|
|
1536
1724
|
line: loc.line,
|
|
1537
1725
|
column: loc.column,
|
|
1538
1726
|
path
|
|
@@ -1546,11 +1734,11 @@ var UssXsdEngine = (() => {
|
|
|
1546
1734
|
(child) => ["sequence", "choice", "all"].includes(child.localName)
|
|
1547
1735
|
);
|
|
1548
1736
|
const qName = node.getAttribute("name");
|
|
1549
|
-
const
|
|
1737
|
+
const namespaceUri4 = schema.targetNamespace || null;
|
|
1550
1738
|
return createGroupDecl({
|
|
1551
1739
|
name: qName ? parseQName(qName).localName : null,
|
|
1552
1740
|
qName,
|
|
1553
|
-
namespaceUri:
|
|
1741
|
+
namespaceUri: namespaceUri4,
|
|
1554
1742
|
content: contentNode ? parseContentNode(contentNode, xsdText, lineStarts, path, schema, issues) : null,
|
|
1555
1743
|
line: loc.line,
|
|
1556
1744
|
column: loc.column,
|
|
@@ -1572,11 +1760,11 @@ var UssXsdEngine = (() => {
|
|
|
1572
1760
|
issues
|
|
1573
1761
|
);
|
|
1574
1762
|
const qName = node.getAttribute("name");
|
|
1575
|
-
const
|
|
1763
|
+
const namespaceUri4 = schema.targetNamespace || null;
|
|
1576
1764
|
return createAttributeGroupDecl({
|
|
1577
1765
|
name: qName ? parseQName(qName).localName : null,
|
|
1578
1766
|
qName,
|
|
1579
|
-
namespaceUri:
|
|
1767
|
+
namespaceUri: namespaceUri4,
|
|
1580
1768
|
attributes,
|
|
1581
1769
|
line: loc.line,
|
|
1582
1770
|
column: loc.column,
|
|
@@ -1680,24 +1868,24 @@ var UssXsdEngine = (() => {
|
|
|
1680
1868
|
}
|
|
1681
1869
|
}
|
|
1682
1870
|
if (ref?.kind === "import" && ref.namespace) {
|
|
1683
|
-
const
|
|
1871
|
+
const namespaceMatches2 = entries.filter((entry) => {
|
|
1684
1872
|
const declaredTargetNamespace = getDeclaredTargetNamespaceFromText(
|
|
1685
1873
|
entry.text
|
|
1686
1874
|
);
|
|
1687
1875
|
return (declaredTargetNamespace || null) === (ref.namespace || null);
|
|
1688
1876
|
});
|
|
1689
|
-
if (
|
|
1877
|
+
if (namespaceMatches2.length === 1) {
|
|
1690
1878
|
return {
|
|
1691
1879
|
kind: "namespace",
|
|
1692
|
-
entry:
|
|
1693
|
-
matches:
|
|
1880
|
+
entry: namespaceMatches2[0],
|
|
1881
|
+
matches: namespaceMatches2
|
|
1694
1882
|
};
|
|
1695
1883
|
}
|
|
1696
|
-
if (
|
|
1884
|
+
if (namespaceMatches2.length > 1) {
|
|
1697
1885
|
return {
|
|
1698
1886
|
kind: "ambiguous-namespace",
|
|
1699
1887
|
entry: null,
|
|
1700
|
-
matches:
|
|
1888
|
+
matches: namespaceMatches2
|
|
1701
1889
|
};
|
|
1702
1890
|
}
|
|
1703
1891
|
}
|
|
@@ -2314,6 +2502,115 @@ var UssXsdEngine = (() => {
|
|
|
2314
2502
|
}
|
|
2315
2503
|
}
|
|
2316
2504
|
}
|
|
2505
|
+
function checkWildcardRestriction(schema, derivedType, baseType, issues) {
|
|
2506
|
+
const derivedContent = getEffectiveContent(schema, derivedType);
|
|
2507
|
+
const baseContent = getEffectiveContent(schema, baseType);
|
|
2508
|
+
const derivedWildcards = [];
|
|
2509
|
+
const baseWildcards = [];
|
|
2510
|
+
function collectWildcards(node, arr) {
|
|
2511
|
+
if (!node) return;
|
|
2512
|
+
if (node.kind === "any") {
|
|
2513
|
+
arr.push(node);
|
|
2514
|
+
return;
|
|
2515
|
+
}
|
|
2516
|
+
if (node.children) {
|
|
2517
|
+
for (const child of asArray(node.children)) {
|
|
2518
|
+
collectWildcards(child, arr);
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
collectWildcards(derivedContent, derivedWildcards);
|
|
2523
|
+
collectWildcards(baseContent, baseWildcards);
|
|
2524
|
+
if (derivedWildcards.length > 0 && baseWildcards.length === 0) {
|
|
2525
|
+
issues.push(
|
|
2526
|
+
buildRestrictionIssue(
|
|
2527
|
+
"XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
|
|
2528
|
+
`Restricted type introduces wildcard elements that base type does not have.`,
|
|
2529
|
+
derivedType
|
|
2530
|
+
)
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
|
|
2534
|
+
const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
|
|
2535
|
+
const derivedHasAnyAttribute = derivedAttrs.some((a) => a?.kind === "anyAttribute");
|
|
2536
|
+
const baseHasAnyAttribute = baseAttrs.some((a) => a?.kind === "anyAttribute");
|
|
2537
|
+
if (derivedHasAnyAttribute && !baseHasAnyAttribute) {
|
|
2538
|
+
issues.push(
|
|
2539
|
+
buildRestrictionIssue(
|
|
2540
|
+
"XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
|
|
2541
|
+
`Restricted type introduces anyAttribute that base type does not have.`,
|
|
2542
|
+
derivedType
|
|
2543
|
+
)
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
function checkOccurrenceCompatibility(derived, base, name) {
|
|
2548
|
+
const dMin = typeof derived.minOccurs === "number" ? derived.minOccurs : 1;
|
|
2549
|
+
const bMin = typeof base.minOccurs === "number" ? base.minOccurs : 1;
|
|
2550
|
+
const dMax = maxToNumber(derived.maxOccurs ?? 1);
|
|
2551
|
+
const bMax = maxToNumber(base.maxOccurs ?? 1);
|
|
2552
|
+
return dMin >= bMin && dMax <= bMax;
|
|
2553
|
+
}
|
|
2554
|
+
function checkComplexContentRestriction(schema, derivedType, baseType, issues) {
|
|
2555
|
+
const derivedContent = getEffectiveContent(schema, derivedType);
|
|
2556
|
+
const baseContent = getEffectiveContent(schema, baseType);
|
|
2557
|
+
if (!derivedContent || !baseContent) return;
|
|
2558
|
+
const derivedFlat = flattenContent(derivedContent, []);
|
|
2559
|
+
const baseFlat = flattenContent(baseContent, []);
|
|
2560
|
+
const baseMap = new Map(baseFlat.map((item) => [item.name, item]));
|
|
2561
|
+
for (const item of derivedFlat) {
|
|
2562
|
+
const baseItem = baseMap.get(item.name);
|
|
2563
|
+
if (!baseItem) {
|
|
2564
|
+
issues.push(
|
|
2565
|
+
buildRestrictionIssue(
|
|
2566
|
+
"XSD_RESTRICTION_NOT_SUBSET",
|
|
2567
|
+
`Restricted type contains element '${item.name}' not in base type.`,
|
|
2568
|
+
item
|
|
2569
|
+
)
|
|
2570
|
+
);
|
|
2571
|
+
continue;
|
|
2572
|
+
}
|
|
2573
|
+
if (!checkOccurrenceCompatibility(item, baseItem, item.name)) {
|
|
2574
|
+
issues.push(
|
|
2575
|
+
buildRestrictionIssue(
|
|
2576
|
+
"XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
|
|
2577
|
+
`Restricted type has incompatible occurrence constraints for '${item.name}'.`,
|
|
2578
|
+
item
|
|
2579
|
+
)
|
|
2580
|
+
);
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
function checkSimpleContentRestriction(schema, derivedType, baseType, issues) {
|
|
2585
|
+
if (baseType.contentModel !== "simple") {
|
|
2586
|
+
issues.push(
|
|
2587
|
+
buildRestrictionIssue(
|
|
2588
|
+
"XSD_RESTRICTION_NOT_SUBSET",
|
|
2589
|
+
`SimpleContent restriction requires base type to have simple content.`,
|
|
2590
|
+
derivedType
|
|
2591
|
+
)
|
|
2592
|
+
);
|
|
2593
|
+
}
|
|
2594
|
+
const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
|
|
2595
|
+
const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
|
|
2596
|
+
const baseAttrMap = new Map(
|
|
2597
|
+
baseAttrs.filter((attr) => attr?.kind === "attribute").map((attr) => [localDeclName(attr), attr])
|
|
2598
|
+
);
|
|
2599
|
+
for (const attr of derivedAttrs) {
|
|
2600
|
+
if (attr?.kind !== "attribute") continue;
|
|
2601
|
+
const name = localDeclName(attr);
|
|
2602
|
+
const baseAttr = baseAttrMap.get(name);
|
|
2603
|
+
if (!baseAttr && !baseAttrs.some((a) => a?.kind === "anyAttribute")) {
|
|
2604
|
+
issues.push(
|
|
2605
|
+
buildRestrictionIssue(
|
|
2606
|
+
"XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
|
|
2607
|
+
`SimpleContent restricted type adds attribute '${name}' not in base type.`,
|
|
2608
|
+
attr
|
|
2609
|
+
)
|
|
2610
|
+
);
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2317
2614
|
function runRestrictionDiagnostics(schema) {
|
|
2318
2615
|
const issues = [];
|
|
2319
2616
|
for (const complexType of Object.values(schema.globals.complexTypes || {})) {
|
|
@@ -2323,6 +2620,12 @@ var UssXsdEngine = (() => {
|
|
|
2323
2620
|
if (!baseType) continue;
|
|
2324
2621
|
checkRestrictedContentSubset(schema, complexType, baseType, issues);
|
|
2325
2622
|
checkRestrictedAttributes(schema, complexType, baseType, issues);
|
|
2623
|
+
checkWildcardRestriction(schema, complexType, baseType, issues);
|
|
2624
|
+
if (complexType.contentModel === "complex" && baseType.contentModel === "complex") {
|
|
2625
|
+
checkComplexContentRestriction(schema, complexType, baseType, issues);
|
|
2626
|
+
} else if (complexType.contentModel === "simple" && baseType.contentModel === "simple") {
|
|
2627
|
+
checkSimpleContentRestriction(schema, complexType, baseType, issues);
|
|
2628
|
+
}
|
|
2326
2629
|
}
|
|
2327
2630
|
return issues;
|
|
2328
2631
|
}
|
|
@@ -2359,6 +2662,188 @@ var UssXsdEngine = (() => {
|
|
|
2359
2662
|
return issues;
|
|
2360
2663
|
}
|
|
2361
2664
|
|
|
2665
|
+
// src/diagnostics/schemaIdentityConstraintDiagnostics.js
|
|
2666
|
+
function isValidConstraintXPath(xpath) {
|
|
2667
|
+
if (!xpath || typeof xpath !== "string") return false;
|
|
2668
|
+
const trimmed = xpath.trim();
|
|
2669
|
+
if (!trimmed) return false;
|
|
2670
|
+
let normalized = trimmed;
|
|
2671
|
+
if (trimmed.startsWith("./")) {
|
|
2672
|
+
if (trimmed.startsWith(".//")) normalized = trimmed.slice(1);
|
|
2673
|
+
else normalized = trimmed.slice(2);
|
|
2674
|
+
}
|
|
2675
|
+
if (normalized.startsWith("/") && !normalized.startsWith("//")) return false;
|
|
2676
|
+
if (normalized.includes("///")) return false;
|
|
2677
|
+
let segments = normalized.split(
|
|
2678
|
+
/\/+/
|
|
2679
|
+
);
|
|
2680
|
+
if (normalized.startsWith("//")) segments = segments.slice(1);
|
|
2681
|
+
if (normalized.endsWith("//")) segments = segments.slice(0, -1);
|
|
2682
|
+
if (segments.some((segment) => segment.length === 0)) return false;
|
|
2683
|
+
for (const segment of segments) {
|
|
2684
|
+
if (segment === ".") continue;
|
|
2685
|
+
if (segment === "*") continue;
|
|
2686
|
+
if (segment.startsWith("@")) {
|
|
2687
|
+
const attrName = segment.slice(1);
|
|
2688
|
+
if (!/^[A-Za-z_][\w.-]*$/.test(attrName)) return false;
|
|
2689
|
+
continue;
|
|
2690
|
+
}
|
|
2691
|
+
const parsed = parseQName(segment);
|
|
2692
|
+
if (!parsed.localName) return false;
|
|
2693
|
+
}
|
|
2694
|
+
return true;
|
|
2695
|
+
}
|
|
2696
|
+
function getConstraintKey(constraint) {
|
|
2697
|
+
return `${constraint.ownerPath || ""}::${constraint.name || ""}`;
|
|
2698
|
+
}
|
|
2699
|
+
function findReferencedKey(schema, refer) {
|
|
2700
|
+
if (!refer) return null;
|
|
2701
|
+
const referName = parseQName(refer).localName;
|
|
2702
|
+
return schema.identityConstraints.find(
|
|
2703
|
+
(constraint) => constraint.kind === "key" && constraint.name === referName
|
|
2704
|
+
);
|
|
2705
|
+
}
|
|
2706
|
+
function runIdentityConstraintDiagnostics(schema) {
|
|
2707
|
+
const issues = [];
|
|
2708
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
2709
|
+
for (const constraint of schema.identityConstraints || []) {
|
|
2710
|
+
const key = getConstraintKey(constraint);
|
|
2711
|
+
if (seenNames.has(key)) {
|
|
2712
|
+
issues.push(
|
|
2713
|
+
createIssue({
|
|
2714
|
+
code: ISSUE_CODES.DUPLICATE_CONSTRAINT_NAME,
|
|
2715
|
+
severity: "error",
|
|
2716
|
+
message: `Duplicate identity constraint name '${constraint.name}' in the same scope.`,
|
|
2717
|
+
line: constraint.line,
|
|
2718
|
+
column: constraint.column,
|
|
2719
|
+
path: constraint.path,
|
|
2720
|
+
source: "xsd",
|
|
2721
|
+
nodeKind: constraint.kind,
|
|
2722
|
+
name: constraint.name,
|
|
2723
|
+
details: {
|
|
2724
|
+
ownerPath: constraint.ownerPath,
|
|
2725
|
+
ownerName: constraint.ownerName
|
|
2726
|
+
}
|
|
2727
|
+
})
|
|
2728
|
+
);
|
|
2729
|
+
} else {
|
|
2730
|
+
seenNames.add(key);
|
|
2731
|
+
}
|
|
2732
|
+
if (!constraint.selector || !constraint.selector.xpath) {
|
|
2733
|
+
issues.push(
|
|
2734
|
+
createIssue({
|
|
2735
|
+
code: ISSUE_CODES.INVALID_CONSTRAINT_SELECTOR,
|
|
2736
|
+
severity: "error",
|
|
2737
|
+
message: `Identity constraint '${constraint.name || constraint.kind}' is missing a selector xpath.`,
|
|
2738
|
+
line: constraint.line,
|
|
2739
|
+
column: constraint.column,
|
|
2740
|
+
path: constraint.path,
|
|
2741
|
+
source: "xsd",
|
|
2742
|
+
nodeKind: constraint.kind,
|
|
2743
|
+
name: constraint.name,
|
|
2744
|
+
details: {
|
|
2745
|
+
ownerPath: constraint.ownerPath,
|
|
2746
|
+
ownerName: constraint.ownerName
|
|
2747
|
+
}
|
|
2748
|
+
})
|
|
2749
|
+
);
|
|
2750
|
+
} else if (!isValidConstraintXPath(constraint.selector.xpath)) {
|
|
2751
|
+
issues.push(
|
|
2752
|
+
createIssue({
|
|
2753
|
+
code: ISSUE_CODES.INVALID_CONSTRAINT_SELECTOR,
|
|
2754
|
+
severity: "error",
|
|
2755
|
+
message: `Invalid selector xpath '${constraint.selector.xpath}'.`,
|
|
2756
|
+
line: constraint.line,
|
|
2757
|
+
column: constraint.column,
|
|
2758
|
+
path: constraint.selector.path,
|
|
2759
|
+
source: "xsd",
|
|
2760
|
+
nodeKind: constraint.kind,
|
|
2761
|
+
name: constraint.name,
|
|
2762
|
+
details: {
|
|
2763
|
+
selector: constraint.selector.xpath,
|
|
2764
|
+
ownerPath: constraint.ownerPath
|
|
2765
|
+
}
|
|
2766
|
+
})
|
|
2767
|
+
);
|
|
2768
|
+
}
|
|
2769
|
+
if (!constraint.fields?.length) {
|
|
2770
|
+
issues.push(
|
|
2771
|
+
createIssue({
|
|
2772
|
+
code: ISSUE_CODES.INVALID_CONSTRAINT_FIELD,
|
|
2773
|
+
severity: "error",
|
|
2774
|
+
message: `Identity constraint '${constraint.name || constraint.kind}' must declare at least one field.`,
|
|
2775
|
+
line: constraint.line,
|
|
2776
|
+
column: constraint.column,
|
|
2777
|
+
path: constraint.path,
|
|
2778
|
+
source: "xsd",
|
|
2779
|
+
nodeKind: constraint.kind,
|
|
2780
|
+
name: constraint.name,
|
|
2781
|
+
details: { ownerPath: constraint.ownerPath }
|
|
2782
|
+
})
|
|
2783
|
+
);
|
|
2784
|
+
} else {
|
|
2785
|
+
for (const field of constraint.fields) {
|
|
2786
|
+
if (!field.xpath || !isValidConstraintXPath(field.xpath)) {
|
|
2787
|
+
issues.push(
|
|
2788
|
+
createIssue({
|
|
2789
|
+
code: ISSUE_CODES.INVALID_CONSTRAINT_FIELD,
|
|
2790
|
+
severity: "error",
|
|
2791
|
+
message: `Invalid field xpath '${field.xpath}'.`,
|
|
2792
|
+
line: field.line,
|
|
2793
|
+
column: field.column,
|
|
2794
|
+
path: field.path,
|
|
2795
|
+
source: "xsd",
|
|
2796
|
+
nodeKind: constraint.kind,
|
|
2797
|
+
name: constraint.name,
|
|
2798
|
+
details: {
|
|
2799
|
+
field: field.xpath,
|
|
2800
|
+
ownerPath: constraint.ownerPath
|
|
2801
|
+
}
|
|
2802
|
+
})
|
|
2803
|
+
);
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
if (constraint.kind === "keyref") {
|
|
2808
|
+
if (!constraint.refer) {
|
|
2809
|
+
issues.push(
|
|
2810
|
+
createIssue({
|
|
2811
|
+
code: ISSUE_CODES.UNKNOWN_KEY_REFERENCE,
|
|
2812
|
+
severity: "error",
|
|
2813
|
+
message: `xs:keyref '${constraint.name || "unnamed"}' is missing a refer attribute.`,
|
|
2814
|
+
line: constraint.line,
|
|
2815
|
+
column: constraint.column,
|
|
2816
|
+
path: constraint.path,
|
|
2817
|
+
source: "xsd",
|
|
2818
|
+
nodeKind: constraint.kind,
|
|
2819
|
+
name: constraint.name,
|
|
2820
|
+
details: { ownerPath: constraint.ownerPath }
|
|
2821
|
+
})
|
|
2822
|
+
);
|
|
2823
|
+
} else if (!findReferencedKey(schema, constraint.refer)) {
|
|
2824
|
+
issues.push(
|
|
2825
|
+
createIssue({
|
|
2826
|
+
code: ISSUE_CODES.UNKNOWN_KEY_REFERENCE,
|
|
2827
|
+
severity: "error",
|
|
2828
|
+
message: `xs:keyref refers to unknown key '${constraint.refer}'.`,
|
|
2829
|
+
line: constraint.line,
|
|
2830
|
+
column: constraint.column,
|
|
2831
|
+
path: constraint.path,
|
|
2832
|
+
source: "xsd",
|
|
2833
|
+
nodeKind: constraint.kind,
|
|
2834
|
+
name: constraint.name,
|
|
2835
|
+
details: {
|
|
2836
|
+
refer: constraint.refer,
|
|
2837
|
+
ownerPath: constraint.ownerPath
|
|
2838
|
+
}
|
|
2839
|
+
})
|
|
2840
|
+
);
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
return issues;
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2362
2847
|
// src/diagnostics/schemaImportDiagnostics.js
|
|
2363
2848
|
function normalizeSchemaPath2(value) {
|
|
2364
2849
|
if (!value || typeof value !== "string") return null;
|
|
@@ -2467,6 +2952,130 @@ var UssXsdEngine = (() => {
|
|
|
2467
2952
|
return issues;
|
|
2468
2953
|
}
|
|
2469
2954
|
|
|
2955
|
+
// src/diagnostics/schemaWildcardDiagnostics.js
|
|
2956
|
+
function validateWildcardNamespace(namespace, path) {
|
|
2957
|
+
if (!namespace) return null;
|
|
2958
|
+
const trimmed = namespace.trim();
|
|
2959
|
+
if (!trimmed) return null;
|
|
2960
|
+
const parts = trimmed.split(/\s+/);
|
|
2961
|
+
for (const part of parts) {
|
|
2962
|
+
if (part === "##any" || part === "##other" || part === "##targetNamespace") {
|
|
2963
|
+
continue;
|
|
2964
|
+
}
|
|
2965
|
+
if (!part.includes(":") && part !== "") {
|
|
2966
|
+
return createIssue({
|
|
2967
|
+
code: "INVALID_WILDCARD_NAMESPACE",
|
|
2968
|
+
severity: "warning",
|
|
2969
|
+
message: `Invalid namespace in wildcard constraint: '${part}'. Expected ##any, ##other, ##targetNamespace, or a valid namespace URI.`,
|
|
2970
|
+
path
|
|
2971
|
+
});
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
return null;
|
|
2975
|
+
}
|
|
2976
|
+
function validateProcessContents(processContents, path) {
|
|
2977
|
+
if (!processContents) return null;
|
|
2978
|
+
const trimmed = processContents.trim();
|
|
2979
|
+
if (trimmed === "strict" || trimmed === "lax" || trimmed === "skip") {
|
|
2980
|
+
return null;
|
|
2981
|
+
}
|
|
2982
|
+
return createIssue({
|
|
2983
|
+
code: "INVALID_PROCESS_CONTENTS",
|
|
2984
|
+
severity: "error",
|
|
2985
|
+
message: `Invalid processContents value: '${processContents}'. Must be 'strict', 'lax', or 'skip'.`,
|
|
2986
|
+
path
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
function validateSingleWildcard(wildcardNode, nodeName) {
|
|
2990
|
+
const issues = [];
|
|
2991
|
+
const nsIssue = validateWildcardNamespace(wildcardNode.namespace, wildcardNode.path);
|
|
2992
|
+
if (nsIssue) {
|
|
2993
|
+
issues.push(nsIssue);
|
|
2994
|
+
}
|
|
2995
|
+
const pcIssue = validateProcessContents(wildcardNode.processContents, wildcardNode.path);
|
|
2996
|
+
if (pcIssue) {
|
|
2997
|
+
issues.push(pcIssue);
|
|
2998
|
+
}
|
|
2999
|
+
if (wildcardNode.notNamespace && wildcardNode.notNamespace.length > 0) {
|
|
3000
|
+
if (wildcardNode.namespace !== "##other" && wildcardNode.namespace !== "##targetNamespace") {
|
|
3001
|
+
issues.push(
|
|
3002
|
+
createIssue({
|
|
3003
|
+
code: "INVALID_NOT_NAMESPACE_USAGE",
|
|
3004
|
+
severity: "warning",
|
|
3005
|
+
message: `notNamespace is only meaningful with ##other or ##targetNamespace namespace constraint.`,
|
|
3006
|
+
path: wildcardNode.path
|
|
3007
|
+
})
|
|
3008
|
+
);
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
if (wildcardNode.notQName && wildcardNode.notQName.length > 0) {
|
|
3012
|
+
for (const qname of wildcardNode.notQName) {
|
|
3013
|
+
if (!qname || qname.trim() === "") {
|
|
3014
|
+
issues.push(
|
|
3015
|
+
createIssue({
|
|
3016
|
+
code: "INVALID_NOT_QNAME",
|
|
3017
|
+
severity: "warning",
|
|
3018
|
+
message: `Empty QName in notQName constraint.`,
|
|
3019
|
+
path: wildcardNode.path
|
|
3020
|
+
})
|
|
3021
|
+
);
|
|
3022
|
+
break;
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
return issues;
|
|
3027
|
+
}
|
|
3028
|
+
function findWildcardsInContent(node, wildcards) {
|
|
3029
|
+
if (!node) return;
|
|
3030
|
+
if (node.kind === "any" || node.kind === "anyAttribute") {
|
|
3031
|
+
wildcards.push(node);
|
|
3032
|
+
return;
|
|
3033
|
+
}
|
|
3034
|
+
if (node.children && Array.isArray(node.children)) {
|
|
3035
|
+
for (const child of node.children) {
|
|
3036
|
+
findWildcardsInContent(child, wildcards);
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
function findWildcardsInAttributes(attributes, wildcards) {
|
|
3041
|
+
if (!attributes || !Array.isArray(attributes)) return;
|
|
3042
|
+
for (const attr of attributes) {
|
|
3043
|
+
if (attr.kind === "anyAttribute") {
|
|
3044
|
+
wildcards.push(attr);
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
function runWildcardDiagnostics(schema) {
|
|
3049
|
+
const issues = [];
|
|
3050
|
+
const wildcards = [];
|
|
3051
|
+
for (const elem of Object.values(schema.globals.elements || {})) {
|
|
3052
|
+
if (elem.inlineType?.content) {
|
|
3053
|
+
findWildcardsInContent(elem.inlineType.content, wildcards);
|
|
3054
|
+
}
|
|
3055
|
+
if (elem.inlineType?.attributes) {
|
|
3056
|
+
findWildcardsInAttributes(elem.inlineType.attributes, wildcards);
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
for (const complexType of Object.values(schema.globals.complexTypes || {})) {
|
|
3060
|
+
if (complexType.content) {
|
|
3061
|
+
findWildcardsInContent(complexType.content, wildcards);
|
|
3062
|
+
}
|
|
3063
|
+
if (complexType.attributes) {
|
|
3064
|
+
findWildcardsInAttributes(complexType.attributes, wildcards);
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
for (const group of Object.values(schema.globals.groups || {})) {
|
|
3068
|
+
if (group.content) {
|
|
3069
|
+
findWildcardsInContent(group.content, wildcards);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
for (const wildcard of wildcards) {
|
|
3073
|
+
const wildcardIssues = validateSingleWildcard(wildcard, wildcard.kind);
|
|
3074
|
+
issues.push(...wildcardIssues);
|
|
3075
|
+
}
|
|
3076
|
+
return issues;
|
|
3077
|
+
}
|
|
3078
|
+
|
|
2470
3079
|
// src/diagnostics/schemaDiagnostics.js
|
|
2471
3080
|
function buildStats(schema) {
|
|
2472
3081
|
return {
|
|
@@ -2494,11 +3103,14 @@ var UssXsdEngine = (() => {
|
|
|
2494
3103
|
"element",
|
|
2495
3104
|
"extension",
|
|
2496
3105
|
"group",
|
|
3106
|
+
"key",
|
|
3107
|
+
"keyref",
|
|
2497
3108
|
"restriction",
|
|
2498
3109
|
"schema",
|
|
2499
3110
|
"sequence",
|
|
2500
3111
|
"simpleContent",
|
|
2501
|
-
"simpleType"
|
|
3112
|
+
"simpleType",
|
|
3113
|
+
"unique"
|
|
2502
3114
|
].includes(name)
|
|
2503
3115
|
).map((name) => `xs:${name}`)
|
|
2504
3116
|
);
|
|
@@ -2635,7 +3247,11 @@ var UssXsdEngine = (() => {
|
|
|
2635
3247
|
checkMissingBaseTypes(schema, issues);
|
|
2636
3248
|
checkUnknownGroups(schema, issues);
|
|
2637
3249
|
checkUnknownAttributeGroups(schema, issues);
|
|
3250
|
+
const identityIssues = runIdentityConstraintDiagnostics(schema);
|
|
3251
|
+
issues.push(...identityIssues);
|
|
2638
3252
|
emitUnsupportedFeatureWarnings(schema, issues, options);
|
|
3253
|
+
const wildcardIssues = runWildcardDiagnostics(schema);
|
|
3254
|
+
issues.push(...wildcardIssues);
|
|
2639
3255
|
const facetIssues = runFacetDiagnostics(schema, options);
|
|
2640
3256
|
issues.push(...facetIssues);
|
|
2641
3257
|
const restrictionIssues = runRestrictionDiagnostics(schema);
|
|
@@ -2656,7 +3272,7 @@ var UssXsdEngine = (() => {
|
|
|
2656
3272
|
}
|
|
2657
3273
|
|
|
2658
3274
|
// src/version.js
|
|
2659
|
-
var ENGINE_VERSION = "v0.
|
|
3275
|
+
var ENGINE_VERSION = "v0.2.1";
|
|
2660
3276
|
|
|
2661
3277
|
// src/utils/result.js
|
|
2662
3278
|
function summarizeIssues(issues = []) {
|
|
@@ -2722,7 +3338,7 @@ var UssXsdEngine = (() => {
|
|
|
2722
3338
|
refName = null,
|
|
2723
3339
|
baseTypeName = null,
|
|
2724
3340
|
derivation = null,
|
|
2725
|
-
namespaceUri:
|
|
3341
|
+
namespaceUri: namespaceUri4 = null,
|
|
2726
3342
|
minOccurs = 1,
|
|
2727
3343
|
maxOccurs = 1,
|
|
2728
3344
|
use = null,
|
|
@@ -2739,7 +3355,7 @@ var UssXsdEngine = (() => {
|
|
|
2739
3355
|
refName,
|
|
2740
3356
|
baseTypeName,
|
|
2741
3357
|
derivation,
|
|
2742
|
-
namespaceUri:
|
|
3358
|
+
namespaceUri: namespaceUri4,
|
|
2743
3359
|
minOccurs,
|
|
2744
3360
|
maxOccurs,
|
|
2745
3361
|
use,
|
|
@@ -2751,9 +3367,9 @@ var UssXsdEngine = (() => {
|
|
|
2751
3367
|
}
|
|
2752
3368
|
|
|
2753
3369
|
// src/tree/extractTree.js
|
|
2754
|
-
function buildQualifiedLabel(name,
|
|
3370
|
+
function buildQualifiedLabel(name, namespaceUri4) {
|
|
2755
3371
|
if (!name) return name;
|
|
2756
|
-
return
|
|
3372
|
+
return namespaceUri4 ? `{${namespaceUri4}} ${name}` : name;
|
|
2757
3373
|
}
|
|
2758
3374
|
function asArray2(value) {
|
|
2759
3375
|
return Array.isArray(value) ? value : [];
|
|
@@ -3394,8 +4010,8 @@ var UssXsdEngine = (() => {
|
|
|
3394
4010
|
Object.assign(target, source);
|
|
3395
4011
|
}
|
|
3396
4012
|
function qualifiedElementName(schema, elementDecl, state, isRoot = false) {
|
|
3397
|
-
const
|
|
3398
|
-
const bare =
|
|
4013
|
+
const localName4 = elementDecl.name || elementDecl.refName || "element";
|
|
4014
|
+
const bare = localName4.includes(":") ? localName4.split(":")[1] : localName4;
|
|
3399
4015
|
const ns = elementDecl.namespaceUri;
|
|
3400
4016
|
if (!ns) return bare;
|
|
3401
4017
|
const prefix = state.nsContext.getPrefix(ns);
|
|
@@ -3544,6 +4160,24 @@ var UssXsdEngine = (() => {
|
|
|
3544
4160
|
function buildComplexTypeContent(schema, complexTypeDecl, options, state) {
|
|
3545
4161
|
const content = getEffectiveContent(schema, complexTypeDecl);
|
|
3546
4162
|
const attributes = getEffectiveAttributes(schema, complexTypeDecl);
|
|
4163
|
+
if (state.currentDepth >= options.maxDepth) {
|
|
4164
|
+
return {
|
|
4165
|
+
attributes: buildAttributesObject(schema, attributes, options, state),
|
|
4166
|
+
children: []
|
|
4167
|
+
};
|
|
4168
|
+
}
|
|
4169
|
+
const typeKey = complexTypeDecl.name || complexTypeDecl.qName;
|
|
4170
|
+
if (typeKey && state.visitedTypes.has(typeKey)) {
|
|
4171
|
+
return {
|
|
4172
|
+
attributes: buildAttributesObject(schema, attributes, options, state),
|
|
4173
|
+
children: []
|
|
4174
|
+
};
|
|
4175
|
+
}
|
|
4176
|
+
if (typeKey) {
|
|
4177
|
+
state.visitedTypes.add(typeKey);
|
|
4178
|
+
}
|
|
4179
|
+
const previousDepth = state.currentDepth;
|
|
4180
|
+
state.currentDepth += 1;
|
|
3547
4181
|
let children = content ? buildNodesFromContent(schema, content, options, state) : [];
|
|
3548
4182
|
if (options.mode === "minimal" && children.length === 0 && content) {
|
|
3549
4183
|
children = buildRepresentativeNodesFromContent(
|
|
@@ -3553,6 +4187,10 @@ var UssXsdEngine = (() => {
|
|
|
3553
4187
|
state
|
|
3554
4188
|
);
|
|
3555
4189
|
}
|
|
4190
|
+
state.currentDepth = previousDepth;
|
|
4191
|
+
if (typeKey) {
|
|
4192
|
+
state.visitedTypes.delete(typeKey);
|
|
4193
|
+
}
|
|
3556
4194
|
return {
|
|
3557
4195
|
attributes: buildAttributesObject(schema, attributes, options, state),
|
|
3558
4196
|
children
|
|
@@ -3631,7 +4269,10 @@ var UssXsdEngine = (() => {
|
|
|
3631
4269
|
function generateXmlFromSchema(schema, options = {}, helpers = {}) {
|
|
3632
4270
|
const normalizedOptions = {
|
|
3633
4271
|
mode: options.mode === "full" ? "full" : "minimal",
|
|
3634
|
-
includeOptionalAttributes: options.includeOptionalAttributes === true
|
|
4272
|
+
includeOptionalAttributes: options.includeOptionalAttributes === true,
|
|
4273
|
+
maxDepth: options.maxDepth ?? 3,
|
|
4274
|
+
maxChoiceBranches: options.maxChoiceBranches ?? 1,
|
|
4275
|
+
expandRepeatingElements: options.expandRepeatingElements ?? 2
|
|
3635
4276
|
};
|
|
3636
4277
|
const root = selectRoot(schema, options);
|
|
3637
4278
|
if (!root) {
|
|
@@ -3644,7 +4285,9 @@ var UssXsdEngine = (() => {
|
|
|
3644
4285
|
const state = {
|
|
3645
4286
|
resolveAttributeGroup: helpers.resolveAttributeGroup,
|
|
3646
4287
|
targetPrefix: options.targetPrefix || "tns",
|
|
3647
|
-
nsContext
|
|
4288
|
+
nsContext,
|
|
4289
|
+
visitedTypes: /* @__PURE__ */ new Set(),
|
|
4290
|
+
currentDepth: 0
|
|
3648
4291
|
};
|
|
3649
4292
|
const [rootNode] = buildElementInstances(
|
|
3650
4293
|
schema,
|
|
@@ -3747,6 +4390,80 @@ ${writeNode(rootNode, 0)}`;
|
|
|
3747
4390
|
});
|
|
3748
4391
|
}
|
|
3749
4392
|
|
|
4393
|
+
// src/validation/wildcardValidator.js
|
|
4394
|
+
function namespaceMatches(elementNamespace, wildcardNamespace, targetNamespace) {
|
|
4395
|
+
if (!wildcardNamespace) return true;
|
|
4396
|
+
if (wildcardNamespace === "##any") return true;
|
|
4397
|
+
if (wildcardNamespace === "##targetNamespace") {
|
|
4398
|
+
return elementNamespace === targetNamespace;
|
|
4399
|
+
}
|
|
4400
|
+
if (wildcardNamespace === "##other") {
|
|
4401
|
+
return elementNamespace !== targetNamespace;
|
|
4402
|
+
}
|
|
4403
|
+
if (Array.isArray(wildcardNamespace)) {
|
|
4404
|
+
return wildcardNamespace.includes(elementNamespace);
|
|
4405
|
+
}
|
|
4406
|
+
return elementNamespace === wildcardNamespace;
|
|
4407
|
+
}
|
|
4408
|
+
function isExcludedByNotNamespace(elementNamespace, notNamespace) {
|
|
4409
|
+
if (!notNamespace || notNamespace.length === 0) return false;
|
|
4410
|
+
return notNamespace.includes(elementNamespace);
|
|
4411
|
+
}
|
|
4412
|
+
function isExcludedByNotQName(qName, notQName) {
|
|
4413
|
+
if (!notQName || notQName.length === 0) return false;
|
|
4414
|
+
return notQName.includes(qName);
|
|
4415
|
+
}
|
|
4416
|
+
function buildQName(localName4, namespaceUri4) {
|
|
4417
|
+
if (!namespaceUri4 || namespaceUri4 === "") {
|
|
4418
|
+
return localName4;
|
|
4419
|
+
}
|
|
4420
|
+
return `{${namespaceUri4}}${localName4}`;
|
|
4421
|
+
}
|
|
4422
|
+
function elementMatchesWildcard(elementLocalName, elementNamespace, wildcardNode, targetNamespace) {
|
|
4423
|
+
if (!wildcardNode || wildcardNode.kind !== "any") {
|
|
4424
|
+
return false;
|
|
4425
|
+
}
|
|
4426
|
+
if (!namespaceMatches(elementNamespace, wildcardNode.namespace, targetNamespace)) {
|
|
4427
|
+
return false;
|
|
4428
|
+
}
|
|
4429
|
+
if (isExcludedByNotNamespace(elementNamespace, wildcardNode.notNamespace)) {
|
|
4430
|
+
return false;
|
|
4431
|
+
}
|
|
4432
|
+
const qName = buildQName(elementLocalName, elementNamespace);
|
|
4433
|
+
if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
|
|
4434
|
+
return false;
|
|
4435
|
+
}
|
|
4436
|
+
return true;
|
|
4437
|
+
}
|
|
4438
|
+
function attributeMatchesWildcard(attrLocalName, attrNamespace, wildcardNode, targetNamespace) {
|
|
4439
|
+
if (!wildcardNode || wildcardNode.kind !== "anyAttribute") {
|
|
4440
|
+
return false;
|
|
4441
|
+
}
|
|
4442
|
+
if (!namespaceMatches(attrNamespace, wildcardNode.namespace, targetNamespace)) {
|
|
4443
|
+
return false;
|
|
4444
|
+
}
|
|
4445
|
+
if (isExcludedByNotNamespace(attrNamespace, wildcardNode.notNamespace)) {
|
|
4446
|
+
return false;
|
|
4447
|
+
}
|
|
4448
|
+
const qName = buildQName(attrLocalName, attrNamespace);
|
|
4449
|
+
if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
|
|
4450
|
+
return false;
|
|
4451
|
+
}
|
|
4452
|
+
return true;
|
|
4453
|
+
}
|
|
4454
|
+
function normalizeProcessContents(processContents) {
|
|
4455
|
+
if (processContents === "lax" || processContents === "skip") {
|
|
4456
|
+
return processContents;
|
|
4457
|
+
}
|
|
4458
|
+
return "strict";
|
|
4459
|
+
}
|
|
4460
|
+
function isStrictWildcardValidation(processContents) {
|
|
4461
|
+
return normalizeProcessContents(processContents) === "strict";
|
|
4462
|
+
}
|
|
4463
|
+
function shouldSkipWildcardValidation(processContents) {
|
|
4464
|
+
return normalizeProcessContents(processContents) === "skip";
|
|
4465
|
+
}
|
|
4466
|
+
|
|
3750
4467
|
// src/validation/structureValidator.js
|
|
3751
4468
|
function elementChildren2(xmlNode) {
|
|
3752
4469
|
return Array.from(xmlNode?.children || []).filter((child) => child.nodeType === 1);
|
|
@@ -3816,6 +4533,7 @@ ${writeNode(rootNode, 0)}`;
|
|
|
3816
4533
|
function validateAttributes(xmlNode, attributes, context) {
|
|
3817
4534
|
const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts, validateAttributeValue: validateAttributeValue2 } = context;
|
|
3818
4535
|
const allowed = /* @__PURE__ */ new Map();
|
|
4536
|
+
let anyAttributeWildcard = null;
|
|
3819
4537
|
for (const attr of attributes || []) {
|
|
3820
4538
|
if (!attr) continue;
|
|
3821
4539
|
if (attr.kind === "attribute") {
|
|
@@ -3827,6 +4545,8 @@ ${writeNode(rootNode, 0)}`;
|
|
|
3827
4545
|
const group = context.resolveAttributeGroup?.(attr.refName);
|
|
3828
4546
|
if (!group) continue;
|
|
3829
4547
|
validateAttributes(xmlNode, group.attributes || [], context);
|
|
4548
|
+
} else if (attr.kind === "anyAttribute") {
|
|
4549
|
+
anyAttributeWildcard = attr;
|
|
3830
4550
|
}
|
|
3831
4551
|
}
|
|
3832
4552
|
for (const attrDecl of allowed.values()) {
|
|
@@ -3872,6 +4592,15 @@ ${writeNode(rootNode, 0)}`;
|
|
|
3872
4592
|
continue;
|
|
3873
4593
|
}
|
|
3874
4594
|
if (!allowed.has(attr.name)) {
|
|
4595
|
+
if (anyAttributeWildcard) {
|
|
4596
|
+
const attrLocalName = attr.localName || attr.name.split(":")[1] || attr.name;
|
|
4597
|
+
const attrNamespace = attr.namespaceURI || null;
|
|
4598
|
+
if (attributeMatchesWildcard(attrLocalName, attrNamespace, anyAttributeWildcard, schema.targetNamespace)) {
|
|
4599
|
+
if (!shouldSkipWildcardValidation(anyAttributeWildcard.processContents)) {
|
|
4600
|
+
}
|
|
4601
|
+
continue;
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
3875
4604
|
issues.push(
|
|
3876
4605
|
createIssue2({
|
|
3877
4606
|
code: ISSUE_CODES2.XML_UNEXPECTED_ATTRIBUTE,
|
|
@@ -4289,7 +5018,16 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4289
5018
|
return validateAll(children, startIndex, modelNode, context, pathParts, silent);
|
|
4290
5019
|
case "any":
|
|
4291
5020
|
if (startIndex < children.length) {
|
|
4292
|
-
|
|
5021
|
+
const childNode = children[startIndex];
|
|
5022
|
+
const childLocalName = localName(childNode);
|
|
5023
|
+
const childNamespace = namespaceUri(childNode);
|
|
5024
|
+
if (elementMatchesWildcard(childLocalName, childNamespace, modelNode, context.schema.targetNamespace)) {
|
|
5025
|
+
if (isStrictWildcardValidation(modelNode.processContents)) {
|
|
5026
|
+
validateElementDecl(childNode, { name: childLocalName, typeName: null }, context, [...pathParts, childLocalName]);
|
|
5027
|
+
} else if (!shouldSkipWildcardValidation(modelNode.processContents)) {
|
|
5028
|
+
}
|
|
5029
|
+
return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
|
|
5030
|
+
}
|
|
4293
5031
|
}
|
|
4294
5032
|
return { nextIndex: startIndex, matched: true, matchedAny: false };
|
|
4295
5033
|
default:
|
|
@@ -4297,6 +5035,461 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4297
5035
|
}
|
|
4298
5036
|
}
|
|
4299
5037
|
|
|
5038
|
+
// src/utils/xpathEvaluator.js
|
|
5039
|
+
function nodeMatchesQName(schema, node, qName) {
|
|
5040
|
+
if (!node || !qName) return false;
|
|
5041
|
+
const parsed = parseQName(qName);
|
|
5042
|
+
const expectedNs = resolveNamespaceUri(schema, parsed.prefix);
|
|
5043
|
+
const nodeLocal = node.localName || node.nodeName || null;
|
|
5044
|
+
const nodeNs = node.namespaceURI || null;
|
|
5045
|
+
if (parsed.prefix) {
|
|
5046
|
+
let nsToCompare = expectedNs || null;
|
|
5047
|
+
if (!nsToCompare) {
|
|
5048
|
+
if (typeof node.lookupNamespaceURI === "function") {
|
|
5049
|
+
try {
|
|
5050
|
+
nsToCompare = node.lookupNamespaceURI(parsed.prefix) || null;
|
|
5051
|
+
} catch (e) {
|
|
5052
|
+
nsToCompare = null;
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
if (!nsToCompare && node.prefix) {
|
|
5056
|
+
return nodeLocal === parsed.localName && node.prefix === parsed.prefix;
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
return nodeLocal === parsed.localName && (nodeNs || null) === (nsToCompare || null);
|
|
5060
|
+
}
|
|
5061
|
+
return nodeLocal === parsed.localName;
|
|
5062
|
+
}
|
|
5063
|
+
function collectDescendants(node, predicate) {
|
|
5064
|
+
const matches = [];
|
|
5065
|
+
function traverse(n) {
|
|
5066
|
+
if (!n || n.nodeType !== 1) return;
|
|
5067
|
+
if (predicate(n)) matches.push(n);
|
|
5068
|
+
for (const child of Array.from(n.childNodes || [])) {
|
|
5069
|
+
traverse(child);
|
|
5070
|
+
}
|
|
5071
|
+
}
|
|
5072
|
+
traverse(node);
|
|
5073
|
+
return matches;
|
|
5074
|
+
}
|
|
5075
|
+
function evaluateSelector(schema, startNodes, selectorXPath) {
|
|
5076
|
+
if (!selectorXPath || !Array.isArray(startNodes) || startNodes.length === 0) return [];
|
|
5077
|
+
let xpath = selectorXPath.trim();
|
|
5078
|
+
if (xpath.startsWith("./")) xpath = xpath.slice(2);
|
|
5079
|
+
if (xpath === "." || xpath === "") return startNodes;
|
|
5080
|
+
if (xpath.includes("//")) {
|
|
5081
|
+
return evaluateSelectorWithDescendant(schema, startNodes, xpath);
|
|
5082
|
+
}
|
|
5083
|
+
const segments = xpath.split("/");
|
|
5084
|
+
let nodes = startNodes;
|
|
5085
|
+
for (const raw of segments) {
|
|
5086
|
+
if (!raw || raw === ".") continue;
|
|
5087
|
+
const m = raw.match(/^([^\[]+)(?:\[(.+)\])?$/);
|
|
5088
|
+
if (!m) return [];
|
|
5089
|
+
const step = m[1];
|
|
5090
|
+
const predicate = m[2] || null;
|
|
5091
|
+
if (step === "*") {
|
|
5092
|
+
nodes = nodes.flatMap((n) => Array.from(n.childNodes || []).filter((c) => c.nodeType === 1));
|
|
5093
|
+
} else if (step.startsWith("@")) {
|
|
5094
|
+
return [];
|
|
5095
|
+
} else {
|
|
5096
|
+
nodes = nodes.flatMap(
|
|
5097
|
+
(n) => Array.from(n.childNodes || []).filter((c) => c.nodeType === 1).filter((c) => {
|
|
5098
|
+
return nodeMatchesQName(schema, c, step);
|
|
5099
|
+
})
|
|
5100
|
+
);
|
|
5101
|
+
if (predicate && nodes.length) {
|
|
5102
|
+
const num = Number(predicate);
|
|
5103
|
+
if (Number.isInteger(num) && num > 0) {
|
|
5104
|
+
const idx = num - 1;
|
|
5105
|
+
nodes = nodes.length > idx ? [nodes[idx]] : [];
|
|
5106
|
+
} else {
|
|
5107
|
+
const attrMatch = predicate.match(/^@([A-Za-z_][\w.-]*)=['"](.*)['"]$/);
|
|
5108
|
+
if (attrMatch) {
|
|
5109
|
+
const attrName = attrMatch[1];
|
|
5110
|
+
const attrValue = attrMatch[2];
|
|
5111
|
+
nodes = nodes.filter((n) => (n.getAttribute(attrName) || "") === attrValue);
|
|
5112
|
+
} else {
|
|
5113
|
+
nodes = [];
|
|
5114
|
+
}
|
|
5115
|
+
}
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
return nodes;
|
|
5120
|
+
}
|
|
5121
|
+
function evaluateSelectorWithDescendant(schema, startNodes, xpath) {
|
|
5122
|
+
const fullParts = xpath.split(/\/\//);
|
|
5123
|
+
let nodes = startNodes;
|
|
5124
|
+
for (let partIdx = 0; partIdx < fullParts.length; partIdx++) {
|
|
5125
|
+
const part = fullParts[partIdx].trim();
|
|
5126
|
+
if (!part) continue;
|
|
5127
|
+
if (partIdx === 0) {
|
|
5128
|
+
if (part !== ".") {
|
|
5129
|
+
const segments = part.split("/");
|
|
5130
|
+
for (const seg of segments) {
|
|
5131
|
+
if (!seg || seg === ".") continue;
|
|
5132
|
+
const m = seg.match(/^([^\[]+)(?:\[(.+)\])?$/);
|
|
5133
|
+
if (!m) return [];
|
|
5134
|
+
const step = m[1];
|
|
5135
|
+
const predicate = m[2] || null;
|
|
5136
|
+
if (step === "*") {
|
|
5137
|
+
nodes = nodes.flatMap((n) => Array.from(n.childNodes || []).filter((c) => c.nodeType === 1));
|
|
5138
|
+
} else if (step.startsWith("@")) {
|
|
5139
|
+
return [];
|
|
5140
|
+
} else {
|
|
5141
|
+
nodes = nodes.flatMap(
|
|
5142
|
+
(n) => Array.from(n.childNodes || []).filter((c) => c.nodeType === 1).filter((c) => nodeMatchesQName(schema, c, step))
|
|
5143
|
+
);
|
|
5144
|
+
if (predicate && nodes.length) {
|
|
5145
|
+
const num = Number(predicate);
|
|
5146
|
+
if (Number.isInteger(num) && num > 0) {
|
|
5147
|
+
const idx = num - 1;
|
|
5148
|
+
nodes = nodes.length > idx ? [nodes[idx]] : [];
|
|
5149
|
+
} else {
|
|
5150
|
+
const attrMatch = predicate.match(/^@([A-Za-z_][\w.-]*)=['"](.*)['"]$/);
|
|
5151
|
+
if (attrMatch) {
|
|
5152
|
+
const attrName = attrMatch[1];
|
|
5153
|
+
const attrValue = attrMatch[2];
|
|
5154
|
+
nodes = nodes.filter((n) => (n.getAttribute(attrName) || "") === attrValue);
|
|
5155
|
+
} else {
|
|
5156
|
+
nodes = [];
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
} else {
|
|
5164
|
+
const segments = part.split("/");
|
|
5165
|
+
for (let segIdx = 0; segIdx < segments.length; segIdx++) {
|
|
5166
|
+
const segment = segments[segIdx];
|
|
5167
|
+
if (!segment || segment === ".") continue;
|
|
5168
|
+
const m = segment.match(/^([^\[]+)(?:\[(.+)\])?$/);
|
|
5169
|
+
if (!m) return [];
|
|
5170
|
+
const step = m[1];
|
|
5171
|
+
const predicate = m[2] || null;
|
|
5172
|
+
if (segIdx === 0) {
|
|
5173
|
+
const descendants = [];
|
|
5174
|
+
for (const node of nodes) {
|
|
5175
|
+
const matches = collectDescendants(node, (n) => {
|
|
5176
|
+
if (step === "*") return true;
|
|
5177
|
+
if (step.startsWith("@")) return false;
|
|
5178
|
+
return nodeMatchesQName(schema, n, step);
|
|
5179
|
+
});
|
|
5180
|
+
descendants.push(...matches);
|
|
5181
|
+
}
|
|
5182
|
+
nodes = descendants;
|
|
5183
|
+
if (predicate && nodes.length) {
|
|
5184
|
+
const predicateMatch = predicate.match(/^\[(.+)\]$/);
|
|
5185
|
+
if (predicateMatch) {
|
|
5186
|
+
const pred = predicateMatch[1];
|
|
5187
|
+
const num = Number(pred);
|
|
5188
|
+
if (Number.isInteger(num) && num > 0) {
|
|
5189
|
+
const idx = num - 1;
|
|
5190
|
+
nodes = nodes.length > idx ? [nodes[idx]] : [];
|
|
5191
|
+
} else {
|
|
5192
|
+
const attrMatch = pred.match(/^@([A-Za-z_][\w.-]*)=['"](.*)['"]$/);
|
|
5193
|
+
if (attrMatch) {
|
|
5194
|
+
const attrName = attrMatch[1];
|
|
5195
|
+
const attrValue = attrMatch[2];
|
|
5196
|
+
nodes = nodes.filter((n) => (n.getAttribute(attrName) || "") === attrValue);
|
|
5197
|
+
} else {
|
|
5198
|
+
nodes = [];
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
5203
|
+
} else {
|
|
5204
|
+
nodes = nodes.flatMap(
|
|
5205
|
+
(n) => Array.from(n.childNodes || []).filter((c) => c.nodeType === 1).filter((c) => {
|
|
5206
|
+
if (step === "*") return true;
|
|
5207
|
+
if (step.startsWith("@")) return false;
|
|
5208
|
+
return nodeMatchesQName(schema, c, step);
|
|
5209
|
+
})
|
|
5210
|
+
);
|
|
5211
|
+
if (predicate && nodes.length) {
|
|
5212
|
+
const predicateMatch = predicate.match(/^\[(.+)\]$/);
|
|
5213
|
+
if (predicateMatch) {
|
|
5214
|
+
const pred = predicateMatch[1];
|
|
5215
|
+
const num = Number(pred);
|
|
5216
|
+
if (Number.isInteger(num) && num > 0) {
|
|
5217
|
+
const idx = num - 1;
|
|
5218
|
+
nodes = nodes.length > idx ? [nodes[idx]] : [];
|
|
5219
|
+
} else {
|
|
5220
|
+
const attrMatch = pred.match(/^@([A-Za-z_][\w.-]*)=['"](.*)['"]$/);
|
|
5221
|
+
if (attrMatch) {
|
|
5222
|
+
const attrName = attrMatch[1];
|
|
5223
|
+
const attrValue = attrMatch[2];
|
|
5224
|
+
nodes = nodes.filter((n) => (n.getAttribute(attrName) || "") === attrValue);
|
|
5225
|
+
} else {
|
|
5226
|
+
nodes = [];
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
}
|
|
5234
|
+
if (!nodes.length && partIdx < fullParts.length - 1) {
|
|
5235
|
+
return [];
|
|
5236
|
+
}
|
|
5237
|
+
}
|
|
5238
|
+
return nodes;
|
|
5239
|
+
}
|
|
5240
|
+
function evaluateField(schema, contextNode, fieldXPath) {
|
|
5241
|
+
if (!fieldXPath || !contextNode) return null;
|
|
5242
|
+
let xpath = fieldXPath.trim();
|
|
5243
|
+
if (xpath.startsWith("./")) xpath = xpath.slice(2);
|
|
5244
|
+
if (xpath === ".") return (contextNode.textContent || "").trim() || null;
|
|
5245
|
+
if (xpath.startsWith("@")) {
|
|
5246
|
+
const attr = xpath.slice(1);
|
|
5247
|
+
return contextNode.getAttribute(attr) ?? null;
|
|
5248
|
+
}
|
|
5249
|
+
if (xpath.includes("//")) {
|
|
5250
|
+
return evaluateFieldWithDescendant(schema, contextNode, xpath);
|
|
5251
|
+
}
|
|
5252
|
+
const segments = xpath.split("/");
|
|
5253
|
+
let nodes = [contextNode];
|
|
5254
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
5255
|
+
const raw = segments[i];
|
|
5256
|
+
if (!raw || raw === ".") continue;
|
|
5257
|
+
const m = raw.match(/^([^\[]+)(?:\[(.+)\])?$/);
|
|
5258
|
+
if (!m) return null;
|
|
5259
|
+
const step = m[1];
|
|
5260
|
+
const predicate = m[2] || null;
|
|
5261
|
+
if (step.startsWith("@")) {
|
|
5262
|
+
if (i !== segments.length - 1) return null;
|
|
5263
|
+
return nodes[0]?.getAttribute(step.slice(1)) ?? null;
|
|
5264
|
+
}
|
|
5265
|
+
nodes = nodes.flatMap(
|
|
5266
|
+
(n) => Array.from(n.childNodes || []).filter((c) => c.nodeType === 1 && nodeMatchesQName(schema, c, step))
|
|
5267
|
+
);
|
|
5268
|
+
if (!nodes.length) return null;
|
|
5269
|
+
if (predicate) {
|
|
5270
|
+
const num = Number(predicate);
|
|
5271
|
+
if (Number.isInteger(num) && num > 0) {
|
|
5272
|
+
const idx = num - 1;
|
|
5273
|
+
nodes = nodes.length > idx ? [nodes[idx]] : [];
|
|
5274
|
+
} else {
|
|
5275
|
+
const attrMatch = predicate.match(/^@([A-Za-z_][\w.-]*)=['"](.*)['"]$/);
|
|
5276
|
+
if (attrMatch) {
|
|
5277
|
+
const attrName = attrMatch[1];
|
|
5278
|
+
const attrValue = attrMatch[2];
|
|
5279
|
+
nodes = nodes.filter((n) => (n.getAttribute(attrName) || "") === attrValue);
|
|
5280
|
+
} else {
|
|
5281
|
+
return null;
|
|
5282
|
+
}
|
|
5283
|
+
}
|
|
5284
|
+
}
|
|
5285
|
+
}
|
|
5286
|
+
const v = nodes[0];
|
|
5287
|
+
if (!v) return null;
|
|
5288
|
+
return (v.textContent || "").trim() || null;
|
|
5289
|
+
}
|
|
5290
|
+
function evaluateFieldWithDescendant(schema, contextNode, xpath) {
|
|
5291
|
+
const parts = xpath.split(/\/\//);
|
|
5292
|
+
let nodes = [contextNode];
|
|
5293
|
+
for (let i = 0; i < parts.length; i++) {
|
|
5294
|
+
const part = parts[i].trim();
|
|
5295
|
+
if (!part) continue;
|
|
5296
|
+
if (i === 0) {
|
|
5297
|
+
if (part !== "." && part !== "") {
|
|
5298
|
+
const val = evaluateField(schema, nodes[0], part);
|
|
5299
|
+
if (val !== null) return val;
|
|
5300
|
+
nodes = [];
|
|
5301
|
+
}
|
|
5302
|
+
} else {
|
|
5303
|
+
const m = part.match(/^([^\[]+)(?:\[(.+)\])?/);
|
|
5304
|
+
if (!m) return null;
|
|
5305
|
+
const step = m[1];
|
|
5306
|
+
const predicate = part.slice(m[0].length);
|
|
5307
|
+
if (step.startsWith("@")) {
|
|
5308
|
+
const attrName = step.slice(1);
|
|
5309
|
+
for (const node of nodes) {
|
|
5310
|
+
const descendants2 = collectDescendants(node, () => true);
|
|
5311
|
+
if (descendants2.length) {
|
|
5312
|
+
return descendants2[0]?.getAttribute(attrName) ?? null;
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
return null;
|
|
5316
|
+
}
|
|
5317
|
+
const descendants = [];
|
|
5318
|
+
for (const node of nodes) {
|
|
5319
|
+
descendants.push(
|
|
5320
|
+
...collectDescendants(node, (n) => {
|
|
5321
|
+
if (step === "*") return true;
|
|
5322
|
+
return nodeMatchesQName(schema, n, step);
|
|
5323
|
+
})
|
|
5324
|
+
);
|
|
5325
|
+
}
|
|
5326
|
+
nodes = descendants;
|
|
5327
|
+
if (!nodes.length) return null;
|
|
5328
|
+
if (predicate) {
|
|
5329
|
+
const predicateMatch = predicate.match(/^\[(.+)\]$/);
|
|
5330
|
+
if (predicateMatch) {
|
|
5331
|
+
const pred = predicateMatch[1];
|
|
5332
|
+
const num = Number(pred);
|
|
5333
|
+
if (Number.isInteger(num) && num > 0) {
|
|
5334
|
+
const idx = num - 1;
|
|
5335
|
+
nodes = nodes.length > idx ? [nodes[idx]] : [];
|
|
5336
|
+
} else {
|
|
5337
|
+
const attrMatch = pred.match(/^@([A-Za-z_][\w.-]*)=['"](.*)['"]$/);
|
|
5338
|
+
if (attrMatch) {
|
|
5339
|
+
const attrName = attrMatch[1];
|
|
5340
|
+
const attrValue = attrMatch[2];
|
|
5341
|
+
nodes = nodes.filter((n) => (n.getAttribute(attrName) || "") === attrValue);
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
5344
|
+
}
|
|
5345
|
+
}
|
|
5346
|
+
if (nodes.length) {
|
|
5347
|
+
const v = nodes[0];
|
|
5348
|
+
return (v.textContent || "").trim() || null;
|
|
5349
|
+
}
|
|
5350
|
+
}
|
|
5351
|
+
}
|
|
5352
|
+
return null;
|
|
5353
|
+
}
|
|
5354
|
+
|
|
5355
|
+
// src/validation/identityConstraintValidator.js
|
|
5356
|
+
function localName2(node) {
|
|
5357
|
+
return node?.localName || node?.nodeName || null;
|
|
5358
|
+
}
|
|
5359
|
+
function namespaceUri2(node) {
|
|
5360
|
+
return node?.namespaceURI || null;
|
|
5361
|
+
}
|
|
5362
|
+
function collectOwnerXmlNodes(xmlRoot, ownerName, ownerNamespaceUri) {
|
|
5363
|
+
const matches = [];
|
|
5364
|
+
function traverse(node) {
|
|
5365
|
+
if (!node || node.nodeType !== 1) return;
|
|
5366
|
+
if (localName2(node) === ownerName && (ownerNamespaceUri == null || ownerNamespaceUri === namespaceUri2(node))) {
|
|
5367
|
+
matches.push(node);
|
|
5368
|
+
}
|
|
5369
|
+
for (const child of Array.from(node.children || [])) {
|
|
5370
|
+
traverse(child);
|
|
5371
|
+
}
|
|
5372
|
+
}
|
|
5373
|
+
traverse(xmlRoot);
|
|
5374
|
+
return matches;
|
|
5375
|
+
}
|
|
5376
|
+
function getConstraintOwnerNodes(schema, xmlRoot, constraint) {
|
|
5377
|
+
if (!constraint.ownerName) {
|
|
5378
|
+
return [xmlRoot];
|
|
5379
|
+
}
|
|
5380
|
+
return collectOwnerXmlNodes(
|
|
5381
|
+
xmlRoot,
|
|
5382
|
+
constraint.ownerName,
|
|
5383
|
+
constraint.ownerNamespaceUri
|
|
5384
|
+
);
|
|
5385
|
+
}
|
|
5386
|
+
function validateIdentityConstraints(schema, xmlRoot, getNodeLocation) {
|
|
5387
|
+
const issues = [];
|
|
5388
|
+
const keySets = /* @__PURE__ */ new Map();
|
|
5389
|
+
function buildKeySet(constraint) {
|
|
5390
|
+
if (keySets.has(constraint.name)) {
|
|
5391
|
+
return keySets.get(constraint.name);
|
|
5392
|
+
}
|
|
5393
|
+
const set = /* @__PURE__ */ new Set();
|
|
5394
|
+
const ownerNodes = getConstraintOwnerNodes(schema, xmlRoot, constraint);
|
|
5395
|
+
for (const ownerNode of ownerNodes) {
|
|
5396
|
+
const selected = evaluateSelector(schema, [ownerNode], constraint.selector?.xpath);
|
|
5397
|
+
for (const selectedNode of selected) {
|
|
5398
|
+
const tuple = constraint.fields.map((field) => evaluateField(schema, selectedNode, field.xpath));
|
|
5399
|
+
set.add(JSON.stringify(tuple));
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
keySets.set(constraint.name, set);
|
|
5403
|
+
return set;
|
|
5404
|
+
}
|
|
5405
|
+
for (const constraint of schema.identityConstraints || []) {
|
|
5406
|
+
const ownerNodes = getConstraintOwnerNodes(schema, xmlRoot, constraint);
|
|
5407
|
+
if (!ownerNodes.length) {
|
|
5408
|
+
continue;
|
|
5409
|
+
}
|
|
5410
|
+
const valueIndex = /* @__PURE__ */ new Map();
|
|
5411
|
+
const referenceKeyConstraint = schema.identityConstraints.find(
|
|
5412
|
+
(item) => item.kind === "key" && item.name === parseQName(constraint.refer || "").localName
|
|
5413
|
+
);
|
|
5414
|
+
const referenceKeySet = constraint.kind === "keyref" && referenceKeyConstraint ? buildKeySet(referenceKeyConstraint) : null;
|
|
5415
|
+
for (const ownerNode of ownerNodes) {
|
|
5416
|
+
const selected = evaluateSelector(schema, [ownerNode], constraint.selector?.xpath);
|
|
5417
|
+
for (const selectedNode of selected) {
|
|
5418
|
+
const tuple = constraint.fields.map((field) => evaluateField(schema, selectedNode, field.xpath));
|
|
5419
|
+
const tupleKey = JSON.stringify(tuple);
|
|
5420
|
+
const rawLocation = getNodeLocation ? getNodeLocation(selectedNode) : null;
|
|
5421
|
+
const location = rawLocation || { line: constraint.line || 1, column: constraint.column || 1 };
|
|
5422
|
+
if (tuple.some((value) => value == null || value === "")) {
|
|
5423
|
+
if (constraint.kind === "key") {
|
|
5424
|
+
issues.push(
|
|
5425
|
+
createIssue({
|
|
5426
|
+
code: ISSUE_CODES.XML_KEY_NULL_VIOLATION,
|
|
5427
|
+
severity: "error",
|
|
5428
|
+
message: `xs:key '${constraint.name}' requires non-empty values for all fields.`,
|
|
5429
|
+
line: location.line,
|
|
5430
|
+
column: location.column,
|
|
5431
|
+
path: constraint.path,
|
|
5432
|
+
source: "xml",
|
|
5433
|
+
nodeKind: "element",
|
|
5434
|
+
name: constraint.name,
|
|
5435
|
+
details: {
|
|
5436
|
+
selector: constraint.selector?.xpath,
|
|
5437
|
+
fields: constraint.fields.map((field) => field.xpath)
|
|
5438
|
+
}
|
|
5439
|
+
})
|
|
5440
|
+
);
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
if (constraint.kind === "key" || constraint.kind === "unique") {
|
|
5444
|
+
if (valueIndex.has(tupleKey)) {
|
|
5445
|
+
issues.push(
|
|
5446
|
+
createIssue({
|
|
5447
|
+
code: constraint.kind === "key" ? ISSUE_CODES.XML_KEY_VIOLATION : ISSUE_CODES.XML_UNIQUE_VIOLATION,
|
|
5448
|
+
severity: "error",
|
|
5449
|
+
message: `Duplicate ${constraint.kind} value for '${constraint.name}'.`,
|
|
5450
|
+
line: location.line,
|
|
5451
|
+
column: location.column,
|
|
5452
|
+
path: constraint.path,
|
|
5453
|
+
source: "xml",
|
|
5454
|
+
nodeKind: "element",
|
|
5455
|
+
name: constraint.name,
|
|
5456
|
+
details: {
|
|
5457
|
+
selector: constraint.selector?.xpath,
|
|
5458
|
+
fields: constraint.fields.map((field) => field.xpath)
|
|
5459
|
+
}
|
|
5460
|
+
})
|
|
5461
|
+
);
|
|
5462
|
+
}
|
|
5463
|
+
valueIndex.set(tupleKey, true);
|
|
5464
|
+
}
|
|
5465
|
+
if (constraint.kind === "keyref" && referenceKeySet) {
|
|
5466
|
+
if (!referenceKeySet.has(tupleKey)) {
|
|
5467
|
+
issues.push(
|
|
5468
|
+
createIssue({
|
|
5469
|
+
code: ISSUE_CODES.XML_KEYREF_VIOLATION,
|
|
5470
|
+
severity: "error",
|
|
5471
|
+
message: `xs:keyref '${constraint.name}' references a missing key value.`,
|
|
5472
|
+
line: location.line,
|
|
5473
|
+
column: location.column,
|
|
5474
|
+
path: constraint.path,
|
|
5475
|
+
source: "xml",
|
|
5476
|
+
nodeKind: "element",
|
|
5477
|
+
name: constraint.name,
|
|
5478
|
+
details: {
|
|
5479
|
+
refer: constraint.refer,
|
|
5480
|
+
selector: constraint.selector?.xpath,
|
|
5481
|
+
fields: constraint.fields.map((field) => field.xpath)
|
|
5482
|
+
}
|
|
5483
|
+
})
|
|
5484
|
+
);
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
5487
|
+
}
|
|
5488
|
+
}
|
|
5489
|
+
}
|
|
5490
|
+
return issues;
|
|
5491
|
+
}
|
|
5492
|
+
|
|
4300
5493
|
// src/validation/builtinTypeValidators.js
|
|
4301
5494
|
function isIntegerString(value) {
|
|
4302
5495
|
return /^[-+]?\d+$/.test(value);
|
|
@@ -4794,12 +5987,12 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4794
5987
|
const end = tagText.indexOf(quoteChar, start);
|
|
4795
5988
|
return end >= start ? start : -1;
|
|
4796
5989
|
}
|
|
4797
|
-
function findTextContentOffset(text, tagEndOffset,
|
|
5990
|
+
function findTextContentOffset(text, tagEndOffset, localName4) {
|
|
4798
5991
|
let i = tagEndOffset + 1;
|
|
4799
5992
|
while (i < text.length && /\s/.test(text[i])) {
|
|
4800
5993
|
i += 1;
|
|
4801
5994
|
}
|
|
4802
|
-
if (text.startsWith(`</${
|
|
5995
|
+
if (text.startsWith(`</${localName4}`, i) || text[i] === "<") {
|
|
4803
5996
|
return -1;
|
|
4804
5997
|
}
|
|
4805
5998
|
return i < text.length ? i : -1;
|
|
@@ -4826,10 +6019,20 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4826
6019
|
}
|
|
4827
6020
|
};
|
|
4828
6021
|
}
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
...Array.from(documentElement.querySelectorAll("*"))
|
|
4832
|
-
|
|
6022
|
+
let orderedNodes = null;
|
|
6023
|
+
if (typeof documentElement.querySelectorAll === "function") {
|
|
6024
|
+
orderedNodes = [documentElement, ...Array.from(documentElement.querySelectorAll("*"))];
|
|
6025
|
+
} else {
|
|
6026
|
+
let collect = function(node) {
|
|
6027
|
+
if (!node || node.nodeType !== 1) return;
|
|
6028
|
+
orderedNodes.push(node);
|
|
6029
|
+
for (const child of Array.from(node.children || [])) {
|
|
6030
|
+
collect(child);
|
|
6031
|
+
}
|
|
6032
|
+
};
|
|
6033
|
+
orderedNodes = [];
|
|
6034
|
+
collect(documentElement);
|
|
6035
|
+
}
|
|
4833
6036
|
let searchFrom = 0;
|
|
4834
6037
|
for (const node of orderedNodes) {
|
|
4835
6038
|
const expectedLocalName = getNodeLocalName(node);
|
|
@@ -4906,10 +6109,10 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4906
6109
|
(child) => child.nodeType === 1
|
|
4907
6110
|
);
|
|
4908
6111
|
}
|
|
4909
|
-
function
|
|
6112
|
+
function localName3(node) {
|
|
4910
6113
|
return node?.localName || node?.nodeName || null;
|
|
4911
6114
|
}
|
|
4912
|
-
function
|
|
6115
|
+
function namespaceUri3(node) {
|
|
4913
6116
|
return node?.namespaceURI || null;
|
|
4914
6117
|
}
|
|
4915
6118
|
function determineRootElement(schema, xmlRootName, xmlRootNs, options) {
|
|
@@ -4954,8 +6157,8 @@ ${writeNode(rootNode, 0)}`;
|
|
|
4954
6157
|
}
|
|
4955
6158
|
const locator = createXmlSourceLocator(xmlText, xmlParse.document);
|
|
4956
6159
|
const xmlRoot = xmlParse.document.documentElement;
|
|
4957
|
-
const xmlRootName =
|
|
4958
|
-
const xmlRootNs =
|
|
6160
|
+
const xmlRootName = localName3(xmlRoot);
|
|
6161
|
+
const xmlRootNs = namespaceUri3(xmlRoot);
|
|
4959
6162
|
const issues = [...parseIssues];
|
|
4960
6163
|
if (!xmlRoot) {
|
|
4961
6164
|
return {
|
|
@@ -5075,7 +6278,7 @@ ${writeNode(rootNode, 0)}`;
|
|
|
5075
6278
|
const children2 = elementChildren3(xmlRoot);
|
|
5076
6279
|
if (children2.length > 0) {
|
|
5077
6280
|
for (const childNode of children2) {
|
|
5078
|
-
const childName =
|
|
6281
|
+
const childName = localName3(childNode);
|
|
5079
6282
|
issues.push(
|
|
5080
6283
|
createIssue({
|
|
5081
6284
|
code: ISSUE_CODES.XML_UNEXPECTED_ELEMENT,
|
|
@@ -5087,7 +6290,7 @@ ${writeNode(rootNode, 0)}`;
|
|
|
5087
6290
|
nodeKind: "element",
|
|
5088
6291
|
name: childName,
|
|
5089
6292
|
details: {
|
|
5090
|
-
namespaceUri:
|
|
6293
|
+
namespaceUri: namespaceUri3(childNode)
|
|
5091
6294
|
}
|
|
5092
6295
|
})
|
|
5093
6296
|
);
|
|
@@ -5164,7 +6367,7 @@ ${writeNode(rootNode, 0)}`;
|
|
|
5164
6367
|
if (result.nextIndex < children.length) {
|
|
5165
6368
|
for (let i = result.nextIndex; i < children.length; i += 1) {
|
|
5166
6369
|
const childNode = children[i];
|
|
5167
|
-
const childName =
|
|
6370
|
+
const childName = localName3(childNode);
|
|
5168
6371
|
issues.push(
|
|
5169
6372
|
createIssue({
|
|
5170
6373
|
code: ISSUE_CODES.XML_UNEXPECTED_ELEMENT,
|
|
@@ -5176,7 +6379,7 @@ ${writeNode(rootNode, 0)}`;
|
|
|
5176
6379
|
nodeKind: "element",
|
|
5177
6380
|
name: childName,
|
|
5178
6381
|
details: {
|
|
5179
|
-
namespaceUri:
|
|
6382
|
+
namespaceUri: namespaceUri3(childNode)
|
|
5180
6383
|
}
|
|
5181
6384
|
})
|
|
5182
6385
|
);
|
|
@@ -5207,6 +6410,12 @@ ${writeNode(rootNode, 0)}`;
|
|
|
5207
6410
|
);
|
|
5208
6411
|
}
|
|
5209
6412
|
}
|
|
6413
|
+
const identityConstraintIssues = validateIdentityConstraints(
|
|
6414
|
+
schema,
|
|
6415
|
+
xmlRoot,
|
|
6416
|
+
locator.getNodeLocation
|
|
6417
|
+
);
|
|
6418
|
+
issues.push(...identityConstraintIssues);
|
|
5210
6419
|
return {
|
|
5211
6420
|
data: {
|
|
5212
6421
|
xmlValid: !issues.some((issue) => issue.severity === "error")
|