@abapify/ts-xsd 0.4.34 → 0.4.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -320
- package/dist/codegen/cli.mjs +6 -4
- package/dist/codegen/cli.mjs.map +1 -1
- package/dist/{generate-DQJ38rjv.mjs → generate-BWLnwHUW.mjs} +38 -33
- package/dist/generate-BWLnwHUW.mjs.map +1 -0
- package/dist/generators/index.d.mts +1 -1
- package/dist/generators/index.mjs +130 -116
- package/dist/generators/index.mjs.map +1 -1
- package/dist/index.d.mts +6 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +495 -368
- package/dist/index.mjs.map +1 -1
- package/dist/{runner-BGNA8Sl-.mjs → runner-BZNOc_YZ.mjs} +439 -334
- package/dist/runner-BZNOc_YZ.mjs.map +1 -0
- package/dist/{runner-CDEKB5AE.d.mts → runner-x86T9IvM.d.mts} +5 -5
- package/dist/{runner-CDEKB5AE.d.mts.map → runner-x86T9IvM.d.mts.map} +1 -1
- package/dist/{types-CySWjUcM.mjs → types-BAx8yQfm.mjs} +151 -115
- package/dist/types-BAx8yQfm.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/generate-DQJ38rjv.mjs.map +0 -1
- package/dist/runner-BGNA8Sl-.mjs.map +0 -1
- package/dist/types-CySWjUcM.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { _ as getLocalName, a as loadAndLinkSchema, c as getSubstitutes, d as SchemaTraverser, f as resolveSchemaTypes, g as getChildElements, h as getAttributeValue, i as linkSchema, l as resolveSchema, m as getAllChildElements, n as createSchemaLoader, o as loadSchema, p as parseXsd, r as defaultLoader, s as parseSchemaContent, t as runCodegen, u as SchemaResolver, v as getTextContent } from "./runner-
|
|
2
|
-
import { n as generateSchemaLiteral, t as generateSchemaFile } from "./generate-
|
|
3
|
-
import { n as deriveRootTypeName, r as generateInterfaces, t as defineConfig } from "./types-
|
|
1
|
+
import { _ as getLocalName, a as loadAndLinkSchema, c as getSubstitutes, d as SchemaTraverser, f as resolveSchemaTypes, g as getChildElements, h as getAttributeValue, i as linkSchema, l as resolveSchema, m as getAllChildElements, n as createSchemaLoader, o as loadSchema, p as parseXsd, r as defaultLoader, s as parseSchemaContent, t as runCodegen, u as SchemaResolver, v as getTextContent } from "./runner-BZNOc_YZ.mjs";
|
|
2
|
+
import { n as generateSchemaLiteral, t as generateSchemaFile } from "./generate-BWLnwHUW.mjs";
|
|
3
|
+
import { n as deriveRootTypeName, r as generateInterfaces, t as defineConfig } from "./types-BAx8yQfm.mjs";
|
|
4
4
|
import { DOMImplementation, DOMParser, XMLSerializer } from "@xmldom/xmldom";
|
|
5
5
|
|
|
6
6
|
// src/xsd/build.ts
|
|
@@ -17,14 +17,12 @@ function buildXsd(schema, options = {}) {
|
|
|
17
17
|
level: 0
|
|
18
18
|
};
|
|
19
19
|
const lines = [];
|
|
20
|
-
lines.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
|
21
|
-
lines.push(buildSchema(schema, ctx));
|
|
20
|
+
lines.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", buildSchema(schema, ctx));
|
|
22
21
|
return lines.join(pretty ? "\n" : "");
|
|
23
22
|
}
|
|
24
23
|
function buildSchema(schema, ctx) {
|
|
25
24
|
const attrs = [];
|
|
26
|
-
|
|
27
|
-
else attrs.push(`xmlns:${prefix}="${uri}"`);
|
|
25
|
+
addXmlnsAttrs(attrs, schema.$xmlns);
|
|
28
26
|
addAttr(attrs, "id", schema.id);
|
|
29
27
|
addAttr(attrs, "targetNamespace", schema.targetNamespace);
|
|
30
28
|
addAttr(attrs, "version", schema.version);
|
|
@@ -40,19 +38,19 @@ function buildSchema(schema, ctx) {
|
|
|
40
38
|
...ctx,
|
|
41
39
|
level: ctx.level + 1
|
|
42
40
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
appendBuilt(children, schema.annotation, (ann) => buildAnnotation(ann, childCtx));
|
|
42
|
+
appendBuilt(children, schema.include, (inc) => buildInclude(inc, childCtx));
|
|
43
|
+
appendBuilt(children, schema.import, (imp) => buildImport(imp, childCtx));
|
|
44
|
+
appendBuilt(children, schema.redefine, (red) => buildRedefine(red, childCtx));
|
|
45
|
+
appendBuilt(children, schema.override, (ovr) => buildOverride(ovr, childCtx));
|
|
46
|
+
appendBuiltOne(children, schema.defaultOpenContent, (doc) => buildDefaultOpenContent(doc, childCtx));
|
|
47
|
+
appendBuilt(children, Array.isArray(schema.simpleType) ? schema.simpleType : [], (st) => buildTopLevelSimpleType(st, childCtx));
|
|
48
|
+
appendBuilt(children, Array.isArray(schema.complexType) ? schema.complexType : [], (ct) => buildTopLevelComplexType(ct, childCtx));
|
|
49
|
+
appendBuilt(children, schema.group, (grp) => buildNamedGroup(grp, childCtx));
|
|
50
|
+
appendBuilt(children, schema.attributeGroup, (ag) => buildNamedAttributeGroup(ag, childCtx));
|
|
51
|
+
appendBuilt(children, schema.element, (el) => buildTopLevelElement(el, childCtx));
|
|
52
|
+
appendBuilt(children, schema.attribute, (attr) => buildTopLevelAttribute(attr, childCtx));
|
|
53
|
+
appendBuilt(children, schema.notation, (not) => buildNotation(not, childCtx));
|
|
56
54
|
return buildElement$1(`${ctx.prefix}:schema`, attrs, children, ctx);
|
|
57
55
|
}
|
|
58
56
|
function buildAnnotation(ann, ctx) {
|
|
@@ -128,14 +126,14 @@ function buildOverride(ovr, ctx) {
|
|
|
128
126
|
...ctx,
|
|
129
127
|
level: ctx.level + 1
|
|
130
128
|
};
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
129
|
+
appendBuilt(children, ovr.annotation, (ann) => buildAnnotation(ann, childCtx));
|
|
130
|
+
appendBuilt(children, ovr.simpleType, (st) => buildTopLevelSimpleType(st, childCtx));
|
|
131
|
+
appendBuilt(children, ovr.complexType, (ct) => buildTopLevelComplexType(ct, childCtx));
|
|
132
|
+
appendBuilt(children, ovr.group, (grp) => buildNamedGroup(grp, childCtx));
|
|
133
|
+
appendBuilt(children, ovr.attributeGroup, (ag) => buildNamedAttributeGroup(ag, childCtx));
|
|
134
|
+
appendBuilt(children, ovr.element, (el) => buildTopLevelElement(el, childCtx));
|
|
135
|
+
appendBuilt(children, ovr.attribute, (attr) => buildTopLevelAttribute(attr, childCtx));
|
|
136
|
+
appendBuilt(children, ovr.notation, (not) => buildNotation(not, childCtx));
|
|
139
137
|
return buildElement$1(`${ctx.prefix}:override`, attrs, children, ctx);
|
|
140
138
|
}
|
|
141
139
|
function buildTopLevelElement(el, ctx) {
|
|
@@ -253,22 +251,24 @@ function buildComplexTypeContent(ct, attrs, ctx) {
|
|
|
253
251
|
...ctx,
|
|
254
252
|
level: ctx.level + 1
|
|
255
253
|
};
|
|
256
|
-
|
|
254
|
+
appendBuiltOne(children, ct.annotation, (ann) => buildAnnotation(ann, childCtx));
|
|
257
255
|
if (ct.simpleContent) children.push(buildSimpleContent(ct.simpleContent, childCtx));
|
|
258
256
|
else if (ct.complexContent) children.push(buildComplexContent(ct.complexContent, childCtx));
|
|
259
|
-
else
|
|
260
|
-
if (ct.openContent) children.push(buildOpenContent(ct.openContent, childCtx));
|
|
261
|
-
if (ct.group) children.push(buildGroupRef(ct.group, childCtx));
|
|
262
|
-
if (ct.all) children.push(buildAll(ct.all, childCtx));
|
|
263
|
-
if (ct.choice) children.push(buildExplicitGroup(ct.choice, "choice", childCtx));
|
|
264
|
-
if (ct.sequence) children.push(buildExplicitGroup(ct.sequence, "sequence", childCtx));
|
|
265
|
-
if (ct.attribute) for (const attr of ct.attribute) children.push(buildLocalAttribute(attr, childCtx));
|
|
266
|
-
if (ct.attributeGroup) for (const ag of ct.attributeGroup) children.push(buildAttributeGroupRef(ag, childCtx));
|
|
267
|
-
if (ct.anyAttribute) children.push(buildAnyAttribute(ct.anyAttribute, childCtx));
|
|
268
|
-
if (ct.assert) for (const a of ct.assert) children.push(buildAssertion(a, childCtx));
|
|
269
|
-
}
|
|
257
|
+
else buildComplexTypeShortForm(ct, children, childCtx);
|
|
270
258
|
return buildElement$1(`${ctx.prefix}:complexType`, attrs, children, ctx);
|
|
271
259
|
}
|
|
260
|
+
/** Short form: content model and attributes directly on the complexType. */
|
|
261
|
+
function buildComplexTypeShortForm(ct, children, childCtx) {
|
|
262
|
+
appendBuiltOne(children, ct.openContent, (oc) => buildOpenContent(oc, childCtx));
|
|
263
|
+
appendBuiltOne(children, ct.group, (grp) => buildGroupRef(grp, childCtx));
|
|
264
|
+
appendBuiltOne(children, ct.all, (all) => buildAll(all, childCtx));
|
|
265
|
+
appendBuiltOne(children, ct.choice, (c) => buildExplicitGroup(c, "choice", childCtx));
|
|
266
|
+
appendBuiltOne(children, ct.sequence, (s) => buildExplicitGroup(s, "sequence", childCtx));
|
|
267
|
+
appendBuilt(children, ct.attribute, (attr) => buildLocalAttribute(attr, childCtx));
|
|
268
|
+
appendBuilt(children, ct.attributeGroup, (ag) => buildAttributeGroupRef(ag, childCtx));
|
|
269
|
+
appendBuiltOne(children, ct.anyAttribute, (aa) => buildAnyAttribute(aa, childCtx));
|
|
270
|
+
appendBuilt(children, ct.assert, (a) => buildAssertion(a, childCtx));
|
|
271
|
+
}
|
|
272
272
|
function buildTopLevelSimpleType(st, ctx) {
|
|
273
273
|
const attrs = [];
|
|
274
274
|
addAttr(attrs, "id", st.id);
|
|
@@ -308,20 +308,20 @@ function buildSimpleTypeRestriction(r, ctx) {
|
|
|
308
308
|
return buildElement$1(`${ctx.prefix}:restriction`, attrs, children, ctx);
|
|
309
309
|
}
|
|
310
310
|
function buildFacets(r, children, ctx) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
311
|
+
appendBuilt(children, r.minExclusive, (f) => buildFacet(f, "minExclusive", ctx));
|
|
312
|
+
appendBuilt(children, r.minInclusive, (f) => buildFacet(f, "minInclusive", ctx));
|
|
313
|
+
appendBuilt(children, r.maxExclusive, (f) => buildFacet(f, "maxExclusive", ctx));
|
|
314
|
+
appendBuilt(children, r.maxInclusive, (f) => buildFacet(f, "maxInclusive", ctx));
|
|
315
|
+
appendBuilt(children, r.totalDigits, (f) => buildFacet(f, "totalDigits", ctx));
|
|
316
|
+
appendBuilt(children, r.fractionDigits, (f) => buildFacet(f, "fractionDigits", ctx));
|
|
317
|
+
appendBuilt(children, r.length, (f) => buildFacet(f, "length", ctx));
|
|
318
|
+
appendBuilt(children, r.minLength, (f) => buildFacet(f, "minLength", ctx));
|
|
319
|
+
appendBuilt(children, r.maxLength, (f) => buildFacet(f, "maxLength", ctx));
|
|
320
|
+
appendBuilt(children, r.enumeration, (f) => buildFacet(f, "enumeration", ctx));
|
|
321
|
+
appendBuilt(children, r.whiteSpace, (f) => buildFacet(f, "whiteSpace", ctx));
|
|
322
|
+
appendBuilt(children, r.pattern, (p) => buildPattern(p, ctx));
|
|
323
|
+
appendBuilt(children, r.assertion, (a) => buildAssertion(a, ctx));
|
|
324
|
+
appendBuilt(children, r.explicitTimezone, (f) => buildFacet(f, "explicitTimezone", ctx));
|
|
325
325
|
}
|
|
326
326
|
function buildFacet(f, name, ctx) {
|
|
327
327
|
const attrs = [];
|
|
@@ -408,16 +408,16 @@ function buildComplexContentRestriction(r, ctx) {
|
|
|
408
408
|
...ctx,
|
|
409
409
|
level: ctx.level + 1
|
|
410
410
|
};
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
411
|
+
appendBuiltOne(children, r.annotation, (ann) => buildAnnotation(ann, childCtx));
|
|
412
|
+
appendBuiltOne(children, r.openContent, (oc) => buildOpenContent(oc, childCtx));
|
|
413
|
+
appendBuiltOne(children, r.group, (grp) => buildGroupRef(grp, childCtx));
|
|
414
|
+
appendBuiltOne(children, r.all, (all) => buildAll(all, childCtx));
|
|
415
|
+
appendBuiltOne(children, r.choice, (c) => buildExplicitGroup(c, "choice", childCtx));
|
|
416
|
+
appendBuiltOne(children, r.sequence, (s) => buildExplicitGroup(s, "sequence", childCtx));
|
|
417
|
+
appendBuilt(children, r.attribute, (attr) => buildLocalAttribute(attr, childCtx));
|
|
418
|
+
appendBuilt(children, r.attributeGroup, (ag) => buildAttributeGroupRef(ag, childCtx));
|
|
419
|
+
appendBuiltOne(children, r.anyAttribute, (aa) => buildAnyAttribute(aa, childCtx));
|
|
420
|
+
appendBuilt(children, r.assert, (a) => buildAssertion(a, childCtx));
|
|
421
421
|
return buildElement$1(`${ctx.prefix}:restriction`, attrs, children, ctx);
|
|
422
422
|
}
|
|
423
423
|
function buildComplexContentExtension(e, ctx) {
|
|
@@ -429,16 +429,16 @@ function buildComplexContentExtension(e, ctx) {
|
|
|
429
429
|
...ctx,
|
|
430
430
|
level: ctx.level + 1
|
|
431
431
|
};
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
432
|
+
appendBuiltOne(children, e.annotation, (ann) => buildAnnotation(ann, childCtx));
|
|
433
|
+
appendBuiltOne(children, e.openContent, (oc) => buildOpenContent(oc, childCtx));
|
|
434
|
+
appendBuiltOne(children, e.group, (grp) => buildGroupRef(grp, childCtx));
|
|
435
|
+
appendBuiltOne(children, e.all, (all) => buildAll(all, childCtx));
|
|
436
|
+
appendBuiltOne(children, e.choice, (c) => buildExplicitGroup(c, "choice", childCtx));
|
|
437
|
+
appendBuiltOne(children, e.sequence, (s) => buildExplicitGroup(s, "sequence", childCtx));
|
|
438
|
+
appendBuilt(children, e.attribute, (attr) => buildLocalAttribute(attr, childCtx));
|
|
439
|
+
appendBuilt(children, e.attributeGroup, (ag) => buildAttributeGroupRef(ag, childCtx));
|
|
440
|
+
appendBuiltOne(children, e.anyAttribute, (aa) => buildAnyAttribute(aa, childCtx));
|
|
441
|
+
appendBuilt(children, e.assert, (a) => buildAssertion(a, childCtx));
|
|
442
442
|
return buildElement$1(`${ctx.prefix}:extension`, attrs, children, ctx);
|
|
443
443
|
}
|
|
444
444
|
function buildSimpleContentRestriction(r, ctx) {
|
|
@@ -485,12 +485,12 @@ function buildExplicitGroup(g, name, ctx) {
|
|
|
485
485
|
...ctx,
|
|
486
486
|
level: ctx.level + 1
|
|
487
487
|
};
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
488
|
+
appendBuiltOne(children, g.annotation, (ann) => buildAnnotation(ann, childCtx));
|
|
489
|
+
appendBuilt(children, g.element, (el) => buildLocalElement(el, childCtx));
|
|
490
|
+
appendBuilt(children, g.group, (grp) => buildGroupRef(grp, childCtx));
|
|
491
|
+
appendBuilt(children, g.choice, (c) => buildExplicitGroup(c, "choice", childCtx));
|
|
492
|
+
appendBuilt(children, g.sequence, (s) => buildExplicitGroup(s, "sequence", childCtx));
|
|
493
|
+
appendBuilt(children, g.any, (a) => buildAny(a, childCtx));
|
|
494
494
|
return buildElement$1(`${ctx.prefix}:${name}`, attrs, children, ctx);
|
|
495
495
|
}
|
|
496
496
|
function buildAll(a, ctx) {
|
|
@@ -731,17 +731,34 @@ function buildNotation(n, ctx) {
|
|
|
731
731
|
}));
|
|
732
732
|
return buildElement$1(`${ctx.prefix}:notation`, attrs, children, ctx);
|
|
733
733
|
}
|
|
734
|
+
/** Add xmlns:* namespace declaration attributes. */
|
|
735
|
+
function addXmlnsAttrs(attrs, xmlns) {
|
|
736
|
+
if (!xmlns) return;
|
|
737
|
+
for (const [prefix, uri] of Object.entries(xmlns)) if (prefix === "") attrs.push(`xmlns="${uri}"`);
|
|
738
|
+
else attrs.push(`xmlns:${prefix}="${uri}"`);
|
|
739
|
+
}
|
|
740
|
+
/** Append one built child element per item, skipped when `items` is absent. */
|
|
741
|
+
function appendBuilt(children, items, build) {
|
|
742
|
+
if (items) for (const item of items) children.push(build(item));
|
|
743
|
+
}
|
|
744
|
+
/** Append a single built child element when `item` is present. */
|
|
745
|
+
function appendBuiltOne(children, item, build) {
|
|
746
|
+
if (item) children.push(build(item));
|
|
747
|
+
}
|
|
734
748
|
function addAttr(attrs, name, value) {
|
|
735
749
|
if (value !== void 0) attrs.push(`${name}="${escapeXml(value)}"`);
|
|
736
750
|
}
|
|
737
|
-
function
|
|
751
|
+
function addPlainAttr(attrs, name, value) {
|
|
738
752
|
if (value !== void 0) attrs.push(`${name}="${value}"`);
|
|
739
753
|
}
|
|
754
|
+
function addBoolAttr(attrs, name, value) {
|
|
755
|
+
addPlainAttr(attrs, name, value);
|
|
756
|
+
}
|
|
740
757
|
function addOccursAttr(attrs, name, value) {
|
|
741
|
-
|
|
758
|
+
addPlainAttr(attrs, name, value);
|
|
742
759
|
}
|
|
743
760
|
function escapeXml(str) {
|
|
744
|
-
return str.replaceAll(
|
|
761
|
+
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
745
762
|
}
|
|
746
763
|
function buildElement$1(tag, attrs, children, ctx) {
|
|
747
764
|
const indent = ctx.pretty ? ctx.indent.repeat(ctx.level) : "";
|
|
@@ -823,67 +840,86 @@ function linkSchemas(schemas) {
|
|
|
823
840
|
* ```
|
|
824
841
|
*/
|
|
825
842
|
function* walkComplexTypes(schema, options = {}) {
|
|
843
|
+
yield* ownComplexTypes(schema);
|
|
844
|
+
yield* redefineComplexTypes(schema);
|
|
845
|
+
yield* overrideComplexTypes(schema);
|
|
846
|
+
yield* walkNestedSchemas(schema, options, walkComplexTypes);
|
|
847
|
+
}
|
|
848
|
+
/** Yield complexTypes declared directly in the schema. */
|
|
849
|
+
function* ownComplexTypes(schema) {
|
|
826
850
|
const complexTypes = schema.complexType;
|
|
827
|
-
if (complexTypes)
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
851
|
+
if (!complexTypes) return;
|
|
852
|
+
if (Array.isArray(complexTypes)) for (const ct of complexTypes) yield {
|
|
853
|
+
ct,
|
|
854
|
+
schema
|
|
855
|
+
};
|
|
856
|
+
else for (const [name, ct] of Object.entries(complexTypes)) yield {
|
|
857
|
+
ct: {
|
|
858
|
+
...ct,
|
|
859
|
+
name
|
|
860
|
+
},
|
|
861
|
+
schema
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
/** Yield complexTypes from redefine blocks. */
|
|
865
|
+
function* redefineComplexTypes(schema) {
|
|
866
|
+
for (const redef of schema.redefine ?? []) for (const ct of redef.complexType ?? []) yield {
|
|
867
|
+
ct,
|
|
868
|
+
schema
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
/** Yield complexTypes from override blocks (XSD 1.1). */
|
|
872
|
+
function* overrideComplexTypes(schema) {
|
|
873
|
+
for (const ovr of schema.override ?? []) for (const ct of ovr.complexType ?? []) yield {
|
|
874
|
+
ct,
|
|
875
|
+
schema
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Recurse into $includes (same namespace), then $imports (different namespace).
|
|
880
|
+
*/
|
|
881
|
+
function* walkNestedSchemas(schema, options, walker) {
|
|
882
|
+
if (schema.$includes) for (const included of schema.$includes) yield* walker(included, options);
|
|
883
|
+
if (!options.includesOnly && schema.$imports) for (const imported of schema.$imports) yield* walker(imported, options);
|
|
854
884
|
}
|
|
855
885
|
/**
|
|
856
886
|
* Walk all simpleTypes in a schema and its $imports/$includes.
|
|
857
887
|
*/
|
|
858
888
|
function* walkSimpleTypes(schema, options = {}) {
|
|
889
|
+
yield* ownSimpleTypes(schema);
|
|
890
|
+
yield* redefineSimpleTypes(schema);
|
|
891
|
+
yield* overrideSimpleTypes(schema);
|
|
892
|
+
yield* walkNestedSchemas(schema, options, walkSimpleTypes);
|
|
893
|
+
}
|
|
894
|
+
/** Yield simpleTypes declared directly in the schema. */
|
|
895
|
+
function* ownSimpleTypes(schema) {
|
|
859
896
|
const simpleTypes = schema.simpleType;
|
|
860
|
-
if (simpleTypes)
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
if (!options.includesOnly && schema.$imports) for (const imported of schema.$imports) yield* walkSimpleTypes(imported, options);
|
|
897
|
+
if (!simpleTypes) return;
|
|
898
|
+
if (Array.isArray(simpleTypes)) for (const st of simpleTypes) yield {
|
|
899
|
+
st,
|
|
900
|
+
schema
|
|
901
|
+
};
|
|
902
|
+
else for (const [name, st] of Object.entries(simpleTypes)) yield {
|
|
903
|
+
st: {
|
|
904
|
+
...st,
|
|
905
|
+
name
|
|
906
|
+
},
|
|
907
|
+
schema
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
/** Yield simpleTypes from redefine blocks. */
|
|
911
|
+
function* redefineSimpleTypes(schema) {
|
|
912
|
+
for (const redef of schema.redefine ?? []) for (const st of redef.simpleType ?? []) yield {
|
|
913
|
+
st,
|
|
914
|
+
schema
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
/** Yield simpleTypes from override blocks (XSD 1.1). */
|
|
918
|
+
function* overrideSimpleTypes(schema) {
|
|
919
|
+
for (const ovr of schema.override ?? []) for (const st of ovr.simpleType ?? []) yield {
|
|
920
|
+
st,
|
|
921
|
+
schema
|
|
922
|
+
};
|
|
887
923
|
}
|
|
888
924
|
/**
|
|
889
925
|
* Walk all top-level elements in a schema and its $imports/$includes.
|
|
@@ -960,46 +996,52 @@ function* walkGroup(group, source, schema, parentOptional = false, parentArray =
|
|
|
960
996
|
const groupOptional = parentOptional || group.minOccurs === 0 || group.minOccurs === "0";
|
|
961
997
|
const groupArray = parentArray || isArray(group);
|
|
962
998
|
const choiceOptional = source === "choice";
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
}
|
|
983
|
-
yield {
|
|
984
|
-
element,
|
|
999
|
+
for (const element of group.element ?? []) yield* elementEntries(element, choiceOptional || groupOptional || element.minOccurs === 0 || element.minOccurs === "0", groupArray || isArray(element), source, schema);
|
|
1000
|
+
for (const nested of asGroupArray(group.sequence)) yield* walkGroup(nested, "sequence", schema, groupOptional, groupArray);
|
|
1001
|
+
for (const nested of asGroupArray(group.choice)) yield* walkGroup(nested, "choice", schema, true, groupArray || isArray(nested));
|
|
1002
|
+
for (const ref of asGroupArray(group.group)) if (ref.ref) yield* walkGroupRef(ref.ref, schema, groupOptional || choiceOptional, groupArray || isArray(ref));
|
|
1003
|
+
}
|
|
1004
|
+
/** Normalize a possibly single group value to an array. */
|
|
1005
|
+
function asGroupArray(value) {
|
|
1006
|
+
if (value == null) return [];
|
|
1007
|
+
return Array.isArray(value) ? value : [value];
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Yield the entries for one direct group element: substitutes of an abstract
|
|
1011
|
+
* element ref when present, otherwise the element itself.
|
|
1012
|
+
*/
|
|
1013
|
+
function* elementEntries(element, optional, array, source, schema) {
|
|
1014
|
+
const substitutes = abstractSubstitutes(element, schema);
|
|
1015
|
+
if (substitutes) {
|
|
1016
|
+
for (const sub of substitutes) yield {
|
|
1017
|
+
element: sub,
|
|
985
1018
|
optional,
|
|
986
1019
|
array,
|
|
987
1020
|
source,
|
|
988
1021
|
schema
|
|
989
1022
|
};
|
|
1023
|
+
return;
|
|
990
1024
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1025
|
+
yield {
|
|
1026
|
+
element,
|
|
1027
|
+
optional,
|
|
1028
|
+
array,
|
|
1029
|
+
source,
|
|
1030
|
+
schema
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Substitutes for an element ref to an abstract element, or undefined when
|
|
1035
|
+
* the element needs no substitution handling. No substitutes in this schema
|
|
1036
|
+
* yields undefined so the parser can handle substitution via the root schema.
|
|
1037
|
+
*/
|
|
1038
|
+
function abstractSubstitutes(element, schema) {
|
|
1039
|
+
if (!element.ref) return void 0;
|
|
1040
|
+
const refName = stripNsPrefix(element.ref);
|
|
1041
|
+
const refEntry = findElement(refName, schema);
|
|
1042
|
+
if (!refEntry || !isAbstractElement(refEntry.element)) return void 0;
|
|
1043
|
+
const substitutes = findSubstitutes(refName, schema);
|
|
1044
|
+
return substitutes.length > 0 ? substitutes : void 0;
|
|
1003
1045
|
}
|
|
1004
1046
|
/**
|
|
1005
1047
|
* Walk elements from a group reference (xs:group ref="...").
|
|
@@ -1023,35 +1065,29 @@ function* walkGroupRef(ref, schema, parentOptional = false, parentArray = false)
|
|
|
1023
1065
|
function* walkAttributes(ct, schema) {
|
|
1024
1066
|
if (ct.complexContent?.extension) {
|
|
1025
1067
|
const ext = ct.complexContent.extension;
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
if (baseEntry) yield* walkAttributes(baseEntry.ct, baseEntry.schema);
|
|
1029
|
-
}
|
|
1030
|
-
if (ext.attribute) for (const attr of ext.attribute) {
|
|
1031
|
-
const resolved = resolveAttribute(attr, schema);
|
|
1032
|
-
if (resolved) yield {
|
|
1033
|
-
attribute: resolved,
|
|
1034
|
-
required: resolved.use === "required",
|
|
1035
|
-
schema
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1068
|
+
yield* walkBaseAttributes(ext.base, schema);
|
|
1069
|
+
yield* resolvedAttributes(ext.attribute, schema);
|
|
1038
1070
|
yield* walkAttributeGroupRefs(ext.attributeGroup, schema);
|
|
1039
1071
|
return;
|
|
1040
1072
|
}
|
|
1041
1073
|
if (ct.simpleContent?.extension) {
|
|
1042
1074
|
const ext = ct.simpleContent.extension;
|
|
1043
|
-
|
|
1044
|
-
const resolved = resolveAttribute(attr, schema);
|
|
1045
|
-
if (resolved) yield {
|
|
1046
|
-
attribute: resolved,
|
|
1047
|
-
required: resolved.use === "required",
|
|
1048
|
-
schema
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1075
|
+
yield* resolvedAttributes(ext.attribute, schema);
|
|
1051
1076
|
yield* walkAttributeGroupRefs(ext.attributeGroup, schema);
|
|
1052
1077
|
return;
|
|
1053
1078
|
}
|
|
1054
|
-
|
|
1079
|
+
yield* resolvedAttributes(ct.attribute, schema);
|
|
1080
|
+
yield* walkAttributeGroupRefs(ct.attributeGroup, schema);
|
|
1081
|
+
}
|
|
1082
|
+
/** Yield attributes inherited from the base type of an extension. */
|
|
1083
|
+
function* walkBaseAttributes(base, schema) {
|
|
1084
|
+
if (!base) return;
|
|
1085
|
+
const baseEntry = findComplexType(stripNsPrefix(base), schema);
|
|
1086
|
+
if (baseEntry) yield* walkAttributes(baseEntry.ct, baseEntry.schema);
|
|
1087
|
+
}
|
|
1088
|
+
/** Yield declared attributes with attribute refs resolved. */
|
|
1089
|
+
function* resolvedAttributes(attributes, schema) {
|
|
1090
|
+
for (const attr of attributes ?? []) {
|
|
1055
1091
|
const resolved = resolveAttribute(attr, schema);
|
|
1056
1092
|
if (resolved) yield {
|
|
1057
1093
|
attribute: resolved,
|
|
@@ -1059,7 +1095,6 @@ function* walkAttributes(ct, schema) {
|
|
|
1059
1095
|
schema
|
|
1060
1096
|
};
|
|
1061
1097
|
}
|
|
1062
|
-
yield* walkAttributeGroupRefs(ct.attributeGroup, schema);
|
|
1063
1098
|
}
|
|
1064
1099
|
/**
|
|
1065
1100
|
* Walk attributes from attributeGroup references.
|
|
@@ -1079,38 +1114,41 @@ function* walkAttributeGroupRefs(refs, schema) {
|
|
|
1079
1114
|
}
|
|
1080
1115
|
}
|
|
1081
1116
|
/**
|
|
1117
|
+
* Search a name in the current schema's declarations, then in $includes
|
|
1118
|
+
* (same namespace) and $imports (different namespace), depth-first.
|
|
1119
|
+
*/
|
|
1120
|
+
function findInSchemas(name, schema, searchOwn) {
|
|
1121
|
+
const found = searchOwn(name, schema);
|
|
1122
|
+
if (found) return found;
|
|
1123
|
+
const linkedSchemas = [];
|
|
1124
|
+
if (schema.$includes) linkedSchemas.push(...schema.$includes);
|
|
1125
|
+
if (schema.$imports) linkedSchemas.push(...schema.$imports);
|
|
1126
|
+
for (const linked of linkedSchemas) {
|
|
1127
|
+
const result = findInSchemas(name, linked, searchOwn);
|
|
1128
|
+
if (result) return result;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1082
1132
|
* Find a named group (xs:group) by name.
|
|
1083
1133
|
*/
|
|
1084
1134
|
function findGroup(name, schema) {
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
if (found) return found;
|
|
1091
|
-
}
|
|
1092
|
-
if (schema.$imports) for (const imported of schema.$imports) {
|
|
1093
|
-
const found = findGroup(name, imported);
|
|
1094
|
-
if (found) return found;
|
|
1095
|
-
}
|
|
1135
|
+
return findInSchemas(name, schema, findGroupInSchema);
|
|
1136
|
+
}
|
|
1137
|
+
/** Search a named group in a single schema's declarations. */
|
|
1138
|
+
function findGroupInSchema(name, schema) {
|
|
1139
|
+
for (const g of schema.group ?? []) if (g.name === name) return g;
|
|
1096
1140
|
}
|
|
1097
1141
|
/**
|
|
1098
1142
|
* Find a top-level attribute by name.
|
|
1099
1143
|
* Searches current schema and $imports.
|
|
1100
1144
|
*/
|
|
1101
1145
|
function findAttribute(name, schema) {
|
|
1146
|
+
return findInSchemas(name, schema, findAttributeInSchema);
|
|
1147
|
+
}
|
|
1148
|
+
/** Search a top-level attribute in a single schema's declarations. */
|
|
1149
|
+
function findAttributeInSchema(name, schema) {
|
|
1102
1150
|
const schemaWithAttrs = schema;
|
|
1103
|
-
|
|
1104
|
-
for (const attr of schemaWithAttrs.attribute) if (attr.name === name) return attr;
|
|
1105
|
-
}
|
|
1106
|
-
if (schema.$includes) for (const included of schema.$includes) {
|
|
1107
|
-
const found = findAttribute(name, included);
|
|
1108
|
-
if (found) return found;
|
|
1109
|
-
}
|
|
1110
|
-
if (schema.$imports) for (const imported of schema.$imports) {
|
|
1111
|
-
const found = findAttribute(name, imported);
|
|
1112
|
-
if (found) return found;
|
|
1113
|
-
}
|
|
1151
|
+
for (const attr of schemaWithAttrs.attribute ?? []) if (attr.name === name) return attr;
|
|
1114
1152
|
}
|
|
1115
1153
|
/**
|
|
1116
1154
|
* Resolve an attribute - handles both direct attributes and refs.
|
|
@@ -1136,17 +1174,11 @@ function resolveAttribute(attribute, schema) {
|
|
|
1136
1174
|
* Find an attributeGroup by name.
|
|
1137
1175
|
*/
|
|
1138
1176
|
function findAttributeGroup(name, schema) {
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
if (found) return found;
|
|
1145
|
-
}
|
|
1146
|
-
if (schema.$imports) for (const imported of schema.$imports) {
|
|
1147
|
-
const found = findAttributeGroup(name, imported);
|
|
1148
|
-
if (found) return found;
|
|
1149
|
-
}
|
|
1177
|
+
return findInSchemas(name, schema, findAttributeGroupInSchema);
|
|
1178
|
+
}
|
|
1179
|
+
/** Search an attributeGroup in a single schema's declarations. */
|
|
1180
|
+
function findAttributeGroupInSchema(name, schema) {
|
|
1181
|
+
for (const g of schema.attributeGroup ?? []) if (g.name === name) return g;
|
|
1150
1182
|
}
|
|
1151
1183
|
/**
|
|
1152
1184
|
* Strip namespace prefix from a QName (e.g., "tns:PersonType" -> "PersonType")
|
|
@@ -1323,26 +1355,51 @@ function findElementByName(schema, name) {
|
|
|
1323
1355
|
function parseElement(node, typeDef, schema, rootSchema) {
|
|
1324
1356
|
const result = {};
|
|
1325
1357
|
if (typeDef.simpleContent?.extension) return parseSimpleContent(node, typeDef, schema, rootSchema);
|
|
1358
|
+
parseAttributes(node, typeDef, schema, result);
|
|
1359
|
+
parseChildElements(node, typeDef, schema, rootSchema, result);
|
|
1360
|
+
if (hasWildcard(typeDef, schema)) parseWildcardChildren(node, result);
|
|
1361
|
+
return result;
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Parse declared attributes of an element into the result object.
|
|
1365
|
+
*/
|
|
1366
|
+
function parseAttributes(node, typeDef, schema, result) {
|
|
1326
1367
|
for (const { attribute } of walkAttributes(typeDef, schema)) {
|
|
1327
1368
|
if (!attribute.name) continue;
|
|
1369
|
+
const type = attribute.type || "string";
|
|
1328
1370
|
const value = getAttributeValue(node, attribute.name);
|
|
1329
|
-
if (value !== null)
|
|
1330
|
-
|
|
1371
|
+
if (value !== null) {
|
|
1372
|
+
result[attribute.name] = convertValue(value, type);
|
|
1373
|
+
continue;
|
|
1374
|
+
}
|
|
1375
|
+
if (attribute.default !== void 0) result[attribute.name] = convertValue(String(attribute.default), type);
|
|
1331
1376
|
}
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Parse declared child elements of an element into the result object.
|
|
1380
|
+
*/
|
|
1381
|
+
function parseChildElements(node, typeDef, schema, rootSchema, result) {
|
|
1332
1382
|
for (const { element, array } of walkElements(typeDef, schema)) {
|
|
1333
1383
|
const resolved = resolveElementInfo$1(element, schema);
|
|
1334
1384
|
if (!resolved) continue;
|
|
1335
|
-
if (isAbstractElement$1(resolved.name, rootSchema))
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
if (array || children.length > 1) {
|
|
1339
|
-
const values = children.map((child) => parseChildValue(child, resolved.typeName, schema, rootSchema));
|
|
1340
|
-
if (values.length > 0) result[resolved.name] = values;
|
|
1341
|
-
} else if (children.length === 1) result[resolved.name] = parseChildValue(children[0], resolved.typeName, schema, rootSchema);
|
|
1385
|
+
if (isAbstractElement$1(resolved.name, rootSchema)) {
|
|
1386
|
+
parseSubstitutionChildren(node, resolved.name, rootSchema, result);
|
|
1387
|
+
continue;
|
|
1342
1388
|
}
|
|
1389
|
+
parseRegularChildren(node, resolved, array, schema, rootSchema, result);
|
|
1343
1390
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Parse non-abstract declared children: arrays and single elements.
|
|
1394
|
+
*/
|
|
1395
|
+
function parseRegularChildren(node, resolved, array, schema, rootSchema, result) {
|
|
1396
|
+
const children = getChildElements(node, resolved.name);
|
|
1397
|
+
if (array || children.length > 1) {
|
|
1398
|
+
const values = children.map((child) => parseChildValue(child, resolved.typeName, schema, rootSchema));
|
|
1399
|
+
if (values.length > 0) result[resolved.name] = values;
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
if (children.length === 1) result[resolved.name] = parseChildValue(children[0], resolved.typeName, schema, rootSchema);
|
|
1346
1403
|
}
|
|
1347
1404
|
/**
|
|
1348
1405
|
* Parse children that substitute for an abstract element — substitutes can
|
|
@@ -1353,7 +1410,7 @@ function parseSubstitutionChildren(node, headName, rootSchema, result) {
|
|
|
1353
1410
|
for (const child of getAllChildElements(node)) {
|
|
1354
1411
|
const childName = getLocalName(child);
|
|
1355
1412
|
const substitute = substitutes.find((s) => s.element.name === childName);
|
|
1356
|
-
if (substitute
|
|
1413
|
+
if (substitute?.element.name) {
|
|
1357
1414
|
const subTypeName = substitute.element.type ? stripNsPrefix(substitute.element.type) : void 0;
|
|
1358
1415
|
result[substitute.element.name] = parseChildValue(child, subTypeName, substitute.schema, rootSchema);
|
|
1359
1416
|
}
|
|
@@ -1383,10 +1440,7 @@ function parseWildcardChildren(node, result) {
|
|
|
1383
1440
|
*/
|
|
1384
1441
|
function parseAnyValue(node) {
|
|
1385
1442
|
const result = {};
|
|
1386
|
-
for (
|
|
1387
|
-
const attr = node.attributes[i];
|
|
1388
|
-
result[`@${attr.name}`] = attr.value;
|
|
1389
|
-
}
|
|
1443
|
+
for (const attr of node.attributes) result[`@${attr.name}`] = attr.value;
|
|
1390
1444
|
const children = getAllChildElements(node);
|
|
1391
1445
|
if (children.length === 0) {
|
|
1392
1446
|
if (Object.keys(result).length === 0) return getTextContent(node);
|
|
@@ -1607,11 +1661,15 @@ function formatValue(value, type) {
|
|
|
1607
1661
|
* Only adds newlines for nested elements
|
|
1608
1662
|
*/
|
|
1609
1663
|
function formatXml(xml) {
|
|
1610
|
-
|
|
1611
|
-
|
|
1664
|
+
return renderXmlParts(tokenizeXml(xml)).trim();
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Tokenize XML into tags and text using linear scan (avoids regex backtracking).
|
|
1668
|
+
*/
|
|
1669
|
+
function tokenizeXml(xml) {
|
|
1612
1670
|
const parts = [];
|
|
1613
1671
|
let pos = 0;
|
|
1614
|
-
while (pos < xml.length) if (xml.
|
|
1672
|
+
while (pos < xml.length) if (xml.codePointAt(pos) === 60) {
|
|
1615
1673
|
const end = xml.indexOf(">", pos + 1);
|
|
1616
1674
|
if (end === -1) {
|
|
1617
1675
|
parts.push(xml.slice(pos));
|
|
@@ -1628,6 +1686,14 @@ function formatXml(xml) {
|
|
|
1628
1686
|
if (next > pos) parts.push(xml.slice(pos, next));
|
|
1629
1687
|
pos = next;
|
|
1630
1688
|
}
|
|
1689
|
+
return parts;
|
|
1690
|
+
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Render tokenized XML parts with indentation.
|
|
1693
|
+
*/
|
|
1694
|
+
function renderXmlParts(parts) {
|
|
1695
|
+
let formatted = "";
|
|
1696
|
+
let indent = 0;
|
|
1631
1697
|
let lastWasText = false;
|
|
1632
1698
|
for (let i = 0; i < parts.length; i++) {
|
|
1633
1699
|
const part = parts[i];
|
|
@@ -1637,16 +1703,14 @@ function formatXml(xml) {
|
|
|
1637
1703
|
lastWasText = false;
|
|
1638
1704
|
} else if (part.startsWith("</")) {
|
|
1639
1705
|
indent = Math.max(0, indent - 1);
|
|
1640
|
-
|
|
1641
|
-
else formatted += " ".repeat(indent) + part + "\n";
|
|
1706
|
+
formatted += renderClosingTag(part, indent, lastWasText);
|
|
1642
1707
|
lastWasText = false;
|
|
1643
1708
|
} else if (part.startsWith("<") && part.endsWith("/>")) {
|
|
1644
1709
|
formatted += " ".repeat(indent) + part + "\n";
|
|
1645
1710
|
lastWasText = false;
|
|
1646
1711
|
} else if (part.startsWith("<")) {
|
|
1647
|
-
formatted +=
|
|
1712
|
+
formatted += renderOpeningTag(part, nextPart, indent);
|
|
1648
1713
|
if (!part.includes("</")) indent++;
|
|
1649
|
-
if (nextPart && !nextPart.startsWith("<")) {} else formatted += "\n";
|
|
1650
1714
|
lastWasText = false;
|
|
1651
1715
|
} else {
|
|
1652
1716
|
const trimmed = part.trim();
|
|
@@ -1656,7 +1720,16 @@ function formatXml(xml) {
|
|
|
1656
1720
|
}
|
|
1657
1721
|
}
|
|
1658
1722
|
}
|
|
1659
|
-
return formatted
|
|
1723
|
+
return formatted;
|
|
1724
|
+
}
|
|
1725
|
+
/** Render a closing tag, kept inline when text content precedes it. */
|
|
1726
|
+
function renderClosingTag(part, indent, lastWasText) {
|
|
1727
|
+
return (lastWasText ? "" : " ".repeat(indent)) + part + "\n";
|
|
1728
|
+
}
|
|
1729
|
+
/** Render an opening tag; no newline when text content follows. */
|
|
1730
|
+
function renderOpeningTag(part, nextPart, indent) {
|
|
1731
|
+
const text = " ".repeat(indent) + part;
|
|
1732
|
+
return nextPart && !nextPart.startsWith("<") ? text : text + "\n";
|
|
1660
1733
|
}
|
|
1661
1734
|
|
|
1662
1735
|
// src/xml/build.ts
|
|
@@ -1666,6 +1739,8 @@ function formatXml(xml) {
|
|
|
1666
1739
|
* Build XML string from typed JavaScript object using W3C-compliant Schema definition.
|
|
1667
1740
|
* Uses the walker module for schema traversal.
|
|
1668
1741
|
*/
|
|
1742
|
+
/** Explicit `String()` coercion for untyped values. */
|
|
1743
|
+
const asText = String;
|
|
1669
1744
|
/**
|
|
1670
1745
|
* Collect all namespace prefixes from a schema and its $imports chain
|
|
1671
1746
|
*/
|
|
@@ -1696,41 +1771,8 @@ function build(schema, data, options = {}) {
|
|
|
1696
1771
|
const { xmlDecl = true, encoding = "utf-8", pretty = false } = options;
|
|
1697
1772
|
const prefix = options.prefix ?? getSchemaPrefix(schema);
|
|
1698
1773
|
const doc = createXmlDocument(schema);
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
let elementData = data;
|
|
1702
|
-
if (options.rootElement) {
|
|
1703
|
-
const found = findElement(options.rootElement, schema);
|
|
1704
|
-
if (!found) throw new Error(`Element '${options.rootElement}' not found in schema`);
|
|
1705
|
-
elementDecl = found.element;
|
|
1706
|
-
elementSchema = found.schema;
|
|
1707
|
-
if (elementData[options.rootElement] !== void 0) elementData = elementData[options.rootElement];
|
|
1708
|
-
} else {
|
|
1709
|
-
const dataKeys = Object.keys(elementData);
|
|
1710
|
-
if (dataKeys.length === 1) {
|
|
1711
|
-
const potentialElementName = dataKeys[0];
|
|
1712
|
-
const found = findElement(potentialElementName, schema);
|
|
1713
|
-
if (found) {
|
|
1714
|
-
elementDecl = found.element;
|
|
1715
|
-
elementSchema = found.schema;
|
|
1716
|
-
elementData = elementData[potentialElementName];
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
if (!elementDecl) {
|
|
1720
|
-
elementDecl = findMatchingElement(elementData, schema);
|
|
1721
|
-
if (!elementDecl) throw new Error("Schema has no element declarations");
|
|
1722
|
-
}
|
|
1723
|
-
}
|
|
1724
|
-
let rootType;
|
|
1725
|
-
let rootSchema = elementSchema;
|
|
1726
|
-
if (elementDecl.complexType) rootType = elementDecl.complexType;
|
|
1727
|
-
else if (elementDecl.type) {
|
|
1728
|
-
const typeName = stripNsPrefix(elementDecl.type);
|
|
1729
|
-
const rootTypeEntry = findComplexType(typeName, elementSchema);
|
|
1730
|
-
if (!rootTypeEntry) throw new Error(`Schema missing complexType for: ${typeName}`);
|
|
1731
|
-
rootType = rootTypeEntry.ct;
|
|
1732
|
-
rootSchema = rootTypeEntry.schema;
|
|
1733
|
-
} else throw new Error(`Element ${elementDecl.name} has no type or inline complexType`);
|
|
1774
|
+
const { elementDecl, elementSchema, elementData } = resolveRootElement(schema, data, options.rootElement);
|
|
1775
|
+
const { rootType, rootSchema } = resolveRootType(elementDecl, elementSchema);
|
|
1734
1776
|
const elementName = elementDecl.name ?? elementDecl.ref;
|
|
1735
1777
|
if (!elementName) throw new Error("Element declaration has no name or ref");
|
|
1736
1778
|
const root = createRootElement(doc, elementName, schema, prefix);
|
|
@@ -1744,6 +1786,63 @@ function build(schema, data, options = {}) {
|
|
|
1744
1786
|
return xml;
|
|
1745
1787
|
}
|
|
1746
1788
|
/**
|
|
1789
|
+
* Find the element declaration for the root - either by name or by matching data.
|
|
1790
|
+
*/
|
|
1791
|
+
function resolveRootElement(schema, data, rootElement) {
|
|
1792
|
+
if (rootElement) return resolveNamedRootElement(schema, data, rootElement);
|
|
1793
|
+
return resolveInferredRootElement(schema, data);
|
|
1794
|
+
}
|
|
1795
|
+
/** Resolve the root element by its explicit name. */
|
|
1796
|
+
function resolveNamedRootElement(schema, data, rootElement) {
|
|
1797
|
+
const found = findElement(rootElement, schema);
|
|
1798
|
+
if (!found) throw new Error(`Element '${rootElement}' not found in schema`);
|
|
1799
|
+
const elementData = data[rootElement] !== void 0 ? data[rootElement] : data;
|
|
1800
|
+
return {
|
|
1801
|
+
elementDecl: found.element,
|
|
1802
|
+
elementSchema: found.schema,
|
|
1803
|
+
elementData
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
/** Infer the root element from the wrapped data key or the data structure. */
|
|
1807
|
+
function resolveInferredRootElement(schema, data) {
|
|
1808
|
+
const dataKeys = Object.keys(data);
|
|
1809
|
+
if (dataKeys.length === 1) {
|
|
1810
|
+
const potentialElementName = dataKeys[0];
|
|
1811
|
+
const found = findElement(potentialElementName, schema);
|
|
1812
|
+
if (found) return {
|
|
1813
|
+
elementDecl: found.element,
|
|
1814
|
+
elementSchema: found.schema,
|
|
1815
|
+
elementData: data[potentialElementName]
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1818
|
+
const elementDecl = findMatchingElement(data, schema);
|
|
1819
|
+
if (!elementDecl) throw new Error("Schema has no element declarations");
|
|
1820
|
+
return {
|
|
1821
|
+
elementDecl,
|
|
1822
|
+
elementSchema: schema,
|
|
1823
|
+
elementData: data
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
/**
|
|
1827
|
+
* Get the complexType of the root element - either inline or by reference.
|
|
1828
|
+
*/
|
|
1829
|
+
function resolveRootType(elementDecl, elementSchema) {
|
|
1830
|
+
if (elementDecl.complexType) return {
|
|
1831
|
+
rootType: elementDecl.complexType,
|
|
1832
|
+
rootSchema: elementSchema
|
|
1833
|
+
};
|
|
1834
|
+
if (elementDecl.type) {
|
|
1835
|
+
const typeName = stripNsPrefix(elementDecl.type);
|
|
1836
|
+
const rootTypeEntry = findComplexType(typeName, elementSchema);
|
|
1837
|
+
if (!rootTypeEntry) throw new Error(`Schema missing complexType for: ${typeName}`);
|
|
1838
|
+
return {
|
|
1839
|
+
rootType: rootTypeEntry.ct,
|
|
1840
|
+
rootSchema: rootTypeEntry.schema
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
throw new Error(`Element ${elementDecl.name} has no type or inline complexType`);
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1747
1846
|
* Find the element declaration that best matches the data structure.
|
|
1748
1847
|
* Searches in the main schema first, then in $imports.
|
|
1749
1848
|
*/
|
|
@@ -1751,50 +1850,62 @@ function findMatchingElement(data, schema) {
|
|
|
1751
1850
|
const dataKeys = new Set(Object.keys(data));
|
|
1752
1851
|
let bestMatch;
|
|
1753
1852
|
let bestScore = -1;
|
|
1754
|
-
const
|
|
1755
|
-
|
|
1756
|
-
let ctSchema = searchSchema;
|
|
1757
|
-
if (element.complexType) ct = element.complexType;
|
|
1758
|
-
else if (element.type) {
|
|
1759
|
-
const typeName = stripNsPrefix(element.type);
|
|
1760
|
-
const typeEntry = findComplexType(typeName, searchSchema);
|
|
1761
|
-
if (typeEntry) {
|
|
1762
|
-
ct = typeEntry.ct;
|
|
1763
|
-
ctSchema = typeEntry.schema;
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
if (!ct) return 0;
|
|
1767
|
-
const typeFields = /* @__PURE__ */ new Set();
|
|
1768
|
-
for (const { element: el } of walkElements(ct, ctSchema)) if (el.name) typeFields.add(el.name);
|
|
1769
|
-
for (const { attribute } of walkAttributes(ct, ctSchema)) if (attribute.name) typeFields.add(attribute.name);
|
|
1770
|
-
let score = 0;
|
|
1771
|
-
dataKeys.forEach((key) => {
|
|
1772
|
-
if (typeFields.has(key)) score++;
|
|
1773
|
-
});
|
|
1774
|
-
return score;
|
|
1775
|
-
};
|
|
1776
|
-
const elements = schema.element;
|
|
1777
|
-
if (elements && elements.length > 0) for (const element of elements) {
|
|
1778
|
-
const score = scoreElement(element, schema);
|
|
1853
|
+
for (const { element, schema: candidateSchema } of collectCandidateElements(schema)) {
|
|
1854
|
+
const score = scoreElement(element, candidateSchema, dataKeys);
|
|
1779
1855
|
if (score > bestScore) {
|
|
1780
1856
|
bestScore = score;
|
|
1781
1857
|
bestMatch = element;
|
|
1782
1858
|
}
|
|
1783
1859
|
}
|
|
1860
|
+
const elements = schema.element;
|
|
1861
|
+
if (!bestMatch && elements && elements.length > 0) return elements[0];
|
|
1862
|
+
return bestMatch;
|
|
1863
|
+
}
|
|
1864
|
+
/**
|
|
1865
|
+
* Collect candidate element declarations: main schema first, then $imports.
|
|
1866
|
+
*/
|
|
1867
|
+
function collectCandidateElements(schema) {
|
|
1868
|
+
const candidates = [];
|
|
1869
|
+
const elements = schema.element;
|
|
1870
|
+
if (elements && elements.length > 0) for (const element of elements) candidates.push({
|
|
1871
|
+
element,
|
|
1872
|
+
schema
|
|
1873
|
+
});
|
|
1784
1874
|
const imports = schema.$imports;
|
|
1785
1875
|
if (imports) for (const importedSchema of imports) {
|
|
1786
1876
|
const importedElements = importedSchema.element;
|
|
1787
1877
|
if (!importedElements) continue;
|
|
1788
|
-
for (const element of importedElements) {
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1878
|
+
for (const element of importedElements) candidates.push({
|
|
1879
|
+
element,
|
|
1880
|
+
schema: importedSchema
|
|
1881
|
+
});
|
|
1882
|
+
}
|
|
1883
|
+
return candidates;
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Score an element against the data keys: how many keys its type covers.
|
|
1887
|
+
*/
|
|
1888
|
+
function scoreElement(element, searchSchema, dataKeys) {
|
|
1889
|
+
let ct;
|
|
1890
|
+
let ctSchema = searchSchema;
|
|
1891
|
+
if (element.complexType) ct = element.complexType;
|
|
1892
|
+
else if (element.type) {
|
|
1893
|
+
const typeName = stripNsPrefix(element.type);
|
|
1894
|
+
const typeEntry = findComplexType(typeName, searchSchema);
|
|
1895
|
+
if (typeEntry) {
|
|
1896
|
+
ct = typeEntry.ct;
|
|
1897
|
+
ctSchema = typeEntry.schema;
|
|
1794
1898
|
}
|
|
1795
1899
|
}
|
|
1796
|
-
if (!
|
|
1797
|
-
|
|
1900
|
+
if (!ct) return 0;
|
|
1901
|
+
const typeFields = /* @__PURE__ */ new Set();
|
|
1902
|
+
for (const { element: el } of walkElements(ct, ctSchema)) if (el.name) typeFields.add(el.name);
|
|
1903
|
+
for (const { attribute } of walkAttributes(ct, ctSchema)) if (attribute.name) typeFields.add(attribute.name);
|
|
1904
|
+
let score = 0;
|
|
1905
|
+
dataKeys.forEach((key) => {
|
|
1906
|
+
if (typeFields.has(key)) score++;
|
|
1907
|
+
});
|
|
1908
|
+
return score;
|
|
1798
1909
|
}
|
|
1799
1910
|
/**
|
|
1800
1911
|
* Build element content using its complexType definition
|
|
@@ -1805,7 +1916,11 @@ function buildElement(doc, node, data, typeDef, schema, rootSchema, prefix) {
|
|
|
1805
1916
|
const wildcard = hasWildcard(typeDef, schema);
|
|
1806
1917
|
const consumed = /* @__PURE__ */ new Set();
|
|
1807
1918
|
buildAttributes(node, data, typeDef, schema, rootSchema, consumed);
|
|
1808
|
-
buildDeclaredElements(
|
|
1919
|
+
buildDeclaredElements({
|
|
1920
|
+
doc,
|
|
1921
|
+
rootSchema,
|
|
1922
|
+
prefix
|
|
1923
|
+
}, node, data, typeDef, schema, consumed);
|
|
1809
1924
|
if (wildcard) for (const key of Object.keys(data)) {
|
|
1810
1925
|
if (consumed.has(key)) continue;
|
|
1811
1926
|
buildAnyField(doc, node, key, data[key]);
|
|
@@ -1836,12 +1951,12 @@ function buildAttributes(node, data, typeDef, schema, rootSchema, consumed) {
|
|
|
1836
1951
|
* Build declared child elements via the walker (handles inheritance,
|
|
1837
1952
|
* groups, refs, substitution). Adds each declared key to `consumed`.
|
|
1838
1953
|
*/
|
|
1839
|
-
function buildDeclaredElements(
|
|
1954
|
+
function buildDeclaredElements(env, node, data, typeDef, schema, consumed) {
|
|
1955
|
+
const { doc, rootSchema, prefix } = env;
|
|
1840
1956
|
for (const { element, schema: elementDefSchema } of walkElements(typeDef, schema)) {
|
|
1841
1957
|
if (element.ref) {
|
|
1842
1958
|
const refName = stripNsPrefix(element.ref);
|
|
1843
|
-
|
|
1844
|
-
if (refElement && refElement.element.abstract) {
|
|
1959
|
+
if (findElement(refName, elementDefSchema)?.element.abstract) {
|
|
1845
1960
|
buildSubstituteElements(doc, node, data, refName, rootSchema, prefix, consumed);
|
|
1846
1961
|
continue;
|
|
1847
1962
|
}
|
|
@@ -1850,7 +1965,14 @@ function buildDeclaredElements(doc, node, data, typeDef, schema, rootSchema, pre
|
|
|
1850
1965
|
if (!resolved) continue;
|
|
1851
1966
|
consumed.add(resolved.dataKey);
|
|
1852
1967
|
const value = data[resolved.dataKey];
|
|
1853
|
-
if (value != null) buildFieldWithTagName(
|
|
1968
|
+
if (value != null) buildFieldWithTagName(env, node, {
|
|
1969
|
+
value,
|
|
1970
|
+
tagName: resolved.tagName,
|
|
1971
|
+
typeName: resolved.typeName,
|
|
1972
|
+
inlineComplexType: resolved.inlineComplexType,
|
|
1973
|
+
elementSchema: resolved.elementSchema,
|
|
1974
|
+
elementForm: resolved.form
|
|
1975
|
+
});
|
|
1854
1976
|
}
|
|
1855
1977
|
}
|
|
1856
1978
|
/**
|
|
@@ -1865,7 +1987,14 @@ function buildSubstituteElements(doc, node, data, refName, rootSchema, prefix, c
|
|
|
1865
1987
|
if (!subName) continue;
|
|
1866
1988
|
consumed.add(subName);
|
|
1867
1989
|
const value = data[subName];
|
|
1868
|
-
if (value != null)
|
|
1990
|
+
if (value != null) {
|
|
1991
|
+
const typeName = substitute.element.type ? stripNsPrefix(substitute.element.type) : void 0;
|
|
1992
|
+
buildField({
|
|
1993
|
+
doc,
|
|
1994
|
+
rootSchema,
|
|
1995
|
+
prefix
|
|
1996
|
+
}, node, value, subName, typeName, substitute.schema);
|
|
1997
|
+
}
|
|
1869
1998
|
}
|
|
1870
1999
|
}
|
|
1871
2000
|
/**
|
|
@@ -1880,13 +2009,17 @@ function buildAnyField(doc, parent, tagName, value) {
|
|
|
1880
2009
|
return;
|
|
1881
2010
|
}
|
|
1882
2011
|
const el = doc.createElement(tagName);
|
|
1883
|
-
if (typeof value === "object")
|
|
1884
|
-
|
|
1885
|
-
} else if (key === "_text") el.textContent = String(nested ?? "");
|
|
1886
|
-
else buildAnyField(doc, el, key, nested);
|
|
1887
|
-
else el.textContent = String(value);
|
|
2012
|
+
if (typeof value === "object") buildAnyEntries(doc, el, value);
|
|
2013
|
+
else el.textContent = asText(value);
|
|
1888
2014
|
parent.appendChild(el);
|
|
1889
2015
|
}
|
|
2016
|
+
/** Build the nested entries of a wildcard object element. */
|
|
2017
|
+
function buildAnyEntries(doc, el, value) {
|
|
2018
|
+
for (const [key, nested] of Object.entries(value)) if (key.startsWith("@")) {
|
|
2019
|
+
if (nested !== void 0 && nested !== null) el.setAttribute(key.slice(1), asText(nested));
|
|
2020
|
+
} else if (key === "_text") el.textContent = asText(nested ?? "");
|
|
2021
|
+
else buildAnyField(doc, el, key, nested);
|
|
2022
|
+
}
|
|
1890
2023
|
/**
|
|
1891
2024
|
* Resolve element info (name and type), handling ref
|
|
1892
2025
|
*
|
|
@@ -1935,11 +2068,19 @@ function resolveElementInfo(element, schema) {
|
|
|
1935
2068
|
* - "qualified": local elements get namespace prefix
|
|
1936
2069
|
* - "unqualified" (default): local elements do NOT get namespace prefix
|
|
1937
2070
|
*/
|
|
1938
|
-
function buildField(
|
|
2071
|
+
function buildField(env, parent, value, elementName, typeName, schema) {
|
|
2072
|
+
const { rootSchema, prefix } = env;
|
|
1939
2073
|
const nestedType = typeName ? findComplexType(typeName, schema) : void 0;
|
|
1940
2074
|
const usePrefix = rootSchema.elementFormDefault === "qualified" ? prefix : void 0;
|
|
1941
|
-
|
|
1942
|
-
|
|
2075
|
+
emitFieldChildren(env, parent, value, usePrefix ? `${usePrefix}:${elementName}` : elementName, typeName, nestedType);
|
|
2076
|
+
}
|
|
2077
|
+
/**
|
|
2078
|
+
* Emit the child element(s) of a field value: arrays become repeated siblings.
|
|
2079
|
+
*/
|
|
2080
|
+
function emitFieldChildren(env, parent, value, tagName, typeName, nestedType) {
|
|
2081
|
+
const { doc, rootSchema, prefix } = env;
|
|
2082
|
+
const items = Array.isArray(value) ? value : [value];
|
|
2083
|
+
for (const item of items) {
|
|
1943
2084
|
const child = doc.createElement(tagName);
|
|
1944
2085
|
if (nestedType) buildElement(doc, child, item, nestedType.ct, nestedType.schema, rootSchema, prefix);
|
|
1945
2086
|
else {
|
|
@@ -1948,15 +2089,6 @@ function buildField(doc, parent, value, elementName, typeName, schema, rootSchem
|
|
|
1948
2089
|
}
|
|
1949
2090
|
parent.appendChild(child);
|
|
1950
2091
|
}
|
|
1951
|
-
else {
|
|
1952
|
-
const child = doc.createElement(tagName);
|
|
1953
|
-
if (nestedType) buildElement(doc, child, value, nestedType.ct, nestedType.schema, rootSchema, prefix);
|
|
1954
|
-
else {
|
|
1955
|
-
const text = formatValue(value, typeName || "string");
|
|
1956
|
-
if (text) child.appendChild(doc.createTextNode(text));
|
|
1957
|
-
}
|
|
1958
|
-
parent.appendChild(child);
|
|
1959
|
-
}
|
|
1960
2092
|
}
|
|
1961
2093
|
/**
|
|
1962
2094
|
* Build a field with an explicit tag name (used for element refs with prefix)
|
|
@@ -1966,39 +2098,34 @@ function buildField(doc, parent, value, elementName, typeName, schema, rootSchem
|
|
|
1966
2098
|
* 2. Elements with form="unqualified" - never use prefix
|
|
1967
2099
|
* 3. Direct elements - apply elementFormDefault logic
|
|
1968
2100
|
*/
|
|
1969
|
-
function buildFieldWithTagName(
|
|
2101
|
+
function buildFieldWithTagName(env, parent, spec) {
|
|
2102
|
+
const { rootSchema, prefix } = env;
|
|
2103
|
+
const { value, tagName, typeName, inlineComplexType, elementSchema, elementForm } = spec;
|
|
1970
2104
|
let nestedType;
|
|
1971
2105
|
if (inlineComplexType) nestedType = {
|
|
1972
2106
|
ct: inlineComplexType,
|
|
1973
2107
|
schema: elementSchema
|
|
1974
2108
|
};
|
|
1975
2109
|
else if (typeName) nestedType = findComplexType(typeName, elementSchema);
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
if (
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
if (nestedType) buildElement(doc, child, value, nestedType.ct, nestedType.schema, rootSchema, prefix);
|
|
1996
|
-
else {
|
|
1997
|
-
const text = formatValue(value, typeName || "string");
|
|
1998
|
-
if (text) child.appendChild(doc.createTextNode(text));
|
|
1999
|
-
}
|
|
2000
|
-
parent.appendChild(child);
|
|
2001
|
-
}
|
|
2110
|
+
emitFieldChildren(env, parent, value, resolveTagName(tagName, elementSchema, rootSchema, prefix, elementForm), typeName, nestedType);
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* Determine the actual tag name to use.
|
|
2114
|
+
* Priority: 1. Per-element form attribute, 2. Schema elementFormDefault
|
|
2115
|
+
* If tagName already has a prefix (e.g., "asx:abap"), use it directly
|
|
2116
|
+
*/
|
|
2117
|
+
function resolveTagName(tagName, elementSchema, rootSchema, prefix, elementForm) {
|
|
2118
|
+
if (tagName.includes(":")) return tagName;
|
|
2119
|
+
const usePrefix = resolveElementPrefix(elementSchema, rootSchema, prefix, elementForm);
|
|
2120
|
+
return usePrefix ? `${usePrefix}:${tagName}` : tagName;
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Determine the namespace prefix for a local tag name.
|
|
2124
|
+
*/
|
|
2125
|
+
function resolveElementPrefix(elementSchema, rootSchema, prefix, elementForm) {
|
|
2126
|
+
if (elementForm === "unqualified") return;
|
|
2127
|
+
if (elementForm === "qualified") return getPrefixForSchema(elementSchema, rootSchema) ?? prefix;
|
|
2128
|
+
return (elementSchema.elementFormDefault ?? rootSchema.elementFormDefault) === "qualified" ? getPrefixForSchema(elementSchema, rootSchema) ?? prefix : void 0;
|
|
2002
2129
|
}
|
|
2003
2130
|
/**
|
|
2004
2131
|
* Find all elements that substitute for a given abstract element name.
|