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