uss-xsd-engine 0.1.0-beta.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.
@@ -0,0 +1,4149 @@
1
+ /*!
2
+ * uss-xsd-engine v0.1.0-beta.2
3
+ * (c) 2026 Bernard Mumble
4
+ * MIT License
5
+ */
6
+
7
+ // src/diagnostics/createIssue.js
8
+ function createIssue({
9
+ code,
10
+ severity = "error",
11
+ message,
12
+ line = null,
13
+ column = null,
14
+ path = null,
15
+ source = "xsd",
16
+ nodeKind = null,
17
+ name = null,
18
+ details = {}
19
+ }) {
20
+ return {
21
+ code,
22
+ severity,
23
+ message,
24
+ line,
25
+ column,
26
+ path,
27
+ source,
28
+ nodeKind,
29
+ name,
30
+ details
31
+ };
32
+ }
33
+
34
+ // src/diagnostics/issueCodes.js
35
+ var ISSUE_CODES = {
36
+ XSD_PARSE_ERROR: "XSD_PARSE_ERROR",
37
+ DUPLICATE_GLOBAL_ELEMENT: "DUPLICATE_GLOBAL_ELEMENT",
38
+ DUPLICATE_GLOBAL_COMPLEX_TYPE: "DUPLICATE_GLOBAL_COMPLEX_TYPE",
39
+ DUPLICATE_GLOBAL_SIMPLE_TYPE: "DUPLICATE_GLOBAL_SIMPLE_TYPE",
40
+ DUPLICATE_GLOBAL_ATTRIBUTE: "DUPLICATE_GLOBAL_ATTRIBUTE",
41
+ DUPLICATE_GLOBAL_GROUP: "DUPLICATE_GLOBAL_GROUP",
42
+ DUPLICATE_GLOBAL_ATTRIBUTE_GROUP: "DUPLICATE_GLOBAL_ATTRIBUTE_GROUP",
43
+ UNKNOWN_TYPE: "UNKNOWN_TYPE",
44
+ UNKNOWN_REF: "UNKNOWN_REF",
45
+ UNKNOWN_GROUP: "UNKNOWN_GROUP",
46
+ UNKNOWN_ATTRIBUTE_GROUP: "UNKNOWN_ATTRIBUTE_GROUP",
47
+ MISSING_BASE_TYPE: "MISSING_BASE_TYPE",
48
+ UNSUPPORTED_FEATURE: "UNSUPPORTED_FEATURE",
49
+ INVALID_OCCURS_RANGE: "INVALID_OCCURS_RANGE",
50
+ INVALID_DEFAULT_FIXED_COMBINATION: "INVALID_DEFAULT_FIXED_COMBINATION",
51
+ XML_PARSE_ERROR: "XML_PARSE_ERROR",
52
+ XML_ROOT_ELEMENT_MISMATCH: "XML_ROOT_ELEMENT_MISMATCH",
53
+ XML_UNKNOWN_ROOT_ELEMENT: "XML_UNKNOWN_ROOT_ELEMENT",
54
+ XML_UNEXPECTED_ELEMENT: "XML_UNEXPECTED_ELEMENT",
55
+ XML_MISSING_REQUIRED_ELEMENT: "XML_MISSING_REQUIRED_ELEMENT",
56
+ XML_CHOICE_NOT_SATISFIED: "XML_CHOICE_NOT_SATISFIED",
57
+ XML_ALL_MISSING_REQUIRED_ELEMENT: "XML_ALL_MISSING_REQUIRED_ELEMENT",
58
+ XML_UNEXPECTED_ATTRIBUTE: "XML_UNEXPECTED_ATTRIBUTE",
59
+ XML_MISSING_REQUIRED_ATTRIBUTE: "XML_MISSING_REQUIRED_ATTRIBUTE",
60
+ XML_INVALID_TEXT_FOR_COMPLEX_TYPE: "XML_INVALID_TEXT_FOR_COMPLEX_TYPE",
61
+ XML_VALUE_INVALID: "XML_VALUE_INVALID",
62
+ XML_ENUMERATION_MISMATCH: "XML_ENUMERATION_MISMATCH",
63
+ XML_PATTERN_MISMATCH: "XML_PATTERN_MISMATCH",
64
+ XML_LENGTH_MISMATCH: "XML_LENGTH_MISMATCH",
65
+ XML_MIN_LENGTH_VIOLATION: "XML_MIN_LENGTH_VIOLATION",
66
+ XML_MAX_LENGTH_VIOLATION: "XML_MAX_LENGTH_VIOLATION",
67
+ XML_MIN_INCLUSIVE_VIOLATION: "XML_MIN_INCLUSIVE_VIOLATION",
68
+ XML_MAX_INCLUSIVE_VIOLATION: "XML_MAX_INCLUSIVE_VIOLATION",
69
+ XML_MIN_EXCLUSIVE_VIOLATION: "XML_MIN_EXCLUSIVE_VIOLATION",
70
+ XML_MAX_EXCLUSIVE_VIOLATION: "XML_MAX_EXCLUSIVE_VIOLATION",
71
+ XML_TOTAL_DIGITS_VIOLATION: "XML_TOTAL_DIGITS_VIOLATION",
72
+ XML_FRACTION_DIGITS_VIOLATION: "XML_FRACTION_DIGITS_VIOLATION",
73
+ XML_MIXED_CONTENT_NOT_ALLOWED: "XML_MIXED_CONTENT_NOT_ALLOWED",
74
+ XML_RESTRICTION_VIOLATION: "XML_RESTRICTION_VIOLATION",
75
+ XML_ALL_DUPLICATE_ELEMENT: "XML_ALL_DUPLICATE_ELEMENT",
76
+ XML_CHOICE_MULTIPLE_BRANCHES: "XML_CHOICE_MULTIPLE_BRANCHES",
77
+ XML_RESTRICTED_ELEMENT_NOT_ALLOWED: "XML_RESTRICTED_ELEMENT_NOT_ALLOWED",
78
+ XML_FIXED_VALUE_MISMATCH: "XML_FIXED_VALUE_MISMATCH",
79
+ XSD_LENGTH_CONFLICT: "XSD_LENGTH_CONFLICT",
80
+ XSD_NUMERIC_RANGE_CONFLICT: "XSD_NUMERIC_RANGE_CONFLICT",
81
+ XSD_DIGITS_INVALID: "XSD_DIGITS_INVALID",
82
+ XSD_DIGITS_CONFLICT: "XSD_DIGITS_CONFLICT",
83
+ XSD_ENUM_DUPLICATE: "XSD_ENUM_DUPLICATE",
84
+ XSD_PATTERN_INVALID: "XSD_PATTERN_INVALID",
85
+ XSD_FACET_NOT_ALLOWED: "XSD_FACET_NOT_ALLOWED",
86
+ XSD_RESTRICTION_NOT_SUBSET: "XSD_RESTRICTION_NOT_SUBSET",
87
+ XSD_RESTRICTION_OCCURS_WIDENED: "XSD_RESTRICTION_OCCURS_WIDENED",
88
+ XSD_RESTRICTION_ATTRIBUTE_WIDENED: "XSD_RESTRICTION_ATTRIBUTE_WIDENED",
89
+ XSD_INCLUDE_NOT_PROVIDED: "XSD_INCLUDE_NOT_PROVIDED",
90
+ XSD_IMPORT_NOT_PROVIDED: "XSD_IMPORT_NOT_PROVIDED"
91
+ };
92
+
93
+ // src/parser/parseXsd.js
94
+ function parseXsd(xsdText) {
95
+ const issues = [];
96
+ if (typeof xsdText !== "string" || !xsdText.trim()) {
97
+ issues.push(
98
+ createIssue({
99
+ code: ISSUE_CODES.XSD_PARSE_ERROR,
100
+ severity: "error",
101
+ message: "XSD input must be a non-empty string.",
102
+ source: "xsd"
103
+ })
104
+ );
105
+ return { ok: false, doc: null, issues };
106
+ }
107
+ try {
108
+ const parser = new DOMParser();
109
+ const doc = parser.parseFromString(xsdText, "application/xml");
110
+ const parserError = doc.querySelector("parsererror");
111
+ if (parserError) {
112
+ issues.push(
113
+ createIssue({
114
+ code: ISSUE_CODES.XSD_PARSE_ERROR,
115
+ severity: "error",
116
+ message: parserError.textContent?.trim() || "Failed to parse XSD.",
117
+ source: "xsd"
118
+ })
119
+ );
120
+ return { ok: false, doc: null, issues };
121
+ }
122
+ return { ok: true, doc, issues };
123
+ } catch (error) {
124
+ issues.push(
125
+ createIssue({
126
+ code: ISSUE_CODES.XSD_PARSE_ERROR,
127
+ severity: "error",
128
+ message: error instanceof Error ? error.message : "Failed to parse XSD.",
129
+ source: "xsd"
130
+ })
131
+ );
132
+ return { ok: false, doc: null, issues };
133
+ }
134
+ }
135
+
136
+ // src/model/schemaModel.js
137
+ function createEmptySchemaModel() {
138
+ return {
139
+ kind: "schema",
140
+ targetNamespace: null,
141
+ elementFormDefault: null,
142
+ attributeFormDefault: null,
143
+ namespaces: {
144
+ default: null,
145
+ prefixes: /* @__PURE__ */ Object.create(null)
146
+ },
147
+ globals: {
148
+ elements: /* @__PURE__ */ Object.create(null),
149
+ complexTypes: /* @__PURE__ */ Object.create(null),
150
+ simpleTypes: /* @__PURE__ */ Object.create(null),
151
+ attributes: /* @__PURE__ */ Object.create(null),
152
+ groups: /* @__PURE__ */ Object.create(null),
153
+ attributeGroups: /* @__PURE__ */ Object.create(null)
154
+ },
155
+ documents: [],
156
+ externalRefs: {
157
+ includes: [],
158
+ imports: []
159
+ },
160
+ roots: [],
161
+ references: {
162
+ types: [],
163
+ refs: [],
164
+ baseTypes: [],
165
+ groupRefs: [],
166
+ attributeGroupRefs: []
167
+ },
168
+ usedFeatures: /* @__PURE__ */ new Set(),
169
+ unsupportedFeatures: [],
170
+ sourceInfo: {
171
+ systemId: null
172
+ }
173
+ };
174
+ }
175
+ function normalizeOccurs(value, fallback = 1) {
176
+ if (value == null || value === "") return fallback;
177
+ if (value === "unbounded") return "unbounded";
178
+ const parsed = Number(value);
179
+ if (Number.isInteger(parsed) && parsed >= 0) return parsed;
180
+ return fallback;
181
+ }
182
+ function normalizeUse(value) {
183
+ if (!value) return null;
184
+ if (value === "optional" || value === "required" || value === "prohibited") {
185
+ return value;
186
+ }
187
+ return null;
188
+ }
189
+ function createElementDecl({
190
+ name = null,
191
+ qName = null,
192
+ namespaceUri: namespaceUri3 = null,
193
+ typeName = null,
194
+ refName = null,
195
+ inlineType = null,
196
+ minOccurs = 1,
197
+ maxOccurs = 1,
198
+ defaultValue = null,
199
+ fixedValue = null,
200
+ nillable = false,
201
+ line = null,
202
+ column = null,
203
+ path = null
204
+ } = {}) {
205
+ return {
206
+ kind: "element",
207
+ name,
208
+ qName,
209
+ namespaceUri: namespaceUri3,
210
+ typeName,
211
+ refName,
212
+ inlineType,
213
+ minOccurs,
214
+ maxOccurs,
215
+ defaultValue,
216
+ fixedValue,
217
+ nillable,
218
+ line,
219
+ column,
220
+ path
221
+ };
222
+ }
223
+ function createAttributeDecl({
224
+ name = null,
225
+ qName = null,
226
+ namespaceUri: namespaceUri3 = null,
227
+ typeName = null,
228
+ refName = null,
229
+ inlineType = null,
230
+ use = null,
231
+ defaultValue = null,
232
+ fixedValue = null,
233
+ line = null,
234
+ column = null,
235
+ path = null
236
+ } = {}) {
237
+ return {
238
+ kind: "attribute",
239
+ name,
240
+ qName,
241
+ namespaceUri: namespaceUri3,
242
+ typeName,
243
+ refName,
244
+ inlineType,
245
+ use,
246
+ defaultValue,
247
+ fixedValue,
248
+ line,
249
+ column,
250
+ path
251
+ };
252
+ }
253
+ function createComplexTypeDecl({
254
+ name = null,
255
+ qName = null,
256
+ namespaceUri: namespaceUri3 = null,
257
+ content = null,
258
+ attributes = [],
259
+ derivation = { kind: null, baseTypeName: null },
260
+ mixed = false,
261
+ abstract = false,
262
+ line = null,
263
+ column = null,
264
+ path = null
265
+ } = {}) {
266
+ return {
267
+ kind: "complexType",
268
+ name,
269
+ qName,
270
+ namespaceUri: namespaceUri3,
271
+ content,
272
+ attributes,
273
+ derivation,
274
+ mixed,
275
+ abstract,
276
+ line,
277
+ column,
278
+ path
279
+ };
280
+ }
281
+ function createSimpleTypeDecl({
282
+ name = null,
283
+ qName = null,
284
+ namespaceUri: namespaceUri3 = null,
285
+ baseTypeName = null,
286
+ facets = {},
287
+ enumerations = [],
288
+ line = null,
289
+ column = null,
290
+ path = null
291
+ } = {}) {
292
+ return {
293
+ kind: "simpleType",
294
+ name,
295
+ qName,
296
+ namespaceUri: namespaceUri3,
297
+ baseTypeName,
298
+ facets,
299
+ enumerations,
300
+ line,
301
+ column,
302
+ path
303
+ };
304
+ }
305
+ function createGroupDecl({
306
+ name,
307
+ qName = null,
308
+ namespaceUri: namespaceUri3 = null,
309
+ content = null,
310
+ line = null,
311
+ column = null,
312
+ path = null
313
+ } = {}) {
314
+ return {
315
+ kind: "group",
316
+ name,
317
+ qName,
318
+ namespaceUri: namespaceUri3,
319
+ content,
320
+ line,
321
+ column,
322
+ path
323
+ };
324
+ }
325
+ function createAttributeGroupDecl({
326
+ name,
327
+ qName = null,
328
+ namespaceUri: namespaceUri3 = null,
329
+ attributes = [],
330
+ line = null,
331
+ column = null,
332
+ path = null
333
+ } = {}) {
334
+ return {
335
+ kind: "attributeGroup",
336
+ name,
337
+ qName,
338
+ namespaceUri: namespaceUri3,
339
+ attributes,
340
+ line,
341
+ column,
342
+ path
343
+ };
344
+ }
345
+ function createAttributeGroupRef({
346
+ refName,
347
+ line = null,
348
+ column = null,
349
+ path = null
350
+ } = {}) {
351
+ return {
352
+ kind: "attributeGroupRef",
353
+ refName,
354
+ line,
355
+ column,
356
+ path
357
+ };
358
+ }
359
+ function createSequenceNode({
360
+ children = [],
361
+ minOccurs = 1,
362
+ maxOccurs = 1,
363
+ line = null,
364
+ column = null,
365
+ path = null
366
+ } = {}) {
367
+ return {
368
+ kind: "sequence",
369
+ children,
370
+ minOccurs,
371
+ maxOccurs,
372
+ line,
373
+ column,
374
+ path
375
+ };
376
+ }
377
+ function createChoiceNode({
378
+ children = [],
379
+ minOccurs = 1,
380
+ maxOccurs = 1,
381
+ line = null,
382
+ column = null,
383
+ path = null
384
+ } = {}) {
385
+ return {
386
+ kind: "choice",
387
+ children,
388
+ minOccurs,
389
+ maxOccurs,
390
+ line,
391
+ column,
392
+ path
393
+ };
394
+ }
395
+ function createAllNode({
396
+ children = [],
397
+ minOccurs = 1,
398
+ maxOccurs = 1,
399
+ line = null,
400
+ column = null,
401
+ path = null
402
+ } = {}) {
403
+ return {
404
+ kind: "all",
405
+ children,
406
+ minOccurs,
407
+ maxOccurs,
408
+ line,
409
+ column,
410
+ path
411
+ };
412
+ }
413
+ function createGroupRefNode({
414
+ refName,
415
+ minOccurs = 1,
416
+ maxOccurs = 1,
417
+ line = null,
418
+ column = null,
419
+ path = null
420
+ } = {}) {
421
+ return {
422
+ kind: "groupRef",
423
+ refName,
424
+ minOccurs,
425
+ maxOccurs,
426
+ line,
427
+ column,
428
+ path
429
+ };
430
+ }
431
+ function createAnyNode({
432
+ namespace = null,
433
+ processContents = null,
434
+ minOccurs = 1,
435
+ maxOccurs = 1,
436
+ line = null,
437
+ column = null,
438
+ path = null
439
+ } = {}) {
440
+ return {
441
+ kind: "any",
442
+ namespace,
443
+ processContents,
444
+ minOccurs,
445
+ maxOccurs,
446
+ line,
447
+ column,
448
+ path
449
+ };
450
+ }
451
+
452
+ // src/resolver/schemaResolvers.js
453
+ var BUILTIN_TYPES = /* @__PURE__ */ new Set([
454
+ "string",
455
+ "normalizedString",
456
+ "token",
457
+ "language",
458
+ "Name",
459
+ "NCName",
460
+ "ID",
461
+ "IDREF",
462
+ "IDREFS",
463
+ "ENTITY",
464
+ "ENTITIES",
465
+ "NMTOKEN",
466
+ "NMTOKENS",
467
+ "boolean",
468
+ "decimal",
469
+ "float",
470
+ "double",
471
+ "integer",
472
+ "nonPositiveInteger",
473
+ "negativeInteger",
474
+ "long",
475
+ "int",
476
+ "short",
477
+ "byte",
478
+ "nonNegativeInteger",
479
+ "unsignedLong",
480
+ "unsignedInt",
481
+ "unsignedShort",
482
+ "unsignedByte",
483
+ "positiveInteger",
484
+ "date",
485
+ "time",
486
+ "dateTime",
487
+ "duration",
488
+ "gYear",
489
+ "gYearMonth",
490
+ "gMonth",
491
+ "gMonthDay",
492
+ "gDay",
493
+ "hexBinary",
494
+ "base64Binary",
495
+ "anyURI",
496
+ "QName",
497
+ "NOTATION"
498
+ ]);
499
+ function parseQName(name) {
500
+ if (!name || typeof name !== "string") {
501
+ return { prefix: null, localName: null, qName: name || null };
502
+ }
503
+ const idx = name.indexOf(":");
504
+ if (idx < 0) {
505
+ return { prefix: null, localName: name, qName: name };
506
+ }
507
+ return {
508
+ prefix: name.slice(0, idx),
509
+ localName: name.slice(idx + 1),
510
+ qName: name
511
+ };
512
+ }
513
+ function stripNamespacePrefix(name) {
514
+ return parseQName(name).localName;
515
+ }
516
+ function resolveNamespaceUri(schema, prefix) {
517
+ if (!schema?.namespaces) return null;
518
+ if (prefix == null || prefix === "") {
519
+ return schema.namespaces.default || null;
520
+ }
521
+ return schema.namespaces.prefixes?.[prefix] || null;
522
+ }
523
+ function resolveQName(schema, qName) {
524
+ const parsed = parseQName(qName);
525
+ return {
526
+ ...parsed,
527
+ namespaceUri: resolveNamespaceUri(schema, parsed.prefix)
528
+ };
529
+ }
530
+ function makeLookupKey(namespaceUri3, localName3) {
531
+ return `${namespaceUri3 || ""}::${localName3 || ""}`;
532
+ }
533
+ function isBuiltinType(typeName, schema = null) {
534
+ const q = parseQName(typeName);
535
+ if (!q.localName) return false;
536
+ if (BUILTIN_TYPES.has(q.localName)) {
537
+ if (!q.prefix) return true;
538
+ if (!schema) return true;
539
+ const ns = resolveNamespaceUri(schema, q.prefix);
540
+ return ns === "http://www.w3.org/2001/XMLSchema";
541
+ }
542
+ return false;
543
+ }
544
+ function lookupByQName(bucket, schema, name) {
545
+ if (!bucket || !name) return null;
546
+ const resolved = resolveQName(schema, name);
547
+ const directKey = makeLookupKey(resolved.namespaceUri, resolved.localName);
548
+ return bucket[directKey] || bucket[makeLookupKey(null, resolved.localName)] || null;
549
+ }
550
+ function resolveGlobalElement(schema, name) {
551
+ return lookupByQName(schema?.globals?.elements, schema, name);
552
+ }
553
+ function resolveGlobalComplexType(schema, name) {
554
+ return lookupByQName(schema?.globals?.complexTypes, schema, name);
555
+ }
556
+ function resolveGlobalSimpleType(schema, name) {
557
+ return lookupByQName(schema?.globals?.simpleTypes, schema, name);
558
+ }
559
+ function resolveGlobalAttribute(schema, name) {
560
+ return lookupByQName(schema?.globals?.attributes, schema, name);
561
+ }
562
+ function resolveGroup(schema, name) {
563
+ return lookupByQName(schema?.globals?.groups, schema, name);
564
+ }
565
+ function resolveAttributeGroup(schema, name) {
566
+ return lookupByQName(schema?.globals?.attributeGroups, schema, name);
567
+ }
568
+ function resolveType(schema, typeName) {
569
+ if (!typeName) return null;
570
+ if (isBuiltinType(typeName, schema)) {
571
+ return {
572
+ kind: "builtinType",
573
+ name: parseQName(typeName).localName,
574
+ qName: typeName
575
+ };
576
+ }
577
+ return resolveGlobalSimpleType(schema, typeName) || resolveGlobalComplexType(schema, typeName) || null;
578
+ }
579
+ function resolveElementType(schema, elementDecl) {
580
+ if (!elementDecl) return null;
581
+ if (elementDecl.inlineType) return elementDecl.inlineType;
582
+ if (elementDecl.typeName) return resolveType(schema, elementDecl.typeName);
583
+ if (elementDecl.refName) {
584
+ const target = resolveGlobalElement(schema, elementDecl.refName);
585
+ if (!target) return null;
586
+ return resolveElementType(schema, target);
587
+ }
588
+ return null;
589
+ }
590
+ function resolveAttributeType(schema, attributeDecl) {
591
+ if (!attributeDecl) return null;
592
+ if (attributeDecl.inlineType) return attributeDecl.inlineType;
593
+ if (attributeDecl.typeName) return resolveType(schema, attributeDecl.typeName);
594
+ if (attributeDecl.refName) {
595
+ const target = resolveGlobalAttribute(schema, attributeDecl.refName);
596
+ if (!target) return null;
597
+ return resolveAttributeType(schema, target);
598
+ }
599
+ return null;
600
+ }
601
+ function getEffectiveSimpleType(schema, simpleTypeDecl) {
602
+ if (!simpleTypeDecl) return null;
603
+ const facets = { ...simpleTypeDecl.facets || {} };
604
+ const enumerations = [...simpleTypeDecl.enumerations || []];
605
+ if (simpleTypeDecl.baseTypeName && !isBuiltinType(simpleTypeDecl.baseTypeName, schema)) {
606
+ const base = resolveGlobalSimpleType(schema, simpleTypeDecl.baseTypeName);
607
+ if (base) {
608
+ const baseEffective = getEffectiveSimpleType(schema, base);
609
+ return {
610
+ ...simpleTypeDecl,
611
+ baseTypeName: baseEffective?.baseTypeName || simpleTypeDecl.baseTypeName,
612
+ facets: {
613
+ ...baseEffective?.facets || {},
614
+ ...facets
615
+ },
616
+ enumerations: enumerations.length ? enumerations : [...baseEffective?.enumerations || []]
617
+ };
618
+ }
619
+ }
620
+ return {
621
+ ...simpleTypeDecl,
622
+ facets,
623
+ enumerations
624
+ };
625
+ }
626
+ function mergeAttributeArrays(baseAttrs = [], ownAttrs = []) {
627
+ return [...baseAttrs, ...ownAttrs];
628
+ }
629
+ function getEffectiveAttributes(schema, complexTypeDecl) {
630
+ if (!complexTypeDecl) return [];
631
+ const own = complexTypeDecl.attributes || [];
632
+ const baseTypeName = complexTypeDecl.derivation?.baseTypeName;
633
+ if (!baseTypeName || complexTypeDecl.derivation?.kind !== "extension") {
634
+ return own;
635
+ }
636
+ const base = resolveGlobalComplexType(schema, baseTypeName);
637
+ if (!base) return own;
638
+ return mergeAttributeArrays(getEffectiveAttributes(schema, base), own);
639
+ }
640
+ function getEffectiveContent(schema, complexTypeDecl) {
641
+ if (!complexTypeDecl) return null;
642
+ const ownContent = complexTypeDecl.content || null;
643
+ const derivationKind = complexTypeDecl.derivation?.kind;
644
+ const baseTypeName = complexTypeDecl.derivation?.baseTypeName;
645
+ if (!baseTypeName || !derivationKind) {
646
+ return ownContent;
647
+ }
648
+ const base = resolveGlobalComplexType(schema, baseTypeName);
649
+ if (!base) return ownContent;
650
+ const baseContent = getEffectiveContent(schema, base);
651
+ if (derivationKind === "restriction") {
652
+ return ownContent || baseContent;
653
+ }
654
+ if (derivationKind === "extension") {
655
+ if (!baseContent) return ownContent;
656
+ if (!ownContent) return baseContent;
657
+ return {
658
+ kind: "sequence",
659
+ children: [baseContent, ownContent],
660
+ minOccurs: 1,
661
+ maxOccurs: 1,
662
+ line: complexTypeDecl.line,
663
+ column: complexTypeDecl.column,
664
+ path: `${complexTypeDecl.path || ""}/effectiveExtensionSequence`
665
+ };
666
+ }
667
+ return ownContent || baseContent;
668
+ }
669
+
670
+ // src/parser/buildSchemaModel.js
671
+ var UNSUPPORTED_NODE_FEATURES = /* @__PURE__ */ new Set([
672
+ "key",
673
+ "keyref",
674
+ "unique",
675
+ "any",
676
+ "anyAttribute",
677
+ "redefine",
678
+ "notation"
679
+ ]);
680
+ function elementChildren(node) {
681
+ return Array.from(node?.children || []).filter(
682
+ (child) => child.nodeType === 1
683
+ );
684
+ }
685
+ function recordExternalRef(schema, kind, node, path, loc) {
686
+ const entry = {
687
+ kind,
688
+ namespace: node.getAttribute("namespace") || null,
689
+ schemaLocation: node.getAttribute("schemaLocation") || null,
690
+ line: loc.line,
691
+ column: loc.column,
692
+ path
693
+ };
694
+ if (kind === "include") {
695
+ schema.externalRefs.includes.push(entry);
696
+ } else if (kind === "import") {
697
+ schema.externalRefs.imports.push(entry);
698
+ }
699
+ }
700
+ function mergeGlobalsIntoSchema(targetSchema, sourceSchema, issues, createDuplicateIssue) {
701
+ const buckets = [
702
+ ["elements", "DUPLICATE_GLOBAL_ELEMENT"],
703
+ ["complexTypes", "DUPLICATE_GLOBAL_COMPLEX_TYPE"],
704
+ ["simpleTypes", "DUPLICATE_GLOBAL_SIMPLE_TYPE"],
705
+ ["attributes", "DUPLICATE_GLOBAL_ATTRIBUTE"],
706
+ ["groups", "DUPLICATE_GLOBAL_GROUP"],
707
+ ["attributeGroups", "DUPLICATE_GLOBAL_ATTRIBUTE_GROUP"]
708
+ ];
709
+ for (const [bucketName, duplicateCode] of buckets) {
710
+ for (const [key, decl] of Object.entries(
711
+ sourceSchema.globals[bucketName] || {}
712
+ )) {
713
+ if (targetSchema.globals[bucketName][key]) {
714
+ issues.push(createDuplicateIssue(duplicateCode, decl));
715
+ continue;
716
+ }
717
+ targetSchema.globals[bucketName][key] = decl;
718
+ }
719
+ }
720
+ targetSchema.roots.push(...sourceSchema.roots || []);
721
+ targetSchema.references.types.push(...sourceSchema.references.types || []);
722
+ targetSchema.references.refs.push(...sourceSchema.references.refs || []);
723
+ targetSchema.references.baseTypes.push(
724
+ ...sourceSchema.references.baseTypes || []
725
+ );
726
+ targetSchema.references.groupRefs.push(
727
+ ...sourceSchema.references.groupRefs || []
728
+ );
729
+ targetSchema.references.attributeGroupRefs.push(
730
+ ...sourceSchema.references.attributeGroupRefs || []
731
+ );
732
+ targetSchema.externalRefs.includes.push(
733
+ ...sourceSchema.externalRefs.includes || []
734
+ );
735
+ targetSchema.externalRefs.imports.push(
736
+ ...sourceSchema.externalRefs.imports || []
737
+ );
738
+ for (const feature of sourceSchema.usedFeatures || []) {
739
+ targetSchema.usedFeatures.add(feature);
740
+ }
741
+ targetSchema.unsupportedFeatures.push(
742
+ ...sourceSchema.unsupportedFeatures || []
743
+ );
744
+ }
745
+ function extractNamespaces(schemaRoot, schema) {
746
+ for (const attr of Array.from(schemaRoot.attributes || [])) {
747
+ if (attr.name === "xmlns") {
748
+ schema.namespaces.default = attr.value;
749
+ } else if (attr.name.startsWith("xmlns:")) {
750
+ const prefix = attr.name.slice("xmlns:".length);
751
+ schema.namespaces.prefixes[prefix] = attr.value;
752
+ }
753
+ }
754
+ }
755
+ function getDeclarationNamespaceUri(schema, node, kind) {
756
+ const isQualified = kind === "attribute" ? schema.attributeFormDefault === "qualified" : schema.elementFormDefault === "qualified";
757
+ if (node.parentElement?.localName === "schema") {
758
+ return schema.targetNamespace || null;
759
+ }
760
+ return isQualified ? schema.targetNamespace || null : null;
761
+ }
762
+ function getSchemaRoot(doc) {
763
+ const root = doc?.documentElement || null;
764
+ return root && root.localName === "schema" ? root : null;
765
+ }
766
+ function makeLineIndex(text) {
767
+ const starts = [0];
768
+ for (let i = 0; i < text.length; i += 1) {
769
+ if (text[i] === "\n") starts.push(i + 1);
770
+ }
771
+ return starts;
772
+ }
773
+ function indexToLineColumn(index, lineStarts) {
774
+ let line = 1;
775
+ for (let i = 0; i < lineStarts.length; i += 1) {
776
+ if (lineStarts[i] > index) break;
777
+ line = i + 1;
778
+ }
779
+ const lineStart = lineStarts[line - 1] ?? 0;
780
+ return {
781
+ line,
782
+ column: index - lineStart + 1
783
+ };
784
+ }
785
+ function escapeRegExp(value) {
786
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
787
+ }
788
+ function locateNodeInSource(xsdText, lineStarts, node) {
789
+ if (!xsdText || !node) return { line: null, column: null };
790
+ const localName3 = node.localName;
791
+ const name = node.getAttribute("name");
792
+ const ref = node.getAttribute("ref");
793
+ const base = node.getAttribute("base");
794
+ const type = node.getAttribute("type");
795
+ const candidates = [
796
+ name ? `<(?:[\\w.-]+:)?${escapeRegExp(localName3)}\\b[^>]*\\bname=(["'])${escapeRegExp(name)}\\1` : null,
797
+ ref ? `<(?:[\\w.-]+:)?${escapeRegExp(localName3)}\\b[^>]*\\bref=(["'])${escapeRegExp(ref)}\\1` : null,
798
+ base ? `<(?:[\\w.-]+:)?${escapeRegExp(localName3)}\\b[^>]*\\bbase=(["'])${escapeRegExp(base)}\\1` : null,
799
+ type ? `<(?:[\\w.-]+:)?${escapeRegExp(localName3)}\\b[^>]*\\btype=(["'])${escapeRegExp(type)}\\1` : null,
800
+ `<(?:[\\w.-]+:)?${escapeRegExp(localName3)}\\b`
801
+ ].filter(Boolean);
802
+ for (const pattern of candidates) {
803
+ const regex = new RegExp(pattern, "m");
804
+ const match = regex.exec(xsdText);
805
+ if (match && typeof match.index === "number") {
806
+ return indexToLineColumn(match.index, lineStarts);
807
+ }
808
+ }
809
+ return { line: null, column: null };
810
+ }
811
+ function buildPath(parentPath, node) {
812
+ const kind = node.localName;
813
+ const name = node.getAttribute("name");
814
+ const ref = node.getAttribute("ref");
815
+ const base = node.getAttribute("base");
816
+ let qualifier = "";
817
+ if (name) qualifier = `[name="${name}"]`;
818
+ else if (ref) qualifier = `[ref="${ref}"]`;
819
+ else if (base) qualifier = `[base="${base}"]`;
820
+ return `${parentPath}/${kind}${qualifier}`;
821
+ }
822
+ function registerGlobal(schema, issues, bucketName, duplicateCode, decl) {
823
+ const localName3 = stripNamespacePrefix(decl.name);
824
+ if (!localName3) return;
825
+ const key = makeLookupKey(decl.namespaceUri, localName3);
826
+ if (schema.globals[bucketName][key]) {
827
+ issues.push(
828
+ createIssue({
829
+ code: duplicateCode,
830
+ severity: "error",
831
+ message: `Duplicate global ${decl.kind} declaration '${decl.name}'.`,
832
+ line: decl.line,
833
+ column: decl.column,
834
+ path: decl.path,
835
+ source: "xsd",
836
+ nodeKind: decl.kind,
837
+ name: decl.name,
838
+ details: { declarationName: decl.name }
839
+ })
840
+ );
841
+ return;
842
+ }
843
+ schema.globals[bucketName][key] = decl;
844
+ }
845
+ function collectReference(schema, kind, payload) {
846
+ schema.references[kind].push(payload);
847
+ }
848
+ function collectUnsupportedFeature(schema, feature) {
849
+ schema.unsupportedFeatures.push(feature);
850
+ }
851
+ function collectNodeDiagnostics(schema, issues, node, path, loc) {
852
+ const localName3 = node.localName;
853
+ schema.usedFeatures.add(localName3);
854
+ if (UNSUPPORTED_NODE_FEATURES.has(localName3)) {
855
+ collectUnsupportedFeature(schema, {
856
+ feature: `xs:${localName3}`,
857
+ line: loc.line,
858
+ column: loc.column,
859
+ path,
860
+ nodeKind: localName3,
861
+ name: node.getAttribute("name") || null
862
+ });
863
+ }
864
+ if (node.hasAttribute("substitutionGroup")) {
865
+ collectUnsupportedFeature(schema, {
866
+ feature: "xs:substitutionGroup",
867
+ line: loc.line,
868
+ column: loc.column,
869
+ path,
870
+ nodeKind: localName3,
871
+ name: node.getAttribute("name") || null
872
+ });
873
+ }
874
+ if (node.hasAttribute("type")) {
875
+ collectReference(schema, "types", {
876
+ typeName: node.getAttribute("type"),
877
+ line: loc.line,
878
+ column: loc.column,
879
+ path,
880
+ nodeKind: localName3,
881
+ name: node.getAttribute("name") || node.getAttribute("ref") || null
882
+ });
883
+ }
884
+ if ((localName3 === "element" || localName3 === "attribute") && node.hasAttribute("ref")) {
885
+ collectReference(schema, "refs", {
886
+ refName: node.getAttribute("ref"),
887
+ line: loc.line,
888
+ column: loc.column,
889
+ path,
890
+ nodeKind: localName3,
891
+ name: node.getAttribute("name") || null
892
+ });
893
+ }
894
+ if ((localName3 === "extension" || localName3 === "restriction") && node.hasAttribute("base")) {
895
+ collectReference(schema, "baseTypes", {
896
+ baseTypeName: node.getAttribute("base"),
897
+ line: loc.line,
898
+ column: loc.column,
899
+ path,
900
+ nodeKind: localName3,
901
+ name: node.getAttribute("name") || null
902
+ });
903
+ }
904
+ if (localName3 === "group" && node.hasAttribute("ref")) {
905
+ collectReference(schema, "groupRefs", {
906
+ refName: node.getAttribute("ref"),
907
+ line: loc.line,
908
+ column: loc.column,
909
+ path,
910
+ nodeKind: localName3,
911
+ name: node.getAttribute("name") || null
912
+ });
913
+ }
914
+ if (localName3 === "attributeGroup" && node.hasAttribute("ref")) {
915
+ collectReference(schema, "attributeGroupRefs", {
916
+ refName: node.getAttribute("ref"),
917
+ line: loc.line,
918
+ column: loc.column,
919
+ path,
920
+ nodeKind: localName3,
921
+ name: node.getAttribute("name") || null
922
+ });
923
+ }
924
+ const minOccurs = normalizeOccurs(node.getAttribute("minOccurs"), 1);
925
+ const maxOccurs = normalizeOccurs(node.getAttribute("maxOccurs"), 1);
926
+ if (typeof minOccurs === "number" && typeof maxOccurs === "number" && minOccurs > maxOccurs) {
927
+ issues.push(
928
+ createIssue({
929
+ code: ISSUE_CODES.INVALID_OCCURS_RANGE,
930
+ severity: "error",
931
+ message: `Invalid occurs range: minOccurs (${minOccurs}) is greater than maxOccurs (${maxOccurs}).`,
932
+ line: loc.line,
933
+ column: loc.column,
934
+ path,
935
+ source: "xsd",
936
+ nodeKind: localName3,
937
+ name: node.getAttribute("name") || null,
938
+ details: { minOccurs, maxOccurs }
939
+ })
940
+ );
941
+ }
942
+ if ((localName3 === "element" || localName3 === "attribute") && node.hasAttribute("default") && node.hasAttribute("fixed")) {
943
+ issues.push(
944
+ createIssue({
945
+ code: ISSUE_CODES.INVALID_DEFAULT_FIXED_COMBINATION,
946
+ severity: "error",
947
+ message: "Node cannot declare both default and fixed values.",
948
+ line: loc.line,
949
+ column: loc.column,
950
+ path,
951
+ source: "xsd",
952
+ nodeKind: localName3,
953
+ name: node.getAttribute("name") || node.getAttribute("ref") || null,
954
+ details: {
955
+ defaultValue: node.getAttribute("default"),
956
+ fixedValue: node.getAttribute("fixed")
957
+ }
958
+ })
959
+ );
960
+ }
961
+ }
962
+ function parseFacets(node) {
963
+ const facets = {};
964
+ const enumerations = [];
965
+ for (const child of elementChildren(node)) {
966
+ switch (child.localName) {
967
+ case "enumeration":
968
+ if (child.hasAttribute("value")) {
969
+ enumerations.push(child.getAttribute("value"));
970
+ }
971
+ break;
972
+ case "minLength":
973
+ case "maxLength":
974
+ case "length":
975
+ case "totalDigits":
976
+ case "fractionDigits":
977
+ if (child.hasAttribute("value")) {
978
+ const n = Number(child.getAttribute("value"));
979
+ if (Number.isFinite(n)) facets[child.localName] = n;
980
+ }
981
+ break;
982
+ case "minInclusive":
983
+ case "maxInclusive":
984
+ case "minExclusive":
985
+ case "maxExclusive":
986
+ if (child.hasAttribute("value")) {
987
+ facets[child.localName] = child.getAttribute("value");
988
+ }
989
+ break;
990
+ case "pattern":
991
+ if (!facets.pattern) facets.pattern = [];
992
+ if (child.hasAttribute("value")) {
993
+ facets.pattern.push(child.getAttribute("value"));
994
+ }
995
+ break;
996
+ case "whiteSpace":
997
+ if (child.hasAttribute("value")) {
998
+ facets.whiteSpace = child.getAttribute("value");
999
+ }
1000
+ break;
1001
+ default:
1002
+ break;
1003
+ }
1004
+ }
1005
+ return { facets, enumerations };
1006
+ }
1007
+ function parseSimpleType(node, xsdText, lineStarts, parentPath, schema, issues) {
1008
+ const path = buildPath(parentPath, node);
1009
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1010
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1011
+ let baseTypeName = null;
1012
+ let facets = {};
1013
+ let enumerations = [];
1014
+ const restriction = elementChildren(node).find(
1015
+ (child) => child.localName === "restriction"
1016
+ );
1017
+ if (restriction) {
1018
+ const restrictionPath = buildPath(path, restriction);
1019
+ const restrictionLoc = locateNodeInSource(xsdText, lineStarts, restriction);
1020
+ collectNodeDiagnostics(
1021
+ schema,
1022
+ issues,
1023
+ restriction,
1024
+ restrictionPath,
1025
+ restrictionLoc
1026
+ );
1027
+ baseTypeName = restriction.getAttribute("base");
1028
+ const parsed = parseFacets(restriction);
1029
+ facets = parsed.facets;
1030
+ enumerations = parsed.enumerations;
1031
+ }
1032
+ const qName = node.getAttribute("name");
1033
+ const namespaceUri3 = schema.targetNamespace || null;
1034
+ return createSimpleTypeDecl({
1035
+ name: qName ? parseQName(qName).localName : null,
1036
+ qName,
1037
+ namespaceUri: namespaceUri3,
1038
+ baseTypeName,
1039
+ facets,
1040
+ enumerations,
1041
+ line: loc.line,
1042
+ column: loc.column,
1043
+ path
1044
+ });
1045
+ }
1046
+ function parseAttribute(node, xsdText, lineStarts, parentPath, schema, issues) {
1047
+ const path = buildPath(parentPath, node);
1048
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1049
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1050
+ const inlineSimpleTypeNode = elementChildren(node).find(
1051
+ (child) => child.localName === "simpleType"
1052
+ );
1053
+ const inlineType = inlineSimpleTypeNode ? parseSimpleType(
1054
+ inlineSimpleTypeNode,
1055
+ xsdText,
1056
+ lineStarts,
1057
+ path,
1058
+ schema,
1059
+ issues
1060
+ ) : null;
1061
+ const qName = node.getAttribute("name");
1062
+ const namespaceURI = getDeclarationNamespaceUri(schema, node, "attribute");
1063
+ return createAttributeDecl({
1064
+ name: qName ? parseQName(qName).localName : null,
1065
+ qName,
1066
+ namespaceURI,
1067
+ typeName: node.getAttribute("type"),
1068
+ refName: node.getAttribute("ref"),
1069
+ inlineType,
1070
+ use: normalizeUse(node.getAttribute("use")),
1071
+ defaultValue: node.getAttribute("default"),
1072
+ fixedValue: node.getAttribute("fixed"),
1073
+ line: loc.line,
1074
+ column: loc.column,
1075
+ path
1076
+ });
1077
+ }
1078
+ function parseAttributeGroupRef(node, xsdText, lineStarts, parentPath, schema, issues) {
1079
+ const path = buildPath(parentPath, node);
1080
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1081
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1082
+ return createAttributeGroupRef({
1083
+ refName: node.getAttribute("ref"),
1084
+ line: loc.line,
1085
+ column: loc.column,
1086
+ path
1087
+ });
1088
+ }
1089
+ function parseAttributesContainer(nodes, xsdText, lineStarts, parentPath, schema, issues) {
1090
+ const attributes = [];
1091
+ for (const child of nodes) {
1092
+ if (child.localName === "attribute") {
1093
+ attributes.push(
1094
+ parseAttribute(child, xsdText, lineStarts, parentPath, schema, issues)
1095
+ );
1096
+ } else if (child.localName === "attributeGroup" && child.hasAttribute("ref")) {
1097
+ attributes.push(
1098
+ parseAttributeGroupRef(
1099
+ child,
1100
+ xsdText,
1101
+ lineStarts,
1102
+ parentPath,
1103
+ schema,
1104
+ issues
1105
+ )
1106
+ );
1107
+ }
1108
+ }
1109
+ return attributes;
1110
+ }
1111
+ function parseElement(node, xsdText, lineStarts, parentPath, schema, issues) {
1112
+ const path = buildPath(parentPath, node);
1113
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1114
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1115
+ let inlineType = null;
1116
+ const children = elementChildren(node);
1117
+ const inlineComplexTypeNode = children.find(
1118
+ (child) => child.localName === "complexType"
1119
+ );
1120
+ const inlineSimpleTypeNode = children.find(
1121
+ (child) => child.localName === "simpleType"
1122
+ );
1123
+ if (inlineComplexTypeNode) {
1124
+ inlineType = parseComplexType(
1125
+ inlineComplexTypeNode,
1126
+ xsdText,
1127
+ lineStarts,
1128
+ path,
1129
+ schema,
1130
+ issues
1131
+ );
1132
+ } else if (inlineSimpleTypeNode) {
1133
+ inlineType = parseSimpleType(
1134
+ inlineSimpleTypeNode,
1135
+ xsdText,
1136
+ lineStarts,
1137
+ path,
1138
+ schema,
1139
+ issues
1140
+ );
1141
+ }
1142
+ const qName = node.getAttribute("name");
1143
+ const namespaceUri3 = getDeclarationNamespaceUri(schema, node, "element");
1144
+ return createElementDecl({
1145
+ name: qName ? parseQName(qName).localName : null,
1146
+ qName,
1147
+ namespaceUri: namespaceUri3,
1148
+ typeName: node.getAttribute("type"),
1149
+ refName: node.getAttribute("ref"),
1150
+ inlineType,
1151
+ minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1152
+ maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1153
+ defaultValue: node.getAttribute("default"),
1154
+ fixedValue: node.getAttribute("fixed"),
1155
+ nillable: node.getAttribute("nillable") === "true",
1156
+ line: loc.line,
1157
+ column: loc.column,
1158
+ path
1159
+ });
1160
+ }
1161
+ function parseGroupRef(node, xsdText, lineStarts, parentPath, schema, issues) {
1162
+ const path = buildPath(parentPath, node);
1163
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1164
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1165
+ return createGroupRefNode({
1166
+ refName: node.getAttribute("ref"),
1167
+ minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1168
+ maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1169
+ line: loc.line,
1170
+ column: loc.column,
1171
+ path
1172
+ });
1173
+ }
1174
+ function parseAny(node, xsdText, lineStarts, parentPath, schema, issues) {
1175
+ const path = buildPath(parentPath, node);
1176
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1177
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1178
+ return createAnyNode({
1179
+ namespace: node.getAttribute("namespace"),
1180
+ processContents: node.getAttribute("processContents"),
1181
+ minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1182
+ maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1183
+ line: loc.line,
1184
+ column: loc.column,
1185
+ path
1186
+ });
1187
+ }
1188
+ function parseContentNode(node, xsdText, lineStarts, parentPath, schema, issues) {
1189
+ const path = buildPath(parentPath, node);
1190
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1191
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1192
+ switch (node.localName) {
1193
+ case "sequence":
1194
+ return createSequenceNode({
1195
+ children: parseContentChildren(
1196
+ node,
1197
+ xsdText,
1198
+ lineStarts,
1199
+ path,
1200
+ schema,
1201
+ issues
1202
+ ),
1203
+ minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1204
+ maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1205
+ line: loc.line,
1206
+ column: loc.column,
1207
+ path
1208
+ });
1209
+ case "choice":
1210
+ return createChoiceNode({
1211
+ children: parseContentChildren(
1212
+ node,
1213
+ xsdText,
1214
+ lineStarts,
1215
+ path,
1216
+ schema,
1217
+ issues
1218
+ ),
1219
+ minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1220
+ maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1221
+ line: loc.line,
1222
+ column: loc.column,
1223
+ path
1224
+ });
1225
+ case "all":
1226
+ return createAllNode({
1227
+ children: parseContentChildren(
1228
+ node,
1229
+ xsdText,
1230
+ lineStarts,
1231
+ path,
1232
+ schema,
1233
+ issues
1234
+ ),
1235
+ minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1236
+ maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1237
+ line: loc.line,
1238
+ column: loc.column,
1239
+ path
1240
+ });
1241
+ case "element":
1242
+ return parseElement(
1243
+ node,
1244
+ xsdText,
1245
+ lineStarts,
1246
+ parentPath,
1247
+ schema,
1248
+ issues
1249
+ );
1250
+ case "group":
1251
+ if (node.hasAttribute("ref")) {
1252
+ return parseGroupRef(
1253
+ node,
1254
+ xsdText,
1255
+ lineStarts,
1256
+ parentPath,
1257
+ schema,
1258
+ issues
1259
+ );
1260
+ }
1261
+ return null;
1262
+ case "any":
1263
+ return parseAny(node, xsdText, lineStarts, parentPath, schema, issues);
1264
+ default:
1265
+ return null;
1266
+ }
1267
+ }
1268
+ function parseContentChildren(node, xsdText, lineStarts, parentPath, schema, issues) {
1269
+ const children = [];
1270
+ for (const child of elementChildren(node)) {
1271
+ const parsed = parseContentNode(
1272
+ child,
1273
+ xsdText,
1274
+ lineStarts,
1275
+ parentPath,
1276
+ schema,
1277
+ issues
1278
+ );
1279
+ if (parsed) children.push(parsed);
1280
+ }
1281
+ return children;
1282
+ }
1283
+ function parseDerivationNode(node, xsdText, lineStarts, parentPath, schema, issues) {
1284
+ const path = buildPath(parentPath, node);
1285
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1286
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1287
+ let content = null;
1288
+ const contentNode = elementChildren(node).find(
1289
+ (child) => ["sequence", "choice", "all", "group", "element", "any"].includes(
1290
+ child.localName
1291
+ )
1292
+ );
1293
+ if (contentNode) {
1294
+ content = parseContentNode(
1295
+ contentNode,
1296
+ xsdText,
1297
+ lineStarts,
1298
+ path,
1299
+ schema,
1300
+ issues
1301
+ );
1302
+ }
1303
+ const attributes = parseAttributesContainer(
1304
+ elementChildren(node).filter(
1305
+ (child) => child.localName === "attribute" || child.localName === "attributeGroup"
1306
+ ),
1307
+ xsdText,
1308
+ lineStarts,
1309
+ path,
1310
+ schema,
1311
+ issues
1312
+ );
1313
+ return {
1314
+ derivation: {
1315
+ kind: node.localName,
1316
+ baseTypeName: node.getAttribute("base")
1317
+ },
1318
+ content,
1319
+ attributes,
1320
+ line: loc.line,
1321
+ column: loc.column,
1322
+ path
1323
+ };
1324
+ }
1325
+ function parseComplexType(node, xsdText, lineStarts, parentPath, schema, issues) {
1326
+ const path = buildPath(parentPath, node);
1327
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1328
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1329
+ let content = null;
1330
+ let attributes = [];
1331
+ let derivation = { kind: null, baseTypeName: null };
1332
+ const children = elementChildren(node);
1333
+ const directContentNode = children.find(
1334
+ (child) => ["sequence", "choice", "all", "group", "element", "any"].includes(
1335
+ child.localName
1336
+ )
1337
+ );
1338
+ if (directContentNode) {
1339
+ content = parseContentNode(
1340
+ directContentNode,
1341
+ xsdText,
1342
+ lineStarts,
1343
+ path,
1344
+ schema,
1345
+ issues
1346
+ );
1347
+ }
1348
+ const complexContent = children.find(
1349
+ (child) => child.localName === "complexContent"
1350
+ );
1351
+ const simpleContent = children.find(
1352
+ (child) => child.localName === "simpleContent"
1353
+ );
1354
+ if (complexContent || simpleContent) {
1355
+ const wrapper = complexContent || simpleContent;
1356
+ const wrapperPath = buildPath(path, wrapper);
1357
+ const wrapperLoc = locateNodeInSource(xsdText, lineStarts, wrapper);
1358
+ collectNodeDiagnostics(schema, issues, wrapper, wrapperPath, wrapperLoc);
1359
+ const derivationNode = elementChildren(wrapper).find(
1360
+ (child) => child.localName === "extension" || child.localName === "restriction"
1361
+ );
1362
+ if (derivationNode) {
1363
+ const parsed = parseDerivationNode(
1364
+ derivationNode,
1365
+ xsdText,
1366
+ lineStarts,
1367
+ wrapperPath,
1368
+ schema,
1369
+ issues
1370
+ );
1371
+ derivation = parsed.derivation;
1372
+ if (parsed.content) content = parsed.content;
1373
+ attributes = parsed.attributes;
1374
+ }
1375
+ }
1376
+ if (attributes.length === 0) {
1377
+ attributes = parseAttributesContainer(
1378
+ children.filter(
1379
+ (child) => child.localName === "attribute" || child.localName === "attributeGroup"
1380
+ ),
1381
+ xsdText,
1382
+ lineStarts,
1383
+ path,
1384
+ schema,
1385
+ issues
1386
+ );
1387
+ }
1388
+ const qName = node.getAttribute("name");
1389
+ const namespaceURI = schema.targetNamespace || null;
1390
+ return createComplexTypeDecl({
1391
+ name: qName ? parseQName(qName).localName : null,
1392
+ qName,
1393
+ namespaceURI,
1394
+ content,
1395
+ attributes,
1396
+ derivation,
1397
+ mixed: node.getAttribute("mixed") === "true",
1398
+ abstract: node.getAttribute("abstract") === "true",
1399
+ line: loc.line,
1400
+ column: loc.column,
1401
+ path
1402
+ });
1403
+ }
1404
+ function parseGroup(node, xsdText, lineStarts, parentPath, schema, issues) {
1405
+ const path = buildPath(parentPath, node);
1406
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1407
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1408
+ const contentNode = elementChildren(node).find(
1409
+ (child) => ["sequence", "choice", "all"].includes(child.localName)
1410
+ );
1411
+ const qName = node.getAttribute("name");
1412
+ const namespaceUri3 = schema.targetNamespace || null;
1413
+ return createGroupDecl({
1414
+ name: qName ? parseQName(qName).localName : null,
1415
+ qName,
1416
+ namespaceUri: namespaceUri3,
1417
+ content: contentNode ? parseContentNode(contentNode, xsdText, lineStarts, path, schema, issues) : null,
1418
+ line: loc.line,
1419
+ column: loc.column,
1420
+ path
1421
+ });
1422
+ }
1423
+ function parseAttributeGroup(node, xsdText, lineStarts, parentPath, schema, issues) {
1424
+ const path = buildPath(parentPath, node);
1425
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1426
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1427
+ const attributes = parseAttributesContainer(
1428
+ elementChildren(node).filter(
1429
+ (child) => child.localName === "attribute" || child.localName === "attributeGroup"
1430
+ ),
1431
+ xsdText,
1432
+ lineStarts,
1433
+ path,
1434
+ schema,
1435
+ issues
1436
+ );
1437
+ const qName = node.getAttribute("name");
1438
+ const namespaceUri3 = schema.targetNamespace || null;
1439
+ return createAttributeGroupDecl({
1440
+ name: qName ? parseQName(qName).localName : null,
1441
+ qName,
1442
+ namespaceUri: namespaceUri3,
1443
+ attributes,
1444
+ line: loc.line,
1445
+ column: loc.column,
1446
+ path
1447
+ });
1448
+ }
1449
+ function buildSchemaModel(doc, options = {}) {
1450
+ const issues = [];
1451
+ const schema = createEmptySchemaModel();
1452
+ const xsdText = options.xsdText || "";
1453
+ const lineStarts = makeLineIndex(xsdText);
1454
+ const schemaRoot = getSchemaRoot(doc);
1455
+ if (!schemaRoot) {
1456
+ issues.push(
1457
+ createIssue({
1458
+ code: ISSUE_CODES.XSD_SCHEMA_NODE_MISSING,
1459
+ severity: "error",
1460
+ message: "Document root is not an xs:schema node.",
1461
+ source: "xsd"
1462
+ })
1463
+ );
1464
+ return { schema: null, issues };
1465
+ }
1466
+ schema.targetNamespace = schemaRoot.getAttribute("targetNamespace");
1467
+ schema.elementFormDefault = schemaRoot.getAttribute("elementFormDefault");
1468
+ schema.attributeFormDefault = schemaRoot.getAttribute("attributeFormDefault");
1469
+ extractNamespaces(schemaRoot, schema);
1470
+ const rootPath = "/schema";
1471
+ const rootLoc = locateNodeInSource(xsdText, lineStarts, schemaRoot);
1472
+ collectNodeDiagnostics(schema, issues, schemaRoot, rootPath, rootLoc);
1473
+ const children = elementChildren(schemaRoot);
1474
+ for (const child of children) {
1475
+ switch (child.localName) {
1476
+ case "element": {
1477
+ const decl = parseElement(
1478
+ child,
1479
+ xsdText,
1480
+ lineStarts,
1481
+ rootPath,
1482
+ schema,
1483
+ issues
1484
+ );
1485
+ registerGlobal(
1486
+ schema,
1487
+ issues,
1488
+ "elements",
1489
+ ISSUE_CODES.DUPLICATE_GLOBAL_ELEMENT,
1490
+ decl
1491
+ );
1492
+ if (decl.name) {
1493
+ schema.roots.push({
1494
+ name: decl.name,
1495
+ qName: decl.qName,
1496
+ namespaceUri: decl.namespaceUri,
1497
+ typeName: decl.typeName || decl.inlineType?.name || null,
1498
+ line: decl.line,
1499
+ column: decl.column,
1500
+ path: decl.path
1501
+ });
1502
+ }
1503
+ break;
1504
+ }
1505
+ case "complexType": {
1506
+ const decl = parseComplexType(
1507
+ child,
1508
+ xsdText,
1509
+ lineStarts,
1510
+ rootPath,
1511
+ schema,
1512
+ issues
1513
+ );
1514
+ registerGlobal(
1515
+ schema,
1516
+ issues,
1517
+ "complexTypes",
1518
+ ISSUE_CODES.DUPLICATE_GLOBAL_COMPLEX_TYPE,
1519
+ decl
1520
+ );
1521
+ break;
1522
+ }
1523
+ case "simpleType": {
1524
+ const decl = parseSimpleType(
1525
+ child,
1526
+ xsdText,
1527
+ lineStarts,
1528
+ rootPath,
1529
+ schema,
1530
+ issues
1531
+ );
1532
+ registerGlobal(
1533
+ schema,
1534
+ issues,
1535
+ "simpleTypes",
1536
+ ISSUE_CODES.DUPLICATE_GLOBAL_SIMPLE_TYPE,
1537
+ decl
1538
+ );
1539
+ break;
1540
+ }
1541
+ case "attribute": {
1542
+ const decl = parseAttribute(
1543
+ child,
1544
+ xsdText,
1545
+ lineStarts,
1546
+ rootPath,
1547
+ schema,
1548
+ issues
1549
+ );
1550
+ registerGlobal(
1551
+ schema,
1552
+ issues,
1553
+ "attributes",
1554
+ ISSUE_CODES.DUPLICATE_GLOBAL_ATTRIBUTE,
1555
+ decl
1556
+ );
1557
+ break;
1558
+ }
1559
+ case "group": {
1560
+ if (child.hasAttribute("name")) {
1561
+ const decl = parseGroup(
1562
+ child,
1563
+ xsdText,
1564
+ lineStarts,
1565
+ rootPath,
1566
+ schema,
1567
+ issues
1568
+ );
1569
+ registerGlobal(
1570
+ schema,
1571
+ issues,
1572
+ "groups",
1573
+ ISSUE_CODES.DUPLICATE_GLOBAL_GROUP,
1574
+ decl
1575
+ );
1576
+ } else {
1577
+ const path = buildPath(rootPath, child);
1578
+ const loc = locateNodeInSource(xsdText, lineStarts, child);
1579
+ collectNodeDiagnostics(schema, issues, child, path, loc);
1580
+ }
1581
+ break;
1582
+ }
1583
+ case "attributeGroup": {
1584
+ if (child.hasAttribute("name")) {
1585
+ const decl = parseAttributeGroup(
1586
+ child,
1587
+ xsdText,
1588
+ lineStarts,
1589
+ rootPath,
1590
+ schema,
1591
+ issues
1592
+ );
1593
+ registerGlobal(
1594
+ schema,
1595
+ issues,
1596
+ "attributeGroups",
1597
+ ISSUE_CODES.DUPLICATE_GLOBAL_ATTRIBUTE_GROUP,
1598
+ decl
1599
+ );
1600
+ } else {
1601
+ const path = buildPath(rootPath, child);
1602
+ const loc = locateNodeInSource(xsdText, lineStarts, child);
1603
+ collectNodeDiagnostics(schema, issues, child, path, loc);
1604
+ }
1605
+ break;
1606
+ }
1607
+ case "include": {
1608
+ const path = buildPath(rootPath, child);
1609
+ const loc = locateNodeInSource(xsdText, lineStarts, child);
1610
+ collectNodeDiagnostics(schema, issues, child, path, loc);
1611
+ recordExternalRef(schema, "include", child, path, loc);
1612
+ break;
1613
+ }
1614
+ case "import": {
1615
+ const path = buildPath(rootPath, child);
1616
+ const loc = locateNodeInSource(xsdText, lineStarts, child);
1617
+ collectNodeDiagnostics(schema, issues, child, path, loc);
1618
+ recordExternalRef(schema, "import", child, path, loc);
1619
+ break;
1620
+ }
1621
+ default: {
1622
+ const path = buildPath(rootPath, child);
1623
+ const loc = locateNodeInSource(xsdText, lineStarts, child);
1624
+ collectNodeDiagnostics(schema, issues, child, path, loc);
1625
+ break;
1626
+ }
1627
+ }
1628
+ }
1629
+ const externalDocuments = options.externalDocuments || {};
1630
+ const createDuplicateIssue = (code, decl) => createIssue({
1631
+ code: ISSUE_CODES[code] || code,
1632
+ severity: "error",
1633
+ message: `Duplicate global ${decl.kind} declaration '${decl.name}'.`,
1634
+ line: decl.line,
1635
+ column: decl.column,
1636
+ path: decl.path,
1637
+ source: "xsd",
1638
+ nodeKind: decl.kind,
1639
+ name: decl.name,
1640
+ details: { declarationName: decl.name }
1641
+ });
1642
+ const allExternalRefs = [
1643
+ ...schema.externalRefs.includes || [],
1644
+ ...schema.externalRefs.imports || []
1645
+ ];
1646
+ for (const ref of allExternalRefs) {
1647
+ if (!ref.schemaLocation) continue;
1648
+ const externalXsdText = externalDocuments[ref.schemaLocation];
1649
+ if (!externalXsdText) continue;
1650
+ const parser = new DOMParser();
1651
+ const externalDoc = parser.parseFromString(
1652
+ externalXsdText,
1653
+ "application/xml"
1654
+ );
1655
+ const parserError = externalDoc.querySelector("parsererror");
1656
+ if (parserError) {
1657
+ continue;
1658
+ }
1659
+ const externalBuild = buildSchemaModel(externalDoc, {
1660
+ ...options,
1661
+ xsdText: externalXsdText,
1662
+ externalDocuments: {}
1663
+ });
1664
+ if (externalBuild.schema) {
1665
+ mergeGlobalsIntoSchema(
1666
+ schema,
1667
+ externalBuild.schema,
1668
+ issues,
1669
+ createDuplicateIssue
1670
+ );
1671
+ }
1672
+ issues.push(...externalBuild.issues || []);
1673
+ }
1674
+ return { schema, issues };
1675
+ }
1676
+
1677
+ // src/diagnostics/schemaFacetDiagnostics.js
1678
+ function toNumber(value) {
1679
+ const n = Number(value);
1680
+ return Number.isFinite(n) ? n : null;
1681
+ }
1682
+ function checkLengthConflicts(simpleType, issues, ctx) {
1683
+ const f = simpleType.facets || {};
1684
+ if (f.length != null) {
1685
+ if (f.minLength != null && f.length < f.minLength) {
1686
+ issues.push(ctx.issue("XSD_LENGTH_CONFLICT", `length (${f.length}) is less than minLength (${f.minLength}).`, simpleType));
1687
+ }
1688
+ if (f.maxLength != null && f.length > f.maxLength) {
1689
+ issues.push(ctx.issue("XSD_LENGTH_CONFLICT", `length (${f.length}) exceeds maxLength (${f.maxLength}).`, simpleType));
1690
+ }
1691
+ }
1692
+ if (f.minLength != null && f.maxLength != null && f.minLength > f.maxLength) {
1693
+ issues.push(ctx.issue("XSD_LENGTH_CONFLICT", `minLength (${f.minLength}) is greater than maxLength (${f.maxLength}).`, simpleType));
1694
+ }
1695
+ }
1696
+ function checkNumericConflicts(simpleType, issues, ctx) {
1697
+ const f = simpleType.facets || {};
1698
+ const minInc = toNumber(f.minInclusive);
1699
+ const maxInc = toNumber(f.maxInclusive);
1700
+ const minExc = toNumber(f.minExclusive);
1701
+ const maxExc = toNumber(f.maxExclusive);
1702
+ if (minInc != null && maxInc != null && minInc > maxInc) {
1703
+ issues.push(ctx.issue("XSD_NUMERIC_RANGE_CONFLICT", `minInclusive (${minInc}) > maxInclusive (${maxInc}).`, simpleType));
1704
+ }
1705
+ if (minExc != null && maxExc != null && minExc >= maxExc) {
1706
+ issues.push(ctx.issue("XSD_NUMERIC_RANGE_CONFLICT", `minExclusive (${minExc}) >= maxExclusive (${maxExc}).`, simpleType));
1707
+ }
1708
+ if (minInc != null && maxExc != null && minInc >= maxExc) {
1709
+ issues.push(ctx.issue("XSD_NUMERIC_RANGE_CONFLICT", `minInclusive (${minInc}) >= maxExclusive (${maxExc}).`, simpleType));
1710
+ }
1711
+ if (minExc != null && maxInc != null && minExc >= maxInc) {
1712
+ issues.push(ctx.issue("XSD_NUMERIC_RANGE_CONFLICT", `minExclusive (${minExc}) >= maxInclusive (${maxInc}).`, simpleType));
1713
+ }
1714
+ }
1715
+ function checkDigitConflicts(simpleType, issues, ctx) {
1716
+ const f = simpleType.facets || {};
1717
+ if (f.totalDigits != null && f.totalDigits <= 0) {
1718
+ issues.push(ctx.issue("XSD_DIGITS_INVALID", `totalDigits must be > 0.`, simpleType));
1719
+ }
1720
+ if (f.fractionDigits != null && f.fractionDigits < 0) {
1721
+ issues.push(ctx.issue("XSD_DIGITS_INVALID", `fractionDigits must be >= 0.`, simpleType));
1722
+ }
1723
+ if (f.totalDigits != null && f.fractionDigits != null && f.fractionDigits > f.totalDigits) {
1724
+ issues.push(
1725
+ ctx.issue(
1726
+ "XSD_DIGITS_CONFLICT",
1727
+ `fractionDigits (${f.fractionDigits}) cannot exceed totalDigits (${f.totalDigits}).`,
1728
+ simpleType
1729
+ )
1730
+ );
1731
+ }
1732
+ }
1733
+ function checkEnumeration(simpleType, issues, ctx) {
1734
+ const enums = simpleType.enumerations || [];
1735
+ if (enums.length === 0) return;
1736
+ const seen = /* @__PURE__ */ new Set();
1737
+ for (const val of enums) {
1738
+ if (seen.has(val)) {
1739
+ issues.push(ctx.issue("XSD_ENUM_DUPLICATE", `Duplicate enumeration value '${val}'.`, simpleType));
1740
+ }
1741
+ seen.add(val);
1742
+ }
1743
+ }
1744
+ function checkPattern(simpleType, issues, ctx) {
1745
+ const patterns = simpleType.facets?.pattern || [];
1746
+ for (const pattern of patterns) {
1747
+ try {
1748
+ new RegExp(pattern);
1749
+ } catch {
1750
+ issues.push(ctx.issue("XSD_PATTERN_INVALID", `Invalid regex pattern '${pattern}'.`, simpleType));
1751
+ }
1752
+ }
1753
+ }
1754
+ function allowedFacetMap() {
1755
+ return {
1756
+ string: ["length", "minLength", "maxLength", "pattern", "enumeration"],
1757
+ normalizedString: ["length", "minLength", "maxLength", "pattern", "enumeration"],
1758
+ token: ["length", "minLength", "maxLength", "pattern", "enumeration"],
1759
+ anyURI: ["length", "minLength", "maxLength", "pattern", "enumeration"],
1760
+ QName: ["length", "minLength", "maxLength", "pattern", "enumeration"],
1761
+ decimal: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "totalDigits", "fractionDigits", "pattern", "enumeration"],
1762
+ integer: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "totalDigits", "pattern", "enumeration"],
1763
+ boolean: ["pattern", "enumeration"],
1764
+ date: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1765
+ dateTime: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1766
+ time: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1767
+ gYear: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1768
+ gYearMonth: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1769
+ gMonth: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1770
+ gMonthDay: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"],
1771
+ gDay: ["minInclusive", "maxInclusive", "minExclusive", "maxExclusive", "pattern", "enumeration"]
1772
+ };
1773
+ }
1774
+ function checkFacetCompatibility(simpleType, issues, ctx) {
1775
+ const base = simpleType.baseTypeName;
1776
+ if (!base || !isBuiltinType(base)) return;
1777
+ const local = stripNamespacePrefix(base);
1778
+ const allowed = allowedFacetMap()[local];
1779
+ if (!allowed) return;
1780
+ for (const key of Object.keys(simpleType.facets || {})) {
1781
+ if (!allowed.includes(key)) {
1782
+ issues.push(
1783
+ ctx.issue(
1784
+ "XSD_FACET_NOT_ALLOWED",
1785
+ `Facet '${key}' is not valid for base type '${local}'.`,
1786
+ simpleType
1787
+ )
1788
+ );
1789
+ }
1790
+ }
1791
+ }
1792
+ function runFacetDiagnostics(schema, options = {}) {
1793
+ const issues = [];
1794
+ const ctx = {
1795
+ issue: (code, message, node) => createIssue({
1796
+ code,
1797
+ severity: "warning",
1798
+ message,
1799
+ source: "xsd",
1800
+ nodeKind: "simpleType",
1801
+ name: node.name,
1802
+ line: node.line,
1803
+ column: node.column
1804
+ })
1805
+ };
1806
+ for (const simpleType of Object.values(schema.globals.simpleTypes || {})) {
1807
+ checkFacetCompatibility(simpleType, issues, ctx);
1808
+ checkLengthConflicts(simpleType, issues, ctx);
1809
+ checkNumericConflicts(simpleType, issues, ctx);
1810
+ checkDigitConflicts(simpleType, issues, ctx);
1811
+ checkEnumeration(simpleType, issues, ctx);
1812
+ checkPattern(simpleType, issues, ctx);
1813
+ }
1814
+ return issues;
1815
+ }
1816
+
1817
+ // src/diagnostics/schemaRestrictionDiagnostics.js
1818
+ function asArray(value) {
1819
+ return Array.isArray(value) ? value : [];
1820
+ }
1821
+ function localDeclName(node) {
1822
+ return node?.refName || node?.name || null;
1823
+ }
1824
+ function flattenContent(node, out = []) {
1825
+ if (!node) return out;
1826
+ switch (node.kind) {
1827
+ case "sequence":
1828
+ case "choice":
1829
+ case "all":
1830
+ for (const child of asArray(node.children)) {
1831
+ flattenContent(child, out);
1832
+ }
1833
+ return out;
1834
+ case "groupRef":
1835
+ out.push({
1836
+ kind: "groupRef",
1837
+ name: node.refName,
1838
+ minOccurs: node.minOccurs,
1839
+ maxOccurs: node.maxOccurs,
1840
+ line: node.line,
1841
+ column: node.column,
1842
+ path: node.path
1843
+ });
1844
+ return out;
1845
+ case "element":
1846
+ out.push({
1847
+ kind: "element",
1848
+ name: localDeclName(node),
1849
+ minOccurs: node.minOccurs,
1850
+ maxOccurs: node.maxOccurs,
1851
+ line: node.line,
1852
+ column: node.column,
1853
+ path: node.path
1854
+ });
1855
+ return out;
1856
+ default:
1857
+ return out;
1858
+ }
1859
+ }
1860
+ function maxToNumber(value) {
1861
+ return value === "unbounded" ? Infinity : value;
1862
+ }
1863
+ function isWiderRestriction(derived, base) {
1864
+ const dMin = typeof derived.minOccurs === "number" ? derived.minOccurs : 1;
1865
+ const bMin = typeof base.minOccurs === "number" ? base.minOccurs : 1;
1866
+ const dMax = maxToNumber(derived.maxOccurs ?? 1);
1867
+ const bMax = maxToNumber(base.maxOccurs ?? 1);
1868
+ return dMin < bMin || dMax > bMax;
1869
+ }
1870
+ function attributeUseRank(use) {
1871
+ switch (use) {
1872
+ case "required":
1873
+ return 3;
1874
+ case "optional":
1875
+ return 2;
1876
+ case "prohibited":
1877
+ return 1;
1878
+ default:
1879
+ return 2;
1880
+ }
1881
+ }
1882
+ function buildRestrictionIssue(code, message, node) {
1883
+ return createIssue({
1884
+ code,
1885
+ severity: "warning",
1886
+ message,
1887
+ source: "xsd",
1888
+ nodeKind: node?.kind || "complexType",
1889
+ name: node?.name || null,
1890
+ line: node?.line ?? null,
1891
+ column: node?.column ?? null,
1892
+ path: node?.path ?? null,
1893
+ details: {}
1894
+ });
1895
+ }
1896
+ function checkRestrictedContentSubset(schema, derivedType, baseType, issues) {
1897
+ const derivedContent = flattenContent(getEffectiveContent(schema, derivedType), []);
1898
+ const baseContent = flattenContent(getEffectiveContent(schema, baseType), []);
1899
+ const baseMap = new Map(baseContent.map((item) => [item.name, item]));
1900
+ for (const item of derivedContent) {
1901
+ const baseItem = baseMap.get(item.name);
1902
+ if (!baseItem) {
1903
+ issues.push(
1904
+ buildRestrictionIssue(
1905
+ "XSD_RESTRICTION_NOT_SUBSET",
1906
+ `Restricted type contains element/group '${item.name}' that does not exist in base type '${baseType.name}'.`,
1907
+ item
1908
+ )
1909
+ );
1910
+ continue;
1911
+ }
1912
+ if (isWiderRestriction(item, baseItem)) {
1913
+ issues.push(
1914
+ buildRestrictionIssue(
1915
+ "XSD_RESTRICTION_OCCURS_WIDENED",
1916
+ `Restricted type widens occurrence constraints for '${item.name}'.`,
1917
+ item
1918
+ )
1919
+ );
1920
+ }
1921
+ }
1922
+ }
1923
+ function checkRestrictedAttributes(schema, derivedType, baseType, issues) {
1924
+ const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
1925
+ const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
1926
+ const baseMap = new Map(
1927
+ baseAttrs.filter((attr) => attr?.kind === "attribute").map((attr) => [localDeclName(attr), attr])
1928
+ );
1929
+ for (const attr of derivedAttrs) {
1930
+ if (attr?.kind !== "attribute") continue;
1931
+ const name = localDeclName(attr);
1932
+ const baseAttr = baseMap.get(name);
1933
+ if (!baseAttr) {
1934
+ issues.push(
1935
+ buildRestrictionIssue(
1936
+ "XSD_RESTRICTION_NOT_SUBSET",
1937
+ `Restricted type contains attribute '${name}' that does not exist in base type '${baseType.name}'.`,
1938
+ attr
1939
+ )
1940
+ );
1941
+ continue;
1942
+ }
1943
+ if (attributeUseRank(attr.use) > attributeUseRank(baseAttr.use)) {
1944
+ issues.push(
1945
+ buildRestrictionIssue(
1946
+ "XSD_RESTRICTION_ATTRIBUTE_WIDENED",
1947
+ `Restricted type widens attribute constraint for '${name}'.`,
1948
+ attr
1949
+ )
1950
+ );
1951
+ }
1952
+ }
1953
+ }
1954
+ function runRestrictionDiagnostics(schema) {
1955
+ const issues = [];
1956
+ for (const complexType of Object.values(schema.globals.complexTypes || {})) {
1957
+ if (complexType?.derivation?.kind !== "restriction") continue;
1958
+ if (!complexType?.derivation?.baseTypeName) continue;
1959
+ const baseType = resolveGlobalComplexType(schema, complexType.derivation.baseTypeName);
1960
+ if (!baseType) continue;
1961
+ checkRestrictedContentSubset(schema, complexType, baseType, issues);
1962
+ checkRestrictedAttributes(schema, complexType, baseType, issues);
1963
+ }
1964
+ return issues;
1965
+ }
1966
+
1967
+ // src/diagnostics/schemaDefaultFixedDiagnostics.js
1968
+ function checkDefaultFixedConflict(node, issues) {
1969
+ if (node.defaultValue != null && node.fixedValue != null) {
1970
+ issues.push(
1971
+ createIssue({
1972
+ code: "XSD_DEFAULT_AND_FIXED_CONFLICT",
1973
+ severity: "warning",
1974
+ message: "Element/attribute cannot have both 'default' and 'fixed'.",
1975
+ source: "xsd",
1976
+ nodeKind: node.kind,
1977
+ name: node.name || node.refName,
1978
+ line: node.line,
1979
+ column: node.column
1980
+ })
1981
+ );
1982
+ }
1983
+ }
1984
+ function runDefaultFixedDiagnostics(schema) {
1985
+ const issues = [];
1986
+ for (const el of Object.values(schema.globals.elements || {})) {
1987
+ checkDefaultFixedConflict(el, issues);
1988
+ }
1989
+ for (const type of Object.values(schema.globals.complexTypes || {})) {
1990
+ for (const attr of type.attributes || []) {
1991
+ if (attr.kind === "attribute") {
1992
+ checkDefaultFixedConflict(attr, issues);
1993
+ }
1994
+ }
1995
+ }
1996
+ return issues;
1997
+ }
1998
+
1999
+ // src/diagnostics/schemaImportDiagnostics.js
2000
+ function runImportDiagnostics(schema, options = {}) {
2001
+ const issues = [];
2002
+ const externalDocuments = options.externalDocuments || {};
2003
+ for (const ref of schema.externalRefs.includes || []) {
2004
+ if (!ref.schemaLocation) continue;
2005
+ if (externalDocuments[ref.schemaLocation]) continue;
2006
+ issues.push(
2007
+ createIssue({
2008
+ code: ISSUE_CODES.XSD_INCLUDE_NOT_PROVIDED,
2009
+ severity: "warning",
2010
+ message: `Included schema '${ref.schemaLocation}' was referenced but not provided to the engine.`,
2011
+ source: "xsd",
2012
+ nodeKind: "include",
2013
+ name: ref.schemaLocation,
2014
+ line: ref.line,
2015
+ column: ref.column,
2016
+ path: ref.path,
2017
+ details: {
2018
+ schemaLocation: ref.schemaLocation
2019
+ }
2020
+ })
2021
+ );
2022
+ }
2023
+ for (const ref of schema.externalRefs.imports || []) {
2024
+ if (!ref.schemaLocation) continue;
2025
+ if (externalDocuments[ref.schemaLocation]) continue;
2026
+ issues.push(
2027
+ createIssue({
2028
+ code: ISSUE_CODES.XSD_IMPORT_NOT_PROVIDED,
2029
+ severity: "warning",
2030
+ message: `Imported schema '${ref.schemaLocation}' was referenced but not provided to the engine.`,
2031
+ source: "xsd",
2032
+ nodeKind: "import",
2033
+ name: ref.schemaLocation,
2034
+ line: ref.line,
2035
+ column: ref.column,
2036
+ path: ref.path,
2037
+ details: {
2038
+ schemaLocation: ref.schemaLocation,
2039
+ namespace: ref.namespace
2040
+ }
2041
+ })
2042
+ );
2043
+ }
2044
+ return issues;
2045
+ }
2046
+
2047
+ // src/diagnostics/schemaDiagnostics.js
2048
+ function buildStats(schema) {
2049
+ return {
2050
+ globalElementCount: Object.keys(schema.globals.elements).length,
2051
+ globalComplexTypeCount: Object.keys(schema.globals.complexTypes).length,
2052
+ globalSimpleTypeCount: Object.keys(schema.globals.simpleTypes).length,
2053
+ globalAttributeCount: Object.keys(schema.globals.attributes).length,
2054
+ globalGroupCount: Object.keys(schema.globals.groups).length,
2055
+ globalAttributeGroupCount: Object.keys(schema.globals.attributeGroups).length
2056
+ };
2057
+ }
2058
+ function sortUniqueStrings(values) {
2059
+ return [...new Set(values)].sort((a, b) => a.localeCompare(b));
2060
+ }
2061
+ function getSupportedFeatures(schema) {
2062
+ return sortUniqueStrings(
2063
+ [...schema.usedFeatures].filter(
2064
+ (name) => [
2065
+ "all",
2066
+ "attribute",
2067
+ "attributeGroup",
2068
+ "choice",
2069
+ "complexContent",
2070
+ "complexType",
2071
+ "element",
2072
+ "extension",
2073
+ "group",
2074
+ "restriction",
2075
+ "schema",
2076
+ "sequence",
2077
+ "simpleContent",
2078
+ "simpleType"
2079
+ ].includes(name)
2080
+ ).map((name) => `xs:${name}`)
2081
+ );
2082
+ }
2083
+ function getUnsupportedFeatures(schema) {
2084
+ return sortUniqueStrings(schema.unsupportedFeatures.map((item) => item.feature));
2085
+ }
2086
+ function checkUnknownTypes(schema, issues) {
2087
+ for (const ref of schema.references.types) {
2088
+ if (!ref.typeName) continue;
2089
+ if (isBuiltinType(ref.typeName)) continue;
2090
+ if (resolveType(schema, ref.typeName)) continue;
2091
+ issues.push(
2092
+ createIssue({
2093
+ code: ISSUE_CODES.UNKNOWN_TYPE,
2094
+ severity: "error",
2095
+ message: `Type '${ref.typeName}' could not be resolved.`,
2096
+ line: ref.line,
2097
+ column: ref.column,
2098
+ path: ref.path,
2099
+ source: "xsd",
2100
+ nodeKind: ref.nodeKind,
2101
+ name: ref.name,
2102
+ details: { typeName: ref.typeName }
2103
+ })
2104
+ );
2105
+ }
2106
+ }
2107
+ function checkUnknownRefs(schema, issues) {
2108
+ for (const ref of schema.references.refs) {
2109
+ const targetName = ref.refName;
2110
+ if (!targetName) continue;
2111
+ const resolved = ref.nodeKind === "attribute" ? resolveGlobalAttribute(schema, targetName) : resolveGlobalElement(schema, targetName);
2112
+ if (resolved) continue;
2113
+ issues.push(
2114
+ createIssue({
2115
+ code: ISSUE_CODES.UNKNOWN_REF,
2116
+ severity: "error",
2117
+ message: `${ref.nodeKind === "attribute" ? "Attribute" : "Element"} reference '${targetName}' could not be resolved.`,
2118
+ line: ref.line,
2119
+ column: ref.column,
2120
+ path: ref.path,
2121
+ source: "xsd",
2122
+ nodeKind: ref.nodeKind,
2123
+ name: ref.name,
2124
+ details: { refName: targetName }
2125
+ })
2126
+ );
2127
+ }
2128
+ }
2129
+ function checkMissingBaseTypes(schema, issues) {
2130
+ for (const ref of schema.references.baseTypes) {
2131
+ const targetName = ref.baseTypeName;
2132
+ if (!targetName) continue;
2133
+ if (isBuiltinType(targetName)) continue;
2134
+ if (resolveType(schema, targetName)) continue;
2135
+ issues.push(
2136
+ createIssue({
2137
+ code: ISSUE_CODES.MISSING_BASE_TYPE,
2138
+ severity: "error",
2139
+ message: `Base type '${targetName}' could not be resolved.`,
2140
+ line: ref.line,
2141
+ column: ref.column,
2142
+ path: ref.path,
2143
+ source: "xsd",
2144
+ nodeKind: ref.nodeKind,
2145
+ name: ref.name,
2146
+ details: { baseTypeName: targetName }
2147
+ })
2148
+ );
2149
+ }
2150
+ }
2151
+ function checkUnknownGroups(schema, issues) {
2152
+ for (const ref of schema.references.groupRefs) {
2153
+ if (resolveGroup(schema, ref.refName)) continue;
2154
+ issues.push(
2155
+ createIssue({
2156
+ code: ISSUE_CODES.UNKNOWN_GROUP,
2157
+ severity: "error",
2158
+ message: `Group reference '${ref.refName}' could not be resolved.`,
2159
+ line: ref.line,
2160
+ column: ref.column,
2161
+ path: ref.path,
2162
+ source: "xsd",
2163
+ nodeKind: ref.nodeKind,
2164
+ name: ref.name,
2165
+ details: { refName: ref.refName }
2166
+ })
2167
+ );
2168
+ }
2169
+ }
2170
+ function checkUnknownAttributeGroups(schema, issues) {
2171
+ for (const ref of schema.references.attributeGroupRefs) {
2172
+ if (resolveAttributeGroup(schema, ref.refName)) continue;
2173
+ issues.push(
2174
+ createIssue({
2175
+ code: ISSUE_CODES.UNKNOWN_ATTRIBUTE_GROUP,
2176
+ severity: "error",
2177
+ message: `Attribute group reference '${ref.refName}' could not be resolved.`,
2178
+ line: ref.line,
2179
+ column: ref.column,
2180
+ path: ref.path,
2181
+ source: "xsd",
2182
+ nodeKind: ref.nodeKind,
2183
+ name: ref.name,
2184
+ details: { refName: ref.refName }
2185
+ })
2186
+ );
2187
+ }
2188
+ }
2189
+ function emitUnsupportedFeatureWarnings(schema, issues, options) {
2190
+ if (options.includeWarnings === false) return;
2191
+ for (const feature of schema.unsupportedFeatures) {
2192
+ issues.push(
2193
+ createIssue({
2194
+ code: ISSUE_CODES.UNSUPPORTED_FEATURE,
2195
+ severity: "warning",
2196
+ message: `Feature '${feature.feature}' is recognized but not yet supported.`,
2197
+ line: feature.line,
2198
+ column: feature.column,
2199
+ path: feature.path,
2200
+ source: "engine",
2201
+ nodeKind: feature.nodeKind,
2202
+ name: feature.name,
2203
+ details: { feature: feature.feature }
2204
+ })
2205
+ );
2206
+ }
2207
+ }
2208
+ function runSchemaDiagnostics(schema, options = {}) {
2209
+ const issues = [];
2210
+ checkUnknownTypes(schema, issues);
2211
+ checkUnknownRefs(schema, issues);
2212
+ checkMissingBaseTypes(schema, issues);
2213
+ checkUnknownGroups(schema, issues);
2214
+ checkUnknownAttributeGroups(schema, issues);
2215
+ emitUnsupportedFeatureWarnings(schema, issues, options);
2216
+ const facetIssues = runFacetDiagnostics(schema, options);
2217
+ issues.push(...facetIssues);
2218
+ const restrictionIssues = runRestrictionDiagnostics(schema);
2219
+ issues.push(...restrictionIssues);
2220
+ const defaultFixedIssues = runDefaultFixedDiagnostics(schema);
2221
+ issues.push(...defaultFixedIssues);
2222
+ const importIssues = runImportDiagnostics(schema, options);
2223
+ issues.push(...importIssues);
2224
+ return {
2225
+ data: {
2226
+ roots: options.includeRoots === false ? [] : schema.roots,
2227
+ supportedFeatures: options.includeFeatureSummary === false ? [] : getSupportedFeatures(schema),
2228
+ unsupportedFeatures: options.includeFeatureSummary === false ? [] : getUnsupportedFeatures(schema),
2229
+ schemaStats: buildStats(schema)
2230
+ },
2231
+ issues
2232
+ };
2233
+ }
2234
+
2235
+ // src/utils/result.js
2236
+ function summarizeIssues(issues = []) {
2237
+ return issues.reduce(
2238
+ (acc, issue) => {
2239
+ if (issue.severity === "error") acc.errorCount += 1;
2240
+ else if (issue.severity === "warning") acc.warningCount += 1;
2241
+ else if (issue.severity === "info") acc.infoCount += 1;
2242
+ return acc;
2243
+ },
2244
+ { errorCount: 0, warningCount: 0, infoCount: 0 }
2245
+ );
2246
+ }
2247
+ function hasErrors(issues = []) {
2248
+ return issues.some((issue) => issue.severity === "error");
2249
+ }
2250
+ function makeResult({ data = null, issues = [] } = {}) {
2251
+ return {
2252
+ ok: !hasErrors(issues),
2253
+ data,
2254
+ issues,
2255
+ summary: summarizeIssues(issues)
2256
+ };
2257
+ }
2258
+
2259
+ // src/api/getSchemaDiagnostics.js
2260
+ function getSchemaDiagnostics({ xsdText, options = {} } = {}) {
2261
+ const parseResult = parseXsd(xsdText);
2262
+ if (!parseResult.ok || !parseResult.doc) {
2263
+ return makeResult({
2264
+ data: null,
2265
+ issues: parseResult.issues
2266
+ });
2267
+ }
2268
+ const modelResult = buildSchemaModel(parseResult.doc, {
2269
+ ...options,
2270
+ xsdText
2271
+ });
2272
+ const baseIssues = [
2273
+ ...parseResult.issues || [],
2274
+ ...modelResult.issues || []
2275
+ ];
2276
+ if (!modelResult.schema) {
2277
+ return makeResult({
2278
+ data: null,
2279
+ issues: baseIssues
2280
+ });
2281
+ }
2282
+ const diagnostics = runSchemaDiagnostics(modelResult.schema, options);
2283
+ return makeResult({
2284
+ data: diagnostics.data,
2285
+ issues: [...baseIssues, ...diagnostics.issues || []]
2286
+ });
2287
+ }
2288
+
2289
+ // src/tree/treeNodeBuilders.js
2290
+ function createTreeNode({
2291
+ kind,
2292
+ name = null,
2293
+ label = null,
2294
+ typeName = null,
2295
+ refName = null,
2296
+ baseTypeName = null,
2297
+ derivation = null,
2298
+ minOccurs = 1,
2299
+ maxOccurs = 1,
2300
+ use = null,
2301
+ line = null,
2302
+ column = null,
2303
+ path = null,
2304
+ children = []
2305
+ } = {}) {
2306
+ return {
2307
+ kind,
2308
+ name,
2309
+ label: label ?? name ?? kind,
2310
+ typeName,
2311
+ refName,
2312
+ baseTypeName,
2313
+ derivation,
2314
+ minOccurs,
2315
+ maxOccurs,
2316
+ use,
2317
+ line,
2318
+ column,
2319
+ path,
2320
+ children
2321
+ };
2322
+ }
2323
+
2324
+ // src/tree/extractTree.js
2325
+ function asArray2(value) {
2326
+ return Array.isArray(value) ? value : [];
2327
+ }
2328
+ function makeVisitedKey(prefix, nameOrPath) {
2329
+ return `${prefix}:${nameOrPath || "anonymous"}`;
2330
+ }
2331
+ function buildElementLabel(elementDecl) {
2332
+ if (elementDecl.refName) return elementDecl.refName;
2333
+ if (elementDecl.name) return elementDecl.name;
2334
+ return "element";
2335
+ }
2336
+ function buildAttributeLabel(attributeDecl) {
2337
+ if (attributeDecl.refName) return `@${attributeDecl.refName}`;
2338
+ if (attributeDecl.name) return `@${attributeDecl.name}`;
2339
+ return "@attribute";
2340
+ }
2341
+ function buildSimpleTypeChildren(schema, simpleTypeDecl) {
2342
+ if (!simpleTypeDecl) return [];
2343
+ const children = [];
2344
+ if (simpleTypeDecl.baseTypeName) {
2345
+ children.push(
2346
+ createTreeNode({
2347
+ kind: "baseType",
2348
+ label: `base: ${simpleTypeDecl.baseTypeName}`,
2349
+ baseTypeName: simpleTypeDecl.baseTypeName,
2350
+ line: simpleTypeDecl.line,
2351
+ column: simpleTypeDecl.column,
2352
+ path: simpleTypeDecl.path,
2353
+ children: []
2354
+ })
2355
+ );
2356
+ }
2357
+ const enumerations = asArray2(simpleTypeDecl.enumerations);
2358
+ if (enumerations.length) {
2359
+ children.push(
2360
+ createTreeNode({
2361
+ kind: "enumerations",
2362
+ label: "enumerations",
2363
+ line: simpleTypeDecl.line,
2364
+ column: simpleTypeDecl.column,
2365
+ path: simpleTypeDecl.path ? `${simpleTypeDecl.path}/enumerations` : null,
2366
+ children: enumerations.map(
2367
+ (value, index) => createTreeNode({
2368
+ kind: "enumeration",
2369
+ label: String(value),
2370
+ line: simpleTypeDecl.line,
2371
+ column: simpleTypeDecl.column,
2372
+ path: simpleTypeDecl.path ? `${simpleTypeDecl.path}/enumeration[${index + 1}]` : null,
2373
+ children: []
2374
+ })
2375
+ )
2376
+ })
2377
+ );
2378
+ }
2379
+ return children;
2380
+ }
2381
+ function buildAttributeNode(schema, attributeDecl, state) {
2382
+ const node = createTreeNode({
2383
+ kind: "attribute",
2384
+ name: attributeDecl.name,
2385
+ label: buildAttributeLabel(attributeDecl),
2386
+ typeName: attributeDecl.typeName,
2387
+ refName: attributeDecl.refName,
2388
+ use: attributeDecl.use,
2389
+ line: attributeDecl.line,
2390
+ column: attributeDecl.column,
2391
+ path: attributeDecl.path,
2392
+ children: []
2393
+ });
2394
+ if (attributeDecl.inlineType?.kind === "simpleType") {
2395
+ node.children.push(
2396
+ createTreeNode({
2397
+ kind: "simpleType",
2398
+ name: attributeDecl.inlineType.name,
2399
+ label: attributeDecl.inlineType.name || "simpleType",
2400
+ baseTypeName: attributeDecl.inlineType.baseTypeName,
2401
+ line: attributeDecl.inlineType.line,
2402
+ column: attributeDecl.inlineType.column,
2403
+ path: attributeDecl.inlineType.path,
2404
+ children: buildSimpleTypeChildren(schema, attributeDecl.inlineType)
2405
+ })
2406
+ );
2407
+ }
2408
+ return node;
2409
+ }
2410
+ function buildAttributesNodes(schema, attributes, state) {
2411
+ const nodes = [];
2412
+ for (const attr of asArray2(attributes)) {
2413
+ if (!attr) continue;
2414
+ if (attr.kind === "attribute") {
2415
+ nodes.push(buildAttributeNode(schema, attr, state));
2416
+ } else if (attr.kind === "attributeGroupRef") {
2417
+ const target = state.expandRefs ? state.resolveAttributeGroup?.(attr.refName) : null;
2418
+ const refNode = createTreeNode({
2419
+ kind: "attributeGroupRef",
2420
+ refName: attr.refName,
2421
+ label: `attributeGroup: ${attr.refName}`,
2422
+ line: attr.line,
2423
+ column: attr.column,
2424
+ path: attr.path,
2425
+ children: []
2426
+ });
2427
+ if (target) {
2428
+ refNode.children.push(
2429
+ createTreeNode({
2430
+ kind: "attributeGroup",
2431
+ name: target.name,
2432
+ label: target.name || "attributeGroup",
2433
+ line: target.line,
2434
+ column: target.column,
2435
+ path: target.path,
2436
+ children: buildAttributesNodes(schema, target.attributes || [], state)
2437
+ })
2438
+ );
2439
+ }
2440
+ nodes.push(refNode);
2441
+ }
2442
+ }
2443
+ return nodes;
2444
+ }
2445
+ function buildGroupRefNode(schema, groupRefNode, state) {
2446
+ const node = createTreeNode({
2447
+ kind: "groupRef",
2448
+ refName: groupRefNode.refName,
2449
+ label: `group: ${groupRefNode.refName}`,
2450
+ minOccurs: groupRefNode.minOccurs,
2451
+ maxOccurs: groupRefNode.maxOccurs,
2452
+ line: groupRefNode.line,
2453
+ column: groupRefNode.column,
2454
+ path: groupRefNode.path,
2455
+ children: []
2456
+ });
2457
+ if (!state.expandRefs) return node;
2458
+ const target = resolveGroup(schema, groupRefNode.refName);
2459
+ if (!target) return node;
2460
+ const visitedKey = makeVisitedKey("group", target.name || target.path);
2461
+ if (state.visited.has(visitedKey)) return node;
2462
+ state.visited.add(visitedKey);
2463
+ node.children.push(
2464
+ createTreeNode({
2465
+ kind: "group",
2466
+ name: target.name,
2467
+ label: target.name || "group",
2468
+ line: target.line,
2469
+ column: target.column,
2470
+ path: target.path,
2471
+ children: target.content ? [buildContentNode(schema, target.content, state)] : []
2472
+ })
2473
+ );
2474
+ state.visited.delete(visitedKey);
2475
+ return node;
2476
+ }
2477
+ function buildContentNode(schema, contentNode, state) {
2478
+ if (!contentNode) return null;
2479
+ switch (contentNode.kind) {
2480
+ case "sequence":
2481
+ case "choice":
2482
+ case "all":
2483
+ return createTreeNode({
2484
+ kind: contentNode.kind,
2485
+ label: contentNode.kind,
2486
+ minOccurs: contentNode.minOccurs,
2487
+ maxOccurs: contentNode.maxOccurs,
2488
+ line: contentNode.line,
2489
+ column: contentNode.column,
2490
+ path: contentNode.path,
2491
+ children: asArray2(contentNode.children).map((child) => buildContentNode(schema, child, state)).filter(Boolean)
2492
+ });
2493
+ case "element":
2494
+ return buildElementNode(schema, contentNode, state);
2495
+ case "groupRef":
2496
+ return buildGroupRefNode(schema, contentNode, state);
2497
+ case "any":
2498
+ return createTreeNode({
2499
+ kind: "any",
2500
+ label: "any",
2501
+ minOccurs: contentNode.minOccurs,
2502
+ maxOccurs: contentNode.maxOccurs,
2503
+ line: contentNode.line,
2504
+ column: contentNode.column,
2505
+ path: contentNode.path,
2506
+ children: []
2507
+ });
2508
+ default:
2509
+ return createTreeNode({
2510
+ kind: contentNode.kind || "unknown",
2511
+ label: contentNode.kind || "unknown",
2512
+ line: contentNode.line,
2513
+ column: contentNode.column,
2514
+ path: contentNode.path,
2515
+ children: []
2516
+ });
2517
+ }
2518
+ }
2519
+ function buildComplexTypeNode(schema, complexTypeDecl, state) {
2520
+ const content = getEffectiveContent(schema, complexTypeDecl);
2521
+ const attributes = getEffectiveAttributes(schema, complexTypeDecl);
2522
+ const children = [];
2523
+ if (complexTypeDecl.derivation?.kind || complexTypeDecl.derivation?.baseTypeName) {
2524
+ children.push(
2525
+ createTreeNode({
2526
+ kind: "derivation",
2527
+ label: complexTypeDecl.derivation.kind || "derivation",
2528
+ baseTypeName: complexTypeDecl.derivation.baseTypeName,
2529
+ derivation: complexTypeDecl.derivation.kind,
2530
+ line: complexTypeDecl.line,
2531
+ column: complexTypeDecl.column,
2532
+ path: complexTypeDecl.path ? `${complexTypeDecl.path}/derivation` : null,
2533
+ children: []
2534
+ })
2535
+ );
2536
+ }
2537
+ if (content) {
2538
+ const contentTree = buildContentNode(schema, content, state);
2539
+ if (contentTree) children.push(contentTree);
2540
+ }
2541
+ const attributeNodes = buildAttributesNodes(schema, attributes, state);
2542
+ children.push(...attributeNodes);
2543
+ return createTreeNode({
2544
+ kind: "complexType",
2545
+ name: complexTypeDecl.name,
2546
+ label: complexTypeDecl.name || "complexType",
2547
+ baseTypeName: complexTypeDecl.derivation?.baseTypeName || null,
2548
+ derivation: complexTypeDecl.derivation?.kind || null,
2549
+ line: complexTypeDecl.line,
2550
+ column: complexTypeDecl.column,
2551
+ path: complexTypeDecl.path,
2552
+ children
2553
+ });
2554
+ }
2555
+ function buildSimpleTypeNode(schema, simpleTypeDecl) {
2556
+ return createTreeNode({
2557
+ kind: "simpleType",
2558
+ name: simpleTypeDecl.name,
2559
+ label: simpleTypeDecl.name || "simpleType",
2560
+ baseTypeName: simpleTypeDecl.baseTypeName,
2561
+ line: simpleTypeDecl.line,
2562
+ column: simpleTypeDecl.column,
2563
+ path: simpleTypeDecl.path,
2564
+ children: buildSimpleTypeChildren(schema, simpleTypeDecl)
2565
+ });
2566
+ }
2567
+ function buildReferencedGlobalElementNode(schema, refName, state) {
2568
+ const target = resolveGlobalElement(schema, refName);
2569
+ if (!target) return null;
2570
+ const visitedKey = makeVisitedKey("element", target.name || target.path);
2571
+ if (state.visited.has(visitedKey)) {
2572
+ return createTreeNode({
2573
+ kind: "elementRefTarget",
2574
+ name: target.name,
2575
+ label: target.name || refName,
2576
+ typeName: target.typeName,
2577
+ line: target.line,
2578
+ column: target.column,
2579
+ path: target.path,
2580
+ children: []
2581
+ });
2582
+ }
2583
+ state.visited.add(visitedKey);
2584
+ const node = buildElementNode(schema, target, state);
2585
+ state.visited.delete(visitedKey);
2586
+ return node;
2587
+ }
2588
+ function buildElementNode(schema, elementDecl, state) {
2589
+ const node = createTreeNode({
2590
+ kind: "element",
2591
+ name: elementDecl.name,
2592
+ label: buildElementLabel(elementDecl),
2593
+ typeName: elementDecl.typeName,
2594
+ refName: elementDecl.refName,
2595
+ minOccurs: elementDecl.minOccurs,
2596
+ maxOccurs: elementDecl.maxOccurs,
2597
+ line: elementDecl.line,
2598
+ column: elementDecl.column,
2599
+ path: elementDecl.path,
2600
+ children: []
2601
+ });
2602
+ if (elementDecl.refName && state.expandRefs) {
2603
+ const targetNode = buildReferencedGlobalElementNode(schema, elementDecl.refName, state);
2604
+ if (targetNode) {
2605
+ node.children.push(targetNode);
2606
+ return node;
2607
+ }
2608
+ }
2609
+ const resolvedType = resolveElementType(schema, elementDecl);
2610
+ if (!resolvedType) {
2611
+ return node;
2612
+ }
2613
+ if (resolvedType.kind === "builtinType") {
2614
+ node.children.push(
2615
+ createTreeNode({
2616
+ kind: "builtinType",
2617
+ label: resolvedType.name,
2618
+ typeName: resolvedType.name,
2619
+ line: elementDecl.line,
2620
+ column: elementDecl.column,
2621
+ path: elementDecl.path ? `${elementDecl.path}/builtinType` : null,
2622
+ children: []
2623
+ })
2624
+ );
2625
+ return node;
2626
+ }
2627
+ if (resolvedType.kind === "simpleType") {
2628
+ node.children.push(buildSimpleTypeNode(schema, resolvedType));
2629
+ return node;
2630
+ }
2631
+ if (resolvedType.kind === "complexType") {
2632
+ const typeKey = makeVisitedKey("complexType", resolvedType.name || resolvedType.path);
2633
+ if (state.visited.has(typeKey)) {
2634
+ node.children.push(
2635
+ createTreeNode({
2636
+ kind: "complexType",
2637
+ name: resolvedType.name,
2638
+ label: resolvedType.name || "complexType",
2639
+ line: resolvedType.line,
2640
+ column: resolvedType.column,
2641
+ path: resolvedType.path,
2642
+ children: []
2643
+ })
2644
+ );
2645
+ return node;
2646
+ }
2647
+ state.visited.add(typeKey);
2648
+ node.children.push(buildComplexTypeNode(schema, resolvedType, state));
2649
+ state.visited.delete(typeKey);
2650
+ return node;
2651
+ }
2652
+ return node;
2653
+ }
2654
+ function selectRoots(schema, options = {}) {
2655
+ if (options.rootElementName) {
2656
+ const root = resolveGlobalElement(schema, options.rootElementName);
2657
+ return root ? [root] : [];
2658
+ }
2659
+ return Object.values(schema.globals.elements || {});
2660
+ }
2661
+ function extractTreeFromSchema(schema, options = {}, helpers = {}) {
2662
+ const roots = selectRoots(schema, options);
2663
+ const state = {
2664
+ expandRefs: options.expandRefs !== false,
2665
+ visited: /* @__PURE__ */ new Set(),
2666
+ resolveAttributeGroup: helpers.resolveAttributeGroup
2667
+ };
2668
+ const tree = roots.map((root) => buildElementNode(schema, root, state));
2669
+ return {
2670
+ roots: schema.roots,
2671
+ tree
2672
+ };
2673
+ }
2674
+
2675
+ // src/api/extractSchemaTree.js
2676
+ function extractSchemaTree({ xsdText, options = {} } = {}) {
2677
+ const parseResult = parseXsd(xsdText);
2678
+ if (!parseResult.ok || !parseResult.doc) {
2679
+ return makeResult({
2680
+ data: null,
2681
+ issues: parseResult.issues
2682
+ });
2683
+ }
2684
+ const modelResult = buildSchemaModel(parseResult.doc, {
2685
+ ...options,
2686
+ xsdText
2687
+ });
2688
+ const baseIssues = [
2689
+ ...parseResult.issues || [],
2690
+ ...modelResult.issues || []
2691
+ ];
2692
+ if (!modelResult.schema) {
2693
+ return makeResult({
2694
+ data: null,
2695
+ issues: baseIssues
2696
+ });
2697
+ }
2698
+ const diagnostics = runSchemaDiagnostics(modelResult.schema, {
2699
+ ...options,
2700
+ includeWarnings: true,
2701
+ includeFeatureSummary: false,
2702
+ includeRoots: true
2703
+ });
2704
+ const data = extractTreeFromSchema(modelResult.schema, options, {
2705
+ resolveAttributeGroup: (name) => resolveAttributeGroup(modelResult.schema, name)
2706
+ });
2707
+ return makeResult({
2708
+ data,
2709
+ issues: [...baseIssues, ...diagnostics.issues || []]
2710
+ });
2711
+ }
2712
+
2713
+ // src/generator/sampleValueFactory.js
2714
+ function firstEnumeration(simpleTypeDecl) {
2715
+ const enums = simpleTypeDecl?.enumerations || [];
2716
+ return enums.length ? String(enums[0]) : null;
2717
+ }
2718
+ function padToLength(text, targetLength) {
2719
+ if (text.length >= targetLength) return text.slice(0, targetLength);
2720
+ return text.padEnd(targetLength, "x");
2721
+ }
2722
+ function applyLengthFacet(baseValue, facets = {}) {
2723
+ let value = String(baseValue);
2724
+ if (typeof facets.length === "number") {
2725
+ return padToLength(value, facets.length);
2726
+ }
2727
+ if (typeof facets.minLength === "number" && value.length < facets.minLength) {
2728
+ value = padToLength(value, facets.minLength);
2729
+ }
2730
+ if (typeof facets.maxLength === "number" && value.length > facets.maxLength) {
2731
+ value = value.slice(0, facets.maxLength);
2732
+ }
2733
+ return value;
2734
+ }
2735
+ function numericWithinFacets(defaultValue, facets = {}, isInteger = false) {
2736
+ if (facets.minInclusive != null) return String(facets.minInclusive);
2737
+ if (facets.minExclusive != null) {
2738
+ const n = Number(facets.minExclusive);
2739
+ if (Number.isFinite(n)) return String(isInteger ? Math.floor(n + 1) : n + 0.1);
2740
+ }
2741
+ if (facets.maxInclusive != null) return String(facets.maxInclusive);
2742
+ if (facets.maxExclusive != null) {
2743
+ const n = Number(facets.maxExclusive);
2744
+ if (Number.isFinite(n)) return String(isInteger ? Math.ceil(n - 1) : n - 0.1);
2745
+ }
2746
+ return defaultValue;
2747
+ }
2748
+ function applyDigitFacets(value, facets = {}) {
2749
+ let text = String(value);
2750
+ if (typeof facets.fractionDigits === "number") {
2751
+ const num = Number(text);
2752
+ if (Number.isFinite(num)) {
2753
+ text = num.toFixed(facets.fractionDigits);
2754
+ }
2755
+ }
2756
+ if (typeof facets.totalDigits === "number") {
2757
+ const stripped = text.replace(/^[-+]/, "").replace(".", "");
2758
+ if (stripped.length > facets.totalDigits) {
2759
+ const replacement = "1".repeat(facets.totalDigits);
2760
+ text = typeof facets.fractionDigits === "number" && facets.fractionDigits > 0 ? `${replacement.slice(0, Math.max(1, facets.totalDigits - facets.fractionDigits))}.${replacement.slice(Math.max(1, facets.totalDigits - facets.fractionDigits))}` : replacement;
2761
+ }
2762
+ }
2763
+ return text;
2764
+ }
2765
+ function patternSample(patterns = [], fallback = "example") {
2766
+ const pattern = patterns[0];
2767
+ if (!pattern) return fallback;
2768
+ if (pattern === "[A-Z]+") return "ABC";
2769
+ if (pattern === "[0-9]+") return "123";
2770
+ if (pattern === "[A-Z0-9]+") return "ABC123";
2771
+ if (pattern === "[a-z]+") return "abc";
2772
+ return fallback;
2773
+ }
2774
+ function builtinSample(localTypeName) {
2775
+ switch (localTypeName) {
2776
+ case "string":
2777
+ case "normalizedString":
2778
+ case "token":
2779
+ case "language":
2780
+ case "Name":
2781
+ case "NCName":
2782
+ case "ID":
2783
+ case "IDREF":
2784
+ case "NMTOKEN":
2785
+ case "anyURI":
2786
+ case "QName":
2787
+ return "example";
2788
+ case "boolean":
2789
+ return "true";
2790
+ case "decimal":
2791
+ case "float":
2792
+ case "double":
2793
+ return "0.0";
2794
+ case "integer":
2795
+ case "nonPositiveInteger":
2796
+ case "negativeInteger":
2797
+ case "long":
2798
+ case "int":
2799
+ case "short":
2800
+ case "byte":
2801
+ case "nonNegativeInteger":
2802
+ case "unsignedLong":
2803
+ case "unsignedInt":
2804
+ case "unsignedShort":
2805
+ case "unsignedByte":
2806
+ case "positiveInteger":
2807
+ return "0";
2808
+ case "date":
2809
+ return "2026-01-01";
2810
+ case "time":
2811
+ return "00:00:00";
2812
+ case "dateTime":
2813
+ return "2026-01-01T00:00:00Z";
2814
+ case "duration":
2815
+ return "P1D";
2816
+ case "gYear":
2817
+ return "2026";
2818
+ case "gYearMonth":
2819
+ return "2026-01";
2820
+ case "gMonth":
2821
+ return "--01";
2822
+ case "gMonthDay":
2823
+ return "--01-01";
2824
+ case "gDay":
2825
+ return "---01";
2826
+ case "hexBinary":
2827
+ return "0A";
2828
+ case "base64Binary":
2829
+ return "ZXhhbXBsZQ==";
2830
+ default:
2831
+ return "example";
2832
+ }
2833
+ }
2834
+ function createSampleValueForType(schema, resolvedType) {
2835
+ if (!resolvedType) return "example";
2836
+ if (resolvedType.kind === "builtinType") {
2837
+ return builtinSample(stripNamespacePrefix(resolvedType.name));
2838
+ }
2839
+ if (resolvedType.kind === "simpleType") {
2840
+ const effective = getEffectiveSimpleType(schema, resolvedType);
2841
+ const enumValue = firstEnumeration(effective);
2842
+ if (enumValue != null) return enumValue;
2843
+ const baseType = effective?.baseTypeName;
2844
+ const facets = effective?.facets || {};
2845
+ if (baseType && isBuiltinType(baseType)) {
2846
+ const local = stripNamespacePrefix(baseType);
2847
+ if (facets.pattern?.length) {
2848
+ return applyLengthFacet(patternSample(facets.pattern, builtinSample(local)), facets);
2849
+ }
2850
+ let value = builtinSample(local);
2851
+ if ([
2852
+ "integer",
2853
+ "nonPositiveInteger",
2854
+ "negativeInteger",
2855
+ "long",
2856
+ "int",
2857
+ "short",
2858
+ "byte",
2859
+ "nonNegativeInteger",
2860
+ "unsignedLong",
2861
+ "unsignedInt",
2862
+ "unsignedShort",
2863
+ "unsignedByte",
2864
+ "positiveInteger"
2865
+ ].includes(local)) {
2866
+ value = numericWithinFacets(value, facets, true);
2867
+ value = applyDigitFacets(value, facets);
2868
+ return value;
2869
+ }
2870
+ if (["decimal", "float", "double"].includes(local)) {
2871
+ value = numericWithinFacets(value, facets, false);
2872
+ value = applyDigitFacets(value, facets);
2873
+ return value;
2874
+ }
2875
+ return applyLengthFacet(value, facets);
2876
+ }
2877
+ if (facets.pattern?.length) {
2878
+ return applyLengthFacet(patternSample(facets.pattern, "example"), facets);
2879
+ }
2880
+ return applyLengthFacet("example", facets);
2881
+ }
2882
+ return "example";
2883
+ }
2884
+
2885
+ // src/generator/generateXml.js
2886
+ function asArray3(value) {
2887
+ return Array.isArray(value) ? value : [];
2888
+ }
2889
+ function repeatCount(minOccurs, maxOccurs, mode) {
2890
+ if (mode === "minimal") {
2891
+ return typeof minOccurs === "number" ? minOccurs : 1;
2892
+ }
2893
+ if (mode === "full") {
2894
+ if (typeof maxOccurs === "number") {
2895
+ return Math.max(typeof minOccurs === "number" ? minOccurs : 1, Math.min(maxOccurs, 2));
2896
+ }
2897
+ return Math.max(typeof minOccurs === "number" ? minOccurs : 1, 1);
2898
+ }
2899
+ return 1;
2900
+ }
2901
+ function pickChoiceChildren(children, mode) {
2902
+ if (!children.length) return [];
2903
+ if (mode === "minimal") return [children[0]];
2904
+ return [children[0]];
2905
+ }
2906
+ function mergeAttributes(target, source) {
2907
+ Object.assign(target, source);
2908
+ }
2909
+ function shouldQualifyElement(schema, elementDecl, isRoot = false) {
2910
+ if (isRoot) return !!elementDecl.namespaceUri;
2911
+ return schema.elementFormDefault === "qualified" && !!elementDecl.namespaceUri;
2912
+ }
2913
+ function qualifiedElementName(schema, elementDecl, state, isRoot = false) {
2914
+ const localName3 = elementDecl.name || elementDecl.refName || "element";
2915
+ if (!shouldQualifyElement(schema, elementDecl, isRoot)) {
2916
+ return localName3.includes(":") ? localName3.split(":")[1] : localName3;
2917
+ }
2918
+ const prefix = state.targetPrefix || "tns";
2919
+ const bare = localName3.includes(":") ? localName3.split(":")[1] : localName3;
2920
+ return `${prefix}:${bare}`;
2921
+ }
2922
+ function buildRootNamespaceAttributes(schema, rootDecl, state) {
2923
+ const attrs = {};
2924
+ if (rootDecl.namespaceUri) {
2925
+ attrs[`xmlns:${state.targetPrefix}`] = rootDecl.namespaceUri;
2926
+ }
2927
+ return attrs;
2928
+ }
2929
+ function buildAttributesObject(schema, attributes, options, state) {
2930
+ const out = {};
2931
+ for (const attr of asArray3(attributes)) {
2932
+ if (!attr) continue;
2933
+ if (attr.kind === "attribute") {
2934
+ if (attr.use !== "required" && !options.includeOptionalAttributes) continue;
2935
+ const attrName = attr.name || attr.refName || "attr";
2936
+ const resolvedType = resolveAttributeType(schema, attr);
2937
+ out[attrName] = attr.fixedValue ?? attr.defaultValue ?? createSampleValueForType(schema, resolvedType);
2938
+ } else if (attr.kind === "attributeGroupRef") {
2939
+ const group = state.resolveAttributeGroup?.(attr.refName);
2940
+ if (!group) continue;
2941
+ mergeAttributes(
2942
+ out,
2943
+ buildAttributesObject(schema, group.attributes || [], options, state)
2944
+ );
2945
+ }
2946
+ }
2947
+ return out;
2948
+ }
2949
+ function buildNodesFromContent(schema, contentNode, options, state) {
2950
+ if (!contentNode) return [];
2951
+ switch (contentNode.kind) {
2952
+ case "sequence":
2953
+ case "all": {
2954
+ const result = [];
2955
+ for (const child of asArray3(contentNode.children)) {
2956
+ result.push(...buildNodesFromContent(schema, child, options, state));
2957
+ }
2958
+ return result;
2959
+ }
2960
+ case "choice": {
2961
+ const selected = pickChoiceChildren(asArray3(contentNode.children), options.mode);
2962
+ const result = [];
2963
+ for (const child of selected) {
2964
+ result.push(...buildNodesFromContent(schema, child, options, state));
2965
+ }
2966
+ return result;
2967
+ }
2968
+ case "groupRef": {
2969
+ const group = resolveGroup(schema, contentNode.refName);
2970
+ if (!group?.content) return [];
2971
+ return buildNodesFromContent(schema, group.content, options, state);
2972
+ }
2973
+ case "element":
2974
+ return buildElementInstances(schema, contentNode, options, state, false);
2975
+ case "any":
2976
+ return options.mode === "full" ? [{ name: "anyElement", attributes: {}, children: [], text: "example" }] : [];
2977
+ default:
2978
+ return [];
2979
+ }
2980
+ }
2981
+ function buildComplexTypeContent(schema, complexTypeDecl, options, state) {
2982
+ const content = getEffectiveContent(schema, complexTypeDecl);
2983
+ const attributes = getEffectiveAttributes(schema, complexTypeDecl);
2984
+ return {
2985
+ attributes: buildAttributesObject(schema, attributes, options, state),
2986
+ children: content ? buildNodesFromContent(schema, content, options, state) : []
2987
+ };
2988
+ }
2989
+ function buildSimpleTypeText(schema, simpleTypeDecl) {
2990
+ return createSampleValueForType(schema, simpleTypeDecl);
2991
+ }
2992
+ function buildElementNode2(schema, elementDecl, options, state, isRoot = false) {
2993
+ const resolvedType = resolveElementType(schema, elementDecl);
2994
+ const node = {
2995
+ name: qualifiedElementName(schema, elementDecl, state, isRoot),
2996
+ attributes: isRoot ? buildRootNamespaceAttributes(schema, elementDecl, state) : {},
2997
+ children: [],
2998
+ text: null
2999
+ };
3000
+ if (resolvedType?.kind === "builtinType" || resolvedType?.kind === "simpleType") {
3001
+ node.text = elementDecl.fixedValue ?? elementDecl.defaultValue ?? createSampleValueForType(schema, resolvedType);
3002
+ return node;
3003
+ }
3004
+ if (resolvedType?.kind === "complexType") {
3005
+ const built = buildComplexTypeContent(schema, resolvedType, options, state);
3006
+ node.attributes = {
3007
+ ...node.attributes,
3008
+ ...built.attributes
3009
+ };
3010
+ node.children = built.children;
3011
+ return node;
3012
+ }
3013
+ if (elementDecl.inlineType?.kind === "simpleType") {
3014
+ node.text = elementDecl.fixedValue ?? elementDecl.defaultValue ?? buildSimpleTypeText(schema, elementDecl.inlineType);
3015
+ return node;
3016
+ }
3017
+ node.text = elementDecl.fixedValue ?? elementDecl.defaultValue ?? "example";
3018
+ return node;
3019
+ }
3020
+ function buildElementInstances(schema, elementDecl, options, state, isRoot = false) {
3021
+ if (elementDecl.refName) {
3022
+ const target = resolveGlobalElement(schema, elementDecl.refName);
3023
+ if (target) {
3024
+ const mergedDecl = {
3025
+ ...target,
3026
+ minOccurs: elementDecl.minOccurs,
3027
+ maxOccurs: elementDecl.maxOccurs
3028
+ };
3029
+ return buildElementInstances(schema, mergedDecl, options, state, isRoot);
3030
+ }
3031
+ }
3032
+ const count = repeatCount(elementDecl.minOccurs, elementDecl.maxOccurs, options.mode);
3033
+ const result = [];
3034
+ for (let i = 0; i < count; i += 1) {
3035
+ result.push(buildElementNode2(schema, elementDecl, options, state, isRoot && i === 0));
3036
+ }
3037
+ return result;
3038
+ }
3039
+ function selectRoot(schema, options = {}) {
3040
+ if (options.rootElementName) {
3041
+ return resolveGlobalElement(schema, options.rootElementName);
3042
+ }
3043
+ return Object.values(schema.globals.elements || {})[0] || null;
3044
+ }
3045
+ function generateXmlFromSchema(schema, options = {}, helpers = {}) {
3046
+ const normalizedOptions = {
3047
+ mode: options.mode === "full" ? "full" : "minimal",
3048
+ includeOptionalAttributes: options.includeOptionalAttributes === true
3049
+ };
3050
+ const root = selectRoot(schema, options);
3051
+ if (!root) {
3052
+ return {
3053
+ rootElementName: null,
3054
+ rootNode: null
3055
+ };
3056
+ }
3057
+ const state = {
3058
+ resolveAttributeGroup: helpers.resolveAttributeGroup,
3059
+ targetPrefix: options.targetPrefix || "tns"
3060
+ };
3061
+ const [rootNode] = buildElementInstances(schema, root, normalizedOptions, state, true);
3062
+ return {
3063
+ rootElementName: root.name,
3064
+ rootNode
3065
+ };
3066
+ }
3067
+
3068
+ // src/generator/xmlWriter.js
3069
+ function escapeXml(value) {
3070
+ return String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
3071
+ }
3072
+ function writeAttributes(attributes = {}) {
3073
+ const entries = Object.entries(attributes).filter(([, value]) => value != null);
3074
+ if (!entries.length) return "";
3075
+ return entries.map(([key, value]) => ` ${key}="${escapeXml(value)}"`).join("");
3076
+ }
3077
+ function indent(level) {
3078
+ return " ".repeat(level);
3079
+ }
3080
+ function writeNode(node, level = 0) {
3081
+ const attrs = writeAttributes(node.attributes);
3082
+ if (!node.children?.length && (node.text == null || node.text === "")) {
3083
+ return `${indent(level)}<${node.name}${attrs}/>`;
3084
+ }
3085
+ if (!node.children?.length) {
3086
+ return `${indent(level)}<${node.name}${attrs}>${escapeXml(node.text)}</${node.name}>`;
3087
+ }
3088
+ const childXml = node.children.map((child) => writeNode(child, level + 1)).join("\n");
3089
+ return `${indent(level)}<${node.name}${attrs}>
3090
+ ${childXml}
3091
+ ${indent(level)}</${node.name}>`;
3092
+ }
3093
+ function writeXmlDocument(rootNode) {
3094
+ return `<?xml version="1.0" encoding="UTF-8"?>
3095
+ ${writeNode(rootNode, 0)}`;
3096
+ }
3097
+
3098
+ // src/api/generateSampleXml.js
3099
+ function generateSampleXml({ xsdText, options = {} } = {}) {
3100
+ const parseResult = parseXsd(xsdText);
3101
+ if (!parseResult.ok || !parseResult.doc) {
3102
+ return makeResult({
3103
+ data: null,
3104
+ issues: parseResult.issues
3105
+ });
3106
+ }
3107
+ const modelResult = buildSchemaModel(parseResult.doc, {
3108
+ ...options,
3109
+ xsdText
3110
+ });
3111
+ const baseIssues = [
3112
+ ...parseResult.issues || [],
3113
+ ...modelResult.issues || []
3114
+ ];
3115
+ if (!modelResult.schema) {
3116
+ return makeResult({
3117
+ data: null,
3118
+ issues: baseIssues
3119
+ });
3120
+ }
3121
+ const diagnostics = runSchemaDiagnostics(modelResult.schema, {
3122
+ ...options,
3123
+ includeWarnings: true,
3124
+ includeFeatureSummary: false,
3125
+ includeRoots: true
3126
+ });
3127
+ const generated = generateXmlFromSchema(modelResult.schema, options, {
3128
+ resolveAttributeGroup: (name) => resolveAttributeGroup(modelResult.schema, name)
3129
+ });
3130
+ if (!generated.rootNode) {
3131
+ return makeResult({
3132
+ data: {
3133
+ rootElementName: null,
3134
+ xmlText: ""
3135
+ },
3136
+ issues: [...baseIssues, ...diagnostics.issues || []]
3137
+ });
3138
+ }
3139
+ return makeResult({
3140
+ data: {
3141
+ rootElementName: generated.rootElementName,
3142
+ xmlText: writeXmlDocument(generated.rootNode)
3143
+ },
3144
+ issues: [...baseIssues, ...diagnostics.issues || []]
3145
+ });
3146
+ }
3147
+
3148
+ // src/validation/structureValidator.js
3149
+ function elementChildren2(xmlNode) {
3150
+ return Array.from(xmlNode?.children || []).filter((child) => child.nodeType === 1);
3151
+ }
3152
+ function directTextNodes(xmlNode) {
3153
+ return Array.from(xmlNode?.childNodes || []).filter((node) => node.nodeType === 3);
3154
+ }
3155
+ function textContentTrimmed(xmlNode) {
3156
+ return (xmlNode?.textContent || "").trim();
3157
+ }
3158
+ function localName(node) {
3159
+ return node?.localName || node?.nodeName || null;
3160
+ }
3161
+ function namespaceUri(node) {
3162
+ return node?.namespaceURI || null;
3163
+ }
3164
+ function repeatMin(minOccurs) {
3165
+ return typeof minOccurs === "number" ? minOccurs : 1;
3166
+ }
3167
+ function repeatMax(maxOccurs) {
3168
+ return maxOccurs === "unbounded" ? Infinity : maxOccurs;
3169
+ }
3170
+ function matchesElementDecl(xmlNode, elementDecl) {
3171
+ const xmlName = localName(xmlNode);
3172
+ const xmlNs = namespaceUri(xmlNode);
3173
+ const declName = elementDecl.refName || elementDecl.name;
3174
+ const declLocal = declName?.includes(":") ? declName.split(":")[1] : declName;
3175
+ const declNs = elementDecl.namespaceUri || null;
3176
+ if (xmlName !== declLocal) return false;
3177
+ if (declNs == null) return true;
3178
+ return xmlNs === declNs;
3179
+ }
3180
+ function buildXmlPath(pathParts) {
3181
+ return "/" + pathParts.join("/");
3182
+ }
3183
+ function validateAttributes(xmlNode, attributes, context) {
3184
+ const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts, validateAttributeValue: validateAttributeValue2 } = context;
3185
+ const allowed = /* @__PURE__ */ new Map();
3186
+ for (const attr of attributes || []) {
3187
+ if (!attr) continue;
3188
+ if (attr.kind === "attribute") {
3189
+ const attrName = attr.name || attr.refName;
3190
+ if (attrName) {
3191
+ allowed.set(attrName, attr);
3192
+ }
3193
+ } else if (attr.kind === "attributeGroupRef") {
3194
+ const group = context.resolveAttributeGroup?.(attr.refName);
3195
+ if (!group) continue;
3196
+ validateAttributes(xmlNode, group.attributes || [], context);
3197
+ }
3198
+ }
3199
+ for (const attrDecl of allowed.values()) {
3200
+ const attrName = attrDecl.name || attrDecl.refName;
3201
+ const value = xmlNode.getAttribute(attrName);
3202
+ if (attrDecl.use === "required" && value == null) {
3203
+ issues.push(
3204
+ createIssue2({
3205
+ code: ISSUE_CODES2.XML_MISSING_REQUIRED_ATTRIBUTE,
3206
+ severity: "error",
3207
+ message: `Required attribute '${attrName}' is missing.`,
3208
+ path: buildXmlPath(pathParts),
3209
+ source: "xml",
3210
+ nodeKind: "attribute",
3211
+ name: attrName,
3212
+ details: { attributeName: attrName }
3213
+ })
3214
+ );
3215
+ continue;
3216
+ }
3217
+ if (value != null) {
3218
+ const valueResult = validateAttributeValue2(schema, attrDecl, value);
3219
+ if (!valueResult.ok) {
3220
+ issues.push(
3221
+ createIssue2({
3222
+ code: ISSUE_CODES2[valueResult.code] || valueResult.code,
3223
+ severity: "error",
3224
+ message: valueResult.message,
3225
+ path: buildXmlPath(pathParts),
3226
+ source: "xml",
3227
+ nodeKind: "attribute",
3228
+ name: attrName,
3229
+ details: { attributeName: attrName, value }
3230
+ })
3231
+ );
3232
+ }
3233
+ }
3234
+ }
3235
+ for (const attr of Array.from(xmlNode.attributes || [])) {
3236
+ if (attr.name === "xmlns" || attr.name.startsWith("xmlns:") || attr.prefix === "xmlns") {
3237
+ continue;
3238
+ }
3239
+ if (!allowed.has(attr.name)) {
3240
+ issues.push(
3241
+ createIssue2({
3242
+ code: ISSUE_CODES2.XML_UNEXPECTED_ATTRIBUTE,
3243
+ severity: "error",
3244
+ message: `Unexpected attribute '${attr.name}'.`,
3245
+ path: buildXmlPath(pathParts),
3246
+ source: "xml",
3247
+ nodeKind: "attribute",
3248
+ name: attr.name,
3249
+ details: { attributeName: attr.name }
3250
+ })
3251
+ );
3252
+ }
3253
+ }
3254
+ }
3255
+ function validateSimpleElement(xmlNode, elementDecl, context) {
3256
+ const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts, validateElementValue: validateElementValue2 } = context;
3257
+ const value = textContentTrimmed(xmlNode);
3258
+ const valueResult = validateElementValue2(schema, elementDecl, value);
3259
+ if (!valueResult.ok) {
3260
+ issues.push(
3261
+ createIssue2({
3262
+ code: ISSUE_CODES2[valueResult.code] || valueResult.code,
3263
+ severity: "error",
3264
+ message: valueResult.message,
3265
+ path: buildXmlPath(pathParts),
3266
+ source: "xml",
3267
+ nodeKind: "element",
3268
+ name: elementDecl.name || elementDecl.refName,
3269
+ details: { value }
3270
+ })
3271
+ );
3272
+ }
3273
+ }
3274
+ function validateMixedContent(xmlNode, complexTypeDecl, context, pathParts) {
3275
+ const { createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues } = context;
3276
+ const hasDirectText = directTextNodes(xmlNode).some((node) => node.nodeValue?.trim());
3277
+ if (!complexTypeDecl.mixed && hasDirectText) {
3278
+ issues.push(
3279
+ createIssue2({
3280
+ code: ISSUE_CODES2.XML_MIXED_CONTENT_NOT_ALLOWED,
3281
+ severity: "error",
3282
+ message: "Mixed text content is not allowed for this complex type.",
3283
+ path: buildXmlPath(pathParts),
3284
+ source: "xml",
3285
+ nodeKind: "element",
3286
+ name: localName(xmlNode),
3287
+ details: {}
3288
+ })
3289
+ );
3290
+ }
3291
+ }
3292
+ function validateComplexElement(xmlNode, complexTypeDecl, context) {
3293
+ const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts } = context;
3294
+ const attributes = getEffectiveAttributes(schema, complexTypeDecl);
3295
+ validateAttributes(xmlNode, attributes, context);
3296
+ validateMixedContent(xmlNode, complexTypeDecl, context, pathParts);
3297
+ const text = textContentTrimmed(xmlNode);
3298
+ const children = elementChildren2(xmlNode);
3299
+ const content = getEffectiveContent(schema, complexTypeDecl);
3300
+ if (!complexTypeDecl.mixed && children.length === 0 && text && content) {
3301
+ issues.push(
3302
+ createIssue2({
3303
+ code: ISSUE_CODES2.XML_INVALID_TEXT_FOR_COMPLEX_TYPE,
3304
+ severity: "error",
3305
+ message: "Complex element contains text where structured child content is expected.",
3306
+ path: buildXmlPath(pathParts),
3307
+ source: "xml",
3308
+ nodeKind: "element",
3309
+ name: localName(xmlNode),
3310
+ details: {}
3311
+ })
3312
+ );
3313
+ }
3314
+ if (content) {
3315
+ const result = validateContentModel(children, content, context, pathParts);
3316
+ if (result.nextIndex < children.length) {
3317
+ for (let i = result.nextIndex; i < children.length; i += 1) {
3318
+ issues.push(
3319
+ createIssue2({
3320
+ code: ISSUE_CODES2.XML_UNEXPECTED_ELEMENT,
3321
+ severity: "error",
3322
+ message: `Unexpected element '${localName(children[i])}'.`,
3323
+ path: buildXmlPath([...pathParts, localName(children[i])]),
3324
+ source: "xml",
3325
+ nodeKind: "element",
3326
+ name: localName(children[i]),
3327
+ details: {}
3328
+ })
3329
+ );
3330
+ }
3331
+ }
3332
+ }
3333
+ }
3334
+ function validateElementDecl(xmlNode, elementDecl, context, pathParts) {
3335
+ const resolvedType = resolveElementType(context.schema, elementDecl);
3336
+ if (!resolvedType) return;
3337
+ const nextContext = {
3338
+ ...context,
3339
+ pathParts
3340
+ };
3341
+ if (resolvedType.kind === "builtinType" || resolvedType.kind === "simpleType") {
3342
+ validateSimpleElement(xmlNode, elementDecl, nextContext);
3343
+ return;
3344
+ }
3345
+ if (resolvedType.kind === "complexType") {
3346
+ validateComplexElement(xmlNode, resolvedType, nextContext);
3347
+ }
3348
+ }
3349
+ function consumeMatchingElement(children, startIndex, elementDecl, context, pathParts) {
3350
+ const min = repeatMin(elementDecl.minOccurs);
3351
+ const max = repeatMax(elementDecl.maxOccurs);
3352
+ let count = 0;
3353
+ let index = startIndex;
3354
+ while (index < children.length && matchesElementDecl(children[index], elementDecl) && count < max) {
3355
+ const childNode = children[index];
3356
+ validateElementDecl(childNode, elementDecl, context, [...pathParts, localName(childNode)]);
3357
+ count += 1;
3358
+ index += 1;
3359
+ }
3360
+ if (count < min) {
3361
+ context.issues.push(
3362
+ context.createIssue({
3363
+ code: context.ISSUE_CODES.XML_MISSING_REQUIRED_ELEMENT,
3364
+ severity: "error",
3365
+ message: `Required element '${elementDecl.name || elementDecl.refName}' is missing.`,
3366
+ path: buildXmlPath(pathParts),
3367
+ source: "xml",
3368
+ nodeKind: "element",
3369
+ name: elementDecl.name || elementDecl.refName,
3370
+ details: {
3371
+ minOccurs: elementDecl.minOccurs,
3372
+ actualCount: count
3373
+ }
3374
+ })
3375
+ );
3376
+ }
3377
+ return { nextIndex: index, matched: count >= min };
3378
+ }
3379
+ function validateGroupRef(children, startIndex, groupRefNode, context, pathParts) {
3380
+ const group = resolveGroup(context.schema, groupRefNode.refName);
3381
+ if (!group?.content) {
3382
+ return { nextIndex: startIndex, matched: false };
3383
+ }
3384
+ const min = repeatMin(groupRefNode.minOccurs);
3385
+ const max = repeatMax(groupRefNode.maxOccurs);
3386
+ let count = 0;
3387
+ let index = startIndex;
3388
+ while (count < max) {
3389
+ const result = validateContentModel(children, group.content, context, pathParts, index, true);
3390
+ if (!result.matchedAny) break;
3391
+ index = result.nextIndex;
3392
+ count += 1;
3393
+ }
3394
+ if (count < min) {
3395
+ context.issues.push(
3396
+ context.createIssue({
3397
+ code: context.ISSUE_CODES.XML_MISSING_REQUIRED_ELEMENT,
3398
+ severity: "error",
3399
+ message: `Required group '${groupRefNode.refName}' is missing.`,
3400
+ path: buildXmlPath(pathParts),
3401
+ source: "xml",
3402
+ nodeKind: "groupRef",
3403
+ name: groupRefNode.refName,
3404
+ details: {}
3405
+ })
3406
+ );
3407
+ }
3408
+ return { nextIndex: index, matched: count >= min };
3409
+ }
3410
+ function validateChoice(children, startIndex, choiceNode, context, pathParts, silent = false) {
3411
+ const min = repeatMin(choiceNode.minOccurs);
3412
+ const max = repeatMax(choiceNode.maxOccurs);
3413
+ let count = 0;
3414
+ let index = startIndex;
3415
+ while (count < max) {
3416
+ let matchedBranches = [];
3417
+ for (const childDecl of choiceNode.children || []) {
3418
+ const snapshotIssuesLength = context.issues.length;
3419
+ const result = validateContentModel(children, childDecl, context, pathParts, index, true);
3420
+ if (result.matchedAny) {
3421
+ context.issues.length = snapshotIssuesLength;
3422
+ matchedBranches.push(result);
3423
+ } else {
3424
+ context.issues.length = snapshotIssuesLength;
3425
+ }
3426
+ }
3427
+ if (matchedBranches.length === 0) break;
3428
+ if (matchedBranches.length > 1 && !silent) {
3429
+ context.issues.push(
3430
+ context.createIssue({
3431
+ code: context.ISSUE_CODES.XML_CHOICE_MULTIPLE_BRANCHES,
3432
+ severity: "error",
3433
+ message: "Multiple xs:choice branches appear to match at the same position.",
3434
+ path: buildXmlPath(pathParts),
3435
+ source: "xml",
3436
+ nodeKind: "choice",
3437
+ name: null,
3438
+ details: {}
3439
+ })
3440
+ );
3441
+ }
3442
+ const matchedBranch = matchedBranches[0];
3443
+ index = matchedBranch.nextIndex;
3444
+ count += 1;
3445
+ }
3446
+ if (count < min && !silent) {
3447
+ context.issues.push(
3448
+ context.createIssue({
3449
+ code: context.ISSUE_CODES.XML_CHOICE_NOT_SATISFIED,
3450
+ severity: "error",
3451
+ message: "No valid branch of xs:choice was satisfied.",
3452
+ path: buildXmlPath(pathParts),
3453
+ source: "xml",
3454
+ nodeKind: "choice",
3455
+ name: null,
3456
+ details: {}
3457
+ })
3458
+ );
3459
+ }
3460
+ return { nextIndex: index, matched: count >= min, matchedAny: count > 0 };
3461
+ }
3462
+ function validateAll(children, startIndex, allNode, context, pathParts, silent = false) {
3463
+ const members = allNode.children || [];
3464
+ const matchedIndexes = /* @__PURE__ */ new Set();
3465
+ let index = startIndex;
3466
+ while (index < children.length) {
3467
+ let matchedMemberIndex = -1;
3468
+ for (let i = 0; i < members.length; i += 1) {
3469
+ if (matchedIndexes.has(i)) continue;
3470
+ const result = validateContentModel(children, members[i], context, pathParts, index, true);
3471
+ if (result.matchedAny) {
3472
+ matchedMemberIndex = i;
3473
+ index = result.nextIndex;
3474
+ break;
3475
+ }
3476
+ }
3477
+ if (matchedMemberIndex < 0) break;
3478
+ matchedIndexes.add(matchedMemberIndex);
3479
+ }
3480
+ if (!silent) {
3481
+ for (let i = 0; i < members.length; i += 1) {
3482
+ const member = members[i];
3483
+ const min = repeatMin(member.minOccurs);
3484
+ if (matchedIndexes.has(i) && maxOccursIsSingle(member)) {
3485
+ }
3486
+ if (!matchedIndexes.has(i) && min > 0) {
3487
+ context.issues.push(
3488
+ context.createIssue({
3489
+ code: context.ISSUE_CODES.XML_ALL_MISSING_REQUIRED_ELEMENT,
3490
+ severity: "error",
3491
+ message: `Required xs:all child '${member.name || member.refName}' is missing.`,
3492
+ path: buildXmlPath(pathParts),
3493
+ source: "xml",
3494
+ nodeKind: "all",
3495
+ name: member.name || member.refName,
3496
+ details: {}
3497
+ })
3498
+ );
3499
+ }
3500
+ }
3501
+ }
3502
+ return {
3503
+ nextIndex: index,
3504
+ matched: matchedIndexes.size > 0 || members.every((m) => repeatMin(m.minOccurs) === 0),
3505
+ matchedAny: matchedIndexes.size > 0
3506
+ };
3507
+ }
3508
+ function maxOccursIsSingle(member) {
3509
+ return member.maxOccurs == null || member.maxOccurs === 1;
3510
+ }
3511
+ function flattenAllowedNames(node, out = /* @__PURE__ */ new Set()) {
3512
+ if (!node) return out;
3513
+ switch (node.kind) {
3514
+ case "sequence":
3515
+ case "choice":
3516
+ case "all":
3517
+ for (const child of node.children || []) {
3518
+ flattenAllowedNames(child, out);
3519
+ }
3520
+ return out;
3521
+ case "groupRef":
3522
+ out.add(node.refName);
3523
+ return out;
3524
+ case "element":
3525
+ out.add(node.refName || node.name);
3526
+ return out;
3527
+ default:
3528
+ return out;
3529
+ }
3530
+ }
3531
+ function validateRestrictionCompatibility(modelNode, context, pathParts, children = [], startIndex = 0) {
3532
+ if (!context.currentComplexType?.derivation) return;
3533
+ const derivation = context.currentComplexType.derivation;
3534
+ if (derivation.kind !== "restriction") return;
3535
+ const allowedNames = flattenAllowedNames(modelNode, /* @__PURE__ */ new Set());
3536
+ for (let i = startIndex; i < children.length; i += 1) {
3537
+ const childName = localName(children[i]);
3538
+ if (!allowedNames.has(childName)) {
3539
+ context.issues.push(
3540
+ context.createIssue({
3541
+ code: context.ISSUE_CODES.XML_RESTRICTED_ELEMENT_NOT_ALLOWED,
3542
+ severity: "error",
3543
+ message: `Element '${childName}' is not allowed by the restricted content model.`,
3544
+ path: buildXmlPath([...pathParts, childName]),
3545
+ source: "xml",
3546
+ nodeKind: "element",
3547
+ name: childName,
3548
+ details: {}
3549
+ })
3550
+ );
3551
+ }
3552
+ }
3553
+ }
3554
+ function validateContentModel(children, modelNode, context, pathParts, startIndex = 0, silent = false) {
3555
+ if (!modelNode) {
3556
+ return { nextIndex: startIndex, matched: true, matchedAny: false };
3557
+ }
3558
+ validateRestrictionCompatibility(modelNode, context, pathParts, children, startIndex);
3559
+ switch (modelNode.kind) {
3560
+ case "element": {
3561
+ const result = consumeMatchingElement(children, startIndex, modelNode, context, pathParts);
3562
+ return {
3563
+ nextIndex: result.nextIndex,
3564
+ matched: result.matched,
3565
+ matchedAny: result.nextIndex > startIndex
3566
+ };
3567
+ }
3568
+ case "groupRef":
3569
+ return validateGroupRef(children, startIndex, modelNode, context, pathParts);
3570
+ case "sequence": {
3571
+ let index = startIndex;
3572
+ let matchedAny = false;
3573
+ for (const childDecl of modelNode.children || []) {
3574
+ const result = validateContentModel(children, childDecl, context, pathParts, index, silent);
3575
+ if (!result.matched && !silent) {
3576
+ return { nextIndex: index, matched: false, matchedAny };
3577
+ }
3578
+ index = result.nextIndex;
3579
+ matchedAny = matchedAny || result.matchedAny;
3580
+ }
3581
+ return { nextIndex: index, matched: true, matchedAny };
3582
+ }
3583
+ case "choice":
3584
+ return validateChoice(children, startIndex, modelNode, context, pathParts, silent);
3585
+ case "all":
3586
+ return validateAll(children, startIndex, modelNode, context, pathParts, silent);
3587
+ case "any":
3588
+ if (startIndex < children.length) {
3589
+ return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
3590
+ }
3591
+ return { nextIndex: startIndex, matched: true, matchedAny: false };
3592
+ default:
3593
+ return { nextIndex: startIndex, matched: true, matchedAny: false };
3594
+ }
3595
+ }
3596
+
3597
+ // src/validation/builtinTypeValidators.js
3598
+ function isIntegerString(value) {
3599
+ return /^[-+]?\d+$/.test(value);
3600
+ }
3601
+ function isDecimalString(value) {
3602
+ return /^[-+]?(?:\d+|\d*\.\d+)$/.test(value);
3603
+ }
3604
+ function isBooleanString(value) {
3605
+ return value === "true" || value === "false" || value === "1" || value === "0";
3606
+ }
3607
+ function isDateString(value) {
3608
+ return /^\d{4}-\d{2}-\d{2}$/.test(value);
3609
+ }
3610
+ function isDateTimeString(value) {
3611
+ return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?$/.test(value);
3612
+ }
3613
+ function isTimeString(value) {
3614
+ return /^\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(value);
3615
+ }
3616
+ function validateBuiltinType(localTypeName, value) {
3617
+ const text = String(value ?? "");
3618
+ switch (localTypeName) {
3619
+ case "string":
3620
+ case "normalizedString":
3621
+ case "token":
3622
+ case "language":
3623
+ case "Name":
3624
+ case "NCName":
3625
+ case "ID":
3626
+ case "IDREF":
3627
+ case "ENTITY":
3628
+ case "NMTOKEN":
3629
+ case "anyURI":
3630
+ case "QName":
3631
+ case "NOTATION":
3632
+ return true;
3633
+ case "boolean":
3634
+ return isBooleanString(text);
3635
+ case "decimal":
3636
+ case "float":
3637
+ case "double":
3638
+ return isDecimalString(text);
3639
+ case "integer":
3640
+ case "nonPositiveInteger":
3641
+ case "negativeInteger":
3642
+ case "long":
3643
+ case "int":
3644
+ case "short":
3645
+ case "byte":
3646
+ case "nonNegativeInteger":
3647
+ case "unsignedLong":
3648
+ case "unsignedInt":
3649
+ case "unsignedShort":
3650
+ case "unsignedByte":
3651
+ case "positiveInteger":
3652
+ return isIntegerString(text);
3653
+ case "date":
3654
+ return isDateString(text);
3655
+ case "dateTime":
3656
+ return isDateTimeString(text);
3657
+ case "time":
3658
+ return isTimeString(text);
3659
+ default:
3660
+ return true;
3661
+ }
3662
+ }
3663
+
3664
+ // src/validation/facetUtils.js
3665
+ function toNumber2(value) {
3666
+ const num = Number(value);
3667
+ return Number.isFinite(num) ? num : null;
3668
+ }
3669
+ function countDigits(value) {
3670
+ const normalized = String(value).replace(/^[-+]/, "").replace(".", "");
3671
+ return normalized.replace(/\D/g, "").length;
3672
+ }
3673
+ function countFractionDigits(value) {
3674
+ const text = String(value);
3675
+ const idx = text.indexOf(".");
3676
+ if (idx < 0) return 0;
3677
+ return text.slice(idx + 1).replace(/\D/g, "").length;
3678
+ }
3679
+ function testPatterns(patterns, value) {
3680
+ for (const pattern of patterns || []) {
3681
+ try {
3682
+ const regex = new RegExp(pattern);
3683
+ if (!regex.test(String(value))) {
3684
+ return {
3685
+ ok: false,
3686
+ code: "XML_PATTERN_MISMATCH",
3687
+ message: `Value '${value}' does not match required pattern '${pattern}'.`
3688
+ };
3689
+ }
3690
+ } catch {
3691
+ return {
3692
+ ok: false,
3693
+ code: "XML_PATTERN_MISMATCH",
3694
+ message: `Value '${value}' could not be validated against pattern '${pattern}'.`
3695
+ };
3696
+ }
3697
+ }
3698
+ return { ok: true, code: null, message: null };
3699
+ }
3700
+ function validateLengthFacets(value, facets = {}) {
3701
+ const text = String(value ?? "");
3702
+ const len = text.length;
3703
+ if (typeof facets.length === "number" && len !== facets.length) {
3704
+ return {
3705
+ ok: false,
3706
+ code: "XML_LENGTH_MISMATCH",
3707
+ message: `Value '${value}' must have length ${facets.length}.`
3708
+ };
3709
+ }
3710
+ if (typeof facets.minLength === "number" && len < facets.minLength) {
3711
+ return {
3712
+ ok: false,
3713
+ code: "XML_MIN_LENGTH_VIOLATION",
3714
+ message: `Value '${value}' is shorter than minLength ${facets.minLength}.`
3715
+ };
3716
+ }
3717
+ if (typeof facets.maxLength === "number" && len > facets.maxLength) {
3718
+ return {
3719
+ ok: false,
3720
+ code: "XML_MAX_LENGTH_VIOLATION",
3721
+ message: `Value '${value}' is longer than maxLength ${facets.maxLength}.`
3722
+ };
3723
+ }
3724
+ return { ok: true, code: null, message: null };
3725
+ }
3726
+ function validateNumericFacets(value, facets = {}) {
3727
+ const num = toNumber2(value);
3728
+ if (num == null) {
3729
+ return { ok: true, code: null, message: null };
3730
+ }
3731
+ if (facets.minInclusive != null) {
3732
+ const min = toNumber2(facets.minInclusive);
3733
+ if (min != null && num < min) {
3734
+ return {
3735
+ ok: false,
3736
+ code: "XML_MIN_INCLUSIVE_VIOLATION",
3737
+ message: `Value '${value}' is less than minInclusive ${facets.minInclusive}.`
3738
+ };
3739
+ }
3740
+ }
3741
+ if (facets.maxInclusive != null) {
3742
+ const max = toNumber2(facets.maxInclusive);
3743
+ if (max != null && num > max) {
3744
+ return {
3745
+ ok: false,
3746
+ code: "XML_MAX_INCLUSIVE_VIOLATION",
3747
+ message: `Value '${value}' is greater than maxInclusive ${facets.maxInclusive}.`
3748
+ };
3749
+ }
3750
+ }
3751
+ if (facets.minExclusive != null) {
3752
+ const min = toNumber2(facets.minExclusive);
3753
+ if (min != null && num <= min) {
3754
+ return {
3755
+ ok: false,
3756
+ code: "XML_MIN_EXCLUSIVE_VIOLATION",
3757
+ message: `Value '${value}' must be greater than minExclusive ${facets.minExclusive}.`
3758
+ };
3759
+ }
3760
+ }
3761
+ if (facets.maxExclusive != null) {
3762
+ const max = toNumber2(facets.maxExclusive);
3763
+ if (max != null && num >= max) {
3764
+ return {
3765
+ ok: false,
3766
+ code: "XML_MAX_EXCLUSIVE_VIOLATION",
3767
+ message: `Value '${value}' must be less than maxExclusive ${facets.maxExclusive}.`
3768
+ };
3769
+ }
3770
+ }
3771
+ return { ok: true, code: null, message: null };
3772
+ }
3773
+ function validateDigitFacets(value, facets = {}) {
3774
+ const text = String(value ?? "");
3775
+ if (typeof facets.totalDigits === "number") {
3776
+ const total = countDigits(text);
3777
+ if (total > facets.totalDigits) {
3778
+ return {
3779
+ ok: false,
3780
+ code: "XML_TOTAL_DIGITS_VIOLATION",
3781
+ message: `Value '${value}' exceeds totalDigits ${facets.totalDigits}.`
3782
+ };
3783
+ }
3784
+ }
3785
+ if (typeof facets.fractionDigits === "number") {
3786
+ const fraction = countFractionDigits(text);
3787
+ if (fraction > facets.fractionDigits) {
3788
+ return {
3789
+ ok: false,
3790
+ code: "XML_FRACTION_DIGITS_VIOLATION",
3791
+ message: `Value '${value}' exceeds fractionDigits ${facets.fractionDigits}.`
3792
+ };
3793
+ }
3794
+ }
3795
+ return { ok: true, code: null, message: null };
3796
+ }
3797
+ function validatePatternFacets(value, facets = {}) {
3798
+ if (!facets.pattern?.length) {
3799
+ return { ok: true, code: null, message: null };
3800
+ }
3801
+ return testPatterns(facets.pattern, value);
3802
+ }
3803
+ function validateFacets(value, facets = {}) {
3804
+ const checks = [
3805
+ validateLengthFacets(value, facets),
3806
+ validateNumericFacets(value, facets),
3807
+ validateDigitFacets(value, facets),
3808
+ validatePatternFacets(value, facets)
3809
+ ];
3810
+ return checks.find((item) => !item.ok) || { ok: true, code: null, message: null };
3811
+ }
3812
+
3813
+ // src/validation/valueValidator.js
3814
+ function validateByDeclType(schema, decl, value, kindLabel) {
3815
+ const resolvedType = kindLabel === "attribute" ? resolveAttributeType(schema, decl) : resolveElementType(schema, decl);
3816
+ return validateResolvedValue(schema, resolvedType, value);
3817
+ }
3818
+ function validateElementValue(schema, elementDecl, value) {
3819
+ const fixed = elementDecl.fixedValue;
3820
+ if (fixed != null) {
3821
+ if (value !== fixed) {
3822
+ return {
3823
+ ok: false,
3824
+ code: "XML_FIXED_VALUE_MISMATCH",
3825
+ message: `Element '${elementDecl.name || elementDecl.refName}' must have fixed value '${fixed}'.`
3826
+ };
3827
+ }
3828
+ return { ok: true, code: null, message: null };
3829
+ }
3830
+ return validateByDeclType(schema, elementDecl, value, "element");
3831
+ }
3832
+ function validateAttributeValue(schema, attrDecl, value) {
3833
+ const fixed = attrDecl.fixedValue;
3834
+ if (fixed != null) {
3835
+ if (value !== fixed) {
3836
+ return {
3837
+ ok: false,
3838
+ code: "XML_FIXED_VALUE_MISMATCH",
3839
+ message: `Attribute '${attrDecl.name || attrDecl.refName}' must have fixed value '${fixed}'.`
3840
+ };
3841
+ }
3842
+ return { ok: true, code: null, message: null };
3843
+ }
3844
+ return validateByDeclType(schema, attrDecl, value, "attribute");
3845
+ }
3846
+ function validateResolvedValue(schema, resolvedType, value) {
3847
+ if (!resolvedType) {
3848
+ return { ok: true, code: null, message: null };
3849
+ }
3850
+ if (resolvedType.kind === "builtinType") {
3851
+ const local = stripNamespacePrefix(resolvedType.name);
3852
+ const ok = validateBuiltinType(local, value);
3853
+ return ok ? { ok: true, code: null, message: null } : {
3854
+ ok: false,
3855
+ code: "XML_VALUE_INVALID",
3856
+ message: `Value '${value}' is not valid for type '${local}'.`
3857
+ };
3858
+ }
3859
+ if (resolvedType.kind === "simpleType") {
3860
+ const effective = getEffectiveSimpleType(schema, resolvedType);
3861
+ if (effective.enumerations?.length) {
3862
+ const allowed = effective.enumerations.map(String);
3863
+ if (!allowed.includes(String(value))) {
3864
+ return {
3865
+ ok: false,
3866
+ code: "XML_ENUMERATION_MISMATCH",
3867
+ message: `Value '${value}' is not one of the allowed enumeration values: ${allowed.join(", ")}.`
3868
+ };
3869
+ }
3870
+ }
3871
+ if (effective.baseTypeName && isBuiltinType(effective.baseTypeName, schema)) {
3872
+ const local = stripNamespacePrefix(effective.baseTypeName);
3873
+ const builtinOk = validateBuiltinType(local, value);
3874
+ if (!builtinOk) {
3875
+ return {
3876
+ ok: false,
3877
+ code: "XML_VALUE_INVALID",
3878
+ message: `Value '${value}' is not valid for base type '${local}'.`
3879
+ };
3880
+ }
3881
+ }
3882
+ const facetResult = validateFacets(value, effective.facets || {});
3883
+ if (!facetResult.ok) {
3884
+ return facetResult;
3885
+ }
3886
+ return { ok: true, code: null, message: null };
3887
+ }
3888
+ return { ok: true, code: null, message: null };
3889
+ }
3890
+
3891
+ // src/validation/validateXmlAgainstSchema.js
3892
+ function elementChildren3(xmlNode) {
3893
+ return Array.from(xmlNode?.children || []).filter((child) => child.nodeType === 1);
3894
+ }
3895
+ function localName2(node) {
3896
+ return node?.localName || node?.nodeName || null;
3897
+ }
3898
+ function namespaceUri2(node) {
3899
+ return node?.namespaceURI || null;
3900
+ }
3901
+ function parseXml(xmlText) {
3902
+ const parser = new DOMParser();
3903
+ const doc = parser.parseFromString(xmlText, "application/xml");
3904
+ const parserError = doc.querySelector("parsererror");
3905
+ if (parserError) {
3906
+ return {
3907
+ ok: false,
3908
+ doc: null,
3909
+ issues: [
3910
+ createIssue({
3911
+ code: ISSUE_CODES.XML_PARSE_ERROR,
3912
+ severity: "error",
3913
+ message: parserError.textContent?.trim() || "Failed to parse XML.",
3914
+ source: "xml"
3915
+ })
3916
+ ]
3917
+ };
3918
+ }
3919
+ return { ok: true, doc, issues: [] };
3920
+ }
3921
+ function determineRootElement(schema, xmlRootName, xmlRootNs, options) {
3922
+ if (options.rootElementName) {
3923
+ return resolveGlobalElement(schema, options.rootElementName);
3924
+ }
3925
+ const candidates = Object.values(schema?.globals?.elements || {});
3926
+ return candidates.find(
3927
+ (decl) => decl.name === xmlRootName && (decl.namespaceUri || null) === (xmlRootNs || null)
3928
+ ) || candidates.find(
3929
+ (decl) => decl.name === xmlRootName && (decl.namespaceUri == null || decl.namespaceUri === "")
3930
+ ) || null;
3931
+ }
3932
+ function validateXmlAgainstSchema(schema, xmlText, options = {}, helpers = {}) {
3933
+ const xmlParse = parseXml(xmlText);
3934
+ if (!xmlParse.ok || !xmlParse.doc) {
3935
+ return {
3936
+ data: { xmlValid: false },
3937
+ issues: xmlParse.issues
3938
+ };
3939
+ }
3940
+ const xmlRoot = xmlParse.doc.documentElement;
3941
+ const xmlRootName = localName2(xmlRoot);
3942
+ const xmlRootNs = namespaceUri2(xmlRoot);
3943
+ const issues = [...xmlParse.issues];
3944
+ if (!xmlRoot) {
3945
+ return {
3946
+ data: { xmlValid: false },
3947
+ issues: [
3948
+ ...issues,
3949
+ createIssue({
3950
+ code: ISSUE_CODES.XML_PARSE_ERROR,
3951
+ severity: "error",
3952
+ message: "XML document has no document element.",
3953
+ source: "xml"
3954
+ })
3955
+ ]
3956
+ };
3957
+ }
3958
+ const schemaRoot = determineRootElement(schema, xmlRootName, xmlRootNs, options);
3959
+ if (!schemaRoot) {
3960
+ issues.push(
3961
+ createIssue({
3962
+ code: options.rootElementName ? ISSUE_CODES.XML_ROOT_ELEMENT_MISMATCH : ISSUE_CODES.XML_UNKNOWN_ROOT_ELEMENT,
3963
+ severity: "error",
3964
+ message: options.rootElementName ? `XML root '${xmlRootName}' does not match requested schema root '${options.rootElementName}'.` : `No matching global schema root found for XML root '${xmlRootName}'.`,
3965
+ source: "xml",
3966
+ nodeKind: "element",
3967
+ name: xmlRootName,
3968
+ details: { xmlRootName, xmlRootNamespace: xmlRootNs }
3969
+ })
3970
+ );
3971
+ return {
3972
+ data: { xmlValid: false },
3973
+ issues
3974
+ };
3975
+ }
3976
+ if ((schemaRoot.name || schemaRoot.refName) !== xmlRootName) {
3977
+ issues.push(
3978
+ createIssue({
3979
+ code: ISSUE_CODES.XML_ROOT_ELEMENT_MISMATCH,
3980
+ severity: "error",
3981
+ message: `Expected XML root '${schemaRoot.name || schemaRoot.refName}' but found '${xmlRootName}'.`,
3982
+ source: "xml",
3983
+ nodeKind: "element",
3984
+ name: xmlRootName,
3985
+ details: {
3986
+ expectedRoot: schemaRoot.name || schemaRoot.refName,
3987
+ actualRoot: xmlRootName
3988
+ }
3989
+ })
3990
+ );
3991
+ return {
3992
+ data: { xmlValid: false },
3993
+ issues
3994
+ };
3995
+ }
3996
+ if (schemaRoot.namespaceUri && xmlRootNs && schemaRoot.namespaceUri !== xmlRootNs) {
3997
+ issues.push(
3998
+ createIssue({
3999
+ code: ISSUE_CODES.XML_ROOT_ELEMENT_MISMATCH,
4000
+ severity: "error",
4001
+ message: "XML root namespace does not match schema root namespace.",
4002
+ source: "xml",
4003
+ nodeKind: "element",
4004
+ name: xmlRootName,
4005
+ details: {
4006
+ expectedNamespace: schemaRoot.namespaceUri,
4007
+ actualNamespace: xmlRootNs
4008
+ }
4009
+ })
4010
+ );
4011
+ return {
4012
+ data: { xmlValid: false },
4013
+ issues
4014
+ };
4015
+ }
4016
+ const context = {
4017
+ schema,
4018
+ issues,
4019
+ createIssue,
4020
+ ISSUE_CODES,
4021
+ validateElementValue,
4022
+ validateAttributeValue,
4023
+ resolveAttributeGroup: helpers.resolveAttributeGroup
4024
+ };
4025
+ const resolvedRootType = resolveType(schema, schemaRoot.typeName) || schemaRoot.inlineType;
4026
+ if (resolvedRootType?.kind === "complexType") {
4027
+ const rootContext = {
4028
+ ...context,
4029
+ pathParts: [xmlRootName],
4030
+ currentComplexType: resolvedRootType
4031
+ };
4032
+ validateAttributes(xmlRoot, getEffectiveAttributes(schema, resolvedRootType), rootContext);
4033
+ const hasDirectText = Array.from(xmlRoot.childNodes || []).some(
4034
+ (node) => node.nodeType === 3 && node.nodeValue?.trim()
4035
+ );
4036
+ if (!resolvedRootType.mixed && hasDirectText) {
4037
+ issues.push(
4038
+ createIssue({
4039
+ code: ISSUE_CODES.XML_MIXED_CONTENT_NOT_ALLOWED,
4040
+ severity: "error",
4041
+ message: "Mixed text content is not allowed for this complex type.",
4042
+ path: `/${xmlRootName}`,
4043
+ source: "xml",
4044
+ nodeKind: "element",
4045
+ name: xmlRootName,
4046
+ details: {}
4047
+ })
4048
+ );
4049
+ }
4050
+ const children = elementChildren3(xmlRoot);
4051
+ const content = resolvedRootType?.kind === "complexType" ? getEffectiveContent(schema, resolvedRootType) : null;
4052
+ if (content) {
4053
+ const result = validateContentModel(
4054
+ children,
4055
+ content,
4056
+ rootContext,
4057
+ [xmlRootName],
4058
+ 0,
4059
+ false
4060
+ );
4061
+ if (result.nextIndex < children.length) {
4062
+ for (let i = result.nextIndex; i < children.length; i += 1) {
4063
+ const childName = localName2(children[i]);
4064
+ issues.push(
4065
+ createIssue({
4066
+ code: ISSUE_CODES.XML_UNEXPECTED_ELEMENT,
4067
+ severity: "error",
4068
+ message: `Unexpected element '${childName}'.`,
4069
+ path: `/${xmlRootName}/${childName}`,
4070
+ source: "xml",
4071
+ nodeKind: "element",
4072
+ name: childName,
4073
+ details: {
4074
+ namespaceUri: namespaceUri2(children[i])
4075
+ }
4076
+ })
4077
+ );
4078
+ }
4079
+ }
4080
+ }
4081
+ } else {
4082
+ const valueResult = validateElementValue(schema, schemaRoot, (xmlRoot.textContent || "").trim());
4083
+ if (!valueResult.ok) {
4084
+ issues.push(
4085
+ createIssue({
4086
+ code: ISSUE_CODES[valueResult.code] || valueResult.code,
4087
+ severity: "error",
4088
+ message: valueResult.message,
4089
+ path: `/${xmlRootName}`,
4090
+ source: "xml",
4091
+ nodeKind: "element",
4092
+ name: xmlRootName,
4093
+ details: {}
4094
+ })
4095
+ );
4096
+ }
4097
+ }
4098
+ return {
4099
+ data: {
4100
+ xmlValid: !issues.some((issue) => issue.severity === "error")
4101
+ },
4102
+ issues
4103
+ };
4104
+ }
4105
+
4106
+ // src/api/validateXml.js
4107
+ function validateXml({ xsdText, xmlText, options = {} } = {}) {
4108
+ const parseResult = parseXsd(xsdText);
4109
+ if (!parseResult.ok || !parseResult.doc) {
4110
+ return makeResult({
4111
+ data: { xmlValid: false },
4112
+ issues: parseResult.issues
4113
+ });
4114
+ }
4115
+ const modelResult = buildSchemaModel(parseResult.doc, {
4116
+ ...options,
4117
+ xsdText
4118
+ });
4119
+ const baseIssues = [
4120
+ ...parseResult.issues || [],
4121
+ ...modelResult.issues || []
4122
+ ];
4123
+ if (!modelResult.schema) {
4124
+ return makeResult({
4125
+ data: { xmlValid: false },
4126
+ issues: baseIssues
4127
+ });
4128
+ }
4129
+ const diagnostics = runSchemaDiagnostics(modelResult.schema, {
4130
+ ...options,
4131
+ includeWarnings: true,
4132
+ includeFeatureSummary: false,
4133
+ includeRoots: true
4134
+ });
4135
+ const validation = validateXmlAgainstSchema(modelResult.schema, xmlText, options, {
4136
+ resolveAttributeGroup: (name) => resolveAttributeGroup(modelResult.schema, name)
4137
+ });
4138
+ return makeResult({
4139
+ data: validation.data,
4140
+ issues: [...baseIssues, ...diagnostics.issues || [], ...validation.issues || []]
4141
+ });
4142
+ }
4143
+ export {
4144
+ extractSchemaTree,
4145
+ generateSampleXml,
4146
+ getSchemaDiagnostics,
4147
+ validateXml
4148
+ };
4149
+ //# sourceMappingURL=uss-xsd-engine.esm.js.map