@abapify/ts-xsd 0.3.6 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen/cli.d.mts +1 -0
- package/dist/codegen/cli.mjs +137 -0
- package/dist/codegen/cli.mjs.map +1 -0
- package/dist/generate-DnX2dJZe.mjs +262 -0
- package/dist/generate-DnX2dJZe.mjs.map +1 -0
- package/dist/generators/index.d.mts +198 -0
- package/dist/generators/index.d.mts.map +1 -0
- package/dist/generators/index.mjs +635 -0
- package/dist/generators/index.mjs.map +1 -0
- package/dist/index.d.mts +1183 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1116 -0
- package/dist/index.mjs.map +1 -0
- package/dist/runner-C4_p2y5e.d.mts +738 -0
- package/dist/runner-C4_p2y5e.d.mts.map +1 -0
- package/dist/runner-CRhT3smd.mjs +2651 -0
- package/dist/runner-CRhT3smd.mjs.map +1 -0
- package/dist/types-CtrpGRyM.mjs +521 -0
- package/dist/types-CtrpGRyM.mjs.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,2651 @@
|
|
|
1
|
+
import { DOMParser } from "@xmldom/xmldom";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/xml/dom-utils.ts
|
|
6
|
+
/**
|
|
7
|
+
* Type guard to check if a Node is an Element
|
|
8
|
+
*/
|
|
9
|
+
function isElement(node) {
|
|
10
|
+
return node.nodeType === 1;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get attribute value, handling namespaced attributes
|
|
14
|
+
* Tries direct attribute first, then searches by local name
|
|
15
|
+
*/
|
|
16
|
+
function getAttributeValue(node, name) {
|
|
17
|
+
if (node.hasAttribute(name)) return node.getAttribute(name);
|
|
18
|
+
for (let i = 0; i < node.attributes.length; i++) {
|
|
19
|
+
const attr = node.attributes[i];
|
|
20
|
+
if ((attr.localName || attr.name.split(":").pop()) === name) return attr.value;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get child elements by local name (namespace-agnostic)
|
|
26
|
+
*/
|
|
27
|
+
function getChildElements(parent, name) {
|
|
28
|
+
const result = [];
|
|
29
|
+
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
30
|
+
const child = parent.childNodes[i];
|
|
31
|
+
if (isElement(child)) {
|
|
32
|
+
if ((child.localName || child.tagName.split(":").pop()) === name) result.push(child);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get all child elements (any name)
|
|
39
|
+
*/
|
|
40
|
+
function getAllChildElements(parent) {
|
|
41
|
+
const result = [];
|
|
42
|
+
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
43
|
+
const child = parent.childNodes[i];
|
|
44
|
+
if (isElement(child)) result.push(child);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get text content of an element (concatenates all text nodes)
|
|
50
|
+
*/
|
|
51
|
+
function getTextContent(node) {
|
|
52
|
+
let text = "";
|
|
53
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
54
|
+
const child = node.childNodes[i];
|
|
55
|
+
if (child.nodeType === 3) text += child.textContent || "";
|
|
56
|
+
}
|
|
57
|
+
return text.trim();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get local name of an element (strips namespace prefix)
|
|
61
|
+
*/
|
|
62
|
+
function getLocalName(node) {
|
|
63
|
+
return node.localName || node.tagName.split(":").pop() || node.tagName;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/xsd/parse.ts
|
|
68
|
+
/**
|
|
69
|
+
* XSD Parser - Parse XSD documents to typed Schema objects
|
|
70
|
+
*
|
|
71
|
+
* This parser understands XSD semantics and produces correctly typed output
|
|
72
|
+
* matching the W3C XMLSchema.xsd specification.
|
|
73
|
+
*
|
|
74
|
+
* No intermediate JSON - direct XSD to typed objects.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* Parse an XSD string to a typed Schema object
|
|
78
|
+
*/
|
|
79
|
+
function parseXsd(xml) {
|
|
80
|
+
const root = new DOMParser().parseFromString(xml, "text/xml").documentElement;
|
|
81
|
+
if (!root || getLocalName(root) !== "schema") throw new Error("Invalid XSD: root element must be xs:schema");
|
|
82
|
+
return parseSchema(root);
|
|
83
|
+
}
|
|
84
|
+
function parseSchema(el) {
|
|
85
|
+
const schema = {};
|
|
86
|
+
copyXmlns(el, schema);
|
|
87
|
+
copyAttr(el, schema, "id");
|
|
88
|
+
copyAttr(el, schema, "targetNamespace");
|
|
89
|
+
copyAttr(el, schema, "version");
|
|
90
|
+
copyAttr(el, schema, "finalDefault");
|
|
91
|
+
copyAttr(el, schema, "blockDefault");
|
|
92
|
+
copyAttr(el, schema, "attributeFormDefault");
|
|
93
|
+
copyAttr(el, schema, "elementFormDefault");
|
|
94
|
+
copyAttr(el, schema, "defaultAttributes");
|
|
95
|
+
copyAttr(el, schema, "xpathDefaultNamespace");
|
|
96
|
+
copyAttr(el, schema, "xml:lang");
|
|
97
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
98
|
+
case "annotation":
|
|
99
|
+
pushTo(schema, "annotation", parseAnnotation(child));
|
|
100
|
+
break;
|
|
101
|
+
case "include":
|
|
102
|
+
pushTo(schema, "include", parseInclude(child));
|
|
103
|
+
break;
|
|
104
|
+
case "import":
|
|
105
|
+
pushTo(schema, "import", parseImport(child));
|
|
106
|
+
break;
|
|
107
|
+
case "redefine":
|
|
108
|
+
pushTo(schema, "redefine", parseRedefine(child));
|
|
109
|
+
break;
|
|
110
|
+
case "override":
|
|
111
|
+
pushTo(schema, "override", parseOverride(child));
|
|
112
|
+
break;
|
|
113
|
+
case "element":
|
|
114
|
+
pushTo(schema, "element", parseTopLevelElement(child));
|
|
115
|
+
break;
|
|
116
|
+
case "attribute":
|
|
117
|
+
pushTo(schema, "attribute", parseTopLevelAttribute(child));
|
|
118
|
+
break;
|
|
119
|
+
case "simpleType":
|
|
120
|
+
pushTo(schema, "simpleType", parseTopLevelSimpleType(child));
|
|
121
|
+
break;
|
|
122
|
+
case "complexType":
|
|
123
|
+
pushTo(schema, "complexType", parseTopLevelComplexType(child));
|
|
124
|
+
break;
|
|
125
|
+
case "group":
|
|
126
|
+
pushTo(schema, "group", parseNamedGroup(child));
|
|
127
|
+
break;
|
|
128
|
+
case "attributeGroup":
|
|
129
|
+
pushTo(schema, "attributeGroup", parseNamedAttributeGroup(child));
|
|
130
|
+
break;
|
|
131
|
+
case "notation":
|
|
132
|
+
pushTo(schema, "notation", parseNotation(child));
|
|
133
|
+
break;
|
|
134
|
+
case "defaultOpenContent":
|
|
135
|
+
schema.defaultOpenContent = parseDefaultOpenContent(child);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
return schema;
|
|
139
|
+
}
|
|
140
|
+
function parseAnnotation(el) {
|
|
141
|
+
const result = {};
|
|
142
|
+
copyAttr(el, result, "id");
|
|
143
|
+
for (const child of getAllChildElements(el)) {
|
|
144
|
+
const name = getLocalName(child);
|
|
145
|
+
if (name === "documentation") pushTo(result, "documentation", parseDocumentation(child));
|
|
146
|
+
else if (name === "appinfo") pushTo(result, "appinfo", parseAppinfo(child));
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
function parseDocumentation(el) {
|
|
151
|
+
const result = {};
|
|
152
|
+
copyAttr(el, result, "source");
|
|
153
|
+
copyAttr(el, result, "xml:lang");
|
|
154
|
+
const text = getTextContent(el);
|
|
155
|
+
if (text) result._text = text;
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
function parseAppinfo(el) {
|
|
159
|
+
const result = {};
|
|
160
|
+
copyAttr(el, result, "source");
|
|
161
|
+
const text = getTextContent(el);
|
|
162
|
+
if (text) result._text = text;
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
function parseInclude(el) {
|
|
166
|
+
const result = { schemaLocation: "" };
|
|
167
|
+
copyAttr(el, result, "id");
|
|
168
|
+
copyAttr(el, result, "schemaLocation");
|
|
169
|
+
parseAnnotationChild(el, result);
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
function parseImport(el) {
|
|
173
|
+
const result = {};
|
|
174
|
+
copyAttr(el, result, "id");
|
|
175
|
+
copyAttr(el, result, "namespace");
|
|
176
|
+
copyAttr(el, result, "schemaLocation");
|
|
177
|
+
parseAnnotationChild(el, result);
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
function parseRedefine(el) {
|
|
181
|
+
const result = { schemaLocation: "" };
|
|
182
|
+
copyAttr(el, result, "id");
|
|
183
|
+
copyAttr(el, result, "schemaLocation");
|
|
184
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
185
|
+
case "annotation":
|
|
186
|
+
pushTo(result, "annotation", parseAnnotation(child));
|
|
187
|
+
break;
|
|
188
|
+
case "simpleType":
|
|
189
|
+
pushTo(result, "simpleType", parseTopLevelSimpleType(child));
|
|
190
|
+
break;
|
|
191
|
+
case "complexType":
|
|
192
|
+
pushTo(result, "complexType", parseTopLevelComplexType(child));
|
|
193
|
+
break;
|
|
194
|
+
case "group":
|
|
195
|
+
pushTo(result, "group", parseNamedGroup(child));
|
|
196
|
+
break;
|
|
197
|
+
case "attributeGroup":
|
|
198
|
+
pushTo(result, "attributeGroup", parseNamedAttributeGroup(child));
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
function parseOverride(el) {
|
|
204
|
+
const result = { schemaLocation: "" };
|
|
205
|
+
copyAttr(el, result, "id");
|
|
206
|
+
copyAttr(el, result, "schemaLocation");
|
|
207
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
208
|
+
case "annotation":
|
|
209
|
+
pushTo(result, "annotation", parseAnnotation(child));
|
|
210
|
+
break;
|
|
211
|
+
case "simpleType":
|
|
212
|
+
pushTo(result, "simpleType", parseTopLevelSimpleType(child));
|
|
213
|
+
break;
|
|
214
|
+
case "complexType":
|
|
215
|
+
pushTo(result, "complexType", parseTopLevelComplexType(child));
|
|
216
|
+
break;
|
|
217
|
+
case "group":
|
|
218
|
+
pushTo(result, "group", parseNamedGroup(child));
|
|
219
|
+
break;
|
|
220
|
+
case "attributeGroup":
|
|
221
|
+
pushTo(result, "attributeGroup", parseNamedAttributeGroup(child));
|
|
222
|
+
break;
|
|
223
|
+
case "element":
|
|
224
|
+
pushTo(result, "element", parseTopLevelElement(child));
|
|
225
|
+
break;
|
|
226
|
+
case "attribute":
|
|
227
|
+
pushTo(result, "attribute", parseTopLevelAttribute(child));
|
|
228
|
+
break;
|
|
229
|
+
case "notation":
|
|
230
|
+
pushTo(result, "notation", parseNotation(child));
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
function parseTopLevelElement(el) {
|
|
236
|
+
const result = { name: "" };
|
|
237
|
+
copyAttr(el, result, "id");
|
|
238
|
+
copyAttr(el, result, "name");
|
|
239
|
+
copyAttr(el, result, "type");
|
|
240
|
+
copyAttr(el, result, "substitutionGroup");
|
|
241
|
+
copyAttr(el, result, "default");
|
|
242
|
+
copyAttr(el, result, "fixed");
|
|
243
|
+
copyBoolAttr(el, result, "nillable");
|
|
244
|
+
copyBoolAttr(el, result, "abstract");
|
|
245
|
+
copyAttr(el, result, "final");
|
|
246
|
+
copyAttr(el, result, "block");
|
|
247
|
+
parseAnnotationChild(el, result);
|
|
248
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
249
|
+
case "simpleType":
|
|
250
|
+
result.simpleType = parseLocalSimpleType(child);
|
|
251
|
+
break;
|
|
252
|
+
case "complexType":
|
|
253
|
+
result.complexType = parseLocalComplexType(child);
|
|
254
|
+
break;
|
|
255
|
+
case "unique":
|
|
256
|
+
pushTo(result, "unique", parseUnique(child));
|
|
257
|
+
break;
|
|
258
|
+
case "key":
|
|
259
|
+
pushTo(result, "key", parseKey(child));
|
|
260
|
+
break;
|
|
261
|
+
case "keyref":
|
|
262
|
+
pushTo(result, "keyref", parseKeyref(child));
|
|
263
|
+
break;
|
|
264
|
+
case "alternative":
|
|
265
|
+
pushTo(result, "alternative", parseAlternative(child));
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
function parseLocalElement(el) {
|
|
271
|
+
const result = {};
|
|
272
|
+
copyAttr(el, result, "id");
|
|
273
|
+
copyAttr(el, result, "name");
|
|
274
|
+
copyAttr(el, result, "ref");
|
|
275
|
+
copyAttr(el, result, "type");
|
|
276
|
+
copyAttr(el, result, "minOccurs");
|
|
277
|
+
copyAttr(el, result, "maxOccurs");
|
|
278
|
+
copyAttr(el, result, "default");
|
|
279
|
+
copyAttr(el, result, "fixed");
|
|
280
|
+
copyBoolAttr(el, result, "nillable");
|
|
281
|
+
copyAttr(el, result, "block");
|
|
282
|
+
copyAttr(el, result, "form");
|
|
283
|
+
copyAttr(el, result, "targetNamespace");
|
|
284
|
+
parseAnnotationChild(el, result);
|
|
285
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
286
|
+
case "simpleType":
|
|
287
|
+
result.simpleType = parseLocalSimpleType(child);
|
|
288
|
+
break;
|
|
289
|
+
case "complexType":
|
|
290
|
+
result.complexType = parseLocalComplexType(child);
|
|
291
|
+
break;
|
|
292
|
+
case "unique":
|
|
293
|
+
pushTo(result, "unique", parseUnique(child));
|
|
294
|
+
break;
|
|
295
|
+
case "key":
|
|
296
|
+
pushTo(result, "key", parseKey(child));
|
|
297
|
+
break;
|
|
298
|
+
case "keyref":
|
|
299
|
+
pushTo(result, "keyref", parseKeyref(child));
|
|
300
|
+
break;
|
|
301
|
+
case "alternative":
|
|
302
|
+
pushTo(result, "alternative", parseAlternative(child));
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
function parseTopLevelAttribute(el) {
|
|
308
|
+
const result = { name: "" };
|
|
309
|
+
copyAttr(el, result, "id");
|
|
310
|
+
copyAttr(el, result, "name");
|
|
311
|
+
copyAttr(el, result, "type");
|
|
312
|
+
copyAttr(el, result, "default");
|
|
313
|
+
copyAttr(el, result, "fixed");
|
|
314
|
+
copyBoolAttr(el, result, "inheritable");
|
|
315
|
+
parseAnnotationChild(el, result);
|
|
316
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "simpleType") result.simpleType = parseLocalSimpleType(child);
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
function parseLocalAttribute(el) {
|
|
320
|
+
const result = {};
|
|
321
|
+
copyAttr(el, result, "id");
|
|
322
|
+
copyAttr(el, result, "name");
|
|
323
|
+
copyAttr(el, result, "ref");
|
|
324
|
+
copyAttr(el, result, "type");
|
|
325
|
+
copyAttr(el, result, "use");
|
|
326
|
+
copyAttr(el, result, "default");
|
|
327
|
+
copyAttr(el, result, "fixed");
|
|
328
|
+
copyAttr(el, result, "form");
|
|
329
|
+
copyAttr(el, result, "targetNamespace");
|
|
330
|
+
copyBoolAttr(el, result, "inheritable");
|
|
331
|
+
parseAnnotationChild(el, result);
|
|
332
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "simpleType") result.simpleType = parseLocalSimpleType(child);
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
function parseTopLevelComplexType(el) {
|
|
336
|
+
const result = { name: "" };
|
|
337
|
+
copyAttr(el, result, "id");
|
|
338
|
+
copyAttr(el, result, "name");
|
|
339
|
+
copyBoolAttr(el, result, "mixed");
|
|
340
|
+
copyBoolAttr(el, result, "abstract");
|
|
341
|
+
copyAttr(el, result, "final");
|
|
342
|
+
copyAttr(el, result, "block");
|
|
343
|
+
copyBoolAttr(el, result, "defaultAttributesApply");
|
|
344
|
+
parseAnnotationChild(el, result);
|
|
345
|
+
parseComplexTypeContent(el, result);
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
function parseLocalComplexType(el) {
|
|
349
|
+
const result = {};
|
|
350
|
+
copyAttr(el, result, "id");
|
|
351
|
+
copyBoolAttr(el, result, "mixed");
|
|
352
|
+
parseAnnotationChild(el, result);
|
|
353
|
+
parseComplexTypeContent(el, result);
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
function parseComplexTypeContent(el, result) {
|
|
357
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
358
|
+
case "simpleContent":
|
|
359
|
+
result.simpleContent = parseSimpleContent(child);
|
|
360
|
+
break;
|
|
361
|
+
case "complexContent":
|
|
362
|
+
result.complexContent = parseComplexContent(child);
|
|
363
|
+
break;
|
|
364
|
+
case "openContent":
|
|
365
|
+
result.openContent = parseOpenContent(child);
|
|
366
|
+
break;
|
|
367
|
+
case "group":
|
|
368
|
+
result.group = parseGroupRef(child);
|
|
369
|
+
break;
|
|
370
|
+
case "all":
|
|
371
|
+
result.all = parseAll(child);
|
|
372
|
+
break;
|
|
373
|
+
case "choice":
|
|
374
|
+
result.choice = parseExplicitGroup(child);
|
|
375
|
+
break;
|
|
376
|
+
case "sequence":
|
|
377
|
+
result.sequence = parseExplicitGroup(child);
|
|
378
|
+
break;
|
|
379
|
+
case "attribute":
|
|
380
|
+
pushTo(result, "attribute", parseLocalAttribute(child));
|
|
381
|
+
break;
|
|
382
|
+
case "attributeGroup":
|
|
383
|
+
pushTo(result, "attributeGroup", parseAttributeGroupRef(child));
|
|
384
|
+
break;
|
|
385
|
+
case "anyAttribute":
|
|
386
|
+
result.anyAttribute = parseAnyAttribute(child);
|
|
387
|
+
break;
|
|
388
|
+
case "assert":
|
|
389
|
+
pushTo(result, "assert", parseAssertion(child));
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function parseTopLevelSimpleType(el) {
|
|
394
|
+
const result = { name: "" };
|
|
395
|
+
copyAttr(el, result, "id");
|
|
396
|
+
copyAttr(el, result, "name");
|
|
397
|
+
copyAttr(el, result, "final");
|
|
398
|
+
parseAnnotationChild(el, result);
|
|
399
|
+
parseSimpleTypeContent(el, result);
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
function parseLocalSimpleType(el) {
|
|
403
|
+
const result = {};
|
|
404
|
+
copyAttr(el, result, "id");
|
|
405
|
+
parseAnnotationChild(el, result);
|
|
406
|
+
parseSimpleTypeContent(el, result);
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
function parseSimpleTypeContent(el, result) {
|
|
410
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
411
|
+
case "restriction":
|
|
412
|
+
result.restriction = parseSimpleTypeRestriction(child);
|
|
413
|
+
break;
|
|
414
|
+
case "list":
|
|
415
|
+
result.list = parseList(child);
|
|
416
|
+
break;
|
|
417
|
+
case "union":
|
|
418
|
+
result.union = parseUnion(child);
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function parseSimpleTypeRestriction(el) {
|
|
423
|
+
const result = {};
|
|
424
|
+
copyAttr(el, result, "id");
|
|
425
|
+
copyAttr(el, result, "base");
|
|
426
|
+
parseAnnotationChild(el, result);
|
|
427
|
+
for (const child of getAllChildElements(el)) {
|
|
428
|
+
const name = getLocalName(child);
|
|
429
|
+
switch (name) {
|
|
430
|
+
case "simpleType":
|
|
431
|
+
result.simpleType = parseLocalSimpleType(child);
|
|
432
|
+
break;
|
|
433
|
+
case "minExclusive":
|
|
434
|
+
case "minInclusive":
|
|
435
|
+
case "maxExclusive":
|
|
436
|
+
case "maxInclusive":
|
|
437
|
+
case "totalDigits":
|
|
438
|
+
case "fractionDigits":
|
|
439
|
+
case "length":
|
|
440
|
+
case "minLength":
|
|
441
|
+
case "maxLength":
|
|
442
|
+
case "enumeration":
|
|
443
|
+
case "whiteSpace":
|
|
444
|
+
case "explicitTimezone":
|
|
445
|
+
pushTo(result, name, parseFacet(child));
|
|
446
|
+
break;
|
|
447
|
+
case "pattern":
|
|
448
|
+
pushTo(result, "pattern", parsePattern(child));
|
|
449
|
+
break;
|
|
450
|
+
case "assertion":
|
|
451
|
+
pushTo(result, "assertion", parseAssertion(child));
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
function parseList(el) {
|
|
458
|
+
const result = {};
|
|
459
|
+
copyAttr(el, result, "id");
|
|
460
|
+
copyAttr(el, result, "itemType");
|
|
461
|
+
parseAnnotationChild(el, result);
|
|
462
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "simpleType") result.simpleType = parseLocalSimpleType(child);
|
|
463
|
+
return result;
|
|
464
|
+
}
|
|
465
|
+
function parseUnion(el) {
|
|
466
|
+
const result = {};
|
|
467
|
+
copyAttr(el, result, "id");
|
|
468
|
+
copyAttr(el, result, "memberTypes");
|
|
469
|
+
parseAnnotationChild(el, result);
|
|
470
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "simpleType") pushTo(result, "simpleType", parseLocalSimpleType(child));
|
|
471
|
+
return result;
|
|
472
|
+
}
|
|
473
|
+
function parseFacet(el) {
|
|
474
|
+
const result = { value: "" };
|
|
475
|
+
copyAttr(el, result, "id");
|
|
476
|
+
copyAttr(el, result, "value");
|
|
477
|
+
copyBoolAttr(el, result, "fixed");
|
|
478
|
+
parseAnnotationChild(el, result);
|
|
479
|
+
return result;
|
|
480
|
+
}
|
|
481
|
+
function parsePattern(el) {
|
|
482
|
+
const result = { value: "" };
|
|
483
|
+
copyAttr(el, result, "id");
|
|
484
|
+
copyAttr(el, result, "value");
|
|
485
|
+
parseAnnotationChild(el, result);
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
function parseComplexContent(el) {
|
|
489
|
+
const result = {};
|
|
490
|
+
copyAttr(el, result, "id");
|
|
491
|
+
copyBoolAttr(el, result, "mixed");
|
|
492
|
+
parseAnnotationChild(el, result);
|
|
493
|
+
for (const child of getAllChildElements(el)) {
|
|
494
|
+
const name = getLocalName(child);
|
|
495
|
+
if (name === "restriction") result.restriction = parseComplexContentRestriction(child);
|
|
496
|
+
else if (name === "extension") result.extension = parseComplexContentExtension(child);
|
|
497
|
+
}
|
|
498
|
+
return result;
|
|
499
|
+
}
|
|
500
|
+
function parseSimpleContent(el) {
|
|
501
|
+
const result = {};
|
|
502
|
+
copyAttr(el, result, "id");
|
|
503
|
+
parseAnnotationChild(el, result);
|
|
504
|
+
for (const child of getAllChildElements(el)) {
|
|
505
|
+
const name = getLocalName(child);
|
|
506
|
+
if (name === "restriction") result.restriction = parseSimpleContentRestriction(child);
|
|
507
|
+
else if (name === "extension") result.extension = parseSimpleContentExtension(child);
|
|
508
|
+
}
|
|
509
|
+
return result;
|
|
510
|
+
}
|
|
511
|
+
function parseComplexContentRestriction(el) {
|
|
512
|
+
const result = { base: "" };
|
|
513
|
+
copyAttr(el, result, "id");
|
|
514
|
+
copyAttr(el, result, "base");
|
|
515
|
+
parseAnnotationChild(el, result);
|
|
516
|
+
parseComplexTypeContent(el, result);
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
519
|
+
function parseComplexContentExtension(el) {
|
|
520
|
+
const result = { base: "" };
|
|
521
|
+
copyAttr(el, result, "id");
|
|
522
|
+
copyAttr(el, result, "base");
|
|
523
|
+
parseAnnotationChild(el, result);
|
|
524
|
+
parseComplexTypeContent(el, result);
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
function parseSimpleContentRestriction(el) {
|
|
528
|
+
const result = { base: "" };
|
|
529
|
+
copyAttr(el, result, "id");
|
|
530
|
+
copyAttr(el, result, "base");
|
|
531
|
+
parseAnnotationChild(el, result);
|
|
532
|
+
for (const child of getAllChildElements(el)) {
|
|
533
|
+
const name = getLocalName(child);
|
|
534
|
+
switch (name) {
|
|
535
|
+
case "simpleType":
|
|
536
|
+
result.simpleType = parseLocalSimpleType(child);
|
|
537
|
+
break;
|
|
538
|
+
case "minExclusive":
|
|
539
|
+
case "minInclusive":
|
|
540
|
+
case "maxExclusive":
|
|
541
|
+
case "maxInclusive":
|
|
542
|
+
case "totalDigits":
|
|
543
|
+
case "fractionDigits":
|
|
544
|
+
case "length":
|
|
545
|
+
case "minLength":
|
|
546
|
+
case "maxLength":
|
|
547
|
+
case "enumeration":
|
|
548
|
+
case "whiteSpace":
|
|
549
|
+
case "explicitTimezone":
|
|
550
|
+
pushTo(result, name, parseFacet(child));
|
|
551
|
+
break;
|
|
552
|
+
case "pattern":
|
|
553
|
+
pushTo(result, "pattern", parsePattern(child));
|
|
554
|
+
break;
|
|
555
|
+
case "assertion":
|
|
556
|
+
pushTo(result, "assertion", parseAssertion(child));
|
|
557
|
+
break;
|
|
558
|
+
case "attribute":
|
|
559
|
+
pushTo(result, "attribute", parseLocalAttribute(child));
|
|
560
|
+
break;
|
|
561
|
+
case "attributeGroup":
|
|
562
|
+
pushTo(result, "attributeGroup", parseAttributeGroupRef(child));
|
|
563
|
+
break;
|
|
564
|
+
case "anyAttribute":
|
|
565
|
+
result.anyAttribute = parseAnyAttribute(child);
|
|
566
|
+
break;
|
|
567
|
+
case "assert":
|
|
568
|
+
pushTo(result, "assert", parseAssertion(child));
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return result;
|
|
573
|
+
}
|
|
574
|
+
function parseSimpleContentExtension(el) {
|
|
575
|
+
const result = { base: "" };
|
|
576
|
+
copyAttr(el, result, "id");
|
|
577
|
+
copyAttr(el, result, "base");
|
|
578
|
+
parseAnnotationChild(el, result);
|
|
579
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
580
|
+
case "attribute":
|
|
581
|
+
pushTo(result, "attribute", parseLocalAttribute(child));
|
|
582
|
+
break;
|
|
583
|
+
case "attributeGroup":
|
|
584
|
+
pushTo(result, "attributeGroup", parseAttributeGroupRef(child));
|
|
585
|
+
break;
|
|
586
|
+
case "anyAttribute":
|
|
587
|
+
result.anyAttribute = parseAnyAttribute(child);
|
|
588
|
+
break;
|
|
589
|
+
case "assert":
|
|
590
|
+
pushTo(result, "assert", parseAssertion(child));
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
593
|
+
return result;
|
|
594
|
+
}
|
|
595
|
+
function parseExplicitGroup(el) {
|
|
596
|
+
const result = {};
|
|
597
|
+
copyAttr(el, result, "id");
|
|
598
|
+
copyAttr(el, result, "minOccurs");
|
|
599
|
+
copyAttr(el, result, "maxOccurs");
|
|
600
|
+
parseAnnotationChild(el, result);
|
|
601
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
602
|
+
case "element":
|
|
603
|
+
pushTo(result, "element", parseLocalElement(child));
|
|
604
|
+
break;
|
|
605
|
+
case "group":
|
|
606
|
+
pushTo(result, "group", parseGroupRef(child));
|
|
607
|
+
break;
|
|
608
|
+
case "choice":
|
|
609
|
+
pushTo(result, "choice", parseExplicitGroup(child));
|
|
610
|
+
break;
|
|
611
|
+
case "sequence":
|
|
612
|
+
pushTo(result, "sequence", parseExplicitGroup(child));
|
|
613
|
+
break;
|
|
614
|
+
case "any":
|
|
615
|
+
pushTo(result, "any", parseAny(child));
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
return result;
|
|
619
|
+
}
|
|
620
|
+
function parseAll(el) {
|
|
621
|
+
const result = {};
|
|
622
|
+
copyAttr(el, result, "id");
|
|
623
|
+
copyAttr(el, result, "minOccurs");
|
|
624
|
+
copyAttr(el, result, "maxOccurs");
|
|
625
|
+
parseAnnotationChild(el, result);
|
|
626
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
627
|
+
case "element":
|
|
628
|
+
pushTo(result, "element", parseLocalElement(child));
|
|
629
|
+
break;
|
|
630
|
+
case "any":
|
|
631
|
+
pushTo(result, "any", parseAny(child));
|
|
632
|
+
break;
|
|
633
|
+
case "group":
|
|
634
|
+
pushTo(result, "group", parseGroupRef(child));
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
return result;
|
|
638
|
+
}
|
|
639
|
+
function parseNamedGroup(el) {
|
|
640
|
+
const result = { name: "" };
|
|
641
|
+
copyAttr(el, result, "id");
|
|
642
|
+
copyAttr(el, result, "name");
|
|
643
|
+
parseAnnotationChild(el, result);
|
|
644
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
645
|
+
case "all":
|
|
646
|
+
result.all = parseAll(child);
|
|
647
|
+
break;
|
|
648
|
+
case "choice":
|
|
649
|
+
result.choice = parseExplicitGroup(child);
|
|
650
|
+
break;
|
|
651
|
+
case "sequence":
|
|
652
|
+
result.sequence = parseExplicitGroup(child);
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
657
|
+
function parseGroupRef(el) {
|
|
658
|
+
const result = { ref: "" };
|
|
659
|
+
copyAttr(el, result, "id");
|
|
660
|
+
copyAttr(el, result, "ref");
|
|
661
|
+
copyAttr(el, result, "minOccurs");
|
|
662
|
+
copyAttr(el, result, "maxOccurs");
|
|
663
|
+
parseAnnotationChild(el, result);
|
|
664
|
+
return result;
|
|
665
|
+
}
|
|
666
|
+
function parseNamedAttributeGroup(el) {
|
|
667
|
+
const result = { name: "" };
|
|
668
|
+
copyAttr(el, result, "id");
|
|
669
|
+
copyAttr(el, result, "name");
|
|
670
|
+
parseAnnotationChild(el, result);
|
|
671
|
+
for (const child of getAllChildElements(el)) switch (getLocalName(child)) {
|
|
672
|
+
case "attribute":
|
|
673
|
+
pushTo(result, "attribute", parseLocalAttribute(child));
|
|
674
|
+
break;
|
|
675
|
+
case "attributeGroup":
|
|
676
|
+
pushTo(result, "attributeGroup", parseAttributeGroupRef(child));
|
|
677
|
+
break;
|
|
678
|
+
case "anyAttribute":
|
|
679
|
+
result.anyAttribute = parseAnyAttribute(child);
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
684
|
+
function parseAttributeGroupRef(el) {
|
|
685
|
+
const result = { ref: "" };
|
|
686
|
+
copyAttr(el, result, "id");
|
|
687
|
+
copyAttr(el, result, "ref");
|
|
688
|
+
parseAnnotationChild(el, result);
|
|
689
|
+
return result;
|
|
690
|
+
}
|
|
691
|
+
function parseAny(el) {
|
|
692
|
+
const result = {};
|
|
693
|
+
copyAttr(el, result, "id");
|
|
694
|
+
copyAttr(el, result, "minOccurs");
|
|
695
|
+
copyAttr(el, result, "maxOccurs");
|
|
696
|
+
copyAttr(el, result, "namespace");
|
|
697
|
+
copyAttr(el, result, "processContents");
|
|
698
|
+
copyAttr(el, result, "notNamespace");
|
|
699
|
+
copyAttr(el, result, "notQName");
|
|
700
|
+
parseAnnotationChild(el, result);
|
|
701
|
+
return result;
|
|
702
|
+
}
|
|
703
|
+
function parseAnyAttribute(el) {
|
|
704
|
+
const result = {};
|
|
705
|
+
copyAttr(el, result, "id");
|
|
706
|
+
copyAttr(el, result, "namespace");
|
|
707
|
+
copyAttr(el, result, "processContents");
|
|
708
|
+
copyAttr(el, result, "notNamespace");
|
|
709
|
+
copyAttr(el, result, "notQName");
|
|
710
|
+
parseAnnotationChild(el, result);
|
|
711
|
+
return result;
|
|
712
|
+
}
|
|
713
|
+
function parseUnique(el) {
|
|
714
|
+
const result = { name: "" };
|
|
715
|
+
copyAttr(el, result, "id");
|
|
716
|
+
copyAttr(el, result, "name");
|
|
717
|
+
copyAttr(el, result, "ref");
|
|
718
|
+
parseAnnotationChild(el, result);
|
|
719
|
+
for (const child of getAllChildElements(el)) {
|
|
720
|
+
const name = getLocalName(child);
|
|
721
|
+
if (name === "selector") result.selector = parseSelector(child);
|
|
722
|
+
else if (name === "field") pushTo(result, "field", parseField(child));
|
|
723
|
+
}
|
|
724
|
+
return result;
|
|
725
|
+
}
|
|
726
|
+
function parseKey(el) {
|
|
727
|
+
const result = { name: "" };
|
|
728
|
+
copyAttr(el, result, "id");
|
|
729
|
+
copyAttr(el, result, "name");
|
|
730
|
+
copyAttr(el, result, "ref");
|
|
731
|
+
parseAnnotationChild(el, result);
|
|
732
|
+
for (const child of getAllChildElements(el)) {
|
|
733
|
+
const name = getLocalName(child);
|
|
734
|
+
if (name === "selector") result.selector = parseSelector(child);
|
|
735
|
+
else if (name === "field") pushTo(result, "field", parseField(child));
|
|
736
|
+
}
|
|
737
|
+
return result;
|
|
738
|
+
}
|
|
739
|
+
function parseKeyref(el) {
|
|
740
|
+
const result = {
|
|
741
|
+
name: "",
|
|
742
|
+
refer: ""
|
|
743
|
+
};
|
|
744
|
+
copyAttr(el, result, "id");
|
|
745
|
+
copyAttr(el, result, "name");
|
|
746
|
+
copyAttr(el, result, "ref");
|
|
747
|
+
copyAttr(el, result, "refer");
|
|
748
|
+
parseAnnotationChild(el, result);
|
|
749
|
+
for (const child of getAllChildElements(el)) {
|
|
750
|
+
const name = getLocalName(child);
|
|
751
|
+
if (name === "selector") result.selector = parseSelector(child);
|
|
752
|
+
else if (name === "field") pushTo(result, "field", parseField(child));
|
|
753
|
+
}
|
|
754
|
+
return result;
|
|
755
|
+
}
|
|
756
|
+
function parseSelector(el) {
|
|
757
|
+
const result = { xpath: "" };
|
|
758
|
+
copyAttr(el, result, "id");
|
|
759
|
+
copyAttr(el, result, "xpath");
|
|
760
|
+
copyAttr(el, result, "xpathDefaultNamespace");
|
|
761
|
+
parseAnnotationChild(el, result);
|
|
762
|
+
return result;
|
|
763
|
+
}
|
|
764
|
+
function parseField(el) {
|
|
765
|
+
const result = { xpath: "" };
|
|
766
|
+
copyAttr(el, result, "id");
|
|
767
|
+
copyAttr(el, result, "xpath");
|
|
768
|
+
copyAttr(el, result, "xpathDefaultNamespace");
|
|
769
|
+
parseAnnotationChild(el, result);
|
|
770
|
+
return result;
|
|
771
|
+
}
|
|
772
|
+
function parseOpenContent(el) {
|
|
773
|
+
const result = {};
|
|
774
|
+
copyAttr(el, result, "id");
|
|
775
|
+
copyAttr(el, result, "mode");
|
|
776
|
+
parseAnnotationChild(el, result);
|
|
777
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "any") result.any = parseAny(child);
|
|
778
|
+
return result;
|
|
779
|
+
}
|
|
780
|
+
function parseDefaultOpenContent(el) {
|
|
781
|
+
const result = { any: {} };
|
|
782
|
+
copyAttr(el, result, "id");
|
|
783
|
+
copyBoolAttr(el, result, "appliesToEmpty");
|
|
784
|
+
copyAttr(el, result, "mode");
|
|
785
|
+
parseAnnotationChild(el, result);
|
|
786
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "any") result.any = parseAny(child);
|
|
787
|
+
return result;
|
|
788
|
+
}
|
|
789
|
+
function parseAssertion(el) {
|
|
790
|
+
const result = {};
|
|
791
|
+
copyAttr(el, result, "id");
|
|
792
|
+
copyAttr(el, result, "test");
|
|
793
|
+
copyAttr(el, result, "xpathDefaultNamespace");
|
|
794
|
+
parseAnnotationChild(el, result);
|
|
795
|
+
return result;
|
|
796
|
+
}
|
|
797
|
+
function parseAlternative(el) {
|
|
798
|
+
const result = {};
|
|
799
|
+
copyAttr(el, result, "id");
|
|
800
|
+
copyAttr(el, result, "test");
|
|
801
|
+
copyAttr(el, result, "type");
|
|
802
|
+
copyAttr(el, result, "xpathDefaultNamespace");
|
|
803
|
+
parseAnnotationChild(el, result);
|
|
804
|
+
for (const child of getAllChildElements(el)) {
|
|
805
|
+
const name = getLocalName(child);
|
|
806
|
+
if (name === "simpleType") result.simpleType = parseLocalSimpleType(child);
|
|
807
|
+
else if (name === "complexType") result.complexType = parseLocalComplexType(child);
|
|
808
|
+
}
|
|
809
|
+
return result;
|
|
810
|
+
}
|
|
811
|
+
function parseNotation(el) {
|
|
812
|
+
const result = {
|
|
813
|
+
name: "",
|
|
814
|
+
public: ""
|
|
815
|
+
};
|
|
816
|
+
copyAttr(el, result, "id");
|
|
817
|
+
copyAttr(el, result, "name");
|
|
818
|
+
copyAttr(el, result, "public");
|
|
819
|
+
copyAttr(el, result, "system");
|
|
820
|
+
parseAnnotationChild(el, result);
|
|
821
|
+
return result;
|
|
822
|
+
}
|
|
823
|
+
function copyAttr(el, target, name) {
|
|
824
|
+
if (el.hasAttribute(name)) {
|
|
825
|
+
const value = el.getAttribute(name);
|
|
826
|
+
if (value !== null) target[name] = value;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
function copyBoolAttr(el, target, name) {
|
|
830
|
+
if (el.hasAttribute(name)) {
|
|
831
|
+
const value = el.getAttribute(name);
|
|
832
|
+
if (value !== null) target[name] = value === "true";
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
function pushTo(target, name, value) {
|
|
836
|
+
if (!target[name]) target[name] = [];
|
|
837
|
+
target[name].push(value);
|
|
838
|
+
}
|
|
839
|
+
function parseAnnotationChild(el, result) {
|
|
840
|
+
for (const child of getAllChildElements(el)) if (getLocalName(child) === "annotation") {
|
|
841
|
+
result.annotation = parseAnnotation(child);
|
|
842
|
+
break;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Extract xmlns declarations from an element's attributes.
|
|
847
|
+
* Returns undefined if no xmlns declarations found.
|
|
848
|
+
*
|
|
849
|
+
* @example
|
|
850
|
+
* For <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://example.com">
|
|
851
|
+
* Returns: { xs: "http://www.w3.org/2001/XMLSchema", tns: "http://example.com" }
|
|
852
|
+
*
|
|
853
|
+
* For <xs:element xmlns="http://default.com">
|
|
854
|
+
* Returns: { "": "http://default.com" }
|
|
855
|
+
*/
|
|
856
|
+
function extractXmlns(el) {
|
|
857
|
+
const xmlns = {};
|
|
858
|
+
let hasXmlns = false;
|
|
859
|
+
for (let i = 0; i < el.attributes.length; i++) {
|
|
860
|
+
const attr = el.attributes[i];
|
|
861
|
+
const name = attr.name;
|
|
862
|
+
const value = attr.value;
|
|
863
|
+
if (name === "xmlns") {
|
|
864
|
+
xmlns[""] = value;
|
|
865
|
+
hasXmlns = true;
|
|
866
|
+
} else if (name.startsWith("xmlns:")) {
|
|
867
|
+
const prefix = name.substring(6);
|
|
868
|
+
xmlns[prefix] = value;
|
|
869
|
+
hasXmlns = true;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return hasXmlns ? xmlns : void 0;
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Copy xmlns declarations to target if present
|
|
876
|
+
*/
|
|
877
|
+
function copyXmlns(el, target) {
|
|
878
|
+
const xmlns = extractXmlns(el);
|
|
879
|
+
if (xmlns) target.$xmlns = xmlns;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
//#endregion
|
|
883
|
+
//#region src/xsd/build.ts
|
|
884
|
+
/**
|
|
885
|
+
* Build an XSD string from a typed Schema object
|
|
886
|
+
*/
|
|
887
|
+
function buildXsd(schema, options = {}) {
|
|
888
|
+
const prefix = options.prefix ?? "xs";
|
|
889
|
+
const pretty = options.pretty ?? true;
|
|
890
|
+
const ctx = {
|
|
891
|
+
prefix,
|
|
892
|
+
pretty,
|
|
893
|
+
indent: options.indent ?? " ",
|
|
894
|
+
level: 0
|
|
895
|
+
};
|
|
896
|
+
const lines = [];
|
|
897
|
+
lines.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
|
898
|
+
lines.push(buildSchema(schema, ctx));
|
|
899
|
+
return lines.join(pretty ? "\n" : "");
|
|
900
|
+
}
|
|
901
|
+
function buildSchema(schema, ctx) {
|
|
902
|
+
const attrs = [];
|
|
903
|
+
if (schema.$xmlns) for (const [prefix, uri] of Object.entries(schema.$xmlns)) if (prefix === "") attrs.push(`xmlns="${uri}"`);
|
|
904
|
+
else attrs.push(`xmlns:${prefix}="${uri}"`);
|
|
905
|
+
addAttr(attrs, "id", schema.id);
|
|
906
|
+
addAttr(attrs, "targetNamespace", schema.targetNamespace);
|
|
907
|
+
addAttr(attrs, "version", schema.version);
|
|
908
|
+
addAttr(attrs, "finalDefault", schema.finalDefault);
|
|
909
|
+
addAttr(attrs, "blockDefault", schema.blockDefault);
|
|
910
|
+
addAttr(attrs, "attributeFormDefault", schema.attributeFormDefault);
|
|
911
|
+
addAttr(attrs, "elementFormDefault", schema.elementFormDefault);
|
|
912
|
+
addAttr(attrs, "defaultAttributes", schema.defaultAttributes);
|
|
913
|
+
addAttr(attrs, "xpathDefaultNamespace", schema.xpathDefaultNamespace);
|
|
914
|
+
addAttr(attrs, "xml:lang", schema["xml:lang"]);
|
|
915
|
+
const children = [];
|
|
916
|
+
const childCtx = {
|
|
917
|
+
...ctx,
|
|
918
|
+
level: ctx.level + 1
|
|
919
|
+
};
|
|
920
|
+
if (schema.annotation) for (const ann of schema.annotation) children.push(buildAnnotation(ann, childCtx));
|
|
921
|
+
if (schema.include) for (const inc of schema.include) children.push(buildInclude(inc, childCtx));
|
|
922
|
+
if (schema.import) for (const imp of schema.import) children.push(buildImport(imp, childCtx));
|
|
923
|
+
if (schema.redefine) for (const red of schema.redefine) children.push(buildRedefine(red, childCtx));
|
|
924
|
+
if (schema.override) for (const ovr of schema.override) children.push(buildOverride(ovr, childCtx));
|
|
925
|
+
if (schema.defaultOpenContent) children.push(buildDefaultOpenContent(schema.defaultOpenContent, childCtx));
|
|
926
|
+
if (schema.simpleType && Array.isArray(schema.simpleType)) for (const st of schema.simpleType) children.push(buildTopLevelSimpleType(st, childCtx));
|
|
927
|
+
if (schema.complexType && Array.isArray(schema.complexType)) for (const ct of schema.complexType) children.push(buildTopLevelComplexType(ct, childCtx));
|
|
928
|
+
if (schema.group) for (const grp of schema.group) children.push(buildNamedGroup(grp, childCtx));
|
|
929
|
+
if (schema.attributeGroup) for (const ag of schema.attributeGroup) children.push(buildNamedAttributeGroup(ag, childCtx));
|
|
930
|
+
if (schema.element) for (const el of schema.element) children.push(buildTopLevelElement(el, childCtx));
|
|
931
|
+
if (schema.attribute) for (const attr of schema.attribute) children.push(buildTopLevelAttribute(attr, childCtx));
|
|
932
|
+
if (schema.notation) for (const not of schema.notation) children.push(buildNotation(not, childCtx));
|
|
933
|
+
return buildElement(`${ctx.prefix}:schema`, attrs, children, ctx);
|
|
934
|
+
}
|
|
935
|
+
function buildAnnotation(ann, ctx) {
|
|
936
|
+
const attrs = [];
|
|
937
|
+
addAttr(attrs, "id", ann.id);
|
|
938
|
+
const children = [];
|
|
939
|
+
const childCtx = {
|
|
940
|
+
...ctx,
|
|
941
|
+
level: ctx.level + 1
|
|
942
|
+
};
|
|
943
|
+
if (ann.appinfo) for (const ai of ann.appinfo) children.push(buildAppinfo(ai, childCtx));
|
|
944
|
+
if (ann.documentation) for (const doc of ann.documentation) children.push(buildDocumentation(doc, childCtx));
|
|
945
|
+
return buildElement(`${ctx.prefix}:annotation`, attrs, children, ctx);
|
|
946
|
+
}
|
|
947
|
+
function buildDocumentation(doc, ctx) {
|
|
948
|
+
const attrs = [];
|
|
949
|
+
addAttr(attrs, "source", doc.source);
|
|
950
|
+
addAttr(attrs, "xml:lang", doc["xml:lang"]);
|
|
951
|
+
if (doc._text) return buildElementWithText(`${ctx.prefix}:documentation`, attrs, doc._text, ctx);
|
|
952
|
+
return buildElement(`${ctx.prefix}:documentation`, attrs, [], ctx);
|
|
953
|
+
}
|
|
954
|
+
function buildAppinfo(ai, ctx) {
|
|
955
|
+
const attrs = [];
|
|
956
|
+
addAttr(attrs, "source", ai.source);
|
|
957
|
+
if (ai._text) return buildElementWithText(`${ctx.prefix}:appinfo`, attrs, ai._text, ctx);
|
|
958
|
+
return buildElement(`${ctx.prefix}:appinfo`, attrs, [], ctx);
|
|
959
|
+
}
|
|
960
|
+
function buildInclude(inc, ctx) {
|
|
961
|
+
const attrs = [];
|
|
962
|
+
addAttr(attrs, "id", inc.id);
|
|
963
|
+
addAttr(attrs, "schemaLocation", inc.schemaLocation);
|
|
964
|
+
const children = [];
|
|
965
|
+
if (inc.annotation) children.push(buildAnnotation(inc.annotation, {
|
|
966
|
+
...ctx,
|
|
967
|
+
level: ctx.level + 1
|
|
968
|
+
}));
|
|
969
|
+
return buildElement(`${ctx.prefix}:include`, attrs, children, ctx);
|
|
970
|
+
}
|
|
971
|
+
function buildImport(imp, ctx) {
|
|
972
|
+
const attrs = [];
|
|
973
|
+
addAttr(attrs, "id", imp.id);
|
|
974
|
+
addAttr(attrs, "namespace", imp.namespace);
|
|
975
|
+
addAttr(attrs, "schemaLocation", imp.schemaLocation);
|
|
976
|
+
const children = [];
|
|
977
|
+
if (imp.annotation) children.push(buildAnnotation(imp.annotation, {
|
|
978
|
+
...ctx,
|
|
979
|
+
level: ctx.level + 1
|
|
980
|
+
}));
|
|
981
|
+
return buildElement(`${ctx.prefix}:import`, attrs, children, ctx);
|
|
982
|
+
}
|
|
983
|
+
function buildRedefine(red, ctx) {
|
|
984
|
+
const attrs = [];
|
|
985
|
+
addAttr(attrs, "id", red.id);
|
|
986
|
+
addAttr(attrs, "schemaLocation", red.schemaLocation);
|
|
987
|
+
const children = [];
|
|
988
|
+
const childCtx = {
|
|
989
|
+
...ctx,
|
|
990
|
+
level: ctx.level + 1
|
|
991
|
+
};
|
|
992
|
+
if (red.annotation) for (const ann of red.annotation) children.push(buildAnnotation(ann, childCtx));
|
|
993
|
+
if (red.simpleType) for (const st of red.simpleType) children.push(buildTopLevelSimpleType(st, childCtx));
|
|
994
|
+
if (red.complexType) for (const ct of red.complexType) children.push(buildTopLevelComplexType(ct, childCtx));
|
|
995
|
+
if (red.group) for (const grp of red.group) children.push(buildNamedGroup(grp, childCtx));
|
|
996
|
+
if (red.attributeGroup) for (const ag of red.attributeGroup) children.push(buildNamedAttributeGroup(ag, childCtx));
|
|
997
|
+
return buildElement(`${ctx.prefix}:redefine`, attrs, children, ctx);
|
|
998
|
+
}
|
|
999
|
+
function buildOverride(ovr, ctx) {
|
|
1000
|
+
const attrs = [];
|
|
1001
|
+
addAttr(attrs, "id", ovr.id);
|
|
1002
|
+
addAttr(attrs, "schemaLocation", ovr.schemaLocation);
|
|
1003
|
+
const children = [];
|
|
1004
|
+
const childCtx = {
|
|
1005
|
+
...ctx,
|
|
1006
|
+
level: ctx.level + 1
|
|
1007
|
+
};
|
|
1008
|
+
if (ovr.annotation) for (const ann of ovr.annotation) children.push(buildAnnotation(ann, childCtx));
|
|
1009
|
+
if (ovr.simpleType) for (const st of ovr.simpleType) children.push(buildTopLevelSimpleType(st, childCtx));
|
|
1010
|
+
if (ovr.complexType) for (const ct of ovr.complexType) children.push(buildTopLevelComplexType(ct, childCtx));
|
|
1011
|
+
if (ovr.group) for (const grp of ovr.group) children.push(buildNamedGroup(grp, childCtx));
|
|
1012
|
+
if (ovr.attributeGroup) for (const ag of ovr.attributeGroup) children.push(buildNamedAttributeGroup(ag, childCtx));
|
|
1013
|
+
if (ovr.element) for (const el of ovr.element) children.push(buildTopLevelElement(el, childCtx));
|
|
1014
|
+
if (ovr.attribute) for (const attr of ovr.attribute) children.push(buildTopLevelAttribute(attr, childCtx));
|
|
1015
|
+
if (ovr.notation) for (const not of ovr.notation) children.push(buildNotation(not, childCtx));
|
|
1016
|
+
return buildElement(`${ctx.prefix}:override`, attrs, children, ctx);
|
|
1017
|
+
}
|
|
1018
|
+
function buildTopLevelElement(el, ctx) {
|
|
1019
|
+
const attrs = [];
|
|
1020
|
+
addAttr(attrs, "id", el.id);
|
|
1021
|
+
addAttr(attrs, "name", el.name);
|
|
1022
|
+
addAttr(attrs, "type", el.type);
|
|
1023
|
+
addAttr(attrs, "substitutionGroup", el.substitutionGroup);
|
|
1024
|
+
addAttr(attrs, "default", el.default);
|
|
1025
|
+
addAttr(attrs, "fixed", el.fixed);
|
|
1026
|
+
addBoolAttr(attrs, "nillable", el.nillable);
|
|
1027
|
+
addBoolAttr(attrs, "abstract", el.abstract);
|
|
1028
|
+
addAttr(attrs, "final", el.final);
|
|
1029
|
+
addAttr(attrs, "block", el.block);
|
|
1030
|
+
const children = [];
|
|
1031
|
+
const childCtx = {
|
|
1032
|
+
...ctx,
|
|
1033
|
+
level: ctx.level + 1
|
|
1034
|
+
};
|
|
1035
|
+
if (el.annotation) children.push(buildAnnotation(el.annotation, childCtx));
|
|
1036
|
+
if (el.simpleType) children.push(buildLocalSimpleType(el.simpleType, childCtx));
|
|
1037
|
+
if (el.complexType) children.push(buildLocalComplexType(el.complexType, childCtx));
|
|
1038
|
+
if (el.alternative) for (const alt of el.alternative) children.push(buildAlternative(alt, childCtx));
|
|
1039
|
+
if (el.unique) for (const u of el.unique) children.push(buildUnique(u, childCtx));
|
|
1040
|
+
if (el.key) for (const k of el.key) children.push(buildKey(k, childCtx));
|
|
1041
|
+
if (el.keyref) for (const kr of el.keyref) children.push(buildKeyref(kr, childCtx));
|
|
1042
|
+
return buildElement(`${ctx.prefix}:element`, attrs, children, ctx);
|
|
1043
|
+
}
|
|
1044
|
+
function buildLocalElement(el, ctx) {
|
|
1045
|
+
const attrs = [];
|
|
1046
|
+
addAttr(attrs, "id", el.id);
|
|
1047
|
+
addAttr(attrs, "name", el.name);
|
|
1048
|
+
addAttr(attrs, "ref", el.ref);
|
|
1049
|
+
addAttr(attrs, "type", el.type);
|
|
1050
|
+
addOccursAttr(attrs, "minOccurs", el.minOccurs);
|
|
1051
|
+
addOccursAttr(attrs, "maxOccurs", el.maxOccurs);
|
|
1052
|
+
addAttr(attrs, "default", el.default);
|
|
1053
|
+
addAttr(attrs, "fixed", el.fixed);
|
|
1054
|
+
addBoolAttr(attrs, "nillable", el.nillable);
|
|
1055
|
+
addAttr(attrs, "block", el.block);
|
|
1056
|
+
addAttr(attrs, "form", el.form);
|
|
1057
|
+
addAttr(attrs, "targetNamespace", el.targetNamespace);
|
|
1058
|
+
const children = [];
|
|
1059
|
+
const childCtx = {
|
|
1060
|
+
...ctx,
|
|
1061
|
+
level: ctx.level + 1
|
|
1062
|
+
};
|
|
1063
|
+
if (el.annotation) children.push(buildAnnotation(el.annotation, childCtx));
|
|
1064
|
+
if (el.simpleType) children.push(buildLocalSimpleType(el.simpleType, childCtx));
|
|
1065
|
+
if (el.complexType) children.push(buildLocalComplexType(el.complexType, childCtx));
|
|
1066
|
+
if (el.alternative) for (const alt of el.alternative) children.push(buildAlternative(alt, childCtx));
|
|
1067
|
+
if (el.unique) for (const u of el.unique) children.push(buildUnique(u, childCtx));
|
|
1068
|
+
if (el.key) for (const k of el.key) children.push(buildKey(k, childCtx));
|
|
1069
|
+
if (el.keyref) for (const kr of el.keyref) children.push(buildKeyref(kr, childCtx));
|
|
1070
|
+
return buildElement(`${ctx.prefix}:element`, attrs, children, ctx);
|
|
1071
|
+
}
|
|
1072
|
+
function buildTopLevelAttribute(attr, ctx) {
|
|
1073
|
+
const attrs = [];
|
|
1074
|
+
addAttr(attrs, "id", attr.id);
|
|
1075
|
+
addAttr(attrs, "name", attr.name);
|
|
1076
|
+
addAttr(attrs, "type", attr.type);
|
|
1077
|
+
addAttr(attrs, "default", attr.default);
|
|
1078
|
+
addAttr(attrs, "fixed", attr.fixed);
|
|
1079
|
+
addBoolAttr(attrs, "inheritable", attr.inheritable);
|
|
1080
|
+
const children = [];
|
|
1081
|
+
const childCtx = {
|
|
1082
|
+
...ctx,
|
|
1083
|
+
level: ctx.level + 1
|
|
1084
|
+
};
|
|
1085
|
+
if (attr.annotation) children.push(buildAnnotation(attr.annotation, childCtx));
|
|
1086
|
+
if (attr.simpleType) children.push(buildLocalSimpleType(attr.simpleType, childCtx));
|
|
1087
|
+
return buildElement(`${ctx.prefix}:attribute`, attrs, children, ctx);
|
|
1088
|
+
}
|
|
1089
|
+
function buildLocalAttribute(attr, ctx) {
|
|
1090
|
+
const attrs = [];
|
|
1091
|
+
addAttr(attrs, "id", attr.id);
|
|
1092
|
+
addAttr(attrs, "name", attr.name);
|
|
1093
|
+
addAttr(attrs, "ref", attr.ref);
|
|
1094
|
+
addAttr(attrs, "type", attr.type);
|
|
1095
|
+
addAttr(attrs, "use", attr.use);
|
|
1096
|
+
addAttr(attrs, "default", attr.default);
|
|
1097
|
+
addAttr(attrs, "fixed", attr.fixed);
|
|
1098
|
+
addAttr(attrs, "form", attr.form);
|
|
1099
|
+
addAttr(attrs, "targetNamespace", attr.targetNamespace);
|
|
1100
|
+
addBoolAttr(attrs, "inheritable", attr.inheritable);
|
|
1101
|
+
const children = [];
|
|
1102
|
+
const childCtx = {
|
|
1103
|
+
...ctx,
|
|
1104
|
+
level: ctx.level + 1
|
|
1105
|
+
};
|
|
1106
|
+
if (attr.annotation) children.push(buildAnnotation(attr.annotation, childCtx));
|
|
1107
|
+
if (attr.simpleType) children.push(buildLocalSimpleType(attr.simpleType, childCtx));
|
|
1108
|
+
return buildElement(`${ctx.prefix}:attribute`, attrs, children, ctx);
|
|
1109
|
+
}
|
|
1110
|
+
function buildTopLevelComplexType(ct, ctx) {
|
|
1111
|
+
const attrs = [];
|
|
1112
|
+
addAttr(attrs, "id", ct.id);
|
|
1113
|
+
addAttr(attrs, "name", ct.name);
|
|
1114
|
+
addBoolAttr(attrs, "mixed", ct.mixed);
|
|
1115
|
+
addBoolAttr(attrs, "abstract", ct.abstract);
|
|
1116
|
+
addAttr(attrs, "final", ct.final);
|
|
1117
|
+
addAttr(attrs, "block", ct.block);
|
|
1118
|
+
addBoolAttr(attrs, "defaultAttributesApply", ct.defaultAttributesApply);
|
|
1119
|
+
return buildComplexTypeContent(ct, attrs, ctx);
|
|
1120
|
+
}
|
|
1121
|
+
function buildLocalComplexType(ct, ctx) {
|
|
1122
|
+
const attrs = [];
|
|
1123
|
+
addAttr(attrs, "id", ct.id);
|
|
1124
|
+
addBoolAttr(attrs, "mixed", ct.mixed);
|
|
1125
|
+
return buildComplexTypeContent(ct, attrs, ctx);
|
|
1126
|
+
}
|
|
1127
|
+
function buildComplexTypeContent(ct, attrs, ctx) {
|
|
1128
|
+
const children = [];
|
|
1129
|
+
const childCtx = {
|
|
1130
|
+
...ctx,
|
|
1131
|
+
level: ctx.level + 1
|
|
1132
|
+
};
|
|
1133
|
+
if (ct.annotation) children.push(buildAnnotation(ct.annotation, childCtx));
|
|
1134
|
+
if (ct.simpleContent) children.push(buildSimpleContent(ct.simpleContent, childCtx));
|
|
1135
|
+
else if (ct.complexContent) children.push(buildComplexContent(ct.complexContent, childCtx));
|
|
1136
|
+
else {
|
|
1137
|
+
if (ct.openContent) children.push(buildOpenContent(ct.openContent, childCtx));
|
|
1138
|
+
if (ct.group) children.push(buildGroupRef(ct.group, childCtx));
|
|
1139
|
+
if (ct.all) children.push(buildAll(ct.all, childCtx));
|
|
1140
|
+
if (ct.choice) children.push(buildExplicitGroup(ct.choice, "choice", childCtx));
|
|
1141
|
+
if (ct.sequence) children.push(buildExplicitGroup(ct.sequence, "sequence", childCtx));
|
|
1142
|
+
if (ct.attribute) for (const attr of ct.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
1143
|
+
if (ct.attributeGroup) for (const ag of ct.attributeGroup) children.push(buildAttributeGroupRef(ag, childCtx));
|
|
1144
|
+
if (ct.anyAttribute) children.push(buildAnyAttribute(ct.anyAttribute, childCtx));
|
|
1145
|
+
if (ct.assert) for (const a of ct.assert) children.push(buildAssertion(a, childCtx));
|
|
1146
|
+
}
|
|
1147
|
+
return buildElement(`${ctx.prefix}:complexType`, attrs, children, ctx);
|
|
1148
|
+
}
|
|
1149
|
+
function buildTopLevelSimpleType(st, ctx) {
|
|
1150
|
+
const attrs = [];
|
|
1151
|
+
addAttr(attrs, "id", st.id);
|
|
1152
|
+
addAttr(attrs, "name", st.name);
|
|
1153
|
+
addAttr(attrs, "final", st.final);
|
|
1154
|
+
return buildSimpleTypeContent(st, attrs, ctx);
|
|
1155
|
+
}
|
|
1156
|
+
function buildLocalSimpleType(st, ctx) {
|
|
1157
|
+
const attrs = [];
|
|
1158
|
+
addAttr(attrs, "id", st.id);
|
|
1159
|
+
return buildSimpleTypeContent(st, attrs, ctx);
|
|
1160
|
+
}
|
|
1161
|
+
function buildSimpleTypeContent(st, attrs, ctx) {
|
|
1162
|
+
const children = [];
|
|
1163
|
+
const childCtx = {
|
|
1164
|
+
...ctx,
|
|
1165
|
+
level: ctx.level + 1
|
|
1166
|
+
};
|
|
1167
|
+
if (st.annotation) children.push(buildAnnotation(st.annotation, childCtx));
|
|
1168
|
+
if (st.restriction) children.push(buildSimpleTypeRestriction(st.restriction, childCtx));
|
|
1169
|
+
else if (st.list) children.push(buildList(st.list, childCtx));
|
|
1170
|
+
else if (st.union) children.push(buildUnion(st.union, childCtx));
|
|
1171
|
+
return buildElement(`${ctx.prefix}:simpleType`, attrs, children, ctx);
|
|
1172
|
+
}
|
|
1173
|
+
function buildSimpleTypeRestriction(r, ctx) {
|
|
1174
|
+
const attrs = [];
|
|
1175
|
+
addAttr(attrs, "id", r.id);
|
|
1176
|
+
addAttr(attrs, "base", r.base);
|
|
1177
|
+
const children = [];
|
|
1178
|
+
const childCtx = {
|
|
1179
|
+
...ctx,
|
|
1180
|
+
level: ctx.level + 1
|
|
1181
|
+
};
|
|
1182
|
+
if (r.annotation) children.push(buildAnnotation(r.annotation, childCtx));
|
|
1183
|
+
if (r.simpleType) children.push(buildLocalSimpleType(r.simpleType, childCtx));
|
|
1184
|
+
buildFacets(r, children, childCtx);
|
|
1185
|
+
return buildElement(`${ctx.prefix}:restriction`, attrs, children, ctx);
|
|
1186
|
+
}
|
|
1187
|
+
function buildFacets(r, children, ctx) {
|
|
1188
|
+
if (r.minExclusive) for (const f of r.minExclusive) children.push(buildFacet(f, "minExclusive", ctx));
|
|
1189
|
+
if (r.minInclusive) for (const f of r.minInclusive) children.push(buildFacet(f, "minInclusive", ctx));
|
|
1190
|
+
if (r.maxExclusive) for (const f of r.maxExclusive) children.push(buildFacet(f, "maxExclusive", ctx));
|
|
1191
|
+
if (r.maxInclusive) for (const f of r.maxInclusive) children.push(buildFacet(f, "maxInclusive", ctx));
|
|
1192
|
+
if (r.totalDigits) for (const f of r.totalDigits) children.push(buildFacet(f, "totalDigits", ctx));
|
|
1193
|
+
if (r.fractionDigits) for (const f of r.fractionDigits) children.push(buildFacet(f, "fractionDigits", ctx));
|
|
1194
|
+
if (r.length) for (const f of r.length) children.push(buildFacet(f, "length", ctx));
|
|
1195
|
+
if (r.minLength) for (const f of r.minLength) children.push(buildFacet(f, "minLength", ctx));
|
|
1196
|
+
if (r.maxLength) for (const f of r.maxLength) children.push(buildFacet(f, "maxLength", ctx));
|
|
1197
|
+
if (r.enumeration) for (const f of r.enumeration) children.push(buildFacet(f, "enumeration", ctx));
|
|
1198
|
+
if (r.whiteSpace) for (const f of r.whiteSpace) children.push(buildFacet(f, "whiteSpace", ctx));
|
|
1199
|
+
if (r.pattern) for (const p of r.pattern) children.push(buildPattern(p, ctx));
|
|
1200
|
+
if (r.assertion) for (const a of r.assertion) children.push(buildAssertion(a, ctx));
|
|
1201
|
+
if (r.explicitTimezone) for (const f of r.explicitTimezone) children.push(buildFacet(f, "explicitTimezone", ctx));
|
|
1202
|
+
}
|
|
1203
|
+
function buildFacet(f, name, ctx) {
|
|
1204
|
+
const attrs = [];
|
|
1205
|
+
addAttr(attrs, "id", f.id);
|
|
1206
|
+
addAttr(attrs, "value", f.value);
|
|
1207
|
+
addBoolAttr(attrs, "fixed", f.fixed);
|
|
1208
|
+
const children = [];
|
|
1209
|
+
if (f.annotation) children.push(buildAnnotation(f.annotation, {
|
|
1210
|
+
...ctx,
|
|
1211
|
+
level: ctx.level + 1
|
|
1212
|
+
}));
|
|
1213
|
+
return buildElement(`${ctx.prefix}:${name}`, attrs, children, ctx);
|
|
1214
|
+
}
|
|
1215
|
+
function buildPattern(p, ctx) {
|
|
1216
|
+
const attrs = [];
|
|
1217
|
+
addAttr(attrs, "id", p.id);
|
|
1218
|
+
addAttr(attrs, "value", p.value);
|
|
1219
|
+
const children = [];
|
|
1220
|
+
if (p.annotation) children.push(buildAnnotation(p.annotation, {
|
|
1221
|
+
...ctx,
|
|
1222
|
+
level: ctx.level + 1
|
|
1223
|
+
}));
|
|
1224
|
+
return buildElement(`${ctx.prefix}:pattern`, attrs, children, ctx);
|
|
1225
|
+
}
|
|
1226
|
+
function buildList(l, ctx) {
|
|
1227
|
+
const attrs = [];
|
|
1228
|
+
addAttr(attrs, "id", l.id);
|
|
1229
|
+
addAttr(attrs, "itemType", l.itemType);
|
|
1230
|
+
const children = [];
|
|
1231
|
+
const childCtx = {
|
|
1232
|
+
...ctx,
|
|
1233
|
+
level: ctx.level + 1
|
|
1234
|
+
};
|
|
1235
|
+
if (l.annotation) children.push(buildAnnotation(l.annotation, childCtx));
|
|
1236
|
+
if (l.simpleType) children.push(buildLocalSimpleType(l.simpleType, childCtx));
|
|
1237
|
+
return buildElement(`${ctx.prefix}:list`, attrs, children, ctx);
|
|
1238
|
+
}
|
|
1239
|
+
function buildUnion(u, ctx) {
|
|
1240
|
+
const attrs = [];
|
|
1241
|
+
addAttr(attrs, "id", u.id);
|
|
1242
|
+
addAttr(attrs, "memberTypes", u.memberTypes);
|
|
1243
|
+
const children = [];
|
|
1244
|
+
const childCtx = {
|
|
1245
|
+
...ctx,
|
|
1246
|
+
level: ctx.level + 1
|
|
1247
|
+
};
|
|
1248
|
+
if (u.annotation) children.push(buildAnnotation(u.annotation, childCtx));
|
|
1249
|
+
if (u.simpleType) for (const st of u.simpleType) children.push(buildLocalSimpleType(st, childCtx));
|
|
1250
|
+
return buildElement(`${ctx.prefix}:union`, attrs, children, ctx);
|
|
1251
|
+
}
|
|
1252
|
+
function buildComplexContent(cc, ctx) {
|
|
1253
|
+
const attrs = [];
|
|
1254
|
+
addAttr(attrs, "id", cc.id);
|
|
1255
|
+
addBoolAttr(attrs, "mixed", cc.mixed);
|
|
1256
|
+
const children = [];
|
|
1257
|
+
const childCtx = {
|
|
1258
|
+
...ctx,
|
|
1259
|
+
level: ctx.level + 1
|
|
1260
|
+
};
|
|
1261
|
+
if (cc.annotation) children.push(buildAnnotation(cc.annotation, childCtx));
|
|
1262
|
+
if (cc.restriction) children.push(buildComplexContentRestriction(cc.restriction, childCtx));
|
|
1263
|
+
else if (cc.extension) children.push(buildComplexContentExtension(cc.extension, childCtx));
|
|
1264
|
+
return buildElement(`${ctx.prefix}:complexContent`, attrs, children, ctx);
|
|
1265
|
+
}
|
|
1266
|
+
function buildSimpleContent(sc, ctx) {
|
|
1267
|
+
const attrs = [];
|
|
1268
|
+
addAttr(attrs, "id", sc.id);
|
|
1269
|
+
const children = [];
|
|
1270
|
+
const childCtx = {
|
|
1271
|
+
...ctx,
|
|
1272
|
+
level: ctx.level + 1
|
|
1273
|
+
};
|
|
1274
|
+
if (sc.annotation) children.push(buildAnnotation(sc.annotation, childCtx));
|
|
1275
|
+
if (sc.restriction) children.push(buildSimpleContentRestriction(sc.restriction, childCtx));
|
|
1276
|
+
else if (sc.extension) children.push(buildSimpleContentExtension(sc.extension, childCtx));
|
|
1277
|
+
return buildElement(`${ctx.prefix}:simpleContent`, attrs, children, ctx);
|
|
1278
|
+
}
|
|
1279
|
+
function buildComplexContentRestriction(r, ctx) {
|
|
1280
|
+
const attrs = [];
|
|
1281
|
+
addAttr(attrs, "id", r.id);
|
|
1282
|
+
addAttr(attrs, "base", r.base);
|
|
1283
|
+
const children = [];
|
|
1284
|
+
const childCtx = {
|
|
1285
|
+
...ctx,
|
|
1286
|
+
level: ctx.level + 1
|
|
1287
|
+
};
|
|
1288
|
+
if (r.annotation) children.push(buildAnnotation(r.annotation, childCtx));
|
|
1289
|
+
if (r.openContent) children.push(buildOpenContent(r.openContent, childCtx));
|
|
1290
|
+
if (r.group) children.push(buildGroupRef(r.group, childCtx));
|
|
1291
|
+
if (r.all) children.push(buildAll(r.all, childCtx));
|
|
1292
|
+
if (r.choice) children.push(buildExplicitGroup(r.choice, "choice", childCtx));
|
|
1293
|
+
if (r.sequence) children.push(buildExplicitGroup(r.sequence, "sequence", childCtx));
|
|
1294
|
+
if (r.attribute) for (const attr of r.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
1295
|
+
if (r.attributeGroup) for (const ag of r.attributeGroup) children.push(buildAttributeGroupRef(ag, childCtx));
|
|
1296
|
+
if (r.anyAttribute) children.push(buildAnyAttribute(r.anyAttribute, childCtx));
|
|
1297
|
+
if (r.assert) for (const a of r.assert) children.push(buildAssertion(a, childCtx));
|
|
1298
|
+
return buildElement(`${ctx.prefix}:restriction`, attrs, children, ctx);
|
|
1299
|
+
}
|
|
1300
|
+
function buildComplexContentExtension(e, ctx) {
|
|
1301
|
+
const attrs = [];
|
|
1302
|
+
addAttr(attrs, "id", e.id);
|
|
1303
|
+
addAttr(attrs, "base", e.base);
|
|
1304
|
+
const children = [];
|
|
1305
|
+
const childCtx = {
|
|
1306
|
+
...ctx,
|
|
1307
|
+
level: ctx.level + 1
|
|
1308
|
+
};
|
|
1309
|
+
if (e.annotation) children.push(buildAnnotation(e.annotation, childCtx));
|
|
1310
|
+
if (e.openContent) children.push(buildOpenContent(e.openContent, childCtx));
|
|
1311
|
+
if (e.group) children.push(buildGroupRef(e.group, childCtx));
|
|
1312
|
+
if (e.all) children.push(buildAll(e.all, childCtx));
|
|
1313
|
+
if (e.choice) children.push(buildExplicitGroup(e.choice, "choice", childCtx));
|
|
1314
|
+
if (e.sequence) children.push(buildExplicitGroup(e.sequence, "sequence", childCtx));
|
|
1315
|
+
if (e.attribute) for (const attr of e.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
1316
|
+
if (e.attributeGroup) for (const ag of e.attributeGroup) children.push(buildAttributeGroupRef(ag, childCtx));
|
|
1317
|
+
if (e.anyAttribute) children.push(buildAnyAttribute(e.anyAttribute, childCtx));
|
|
1318
|
+
if (e.assert) for (const a of e.assert) children.push(buildAssertion(a, childCtx));
|
|
1319
|
+
return buildElement(`${ctx.prefix}:extension`, attrs, children, ctx);
|
|
1320
|
+
}
|
|
1321
|
+
function buildSimpleContentRestriction(r, ctx) {
|
|
1322
|
+
const attrs = [];
|
|
1323
|
+
addAttr(attrs, "id", r.id);
|
|
1324
|
+
addAttr(attrs, "base", r.base);
|
|
1325
|
+
const children = [];
|
|
1326
|
+
const childCtx = {
|
|
1327
|
+
...ctx,
|
|
1328
|
+
level: ctx.level + 1
|
|
1329
|
+
};
|
|
1330
|
+
if (r.annotation) children.push(buildAnnotation(r.annotation, childCtx));
|
|
1331
|
+
if (r.simpleType) children.push(buildLocalSimpleType(r.simpleType, childCtx));
|
|
1332
|
+
buildFacets(r, children, childCtx);
|
|
1333
|
+
if (r.attribute) for (const attr of r.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
1334
|
+
if (r.attributeGroup) for (const ag of r.attributeGroup) children.push(buildAttributeGroupRef(ag, childCtx));
|
|
1335
|
+
if (r.anyAttribute) children.push(buildAnyAttribute(r.anyAttribute, childCtx));
|
|
1336
|
+
if (r.assert) for (const a of r.assert) children.push(buildAssertion(a, childCtx));
|
|
1337
|
+
return buildElement(`${ctx.prefix}:restriction`, attrs, children, ctx);
|
|
1338
|
+
}
|
|
1339
|
+
function buildSimpleContentExtension(e, ctx) {
|
|
1340
|
+
const attrs = [];
|
|
1341
|
+
addAttr(attrs, "id", e.id);
|
|
1342
|
+
addAttr(attrs, "base", e.base);
|
|
1343
|
+
const children = [];
|
|
1344
|
+
const childCtx = {
|
|
1345
|
+
...ctx,
|
|
1346
|
+
level: ctx.level + 1
|
|
1347
|
+
};
|
|
1348
|
+
if (e.annotation) children.push(buildAnnotation(e.annotation, childCtx));
|
|
1349
|
+
if (e.attribute) for (const attr of e.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
1350
|
+
if (e.attributeGroup) for (const ag of e.attributeGroup) children.push(buildAttributeGroupRef(ag, childCtx));
|
|
1351
|
+
if (e.anyAttribute) children.push(buildAnyAttribute(e.anyAttribute, childCtx));
|
|
1352
|
+
if (e.assert) for (const a of e.assert) children.push(buildAssertion(a, childCtx));
|
|
1353
|
+
return buildElement(`${ctx.prefix}:extension`, attrs, children, ctx);
|
|
1354
|
+
}
|
|
1355
|
+
function buildExplicitGroup(g, name, ctx) {
|
|
1356
|
+
const attrs = [];
|
|
1357
|
+
addAttr(attrs, "id", g.id);
|
|
1358
|
+
addOccursAttr(attrs, "minOccurs", g.minOccurs);
|
|
1359
|
+
addOccursAttr(attrs, "maxOccurs", g.maxOccurs);
|
|
1360
|
+
const children = [];
|
|
1361
|
+
const childCtx = {
|
|
1362
|
+
...ctx,
|
|
1363
|
+
level: ctx.level + 1
|
|
1364
|
+
};
|
|
1365
|
+
if (g.annotation) children.push(buildAnnotation(g.annotation, childCtx));
|
|
1366
|
+
if (g.element) for (const el of g.element) children.push(buildLocalElement(el, childCtx));
|
|
1367
|
+
if (g.group) for (const grp of g.group) children.push(buildGroupRef(grp, childCtx));
|
|
1368
|
+
if (g.choice) for (const c of g.choice) children.push(buildExplicitGroup(c, "choice", childCtx));
|
|
1369
|
+
if (g.sequence) for (const s of g.sequence) children.push(buildExplicitGroup(s, "sequence", childCtx));
|
|
1370
|
+
if (g.any) for (const a of g.any) children.push(buildAny(a, childCtx));
|
|
1371
|
+
return buildElement(`${ctx.prefix}:${name}`, attrs, children, ctx);
|
|
1372
|
+
}
|
|
1373
|
+
function buildAll(a, ctx) {
|
|
1374
|
+
const attrs = [];
|
|
1375
|
+
addAttr(attrs, "id", a.id);
|
|
1376
|
+
addOccursAttr(attrs, "minOccurs", a.minOccurs);
|
|
1377
|
+
addOccursAttr(attrs, "maxOccurs", a.maxOccurs);
|
|
1378
|
+
const children = [];
|
|
1379
|
+
const childCtx = {
|
|
1380
|
+
...ctx,
|
|
1381
|
+
level: ctx.level + 1
|
|
1382
|
+
};
|
|
1383
|
+
if (a.annotation) children.push(buildAnnotation(a.annotation, childCtx));
|
|
1384
|
+
if (a.element) for (const el of a.element) children.push(buildLocalElement(el, childCtx));
|
|
1385
|
+
if (a.any) for (const any of a.any) children.push(buildAny(any, childCtx));
|
|
1386
|
+
if (a.group) for (const grp of a.group) children.push(buildGroupRef(grp, childCtx));
|
|
1387
|
+
return buildElement(`${ctx.prefix}:all`, attrs, children, ctx);
|
|
1388
|
+
}
|
|
1389
|
+
function buildNamedGroup(g, ctx) {
|
|
1390
|
+
const attrs = [];
|
|
1391
|
+
addAttr(attrs, "id", g.id);
|
|
1392
|
+
addAttr(attrs, "name", g.name);
|
|
1393
|
+
const children = [];
|
|
1394
|
+
const childCtx = {
|
|
1395
|
+
...ctx,
|
|
1396
|
+
level: ctx.level + 1
|
|
1397
|
+
};
|
|
1398
|
+
if (g.annotation) children.push(buildAnnotation(g.annotation, childCtx));
|
|
1399
|
+
if (g.all) children.push(buildAll(g.all, childCtx));
|
|
1400
|
+
if (g.choice) children.push(buildExplicitGroup(g.choice, "choice", childCtx));
|
|
1401
|
+
if (g.sequence) children.push(buildExplicitGroup(g.sequence, "sequence", childCtx));
|
|
1402
|
+
return buildElement(`${ctx.prefix}:group`, attrs, children, ctx);
|
|
1403
|
+
}
|
|
1404
|
+
function buildGroupRef(g, ctx) {
|
|
1405
|
+
const attrs = [];
|
|
1406
|
+
addAttr(attrs, "id", g.id);
|
|
1407
|
+
addAttr(attrs, "ref", g.ref);
|
|
1408
|
+
addOccursAttr(attrs, "minOccurs", g.minOccurs);
|
|
1409
|
+
addOccursAttr(attrs, "maxOccurs", g.maxOccurs);
|
|
1410
|
+
const children = [];
|
|
1411
|
+
if (g.annotation) children.push(buildAnnotation(g.annotation, {
|
|
1412
|
+
...ctx,
|
|
1413
|
+
level: ctx.level + 1
|
|
1414
|
+
}));
|
|
1415
|
+
return buildElement(`${ctx.prefix}:group`, attrs, children, ctx);
|
|
1416
|
+
}
|
|
1417
|
+
function buildNamedAttributeGroup(ag, ctx) {
|
|
1418
|
+
const attrs = [];
|
|
1419
|
+
addAttr(attrs, "id", ag.id);
|
|
1420
|
+
addAttr(attrs, "name", ag.name);
|
|
1421
|
+
const children = [];
|
|
1422
|
+
const childCtx = {
|
|
1423
|
+
...ctx,
|
|
1424
|
+
level: ctx.level + 1
|
|
1425
|
+
};
|
|
1426
|
+
if (ag.annotation) children.push(buildAnnotation(ag.annotation, childCtx));
|
|
1427
|
+
if (ag.attribute) for (const attr of ag.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
1428
|
+
if (ag.attributeGroup) for (const agr of ag.attributeGroup) children.push(buildAttributeGroupRef(agr, childCtx));
|
|
1429
|
+
if (ag.anyAttribute) children.push(buildAnyAttribute(ag.anyAttribute, childCtx));
|
|
1430
|
+
return buildElement(`${ctx.prefix}:attributeGroup`, attrs, children, ctx);
|
|
1431
|
+
}
|
|
1432
|
+
function buildAttributeGroupRef(ag, ctx) {
|
|
1433
|
+
const attrs = [];
|
|
1434
|
+
addAttr(attrs, "id", ag.id);
|
|
1435
|
+
addAttr(attrs, "ref", ag.ref);
|
|
1436
|
+
const children = [];
|
|
1437
|
+
if (ag.annotation) children.push(buildAnnotation(ag.annotation, {
|
|
1438
|
+
...ctx,
|
|
1439
|
+
level: ctx.level + 1
|
|
1440
|
+
}));
|
|
1441
|
+
return buildElement(`${ctx.prefix}:attributeGroup`, attrs, children, ctx);
|
|
1442
|
+
}
|
|
1443
|
+
function buildAny(a, ctx) {
|
|
1444
|
+
const attrs = [];
|
|
1445
|
+
addAttr(attrs, "id", a.id);
|
|
1446
|
+
addOccursAttr(attrs, "minOccurs", a.minOccurs);
|
|
1447
|
+
addOccursAttr(attrs, "maxOccurs", a.maxOccurs);
|
|
1448
|
+
addAttr(attrs, "namespace", a.namespace);
|
|
1449
|
+
addAttr(attrs, "processContents", a.processContents);
|
|
1450
|
+
addAttr(attrs, "notNamespace", a.notNamespace);
|
|
1451
|
+
addAttr(attrs, "notQName", a.notQName);
|
|
1452
|
+
const children = [];
|
|
1453
|
+
if (a.annotation) children.push(buildAnnotation(a.annotation, {
|
|
1454
|
+
...ctx,
|
|
1455
|
+
level: ctx.level + 1
|
|
1456
|
+
}));
|
|
1457
|
+
return buildElement(`${ctx.prefix}:any`, attrs, children, ctx);
|
|
1458
|
+
}
|
|
1459
|
+
function buildAnyAttribute(aa, ctx) {
|
|
1460
|
+
const attrs = [];
|
|
1461
|
+
addAttr(attrs, "id", aa.id);
|
|
1462
|
+
addAttr(attrs, "namespace", aa.namespace);
|
|
1463
|
+
addAttr(attrs, "processContents", aa.processContents);
|
|
1464
|
+
addAttr(attrs, "notNamespace", aa.notNamespace);
|
|
1465
|
+
addAttr(attrs, "notQName", aa.notQName);
|
|
1466
|
+
const children = [];
|
|
1467
|
+
if (aa.annotation) children.push(buildAnnotation(aa.annotation, {
|
|
1468
|
+
...ctx,
|
|
1469
|
+
level: ctx.level + 1
|
|
1470
|
+
}));
|
|
1471
|
+
return buildElement(`${ctx.prefix}:anyAttribute`, attrs, children, ctx);
|
|
1472
|
+
}
|
|
1473
|
+
function buildUnique(u, ctx) {
|
|
1474
|
+
const attrs = [];
|
|
1475
|
+
addAttr(attrs, "id", u.id);
|
|
1476
|
+
addAttr(attrs, "name", u.name);
|
|
1477
|
+
addAttr(attrs, "ref", u.ref);
|
|
1478
|
+
const children = [];
|
|
1479
|
+
const childCtx = {
|
|
1480
|
+
...ctx,
|
|
1481
|
+
level: ctx.level + 1
|
|
1482
|
+
};
|
|
1483
|
+
if (u.annotation) children.push(buildAnnotation(u.annotation, childCtx));
|
|
1484
|
+
if (u.selector) children.push(buildSelector(u.selector, childCtx));
|
|
1485
|
+
if (u.field) for (const f of u.field) children.push(buildField(f, childCtx));
|
|
1486
|
+
return buildElement(`${ctx.prefix}:unique`, attrs, children, ctx);
|
|
1487
|
+
}
|
|
1488
|
+
function buildKey(k, ctx) {
|
|
1489
|
+
const attrs = [];
|
|
1490
|
+
addAttr(attrs, "id", k.id);
|
|
1491
|
+
addAttr(attrs, "name", k.name);
|
|
1492
|
+
addAttr(attrs, "ref", k.ref);
|
|
1493
|
+
const children = [];
|
|
1494
|
+
const childCtx = {
|
|
1495
|
+
...ctx,
|
|
1496
|
+
level: ctx.level + 1
|
|
1497
|
+
};
|
|
1498
|
+
if (k.annotation) children.push(buildAnnotation(k.annotation, childCtx));
|
|
1499
|
+
if (k.selector) children.push(buildSelector(k.selector, childCtx));
|
|
1500
|
+
if (k.field) for (const f of k.field) children.push(buildField(f, childCtx));
|
|
1501
|
+
return buildElement(`${ctx.prefix}:key`, attrs, children, ctx);
|
|
1502
|
+
}
|
|
1503
|
+
function buildKeyref(kr, ctx) {
|
|
1504
|
+
const attrs = [];
|
|
1505
|
+
addAttr(attrs, "id", kr.id);
|
|
1506
|
+
addAttr(attrs, "name", kr.name);
|
|
1507
|
+
addAttr(attrs, "ref", kr.ref);
|
|
1508
|
+
addAttr(attrs, "refer", kr.refer);
|
|
1509
|
+
const children = [];
|
|
1510
|
+
const childCtx = {
|
|
1511
|
+
...ctx,
|
|
1512
|
+
level: ctx.level + 1
|
|
1513
|
+
};
|
|
1514
|
+
if (kr.annotation) children.push(buildAnnotation(kr.annotation, childCtx));
|
|
1515
|
+
if (kr.selector) children.push(buildSelector(kr.selector, childCtx));
|
|
1516
|
+
if (kr.field) for (const f of kr.field) children.push(buildField(f, childCtx));
|
|
1517
|
+
return buildElement(`${ctx.prefix}:keyref`, attrs, children, ctx);
|
|
1518
|
+
}
|
|
1519
|
+
function buildSelector(s, ctx) {
|
|
1520
|
+
const attrs = [];
|
|
1521
|
+
addAttr(attrs, "id", s.id);
|
|
1522
|
+
addAttr(attrs, "xpath", s.xpath);
|
|
1523
|
+
addAttr(attrs, "xpathDefaultNamespace", s.xpathDefaultNamespace);
|
|
1524
|
+
const children = [];
|
|
1525
|
+
if (s.annotation) children.push(buildAnnotation(s.annotation, {
|
|
1526
|
+
...ctx,
|
|
1527
|
+
level: ctx.level + 1
|
|
1528
|
+
}));
|
|
1529
|
+
return buildElement(`${ctx.prefix}:selector`, attrs, children, ctx);
|
|
1530
|
+
}
|
|
1531
|
+
function buildField(f, ctx) {
|
|
1532
|
+
const attrs = [];
|
|
1533
|
+
addAttr(attrs, "id", f.id);
|
|
1534
|
+
addAttr(attrs, "xpath", f.xpath);
|
|
1535
|
+
addAttr(attrs, "xpathDefaultNamespace", f.xpathDefaultNamespace);
|
|
1536
|
+
const children = [];
|
|
1537
|
+
if (f.annotation) children.push(buildAnnotation(f.annotation, {
|
|
1538
|
+
...ctx,
|
|
1539
|
+
level: ctx.level + 1
|
|
1540
|
+
}));
|
|
1541
|
+
return buildElement(`${ctx.prefix}:field`, attrs, children, ctx);
|
|
1542
|
+
}
|
|
1543
|
+
function buildOpenContent(oc, ctx) {
|
|
1544
|
+
const attrs = [];
|
|
1545
|
+
addAttr(attrs, "id", oc.id);
|
|
1546
|
+
addAttr(attrs, "mode", oc.mode);
|
|
1547
|
+
const children = [];
|
|
1548
|
+
const childCtx = {
|
|
1549
|
+
...ctx,
|
|
1550
|
+
level: ctx.level + 1
|
|
1551
|
+
};
|
|
1552
|
+
if (oc.annotation) children.push(buildAnnotation(oc.annotation, childCtx));
|
|
1553
|
+
if (oc.any) children.push(buildAny(oc.any, childCtx));
|
|
1554
|
+
return buildElement(`${ctx.prefix}:openContent`, attrs, children, ctx);
|
|
1555
|
+
}
|
|
1556
|
+
function buildDefaultOpenContent(doc, ctx) {
|
|
1557
|
+
const attrs = [];
|
|
1558
|
+
addAttr(attrs, "id", doc.id);
|
|
1559
|
+
addBoolAttr(attrs, "appliesToEmpty", doc.appliesToEmpty);
|
|
1560
|
+
addAttr(attrs, "mode", doc.mode);
|
|
1561
|
+
const children = [];
|
|
1562
|
+
const childCtx = {
|
|
1563
|
+
...ctx,
|
|
1564
|
+
level: ctx.level + 1
|
|
1565
|
+
};
|
|
1566
|
+
if (doc.annotation) children.push(buildAnnotation(doc.annotation, childCtx));
|
|
1567
|
+
children.push(buildAny(doc.any, childCtx));
|
|
1568
|
+
return buildElement(`${ctx.prefix}:defaultOpenContent`, attrs, children, ctx);
|
|
1569
|
+
}
|
|
1570
|
+
function buildAssertion(a, ctx) {
|
|
1571
|
+
const attrs = [];
|
|
1572
|
+
addAttr(attrs, "id", a.id);
|
|
1573
|
+
addAttr(attrs, "test", a.test);
|
|
1574
|
+
addAttr(attrs, "xpathDefaultNamespace", a.xpathDefaultNamespace);
|
|
1575
|
+
const children = [];
|
|
1576
|
+
if (a.annotation) children.push(buildAnnotation(a.annotation, {
|
|
1577
|
+
...ctx,
|
|
1578
|
+
level: ctx.level + 1
|
|
1579
|
+
}));
|
|
1580
|
+
return buildElement(`${ctx.prefix}:assert`, attrs, children, ctx);
|
|
1581
|
+
}
|
|
1582
|
+
function buildAlternative(alt, ctx) {
|
|
1583
|
+
const attrs = [];
|
|
1584
|
+
addAttr(attrs, "id", alt.id);
|
|
1585
|
+
addAttr(attrs, "test", alt.test);
|
|
1586
|
+
addAttr(attrs, "type", alt.type);
|
|
1587
|
+
addAttr(attrs, "xpathDefaultNamespace", alt.xpathDefaultNamespace);
|
|
1588
|
+
const children = [];
|
|
1589
|
+
const childCtx = {
|
|
1590
|
+
...ctx,
|
|
1591
|
+
level: ctx.level + 1
|
|
1592
|
+
};
|
|
1593
|
+
if (alt.annotation) children.push(buildAnnotation(alt.annotation, childCtx));
|
|
1594
|
+
if (alt.simpleType) children.push(buildLocalSimpleType(alt.simpleType, childCtx));
|
|
1595
|
+
if (alt.complexType) children.push(buildLocalComplexType(alt.complexType, childCtx));
|
|
1596
|
+
return buildElement(`${ctx.prefix}:alternative`, attrs, children, ctx);
|
|
1597
|
+
}
|
|
1598
|
+
function buildNotation(n, ctx) {
|
|
1599
|
+
const attrs = [];
|
|
1600
|
+
addAttr(attrs, "id", n.id);
|
|
1601
|
+
addAttr(attrs, "name", n.name);
|
|
1602
|
+
addAttr(attrs, "public", n.public);
|
|
1603
|
+
addAttr(attrs, "system", n.system);
|
|
1604
|
+
const children = [];
|
|
1605
|
+
if (n.annotation) children.push(buildAnnotation(n.annotation, {
|
|
1606
|
+
...ctx,
|
|
1607
|
+
level: ctx.level + 1
|
|
1608
|
+
}));
|
|
1609
|
+
return buildElement(`${ctx.prefix}:notation`, attrs, children, ctx);
|
|
1610
|
+
}
|
|
1611
|
+
function addAttr(attrs, name, value) {
|
|
1612
|
+
if (value !== void 0) attrs.push(`${name}="${escapeXml(value)}"`);
|
|
1613
|
+
}
|
|
1614
|
+
function addBoolAttr(attrs, name, value) {
|
|
1615
|
+
if (value !== void 0) attrs.push(`${name}="${value}"`);
|
|
1616
|
+
}
|
|
1617
|
+
function addOccursAttr(attrs, name, value) {
|
|
1618
|
+
if (value !== void 0) attrs.push(`${name}="${value}"`);
|
|
1619
|
+
}
|
|
1620
|
+
function escapeXml(str) {
|
|
1621
|
+
return str.replaceAll(/&/g, "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
1622
|
+
}
|
|
1623
|
+
function buildElement(tag, attrs, children, ctx) {
|
|
1624
|
+
const indent = ctx.pretty ? ctx.indent.repeat(ctx.level) : "";
|
|
1625
|
+
const attrStr = attrs.length > 0 ? " " + attrs.join(" ") : "";
|
|
1626
|
+
if (children.length === 0) return `${indent}<${tag}${attrStr}/>`;
|
|
1627
|
+
const nl = ctx.pretty ? "\n" : "";
|
|
1628
|
+
return `${indent}<${tag}${attrStr}>${nl}${children.join(nl)}${nl}${indent}</${tag}>`;
|
|
1629
|
+
}
|
|
1630
|
+
function buildElementWithText(tag, attrs, text, ctx) {
|
|
1631
|
+
return `${ctx.pretty ? ctx.indent.repeat(ctx.level) : ""}<${tag}${attrs.length > 0 ? " " + attrs.join(" ") : ""}>${escapeXml(text)}</${tag}>`;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
//#endregion
|
|
1635
|
+
//#region src/xsd/helpers.ts
|
|
1636
|
+
/**
|
|
1637
|
+
* Resolve $imports for a schema by matching import schemaLocation to $filename.
|
|
1638
|
+
*
|
|
1639
|
+
* @param schema - The schema to resolve imports for
|
|
1640
|
+
* @param availableSchemas - Array of schemas that may be imported
|
|
1641
|
+
* @returns A new schema object with $imports populated
|
|
1642
|
+
*
|
|
1643
|
+
* @example
|
|
1644
|
+
* ```typescript
|
|
1645
|
+
* const orderSchema = parseXsd(orderXsd);
|
|
1646
|
+
* const commonSchema = { ...parseXsd(commonXsd), $filename: 'common.xsd' };
|
|
1647
|
+
*
|
|
1648
|
+
* // orderSchema has: import: [{ schemaLocation: 'common.xsd', ... }]
|
|
1649
|
+
* const resolved = resolveImports(orderSchema, [commonSchema]);
|
|
1650
|
+
* // resolved.$imports = [commonSchema]
|
|
1651
|
+
* ```
|
|
1652
|
+
*/
|
|
1653
|
+
function resolveImports(schema, availableSchemas) {
|
|
1654
|
+
const imports = [];
|
|
1655
|
+
if (schema.import) {
|
|
1656
|
+
for (const imp of schema.import) if (imp.schemaLocation) {
|
|
1657
|
+
const found = availableSchemas.find((s) => s.$filename === imp.schemaLocation);
|
|
1658
|
+
if (found) imports.push(found);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
return {
|
|
1662
|
+
...schema,
|
|
1663
|
+
$imports: imports
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Resolve $imports for multiple schemas, linking them together.
|
|
1668
|
+
*
|
|
1669
|
+
* @param schemas - Array of schemas to link together
|
|
1670
|
+
* @returns Array of schemas with $imports populated
|
|
1671
|
+
*
|
|
1672
|
+
* @example
|
|
1673
|
+
* ```typescript
|
|
1674
|
+
* const schemas = [
|
|
1675
|
+
* { ...parseXsd(orderXsd), $filename: 'order.xsd' },
|
|
1676
|
+
* { ...parseXsd(commonXsd), $filename: 'common.xsd' },
|
|
1677
|
+
* ];
|
|
1678
|
+
* const linked = linkSchemas(schemas);
|
|
1679
|
+
* // Each schema now has $imports resolved
|
|
1680
|
+
* ```
|
|
1681
|
+
*/
|
|
1682
|
+
function linkSchemas(schemas) {
|
|
1683
|
+
return schemas.map((schema) => resolveImports(schema, schemas));
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
//#endregion
|
|
1687
|
+
//#region src/xsd/traverser.ts
|
|
1688
|
+
/**
|
|
1689
|
+
* Base class for OO schema traversal using real W3C XSD types.
|
|
1690
|
+
*
|
|
1691
|
+
* Subclass and override the `on*` methods you need.
|
|
1692
|
+
* Context is available via `this` - no parameter passing needed.
|
|
1693
|
+
*/
|
|
1694
|
+
var SchemaTraverser = class {
|
|
1695
|
+
/** Root schema being traversed */
|
|
1696
|
+
rootSchema;
|
|
1697
|
+
/** Current schema being visited */
|
|
1698
|
+
currentSchema;
|
|
1699
|
+
/** Source of current node (direct, redefine, override, include, import) */
|
|
1700
|
+
source = "direct";
|
|
1701
|
+
/** Depth in schema hierarchy (0 = root) */
|
|
1702
|
+
depth = 0;
|
|
1703
|
+
/** Traversal options */
|
|
1704
|
+
options = {
|
|
1705
|
+
includeImports: true,
|
|
1706
|
+
includeIncludes: true,
|
|
1707
|
+
maxDepth: Infinity
|
|
1708
|
+
};
|
|
1709
|
+
/** Visited schemas (prevents infinite loops) */
|
|
1710
|
+
visited = /* @__PURE__ */ new Set();
|
|
1711
|
+
/**
|
|
1712
|
+
* Traverse a schema and all its imports/includes.
|
|
1713
|
+
* Override `on*` methods to handle specific node types.
|
|
1714
|
+
*/
|
|
1715
|
+
traverse(schema, options = {}) {
|
|
1716
|
+
this.rootSchema = schema;
|
|
1717
|
+
this.options = {
|
|
1718
|
+
...this.options,
|
|
1719
|
+
...options
|
|
1720
|
+
};
|
|
1721
|
+
this.visited.clear();
|
|
1722
|
+
this.traverseSchema(schema, "direct", 0);
|
|
1723
|
+
return this;
|
|
1724
|
+
}
|
|
1725
|
+
/** Called when entering a schema */
|
|
1726
|
+
onEnterSchema(_schema) {}
|
|
1727
|
+
/** Called when leaving a schema */
|
|
1728
|
+
onLeaveSchema(_schema) {}
|
|
1729
|
+
/** Called for each top-level complexType */
|
|
1730
|
+
onComplexType(_ct) {}
|
|
1731
|
+
/** Called for each top-level simpleType */
|
|
1732
|
+
onSimpleType(_st) {}
|
|
1733
|
+
/** Called for each top-level element */
|
|
1734
|
+
onElement(_element) {}
|
|
1735
|
+
/** Called for each top-level attribute */
|
|
1736
|
+
onAttribute(_attr) {}
|
|
1737
|
+
/** Called for each named group */
|
|
1738
|
+
onGroup(_group) {}
|
|
1739
|
+
/** Called for each named attributeGroup */
|
|
1740
|
+
onAttributeGroup(_group) {}
|
|
1741
|
+
/** Called for each redefine block */
|
|
1742
|
+
onRedefine(_redefine) {}
|
|
1743
|
+
/** Called for each override block */
|
|
1744
|
+
onOverride(_override) {}
|
|
1745
|
+
traverseSchema(schema, source, depth) {
|
|
1746
|
+
if (this.visited.has(schema)) return;
|
|
1747
|
+
if (depth > this.options.maxDepth) return;
|
|
1748
|
+
this.visited.add(schema);
|
|
1749
|
+
this.currentSchema = schema;
|
|
1750
|
+
this.source = source;
|
|
1751
|
+
this.depth = depth;
|
|
1752
|
+
this.onEnterSchema(schema);
|
|
1753
|
+
this.traverseSchemaChildren(schema);
|
|
1754
|
+
this.traverseRedefines(schema);
|
|
1755
|
+
this.traverseOverrides(schema);
|
|
1756
|
+
this.traverseIncludes(schema, depth);
|
|
1757
|
+
this.traverseImports(schema, depth);
|
|
1758
|
+
this.onLeaveSchema(schema);
|
|
1759
|
+
}
|
|
1760
|
+
traverseSchemaChildren(schema) {
|
|
1761
|
+
if (schema.complexType) for (const ct of schema.complexType) this.onComplexType(ct);
|
|
1762
|
+
if (schema.simpleType) for (const st of schema.simpleType) this.onSimpleType(st);
|
|
1763
|
+
if (schema.element) for (const element of schema.element) this.onElement(element);
|
|
1764
|
+
if (schema.attribute) for (const attr of schema.attribute) this.onAttribute(attr);
|
|
1765
|
+
if (schema.group) for (const group of schema.group) this.onGroup(group);
|
|
1766
|
+
if (schema.attributeGroup) for (const group of schema.attributeGroup) this.onAttributeGroup(group);
|
|
1767
|
+
}
|
|
1768
|
+
traverseRedefines(schema) {
|
|
1769
|
+
if (!schema.redefine) return;
|
|
1770
|
+
const prevSource = this.source;
|
|
1771
|
+
this.source = "redefine";
|
|
1772
|
+
for (const redefine of schema.redefine) {
|
|
1773
|
+
this.onRedefine(redefine);
|
|
1774
|
+
if (redefine.complexType) for (const ct of redefine.complexType) this.onComplexType(ct);
|
|
1775
|
+
if (redefine.simpleType) for (const st of redefine.simpleType) this.onSimpleType(st);
|
|
1776
|
+
if (redefine.group) for (const group of redefine.group) this.onGroup(group);
|
|
1777
|
+
if (redefine.attributeGroup) for (const group of redefine.attributeGroup) this.onAttributeGroup(group);
|
|
1778
|
+
}
|
|
1779
|
+
this.source = prevSource;
|
|
1780
|
+
}
|
|
1781
|
+
traverseOverrides(schema) {
|
|
1782
|
+
if (!schema.override) return;
|
|
1783
|
+
const prevSource = this.source;
|
|
1784
|
+
this.source = "override";
|
|
1785
|
+
for (const override of schema.override) {
|
|
1786
|
+
this.onOverride(override);
|
|
1787
|
+
if (override.complexType) for (const ct of override.complexType) this.onComplexType(ct);
|
|
1788
|
+
if (override.simpleType) for (const st of override.simpleType) this.onSimpleType(st);
|
|
1789
|
+
if (override.element) for (const element of override.element) this.onElement(element);
|
|
1790
|
+
if (override.attribute) for (const attr of override.attribute) this.onAttribute(attr);
|
|
1791
|
+
if (override.group) for (const group of override.group) this.onGroup(group);
|
|
1792
|
+
if (override.attributeGroup) for (const group of override.attributeGroup) this.onAttributeGroup(group);
|
|
1793
|
+
}
|
|
1794
|
+
this.source = prevSource;
|
|
1795
|
+
}
|
|
1796
|
+
traverseIncludes(schema, depth) {
|
|
1797
|
+
if (!this.options.includeIncludes || !schema.$includes) return;
|
|
1798
|
+
for (const included of schema.$includes) this.traverseSchema(included, "include", depth + 1);
|
|
1799
|
+
}
|
|
1800
|
+
traverseImports(schema, depth) {
|
|
1801
|
+
if (!this.options.includeImports || !schema.$imports) return;
|
|
1802
|
+
for (const imported of schema.$imports) this.traverseSchema(imported, "import", depth + 1);
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1805
|
+
/**
|
|
1806
|
+
* Resolves a schema hierarchy into a flat structure.
|
|
1807
|
+
* All types are collected into Maps for O(1) lookup.
|
|
1808
|
+
*
|
|
1809
|
+
* Precedence rules:
|
|
1810
|
+
* - redefine/override types take precedence over original
|
|
1811
|
+
* - root schema types take precedence over imported/included
|
|
1812
|
+
*/
|
|
1813
|
+
var SchemaResolver = class extends SchemaTraverser {
|
|
1814
|
+
complexTypes = /* @__PURE__ */ new Map();
|
|
1815
|
+
simpleTypes = /* @__PURE__ */ new Map();
|
|
1816
|
+
elements = /* @__PURE__ */ new Map();
|
|
1817
|
+
attributes = /* @__PURE__ */ new Map();
|
|
1818
|
+
groups = /* @__PURE__ */ new Map();
|
|
1819
|
+
attributeGroups = /* @__PURE__ */ new Map();
|
|
1820
|
+
xmlns = /* @__PURE__ */ new Map();
|
|
1821
|
+
substitutionGroups = /* @__PURE__ */ new Map();
|
|
1822
|
+
/** Get the resolved schema structure */
|
|
1823
|
+
getResolved() {
|
|
1824
|
+
return {
|
|
1825
|
+
complexTypes: this.complexTypes,
|
|
1826
|
+
simpleTypes: this.simpleTypes,
|
|
1827
|
+
elements: this.elements,
|
|
1828
|
+
attributes: this.attributes,
|
|
1829
|
+
groups: this.groups,
|
|
1830
|
+
attributeGroups: this.attributeGroups,
|
|
1831
|
+
xmlns: this.xmlns,
|
|
1832
|
+
substitutionGroups: this.substitutionGroups
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
onEnterSchema(schema) {
|
|
1836
|
+
if (schema.$xmlns) {
|
|
1837
|
+
for (const [prefix, uri] of Object.entries(schema.$xmlns)) if (!this.xmlns.has(prefix)) this.xmlns.set(prefix, uri);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
onComplexType(ct) {
|
|
1841
|
+
if (!this.complexTypes.has(ct.name) || this.source === "redefine" || this.source === "override" || this.depth === 0 && this.source === "direct") this.complexTypes.set(ct.name, {
|
|
1842
|
+
ct,
|
|
1843
|
+
schema: this.currentSchema
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
onSimpleType(st) {
|
|
1847
|
+
if (!this.simpleTypes.has(st.name) || this.source === "redefine" || this.source === "override" || this.depth === 0 && this.source === "direct") this.simpleTypes.set(st.name, {
|
|
1848
|
+
st,
|
|
1849
|
+
schema: this.currentSchema
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
onElement(element) {
|
|
1853
|
+
if (!this.elements.has(element.name) || this.source === "override" || this.depth === 0 && this.source === "direct") this.elements.set(element.name, {
|
|
1854
|
+
element,
|
|
1855
|
+
schema: this.currentSchema
|
|
1856
|
+
});
|
|
1857
|
+
if (element.substitutionGroup) {
|
|
1858
|
+
const abstractName = stripNsPrefix(element.substitutionGroup);
|
|
1859
|
+
const existing = this.substitutionGroups.get(abstractName) ?? [];
|
|
1860
|
+
existing.push(element);
|
|
1861
|
+
this.substitutionGroups.set(abstractName, existing);
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
onAttribute(attr) {
|
|
1865
|
+
if (!this.attributes.has(attr.name) || this.source === "override" || this.depth === 0 && this.source === "direct") this.attributes.set(attr.name, {
|
|
1866
|
+
attr,
|
|
1867
|
+
schema: this.currentSchema
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
onGroup(group) {
|
|
1871
|
+
if (!this.groups.has(group.name) || this.source === "redefine" || this.source === "override" || this.depth === 0 && this.source === "direct") this.groups.set(group.name, {
|
|
1872
|
+
group,
|
|
1873
|
+
schema: this.currentSchema
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
onAttributeGroup(group) {
|
|
1877
|
+
if (!this.attributeGroups.has(group.name) || this.source === "redefine" || this.source === "override" || this.depth === 0 && this.source === "direct") this.attributeGroups.set(group.name, {
|
|
1878
|
+
group,
|
|
1879
|
+
schema: this.currentSchema
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
/**
|
|
1884
|
+
* Strip namespace prefix from a QName (e.g., "xs:string" -> "string")
|
|
1885
|
+
*/
|
|
1886
|
+
function stripNsPrefix(qname) {
|
|
1887
|
+
const colonIndex = qname.indexOf(":");
|
|
1888
|
+
return colonIndex >= 0 ? qname.slice(colonIndex + 1) : qname;
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Resolve a schema hierarchy into a flat structure.
|
|
1892
|
+
* Convenience function that creates a SchemaResolver and returns the result.
|
|
1893
|
+
*/
|
|
1894
|
+
function resolveSchemaTypes(schema, options = {}) {
|
|
1895
|
+
const resolver = new SchemaResolver();
|
|
1896
|
+
resolver.traverse(schema, options);
|
|
1897
|
+
return resolver.getResolved();
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
//#endregion
|
|
1901
|
+
//#region src/xsd/resolve.ts
|
|
1902
|
+
/**
|
|
1903
|
+
* Collects all schema components into Maps for resolution.
|
|
1904
|
+
*
|
|
1905
|
+
* IMPORTANT: Elements are only collected from schemas with the SAME targetNamespace
|
|
1906
|
+
* as the root schema. This follows XSD semantics where xs:import brings in types
|
|
1907
|
+
* from a different namespace but doesn't merge elements into the current namespace.
|
|
1908
|
+
*/
|
|
1909
|
+
var SchemaCollector = class extends SchemaTraverser {
|
|
1910
|
+
complexTypes = /* @__PURE__ */ new Map();
|
|
1911
|
+
simpleTypes = /* @__PURE__ */ new Map();
|
|
1912
|
+
elements = /* @__PURE__ */ new Map();
|
|
1913
|
+
groups = /* @__PURE__ */ new Map();
|
|
1914
|
+
attributeGroups = /* @__PURE__ */ new Map();
|
|
1915
|
+
substitutionGroups = /* @__PURE__ */ new Map();
|
|
1916
|
+
xmlns = /* @__PURE__ */ new Map();
|
|
1917
|
+
onEnterSchema(schema) {
|
|
1918
|
+
if (schema.$xmlns) {
|
|
1919
|
+
for (const [prefix, uri] of Object.entries(schema.$xmlns)) if (!this.xmlns.has(prefix)) this.xmlns.set(prefix, uri);
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
onComplexType(ct) {
|
|
1923
|
+
if (!this.complexTypes.has(ct.name)) this.complexTypes.set(ct.name, ct);
|
|
1924
|
+
}
|
|
1925
|
+
onSimpleType(st) {
|
|
1926
|
+
if (!this.simpleTypes.has(st.name)) this.simpleTypes.set(st.name, st);
|
|
1927
|
+
}
|
|
1928
|
+
onElement(element) {
|
|
1929
|
+
const rootNs = this.rootSchema.targetNamespace;
|
|
1930
|
+
const currentNs = this.currentSchema.targetNamespace;
|
|
1931
|
+
const sameOrNoNamespace = currentNs === rootNs || !currentNs;
|
|
1932
|
+
const hasSubstitutionGroup = !!element.substitutionGroup;
|
|
1933
|
+
const isAbstract = !!element.abstract;
|
|
1934
|
+
if ((sameOrNoNamespace || hasSubstitutionGroup || isAbstract) && !this.elements.has(element.name)) this.elements.set(element.name, element);
|
|
1935
|
+
if (element.substitutionGroup) {
|
|
1936
|
+
const abstractName = stripNsPrefix(element.substitutionGroup);
|
|
1937
|
+
const existing = this.substitutionGroups.get(abstractName) ?? [];
|
|
1938
|
+
existing.push(element);
|
|
1939
|
+
this.substitutionGroups.set(abstractName, existing);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
onGroup(group) {
|
|
1943
|
+
if (!this.groups.has(group.name)) this.groups.set(group.name, group);
|
|
1944
|
+
}
|
|
1945
|
+
onAttributeGroup(group) {
|
|
1946
|
+
if (!this.attributeGroups.has(group.name)) this.attributeGroups.set(group.name, group);
|
|
1947
|
+
}
|
|
1948
|
+
};
|
|
1949
|
+
/**
|
|
1950
|
+
* Resolve a schema by merging all imports/includes and expanding all references.
|
|
1951
|
+
* Returns a new self-contained schema with no external dependencies.
|
|
1952
|
+
*/
|
|
1953
|
+
function resolveSchema(schema, options = {}) {
|
|
1954
|
+
const { resolveImports = true, resolveIncludes = true, expandExtensions = true, expandSubstitutions = true, filterToRootElements = false, keepImportsRef = false } = options;
|
|
1955
|
+
const collector = new SchemaCollector();
|
|
1956
|
+
collector.traverse(schema, {
|
|
1957
|
+
includeImports: resolveImports,
|
|
1958
|
+
includeIncludes: resolveIncludes
|
|
1959
|
+
});
|
|
1960
|
+
let elements;
|
|
1961
|
+
if (filterToRootElements) {
|
|
1962
|
+
const referencedElements = /* @__PURE__ */ new Set();
|
|
1963
|
+
for (const el of collector.elements.values()) collectElementRefs(el, referencedElements);
|
|
1964
|
+
for (const ct of collector.complexTypes.values()) collectElementRefsFromType(ct, referencedElements);
|
|
1965
|
+
elements = Array.from(collector.elements.values()).filter((el) => {
|
|
1966
|
+
if (el.abstract === true) return false;
|
|
1967
|
+
if (referencedElements.has(el.name)) return false;
|
|
1968
|
+
return true;
|
|
1969
|
+
});
|
|
1970
|
+
} else elements = Array.from(collector.elements.values());
|
|
1971
|
+
let resolvedComplexTypes = Array.from(collector.complexTypes.values());
|
|
1972
|
+
if (expandExtensions) resolvedComplexTypes = resolvedComplexTypes.map((ct) => expandComplexTypeExtension(ct, collector.complexTypes));
|
|
1973
|
+
if (expandSubstitutions) resolvedComplexTypes = resolvedComplexTypes.map((ct) => expandSubstitutionGroupsInType(ct, collector.elements, collector.substitutionGroups));
|
|
1974
|
+
const resolved = {
|
|
1975
|
+
targetNamespace: schema.targetNamespace,
|
|
1976
|
+
elementFormDefault: schema.elementFormDefault,
|
|
1977
|
+
$filename: schema.$filename,
|
|
1978
|
+
$xmlns: collector.xmlns.size > 0 ? Object.fromEntries(collector.xmlns) : schema.$xmlns
|
|
1979
|
+
};
|
|
1980
|
+
if (elements.length > 0) resolved.element = elements;
|
|
1981
|
+
if (resolvedComplexTypes.length > 0) resolved.complexType = resolvedComplexTypes;
|
|
1982
|
+
if (collector.simpleTypes.size > 0) resolved.simpleType = Array.from(collector.simpleTypes.values());
|
|
1983
|
+
if (collector.groups.size > 0) resolved.group = Array.from(collector.groups.values());
|
|
1984
|
+
if (collector.attributeGroups.size > 0) resolved.attributeGroup = Array.from(collector.attributeGroups.values());
|
|
1985
|
+
if (keepImportsRef && schema.$imports) resolved.$imports = schema.$imports;
|
|
1986
|
+
return resolved;
|
|
1987
|
+
}
|
|
1988
|
+
/**
|
|
1989
|
+
* Expand complexContent/extension by merging base type properties.
|
|
1990
|
+
* Uses a visited set to prevent infinite recursion on circular inheritance.
|
|
1991
|
+
*/
|
|
1992
|
+
function expandComplexTypeExtension(ct, allTypes, visited = /* @__PURE__ */ new Set()) {
|
|
1993
|
+
const extension = ct.complexContent?.extension;
|
|
1994
|
+
if (!extension?.base) return ct;
|
|
1995
|
+
if (visited.has(ct.name)) return ct;
|
|
1996
|
+
visited.add(ct.name);
|
|
1997
|
+
const mergedElements = [];
|
|
1998
|
+
const mergedAttributes = [];
|
|
1999
|
+
const baseName = stripNsPrefix(extension.base);
|
|
2000
|
+
const baseType = allTypes.get(baseName);
|
|
2001
|
+
if (baseType && !visited.has(baseName)) {
|
|
2002
|
+
const expandedBase = expandComplexTypeExtension(baseType, allTypes, visited);
|
|
2003
|
+
collectElementsFromType(expandedBase, mergedElements);
|
|
2004
|
+
if (expandedBase.attribute) mergedAttributes.push(...expandedBase.attribute);
|
|
2005
|
+
}
|
|
2006
|
+
collectElementsFromGroup(extension.sequence, mergedElements);
|
|
2007
|
+
collectElementsFromGroup(extension.choice, mergedElements);
|
|
2008
|
+
collectElementsFromGroup(extension.all, mergedElements);
|
|
2009
|
+
if (extension.attribute) mergedAttributes.push(...extension.attribute);
|
|
2010
|
+
const flattened = { name: ct.name };
|
|
2011
|
+
if (mergedElements.length > 0) flattened.all = { element: mergedElements };
|
|
2012
|
+
if (mergedAttributes.length > 0) flattened.attribute = mergedAttributes;
|
|
2013
|
+
for (const [key, value] of Object.entries(ct)) if (![
|
|
2014
|
+
"name",
|
|
2015
|
+
"complexContent",
|
|
2016
|
+
"all",
|
|
2017
|
+
"sequence",
|
|
2018
|
+
"choice",
|
|
2019
|
+
"attribute"
|
|
2020
|
+
].includes(key)) flattened[key] = value;
|
|
2021
|
+
return flattened;
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Collect elements from a complex type's content model.
|
|
2025
|
+
*/
|
|
2026
|
+
function collectElementsFromType(ct, elements) {
|
|
2027
|
+
collectElementsFromGroup(ct.sequence, elements);
|
|
2028
|
+
collectElementsFromGroup(ct.choice, elements);
|
|
2029
|
+
collectElementsFromGroup(ct.all, elements);
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* Collect elements from a group (sequence/choice/all).
|
|
2033
|
+
*/
|
|
2034
|
+
function collectElementsFromGroup(group, elements) {
|
|
2035
|
+
if (!group?.element) return;
|
|
2036
|
+
elements.push(...group.element);
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Expand substitution group references in a complex type.
|
|
2040
|
+
* Replaces abstract element refs with concrete substitute elements.
|
|
2041
|
+
*/
|
|
2042
|
+
function expandSubstitutionGroupsInType(ct, allElements, substitutionGroups) {
|
|
2043
|
+
let changed = false;
|
|
2044
|
+
const result = { ...ct };
|
|
2045
|
+
if (ct.sequence) {
|
|
2046
|
+
const expanded = expandSubstitutionGroupsInGroup(ct.sequence, allElements, substitutionGroups);
|
|
2047
|
+
if (expanded !== ct.sequence) {
|
|
2048
|
+
result.sequence = expanded;
|
|
2049
|
+
changed = true;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
if (ct.all) {
|
|
2053
|
+
const expanded = expandSubstitutionGroupsInGroup(ct.all, allElements, substitutionGroups);
|
|
2054
|
+
if (expanded !== ct.all) {
|
|
2055
|
+
result.all = expanded;
|
|
2056
|
+
changed = true;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
if (ct.choice) {
|
|
2060
|
+
const expanded = expandSubstitutionGroupsInGroup(ct.choice, allElements, substitutionGroups);
|
|
2061
|
+
if (expanded !== ct.choice) {
|
|
2062
|
+
result.choice = expanded;
|
|
2063
|
+
changed = true;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
return changed ? result : ct;
|
|
2067
|
+
}
|
|
2068
|
+
/**
|
|
2069
|
+
* Expand substitution groups in a group (sequence/all/choice).
|
|
2070
|
+
*/
|
|
2071
|
+
function expandSubstitutionGroupsInGroup(group, allElements, substitutionGroups) {
|
|
2072
|
+
if (!group.element) return group;
|
|
2073
|
+
const expandedElements = [];
|
|
2074
|
+
let hasChanges = false;
|
|
2075
|
+
for (const el of group.element) {
|
|
2076
|
+
if (el.ref) {
|
|
2077
|
+
const refName = stripNsPrefix(el.ref);
|
|
2078
|
+
if (allElements.get(refName)?.abstract) {
|
|
2079
|
+
const substitutes = substitutionGroups.get(refName);
|
|
2080
|
+
if (substitutes && substitutes.length > 0) {
|
|
2081
|
+
for (const sub of substitutes) expandedElements.push({
|
|
2082
|
+
name: sub.name,
|
|
2083
|
+
type: sub.type,
|
|
2084
|
+
minOccurs: el.minOccurs ?? 0,
|
|
2085
|
+
maxOccurs: el.maxOccurs
|
|
2086
|
+
});
|
|
2087
|
+
hasChanges = true;
|
|
2088
|
+
continue;
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
expandedElements.push(el);
|
|
2093
|
+
}
|
|
2094
|
+
if (!hasChanges) return group;
|
|
2095
|
+
return {
|
|
2096
|
+
...group,
|
|
2097
|
+
element: expandedElements
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
2100
|
+
/**
|
|
2101
|
+
* Get all substitutes for an abstract element.
|
|
2102
|
+
*/
|
|
2103
|
+
function getSubstitutes(abstractElementName, schema) {
|
|
2104
|
+
const collector = new SchemaCollector();
|
|
2105
|
+
collector.traverse(schema);
|
|
2106
|
+
return collector.substitutionGroups.get(abstractElementName) ?? [];
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* Collect element refs from an element's nested structure
|
|
2110
|
+
*/
|
|
2111
|
+
function collectElementRefs(el, refs) {
|
|
2112
|
+
const record = el;
|
|
2113
|
+
if (record.complexType) collectElementRefsFromType(record.complexType, refs);
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Recursively collect element refs from a complex type
|
|
2117
|
+
*/
|
|
2118
|
+
function collectElementRefsFromType(ct, refs) {
|
|
2119
|
+
const record = ct;
|
|
2120
|
+
for (const groupKey of [
|
|
2121
|
+
"sequence",
|
|
2122
|
+
"all",
|
|
2123
|
+
"choice"
|
|
2124
|
+
]) {
|
|
2125
|
+
const group = record[groupKey];
|
|
2126
|
+
if (group?.element) {
|
|
2127
|
+
const elements = group.element;
|
|
2128
|
+
for (const el of elements) {
|
|
2129
|
+
if (el.ref) {
|
|
2130
|
+
const refName = stripNsPrefix(el.ref);
|
|
2131
|
+
refs.add(refName);
|
|
2132
|
+
}
|
|
2133
|
+
if (el.complexType) collectElementRefsFromType(el.complexType, refs);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
if (record.complexContent) {
|
|
2138
|
+
const cc = record.complexContent;
|
|
2139
|
+
if (cc.extension) collectElementRefsFromType(cc.extension, refs);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
//#endregion
|
|
2144
|
+
//#region src/xsd/loader.ts
|
|
2145
|
+
/**
|
|
2146
|
+
* Schema Loader - Load and parse XSD files from disk
|
|
2147
|
+
*
|
|
2148
|
+
* Simple loader that reads XSD files and parses them into Schema objects.
|
|
2149
|
+
* Resolution of imports/includes is handled by the resolver.
|
|
2150
|
+
*/
|
|
2151
|
+
/**
|
|
2152
|
+
* Default XSD loader - reads from filesystem
|
|
2153
|
+
*/
|
|
2154
|
+
function defaultLoader(schemaLocation, basePath) {
|
|
2155
|
+
const fullPath = resolve(basePath, schemaLocation);
|
|
2156
|
+
if (!existsSync(fullPath)) return null;
|
|
2157
|
+
return readFileSync(fullPath, "utf-8");
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* Load and parse a single XSD file.
|
|
2161
|
+
*
|
|
2162
|
+
* @param schemaPath - Path to the XSD file
|
|
2163
|
+
* @param options - Loader options
|
|
2164
|
+
* @param options.autoLink - Populate $imports/$includes with loaded schemas (preserves structure)
|
|
2165
|
+
* @param options.autoResolve - Flatten into single schema with all types merged (implies autoLink)
|
|
2166
|
+
* @returns Parsed schema
|
|
2167
|
+
*
|
|
2168
|
+
* @example
|
|
2169
|
+
* ```typescript
|
|
2170
|
+
* // Just parse - no linking
|
|
2171
|
+
* const schema = loadSchema('/path/to/schema.xsd');
|
|
2172
|
+
*
|
|
2173
|
+
* // Link - populate $imports/$includes (preserves multi-schema structure)
|
|
2174
|
+
* const linked = loadSchema('/path/to/schema.xsd', { autoLink: true });
|
|
2175
|
+
* // linked.$imports contains actual Schema objects
|
|
2176
|
+
*
|
|
2177
|
+
* // Resolve - flatten everything into one schema
|
|
2178
|
+
* const resolved = loadSchema('/path/to/schema.xsd', { autoResolve: true });
|
|
2179
|
+
* // resolved has all types merged, no $imports/$includes
|
|
2180
|
+
* ```
|
|
2181
|
+
*/
|
|
2182
|
+
function loadSchema(schemaPath, options = {}) {
|
|
2183
|
+
const { basePath = dirname(schemaPath), loader = defaultLoader, autoLink = false, autoResolve = false, throwOnMissing = false } = options;
|
|
2184
|
+
const content = loader(schemaPath, basePath);
|
|
2185
|
+
if (!content) throw new Error(`Failed to load schema: ${schemaPath}`);
|
|
2186
|
+
let schema = parseXsd(content);
|
|
2187
|
+
Object.assign(schema, { $filename: schemaPath });
|
|
2188
|
+
if (autoLink || autoResolve) linkSchema(schema, {
|
|
2189
|
+
basePath,
|
|
2190
|
+
loader,
|
|
2191
|
+
throwOnMissing
|
|
2192
|
+
});
|
|
2193
|
+
if (autoResolve) schema = resolveSchema(schema);
|
|
2194
|
+
return schema;
|
|
2195
|
+
}
|
|
2196
|
+
/**
|
|
2197
|
+
* Load and parse XSD content from a string.
|
|
2198
|
+
*/
|
|
2199
|
+
function parseSchemaContent(content, filename) {
|
|
2200
|
+
const schema = parseXsd(content);
|
|
2201
|
+
if (filename) Object.assign(schema, { $filename: filename });
|
|
2202
|
+
return schema;
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Create a schema loader function that can be passed to the resolver.
|
|
2206
|
+
* The resolver will call this to load schemas referenced by schemaLocation.
|
|
2207
|
+
*/
|
|
2208
|
+
function createSchemaLoader(basePath, loader = defaultLoader) {
|
|
2209
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2210
|
+
return (schemaLocation) => {
|
|
2211
|
+
const fullPath = resolve(basePath, schemaLocation);
|
|
2212
|
+
const cached = cache.get(fullPath);
|
|
2213
|
+
if (cached) return cached;
|
|
2214
|
+
const content = loader(schemaLocation, basePath);
|
|
2215
|
+
if (!content) return null;
|
|
2216
|
+
const schema = parseXsd(content);
|
|
2217
|
+
Object.assign(schema, { $filename: schemaLocation });
|
|
2218
|
+
cache.set(fullPath, schema);
|
|
2219
|
+
return schema;
|
|
2220
|
+
};
|
|
2221
|
+
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Link a schema by resolving all schemaLocation references.
|
|
2224
|
+
*
|
|
2225
|
+
* Processes:
|
|
2226
|
+
* - xs:import → populates $imports
|
|
2227
|
+
* - xs:include → populates $includes
|
|
2228
|
+
* - xs:redefine → loads base schema, keeps redefinitions in redefine array
|
|
2229
|
+
* - xs:override → loads base schema, keeps overrides in override array
|
|
2230
|
+
*
|
|
2231
|
+
* @param schema - Schema to link (will be mutated with $imports/$includes)
|
|
2232
|
+
* @param options - Link options including basePath for resolving paths
|
|
2233
|
+
* @returns The same schema with $imports and $includes populated
|
|
2234
|
+
*
|
|
2235
|
+
* @example
|
|
2236
|
+
* ```typescript
|
|
2237
|
+
* const schema = parseXsd(xsdContent);
|
|
2238
|
+
* linkSchema(schema, { basePath: '/path/to/xsd/files' });
|
|
2239
|
+
* // schema.$imports and schema.$includes are now populated
|
|
2240
|
+
* ```
|
|
2241
|
+
*/
|
|
2242
|
+
function linkSchema(schema, options) {
|
|
2243
|
+
const { basePath, loader = defaultLoader, throwOnMissing = true } = options;
|
|
2244
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2245
|
+
const inProgress = /* @__PURE__ */ new Set();
|
|
2246
|
+
const loadAndLink = (schemaLocation, currentBasePath) => {
|
|
2247
|
+
const fullPath = resolve(currentBasePath, schemaLocation);
|
|
2248
|
+
const cached = cache.get(fullPath);
|
|
2249
|
+
if (cached) return cached;
|
|
2250
|
+
if (inProgress.has(fullPath)) return cache.get(fullPath) ?? null;
|
|
2251
|
+
const content = loader(schemaLocation, currentBasePath);
|
|
2252
|
+
if (!content) {
|
|
2253
|
+
if (throwOnMissing) throw new Error(`Failed to load schema: ${schemaLocation} (resolved: ${fullPath})`);
|
|
2254
|
+
return null;
|
|
2255
|
+
}
|
|
2256
|
+
const loadedSchema = parseXsd(content);
|
|
2257
|
+
Object.assign(loadedSchema, { $filename: schemaLocation });
|
|
2258
|
+
inProgress.add(fullPath);
|
|
2259
|
+
cache.set(fullPath, loadedSchema);
|
|
2260
|
+
linkSchemaInternal(loadedSchema, dirname(fullPath));
|
|
2261
|
+
inProgress.delete(fullPath);
|
|
2262
|
+
return loadedSchema;
|
|
2263
|
+
};
|
|
2264
|
+
const linkSchemaInternal = (s, currentBasePath) => {
|
|
2265
|
+
const imports = [];
|
|
2266
|
+
const includes = [];
|
|
2267
|
+
if (s.import) {
|
|
2268
|
+
for (const imp of s.import) if (imp.schemaLocation) {
|
|
2269
|
+
const linked = loadAndLink(imp.schemaLocation, currentBasePath);
|
|
2270
|
+
if (linked) imports.push(linked);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
if (s.include) {
|
|
2274
|
+
for (const inc of s.include) if (inc.schemaLocation) {
|
|
2275
|
+
const linked = loadAndLink(inc.schemaLocation, currentBasePath);
|
|
2276
|
+
if (linked) includes.push(linked);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
if (s.redefine) {
|
|
2280
|
+
for (const redef of s.redefine) if (redef.schemaLocation) {
|
|
2281
|
+
const linked = loadAndLink(redef.schemaLocation, currentBasePath);
|
|
2282
|
+
if (linked) Object.assign(redef, { $schema: linked });
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
if (s.override) {
|
|
2286
|
+
for (const ovr of s.override) if (ovr.schemaLocation) {
|
|
2287
|
+
const linked = loadAndLink(ovr.schemaLocation, currentBasePath);
|
|
2288
|
+
if (linked) Object.assign(ovr, { $schema: linked });
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
if (imports.length > 0) Object.assign(s, { $imports: imports });
|
|
2292
|
+
if (includes.length > 0) Object.assign(s, { $includes: includes });
|
|
2293
|
+
};
|
|
2294
|
+
linkSchemaInternal(schema, basePath);
|
|
2295
|
+
return schema;
|
|
2296
|
+
}
|
|
2297
|
+
/**
|
|
2298
|
+
* Load and link a schema from a file path.
|
|
2299
|
+
* Convenience function that combines loadSchema + linkSchema.
|
|
2300
|
+
*
|
|
2301
|
+
* @param schemaPath - Path to the XSD file
|
|
2302
|
+
* @param options - Optional loader options
|
|
2303
|
+
* @returns Fully linked schema with $imports and $includes populated
|
|
2304
|
+
*
|
|
2305
|
+
* @example
|
|
2306
|
+
* ```typescript
|
|
2307
|
+
* const schema = loadAndLinkSchema('/path/to/schema.xsd');
|
|
2308
|
+
* // schema.$imports and schema.$includes are populated
|
|
2309
|
+
* // Ready for type inference or resolution
|
|
2310
|
+
* ```
|
|
2311
|
+
*/
|
|
2312
|
+
function loadAndLinkSchema(schemaPath, options = {}) {
|
|
2313
|
+
const basePath = dirname(schemaPath);
|
|
2314
|
+
return linkSchema(loadSchema(schemaPath, {
|
|
2315
|
+
...options,
|
|
2316
|
+
basePath
|
|
2317
|
+
}), {
|
|
2318
|
+
basePath,
|
|
2319
|
+
loader: options.loader
|
|
2320
|
+
});
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
//#endregion
|
|
2324
|
+
//#region src/codegen/runner.ts
|
|
2325
|
+
/**
|
|
2326
|
+
* Config Runner
|
|
2327
|
+
*
|
|
2328
|
+
* Executes the generator pipeline based on configuration.
|
|
2329
|
+
*/
|
|
2330
|
+
/**
|
|
2331
|
+
* Run the codegen pipeline
|
|
2332
|
+
*/
|
|
2333
|
+
async function runCodegen(config, options) {
|
|
2334
|
+
const { rootDir, dryRun = false, verbose = false } = options;
|
|
2335
|
+
const result = {
|
|
2336
|
+
files: [],
|
|
2337
|
+
schemas: [],
|
|
2338
|
+
errors: []
|
|
2339
|
+
};
|
|
2340
|
+
const log = verbose ? console.log.bind(console) : () => {};
|
|
2341
|
+
const sources = {};
|
|
2342
|
+
for (const [name, sourceConfig] of Object.entries(config.sources)) {
|
|
2343
|
+
const xsdDir = isAbsolute(sourceConfig.xsdDir) ? sourceConfig.xsdDir : join(rootDir, sourceConfig.xsdDir);
|
|
2344
|
+
let schemas = sourceConfig.schemas;
|
|
2345
|
+
if (sourceConfig.autoLink) schemas = discoverDependentSchemas(sourceConfig.schemas, xsdDir, log);
|
|
2346
|
+
sources[name] = {
|
|
2347
|
+
name,
|
|
2348
|
+
xsdDir,
|
|
2349
|
+
outputDir: isAbsolute(sourceConfig.outputDir) ? sourceConfig.outputDir : join(rootDir, sourceConfig.outputDir),
|
|
2350
|
+
schemas
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
const setupCtx = {
|
|
2354
|
+
sources,
|
|
2355
|
+
rootDir
|
|
2356
|
+
};
|
|
2357
|
+
if (config.clean) {
|
|
2358
|
+
log(`\n🧹 Cleaning output directories...`);
|
|
2359
|
+
for (const source of Object.values(sources)) if (existsSync(source.outputDir)) {
|
|
2360
|
+
rmSync(source.outputDir, {
|
|
2361
|
+
recursive: true,
|
|
2362
|
+
force: true
|
|
2363
|
+
});
|
|
2364
|
+
log(` ✅ Cleaned ${relative(rootDir, source.outputDir)}`);
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
if (config.beforeAll) {
|
|
2368
|
+
log(`\n🔧 Running beforeAll hook...`);
|
|
2369
|
+
await config.beforeAll({
|
|
2370
|
+
sources,
|
|
2371
|
+
rootDir
|
|
2372
|
+
});
|
|
2373
|
+
}
|
|
2374
|
+
for (const generator of config.generators) if (generator.setup) {
|
|
2375
|
+
log(`[${generator.name}] Running setup...`);
|
|
2376
|
+
await generator.setup(setupCtx);
|
|
2377
|
+
}
|
|
2378
|
+
const processedSchemas = /* @__PURE__ */ new Map();
|
|
2379
|
+
const globalAllSchemas = /* @__PURE__ */ new Map();
|
|
2380
|
+
/**
|
|
2381
|
+
* Recursively discover and parse schemas referenced via xs:include or xs:redefine.
|
|
2382
|
+
* This ensures schemas like types/devc.xsd are in globalAllSchemas when devc.xsd references them.
|
|
2383
|
+
*
|
|
2384
|
+
* @param schema - The parsed schema object
|
|
2385
|
+
* @param xsdDir - The root XSD directory (e.g., '.xsd')
|
|
2386
|
+
* @param currentXsdPath - The path of the current XSD file (for resolving relative paths)
|
|
2387
|
+
* @param sourceName - The source name for logging
|
|
2388
|
+
* @param discovered - Set of already discovered schema names
|
|
2389
|
+
*/
|
|
2390
|
+
function discoverReferencedSchemas(schema, xsdDir, currentXsdPath, sourceName, discovered = /* @__PURE__ */ new Set()) {
|
|
2391
|
+
const includes = schema.include;
|
|
2392
|
+
const redefines = schema.redefine;
|
|
2393
|
+
const refs = [...includes ?? [], ...redefines ?? []];
|
|
2394
|
+
for (const ref of refs) {
|
|
2395
|
+
if (!ref.schemaLocation) continue;
|
|
2396
|
+
const schemaNameWithPath = ref.schemaLocation.replace(/\.xsd$/, "");
|
|
2397
|
+
if (discovered.has(schemaNameWithPath) || globalAllSchemas.has(schemaNameWithPath)) continue;
|
|
2398
|
+
discovered.add(schemaNameWithPath);
|
|
2399
|
+
const currentXsdDir = dirname(currentXsdPath);
|
|
2400
|
+
const refXsdPath = join(currentXsdDir, ref.schemaLocation);
|
|
2401
|
+
if (!existsSync(refXsdPath)) {
|
|
2402
|
+
log(` ⚠️ Referenced schema not found: ${ref.schemaLocation} (resolved from ${currentXsdDir})`);
|
|
2403
|
+
continue;
|
|
2404
|
+
}
|
|
2405
|
+
try {
|
|
2406
|
+
const refXsdContent = readFileSync(refXsdPath, "utf-8");
|
|
2407
|
+
const refSchema = parseXsd(refXsdContent);
|
|
2408
|
+
refSchema.$filename = ref.schemaLocation;
|
|
2409
|
+
const refSchemaInfo = {
|
|
2410
|
+
name: schemaNameWithPath,
|
|
2411
|
+
xsdContent: refXsdContent,
|
|
2412
|
+
schema: refSchema,
|
|
2413
|
+
sourceName,
|
|
2414
|
+
xsdPath: refXsdPath
|
|
2415
|
+
};
|
|
2416
|
+
globalAllSchemas.set(schemaNameWithPath, refSchemaInfo);
|
|
2417
|
+
log(` 📎 Auto-discovered: ${schemaNameWithPath}`);
|
|
2418
|
+
discoverReferencedSchemas(refSchema, xsdDir, refXsdPath, sourceName, discovered);
|
|
2419
|
+
} catch (error) {
|
|
2420
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2421
|
+
log(` ⚠️ Failed to parse referenced schema ${ref.schemaLocation}: ${err.message}`);
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
for (const [sourceName, source] of Object.entries(sources)) {
|
|
2426
|
+
log(`\n📦 Processing source: ${sourceName}`);
|
|
2427
|
+
const schemaInfos = [];
|
|
2428
|
+
for (const schemaName of source.schemas) {
|
|
2429
|
+
const xsdPath = join(source.xsdDir, `${schemaName}.xsd`);
|
|
2430
|
+
if (!existsSync(xsdPath)) {
|
|
2431
|
+
log(` ⚠️ Skipping ${schemaName} - XSD not found`);
|
|
2432
|
+
continue;
|
|
2433
|
+
}
|
|
2434
|
+
try {
|
|
2435
|
+
const xsdContent = readFileSync(xsdPath, "utf-8");
|
|
2436
|
+
const schema = parseXsd(xsdContent);
|
|
2437
|
+
schema.$filename = `${schemaName}.xsd`;
|
|
2438
|
+
linkSchema(schema, {
|
|
2439
|
+
basePath: dirname(xsdPath),
|
|
2440
|
+
throwOnMissing: false
|
|
2441
|
+
});
|
|
2442
|
+
const schemaInfo = {
|
|
2443
|
+
name: schemaName,
|
|
2444
|
+
xsdContent,
|
|
2445
|
+
schema,
|
|
2446
|
+
sourceName,
|
|
2447
|
+
xsdPath
|
|
2448
|
+
};
|
|
2449
|
+
schemaInfos.push(schemaInfo);
|
|
2450
|
+
globalAllSchemas.set(schemaName, schemaInfo);
|
|
2451
|
+
result.schemas.push({
|
|
2452
|
+
name: schemaName,
|
|
2453
|
+
source: sourceName
|
|
2454
|
+
});
|
|
2455
|
+
discoverReferencedSchemas(schema, source.xsdDir, xsdPath, sourceName);
|
|
2456
|
+
} catch (error) {
|
|
2457
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2458
|
+
log(` ❌ Failed to parse ${schemaName}: ${err.message}`);
|
|
2459
|
+
result.errors.push({
|
|
2460
|
+
schema: schemaName,
|
|
2461
|
+
source: sourceName,
|
|
2462
|
+
error: err
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
processedSchemas.set(sourceName, schemaInfos);
|
|
2467
|
+
}
|
|
2468
|
+
for (const [sourceName, source] of Object.entries(sources)) {
|
|
2469
|
+
const schemaInfos = processedSchemas.get(sourceName) ?? [];
|
|
2470
|
+
for (const schemaInfo of schemaInfos) {
|
|
2471
|
+
const transformCtx = {
|
|
2472
|
+
schema: schemaInfo,
|
|
2473
|
+
source,
|
|
2474
|
+
allSchemas: globalAllSchemas,
|
|
2475
|
+
allSources: sources,
|
|
2476
|
+
rootDir,
|
|
2477
|
+
resolveImport: createImportResolver(schemaInfo, source, sources, config)
|
|
2478
|
+
};
|
|
2479
|
+
for (const generator of config.generators) if (generator.transform) try {
|
|
2480
|
+
const files = await generator.transform(transformCtx);
|
|
2481
|
+
for (const file of files) {
|
|
2482
|
+
const fullPath = join(source.outputDir, file.path);
|
|
2483
|
+
if (!dryRun) {
|
|
2484
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
2485
|
+
writeFileSync(fullPath, file.content);
|
|
2486
|
+
}
|
|
2487
|
+
result.files.push({
|
|
2488
|
+
path: fullPath,
|
|
2489
|
+
source: sourceName
|
|
2490
|
+
});
|
|
2491
|
+
log(` ✅ [${generator.name}] Generated ${file.path}`);
|
|
2492
|
+
}
|
|
2493
|
+
} catch (error) {
|
|
2494
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2495
|
+
log(` ❌ [${generator.name}] Failed ${schemaInfo.name}: ${err.message}`);
|
|
2496
|
+
result.errors.push({
|
|
2497
|
+
schema: schemaInfo.name,
|
|
2498
|
+
source: sourceName,
|
|
2499
|
+
error: err
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
const finalizeCtx = {
|
|
2505
|
+
processedSchemas,
|
|
2506
|
+
sources,
|
|
2507
|
+
rootDir
|
|
2508
|
+
};
|
|
2509
|
+
for (const generator of config.generators) if (generator.finalize) try {
|
|
2510
|
+
log(`\n[${generator.name}] Running finalize...`);
|
|
2511
|
+
const files = await generator.finalize(finalizeCtx);
|
|
2512
|
+
for (const file of files) for (const [sourceName, source] of Object.entries(sources)) {
|
|
2513
|
+
const fullPath = join(source.outputDir, file.path);
|
|
2514
|
+
if (!dryRun) {
|
|
2515
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
2516
|
+
writeFileSync(fullPath, file.content);
|
|
2517
|
+
}
|
|
2518
|
+
result.files.push({
|
|
2519
|
+
path: fullPath,
|
|
2520
|
+
source: sourceName
|
|
2521
|
+
});
|
|
2522
|
+
log(` ✅ [${generator.name}] Generated ${file.path} for ${sourceName}`);
|
|
2523
|
+
}
|
|
2524
|
+
} catch (error) {
|
|
2525
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2526
|
+
log(` ❌ [${generator.name}] Finalize failed: ${err.message}`);
|
|
2527
|
+
result.errors.push({ error: err });
|
|
2528
|
+
}
|
|
2529
|
+
if (config.afterAll) {
|
|
2530
|
+
log(`\n🔧 Running afterAll hook...`);
|
|
2531
|
+
const afterAllCtx = {
|
|
2532
|
+
sources,
|
|
2533
|
+
rootDir,
|
|
2534
|
+
processedSchemas,
|
|
2535
|
+
generatedFiles: result.files.map((f) => ({
|
|
2536
|
+
path: f.path,
|
|
2537
|
+
content: ""
|
|
2538
|
+
}))
|
|
2539
|
+
};
|
|
2540
|
+
const extraFiles = await config.afterAll(afterAllCtx);
|
|
2541
|
+
if (extraFiles && Array.isArray(extraFiles)) for (const file of extraFiles) {
|
|
2542
|
+
const fullPath = join(rootDir, file.path);
|
|
2543
|
+
if (!dryRun) {
|
|
2544
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
2545
|
+
writeFileSync(fullPath, file.content);
|
|
2546
|
+
}
|
|
2547
|
+
result.files.push({
|
|
2548
|
+
path: fullPath,
|
|
2549
|
+
source: "afterAll"
|
|
2550
|
+
});
|
|
2551
|
+
log(` ✅ [afterAll] Generated ${file.path}`);
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
return result;
|
|
2555
|
+
}
|
|
2556
|
+
function createImportResolver(currentSchema, currentSource, allSources, config) {
|
|
2557
|
+
const ext = config.importExtension ?? "";
|
|
2558
|
+
return (schemaLocation) => {
|
|
2559
|
+
const schemaPath = schemaLocation.replace(/\.xsd$/, "");
|
|
2560
|
+
const schemaBaseName = schemaPath.replace(/^.*\//, "");
|
|
2561
|
+
const currentSchemaDir = dirname(currentSchema.name);
|
|
2562
|
+
const normalizedPath = (currentSchemaDir !== "." ? join(currentSchemaDir, schemaPath).replaceAll(/\\/g, "/") : schemaPath).split("/").reduce((acc, part) => {
|
|
2563
|
+
if (part === "..") acc.pop();
|
|
2564
|
+
else if (part !== ".") acc.push(part);
|
|
2565
|
+
return acc;
|
|
2566
|
+
}, []).join("/");
|
|
2567
|
+
if (currentSource.schemas.includes(normalizedPath)) {
|
|
2568
|
+
const fromDir = dirname(currentSchema.name);
|
|
2569
|
+
const toPath = normalizedPath;
|
|
2570
|
+
const relImport = fromDir === dirname(toPath) ? `./${basename(toPath)}${ext}` : relative(fromDir || ".", toPath).replaceAll(/\\/g, "/") || `./${basename(toPath)}`;
|
|
2571
|
+
return relImport.startsWith(".") ? `${relImport}${ext}` : `./${relImport}${ext}`;
|
|
2572
|
+
}
|
|
2573
|
+
if (currentSource.schemas.includes(schemaPath)) return `./${schemaPath}${ext}`;
|
|
2574
|
+
if (currentSource.schemas.includes(schemaBaseName)) return `./${schemaBaseName}${ext}`;
|
|
2575
|
+
for (const [sourceName, source] of Object.entries(allSources)) {
|
|
2576
|
+
if (sourceName === currentSource.name) continue;
|
|
2577
|
+
if (source.schemas.includes(normalizedPath)) return `${relative(currentSource.outputDir, source.outputDir)}/${normalizedPath}${ext}`.replaceAll(/\\/g, "/");
|
|
2578
|
+
if (source.schemas.includes(schemaPath)) return `${relative(currentSource.outputDir, source.outputDir)}/${schemaPath}${ext}`.replaceAll(/\\/g, "/");
|
|
2579
|
+
if (source.schemas.includes(schemaBaseName)) return `${relative(currentSource.outputDir, source.outputDir)}/${schemaBaseName}${ext}`.replaceAll(/\\/g, "/");
|
|
2580
|
+
}
|
|
2581
|
+
return null;
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
/**
|
|
2585
|
+
* Discover all dependent schemas by recursively parsing XSD files
|
|
2586
|
+
* and extracting schemaLocation from xs:import, xs:include, xs:redefine
|
|
2587
|
+
*/
|
|
2588
|
+
function discoverDependentSchemas(entrySchemas, xsdDir, log) {
|
|
2589
|
+
const discovered = /* @__PURE__ */ new Set();
|
|
2590
|
+
const queue = [...entrySchemas];
|
|
2591
|
+
while (queue.length > 0) {
|
|
2592
|
+
const schemaName = queue.shift();
|
|
2593
|
+
if (!schemaName) continue;
|
|
2594
|
+
if (discovered.has(schemaName)) continue;
|
|
2595
|
+
const xsdPath = join(xsdDir, `${schemaName}.xsd`);
|
|
2596
|
+
if (!existsSync(xsdPath)) throw new Error(`Schema not found: ${schemaName}.xsd (resolved: ${xsdPath})`);
|
|
2597
|
+
discovered.add(schemaName);
|
|
2598
|
+
try {
|
|
2599
|
+
const deps = extractSchemaLocations(parseXsd(readFileSync(xsdPath, "utf-8")), xsdDir, schemaName);
|
|
2600
|
+
for (const dep of deps) if (!discovered.has(dep)) {
|
|
2601
|
+
queue.push(dep);
|
|
2602
|
+
log(` 🔗 Discovered dependency: ${dep} (from ${schemaName})`);
|
|
2603
|
+
}
|
|
2604
|
+
} catch {
|
|
2605
|
+
log(` ❌ Failed to parse ${schemaName} for dependency discovery`);
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
return Array.from(discovered);
|
|
2609
|
+
}
|
|
2610
|
+
/**
|
|
2611
|
+
* Extract schema names from schemaLocation attributes
|
|
2612
|
+
*/
|
|
2613
|
+
function extractSchemaLocations(schema, xsdDir, currentSchema) {
|
|
2614
|
+
const locations = [];
|
|
2615
|
+
const currentDir = dirname(join(xsdDir, `${currentSchema}.xsd`));
|
|
2616
|
+
const imports = schema.import;
|
|
2617
|
+
if (imports) {
|
|
2618
|
+
for (const imp of imports) if (imp.schemaLocation) {
|
|
2619
|
+
const name = resolveSchemaName(imp.schemaLocation, currentDir, xsdDir);
|
|
2620
|
+
if (name) locations.push(name);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
const includes = schema.include;
|
|
2624
|
+
if (includes) {
|
|
2625
|
+
for (const inc of includes) if (inc.schemaLocation) {
|
|
2626
|
+
const name = resolveSchemaName(inc.schemaLocation, currentDir, xsdDir);
|
|
2627
|
+
if (name) locations.push(name);
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
const redefines = schema.redefine;
|
|
2631
|
+
if (redefines) {
|
|
2632
|
+
for (const red of redefines) if (red.schemaLocation) {
|
|
2633
|
+
const name = resolveSchemaName(red.schemaLocation, currentDir, xsdDir);
|
|
2634
|
+
if (name) locations.push(name);
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
return locations;
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Resolve schemaLocation to a schema name relative to xsdDir
|
|
2641
|
+
*/
|
|
2642
|
+
function resolveSchemaName(schemaLocation, currentDir, xsdDir) {
|
|
2643
|
+
const fullPath = join(currentDir, schemaLocation);
|
|
2644
|
+
const name = relative(xsdDir, fullPath).replace(/\.xsd$/, "");
|
|
2645
|
+
if (existsSync(fullPath)) return name;
|
|
2646
|
+
return null;
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
//#endregion
|
|
2650
|
+
export { getAllChildElements as _, loadAndLinkSchema as a, getLocalName as b, getSubstitutes as c, SchemaTraverser as d, resolveSchemaTypes as f, parseXsd as g, buildXsd as h, linkSchema as i, resolveSchema as l, resolveImports as m, createSchemaLoader as n, loadSchema as o, linkSchemas as p, defaultLoader as r, parseSchemaContent as s, runCodegen as t, SchemaResolver as u, getAttributeValue as v, getTextContent as x, getChildElements as y };
|
|
2651
|
+
//# sourceMappingURL=runner-CRhT3smd.mjs.map
|