uss-xsd-engine 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * uss-xsd-engine v0.2.0
2
+ * uss-xsd-engine v0.2.1
3
3
  * (c) 2026 Bernard Mumble
4
4
  * MIT License
5
5
  */
@@ -69,6 +69,8 @@ var ISSUE_CODES = {
69
69
  XML_KEY_NULL_VIOLATION: "XML_KEY_NULL_VIOLATION",
70
70
  XML_KEYREF_VIOLATION: "XML_KEYREF_VIOLATION",
71
71
  XML_UNIQUE_VIOLATION: "XML_UNIQUE_VIOLATION",
72
+ XML_ANY_STRICT_VALIDATION_FAILED: "XML_ANY_STRICT_VALIDATION_FAILED",
73
+ XML_ANYATTRIBUTE_STRICT_VALIDATION_FAILED: "XML_ANYATTRIBUTE_STRICT_VALIDATION_FAILED",
72
74
  XML_PATTERN_MISMATCH: "XML_PATTERN_MISMATCH",
73
75
  XML_LENGTH_MISMATCH: "XML_LENGTH_MISMATCH",
74
76
  XML_MIN_LENGTH_VIOLATION: "XML_MIN_LENGTH_VIOLATION",
@@ -95,6 +97,9 @@ var ISSUE_CODES = {
95
97
  XSD_RESTRICTION_NOT_SUBSET: "XSD_RESTRICTION_NOT_SUBSET",
96
98
  XSD_RESTRICTION_OCCURS_WIDENED: "XSD_RESTRICTION_OCCURS_WIDENED",
97
99
  XSD_RESTRICTION_ATTRIBUTE_WIDENED: "XSD_RESTRICTION_ATTRIBUTE_WIDENED",
100
+ XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE: "XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
101
+ XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE: "XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
102
+ XSD_RESTRICTION_WILDCARD_INCOMPATIBLE: "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
98
103
  XSD_INCLUDE_NOT_PROVIDED: "XSD_INCLUDE_NOT_PROVIDED",
99
104
  XSD_IMPORT_NOT_PROVIDED: "XSD_IMPORT_NOT_PROVIDED",
100
105
  XSD_INCLUDE_NAMESPACE_MISMATCH: "XSD_INCLUDE_NAMESPACE_MISMATCH",
@@ -480,9 +485,11 @@ function createGroupRefNode({
480
485
  }
481
486
  function createAnyNode({
482
487
  namespace = null,
483
- processContents = null,
488
+ processContents = "strict",
484
489
  minOccurs = 1,
485
490
  maxOccurs = 1,
491
+ notNamespace = [],
492
+ notQName = [],
486
493
  line = null,
487
494
  column = null,
488
495
  path = null
@@ -490,9 +497,31 @@ function createAnyNode({
490
497
  return {
491
498
  kind: "any",
492
499
  namespace,
493
- processContents,
500
+ processContents: processContents || "strict",
494
501
  minOccurs,
495
502
  maxOccurs,
503
+ notNamespace,
504
+ notQName,
505
+ line,
506
+ column,
507
+ path
508
+ };
509
+ }
510
+ function createAnyAttributeNode({
511
+ namespace = null,
512
+ processContents = "strict",
513
+ notNamespace = [],
514
+ notQName = [],
515
+ line = null,
516
+ column = null,
517
+ path = null
518
+ } = {}) {
519
+ return {
520
+ kind: "anyAttribute",
521
+ namespace,
522
+ processContents: processContents || "strict",
523
+ notNamespace,
524
+ notQName,
496
525
  line,
497
526
  column,
498
527
  path
@@ -817,8 +846,6 @@ function getEffectiveContent(schema, complexTypeDecl) {
817
846
 
818
847
  // src/parser/buildSchemaModel.js
819
848
  var UNSUPPORTED_NODE_FEATURES = /* @__PURE__ */ new Set([
820
- "any",
821
- "anyAttribute",
822
849
  "redefine",
823
850
  "notation"
824
851
  ]);
@@ -1253,6 +1280,10 @@ function parseAttributesContainer(nodes, xsdText, lineStarts, parentPath, schema
1253
1280
  issues
1254
1281
  )
1255
1282
  );
1283
+ } else if (child.localName === "anyAttribute") {
1284
+ attributes.push(
1285
+ parseAnyAttribute(child, xsdText, lineStarts, parentPath, schema, issues)
1286
+ );
1256
1287
  }
1257
1288
  }
1258
1289
  return attributes;
@@ -1336,15 +1367,58 @@ function parseGroupRef(node, xsdText, lineStarts, parentPath, schema, issues) {
1336
1367
  path
1337
1368
  });
1338
1369
  }
1370
+ function parseWildcardNamespace(namespaceStr) {
1371
+ if (!namespaceStr) return null;
1372
+ const trimmed = namespaceStr.trim();
1373
+ if (!trimmed) return null;
1374
+ if (trimmed.includes(" ")) {
1375
+ return trimmed.split(/\s+/).filter((ns) => ns);
1376
+ }
1377
+ return trimmed;
1378
+ }
1379
+ function parseNotNamespace(notNamespaceStr) {
1380
+ if (!notNamespaceStr) return [];
1381
+ const trimmed = notNamespaceStr.trim();
1382
+ if (!trimmed) return [];
1383
+ if (trimmed.includes(" ")) {
1384
+ return trimmed.split(/\s+/).filter((ns) => ns);
1385
+ }
1386
+ return [trimmed];
1387
+ }
1388
+ function parseNotQName(notQNameStr) {
1389
+ if (!notQNameStr) return [];
1390
+ const trimmed = notQNameStr.trim();
1391
+ if (!trimmed) return [];
1392
+ if (trimmed.includes(" ")) {
1393
+ return trimmed.split(/\s+/).filter((qn) => qn);
1394
+ }
1395
+ return [trimmed];
1396
+ }
1339
1397
  function parseAny(node, xsdText, lineStarts, parentPath, schema, issues) {
1340
1398
  const path = buildPath(parentPath, node);
1341
1399
  const loc = locateNodeInSource(xsdText, lineStarts, node);
1342
1400
  collectNodeDiagnostics(schema, issues, node, path, loc);
1343
1401
  return createAnyNode({
1344
- namespace: node.getAttribute("namespace"),
1402
+ namespace: parseWildcardNamespace(node.getAttribute("namespace")),
1345
1403
  processContents: node.getAttribute("processContents"),
1346
1404
  minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1347
1405
  maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1406
+ notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
1407
+ notQName: parseNotQName(node.getAttribute("notQName")),
1408
+ line: loc.line,
1409
+ column: loc.column,
1410
+ path
1411
+ });
1412
+ }
1413
+ function parseAnyAttribute(node, xsdText, lineStarts, parentPath, schema, issues) {
1414
+ const path = buildPath(parentPath, node);
1415
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1416
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1417
+ return createAnyAttributeNode({
1418
+ namespace: parseWildcardNamespace(node.getAttribute("namespace")),
1419
+ processContents: node.getAttribute("processContents"),
1420
+ notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
1421
+ notQName: parseNotQName(node.getAttribute("notQName")),
1348
1422
  line: loc.line,
1349
1423
  column: loc.column,
1350
1424
  path
@@ -1767,24 +1841,24 @@ function resolveExternalDocument(ref, externalDocuments) {
1767
1841
  }
1768
1842
  }
1769
1843
  if (ref?.kind === "import" && ref.namespace) {
1770
- const namespaceMatches = entries.filter((entry) => {
1844
+ const namespaceMatches2 = entries.filter((entry) => {
1771
1845
  const declaredTargetNamespace = getDeclaredTargetNamespaceFromText(
1772
1846
  entry.text
1773
1847
  );
1774
1848
  return (declaredTargetNamespace || null) === (ref.namespace || null);
1775
1849
  });
1776
- if (namespaceMatches.length === 1) {
1850
+ if (namespaceMatches2.length === 1) {
1777
1851
  return {
1778
1852
  kind: "namespace",
1779
- entry: namespaceMatches[0],
1780
- matches: namespaceMatches
1853
+ entry: namespaceMatches2[0],
1854
+ matches: namespaceMatches2
1781
1855
  };
1782
1856
  }
1783
- if (namespaceMatches.length > 1) {
1857
+ if (namespaceMatches2.length > 1) {
1784
1858
  return {
1785
1859
  kind: "ambiguous-namespace",
1786
1860
  entry: null,
1787
- matches: namespaceMatches
1861
+ matches: namespaceMatches2
1788
1862
  };
1789
1863
  }
1790
1864
  }
@@ -2401,6 +2475,115 @@ function checkRestrictedAttributes(schema, derivedType, baseType, issues) {
2401
2475
  }
2402
2476
  }
2403
2477
  }
2478
+ function checkWildcardRestriction(schema, derivedType, baseType, issues) {
2479
+ const derivedContent = getEffectiveContent(schema, derivedType);
2480
+ const baseContent = getEffectiveContent(schema, baseType);
2481
+ const derivedWildcards = [];
2482
+ const baseWildcards = [];
2483
+ function collectWildcards(node, arr) {
2484
+ if (!node) return;
2485
+ if (node.kind === "any") {
2486
+ arr.push(node);
2487
+ return;
2488
+ }
2489
+ if (node.children) {
2490
+ for (const child of asArray(node.children)) {
2491
+ collectWildcards(child, arr);
2492
+ }
2493
+ }
2494
+ }
2495
+ collectWildcards(derivedContent, derivedWildcards);
2496
+ collectWildcards(baseContent, baseWildcards);
2497
+ if (derivedWildcards.length > 0 && baseWildcards.length === 0) {
2498
+ issues.push(
2499
+ buildRestrictionIssue(
2500
+ "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
2501
+ `Restricted type introduces wildcard elements that base type does not have.`,
2502
+ derivedType
2503
+ )
2504
+ );
2505
+ }
2506
+ const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
2507
+ const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
2508
+ const derivedHasAnyAttribute = derivedAttrs.some((a) => a?.kind === "anyAttribute");
2509
+ const baseHasAnyAttribute = baseAttrs.some((a) => a?.kind === "anyAttribute");
2510
+ if (derivedHasAnyAttribute && !baseHasAnyAttribute) {
2511
+ issues.push(
2512
+ buildRestrictionIssue(
2513
+ "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
2514
+ `Restricted type introduces anyAttribute that base type does not have.`,
2515
+ derivedType
2516
+ )
2517
+ );
2518
+ }
2519
+ }
2520
+ function checkOccurrenceCompatibility(derived, base, name) {
2521
+ const dMin = typeof derived.minOccurs === "number" ? derived.minOccurs : 1;
2522
+ const bMin = typeof base.minOccurs === "number" ? base.minOccurs : 1;
2523
+ const dMax = maxToNumber(derived.maxOccurs ?? 1);
2524
+ const bMax = maxToNumber(base.maxOccurs ?? 1);
2525
+ return dMin >= bMin && dMax <= bMax;
2526
+ }
2527
+ function checkComplexContentRestriction(schema, derivedType, baseType, issues) {
2528
+ const derivedContent = getEffectiveContent(schema, derivedType);
2529
+ const baseContent = getEffectiveContent(schema, baseType);
2530
+ if (!derivedContent || !baseContent) return;
2531
+ const derivedFlat = flattenContent(derivedContent, []);
2532
+ const baseFlat = flattenContent(baseContent, []);
2533
+ const baseMap = new Map(baseFlat.map((item) => [item.name, item]));
2534
+ for (const item of derivedFlat) {
2535
+ const baseItem = baseMap.get(item.name);
2536
+ if (!baseItem) {
2537
+ issues.push(
2538
+ buildRestrictionIssue(
2539
+ "XSD_RESTRICTION_NOT_SUBSET",
2540
+ `Restricted type contains element '${item.name}' not in base type.`,
2541
+ item
2542
+ )
2543
+ );
2544
+ continue;
2545
+ }
2546
+ if (!checkOccurrenceCompatibility(item, baseItem, item.name)) {
2547
+ issues.push(
2548
+ buildRestrictionIssue(
2549
+ "XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
2550
+ `Restricted type has incompatible occurrence constraints for '${item.name}'.`,
2551
+ item
2552
+ )
2553
+ );
2554
+ }
2555
+ }
2556
+ }
2557
+ function checkSimpleContentRestriction(schema, derivedType, baseType, issues) {
2558
+ if (baseType.contentModel !== "simple") {
2559
+ issues.push(
2560
+ buildRestrictionIssue(
2561
+ "XSD_RESTRICTION_NOT_SUBSET",
2562
+ `SimpleContent restriction requires base type to have simple content.`,
2563
+ derivedType
2564
+ )
2565
+ );
2566
+ }
2567
+ const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
2568
+ const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
2569
+ const baseAttrMap = new Map(
2570
+ baseAttrs.filter((attr) => attr?.kind === "attribute").map((attr) => [localDeclName(attr), attr])
2571
+ );
2572
+ for (const attr of derivedAttrs) {
2573
+ if (attr?.kind !== "attribute") continue;
2574
+ const name = localDeclName(attr);
2575
+ const baseAttr = baseAttrMap.get(name);
2576
+ if (!baseAttr && !baseAttrs.some((a) => a?.kind === "anyAttribute")) {
2577
+ issues.push(
2578
+ buildRestrictionIssue(
2579
+ "XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
2580
+ `SimpleContent restricted type adds attribute '${name}' not in base type.`,
2581
+ attr
2582
+ )
2583
+ );
2584
+ }
2585
+ }
2586
+ }
2404
2587
  function runRestrictionDiagnostics(schema) {
2405
2588
  const issues = [];
2406
2589
  for (const complexType of Object.values(schema.globals.complexTypes || {})) {
@@ -2410,6 +2593,12 @@ function runRestrictionDiagnostics(schema) {
2410
2593
  if (!baseType) continue;
2411
2594
  checkRestrictedContentSubset(schema, complexType, baseType, issues);
2412
2595
  checkRestrictedAttributes(schema, complexType, baseType, issues);
2596
+ checkWildcardRestriction(schema, complexType, baseType, issues);
2597
+ if (complexType.contentModel === "complex" && baseType.contentModel === "complex") {
2598
+ checkComplexContentRestriction(schema, complexType, baseType, issues);
2599
+ } else if (complexType.contentModel === "simple" && baseType.contentModel === "simple") {
2600
+ checkSimpleContentRestriction(schema, complexType, baseType, issues);
2601
+ }
2413
2602
  }
2414
2603
  return issues;
2415
2604
  }
@@ -2736,6 +2925,130 @@ function runImportDiagnostics(schema, options = {}) {
2736
2925
  return issues;
2737
2926
  }
2738
2927
 
2928
+ // src/diagnostics/schemaWildcardDiagnostics.js
2929
+ function validateWildcardNamespace(namespace, path) {
2930
+ if (!namespace) return null;
2931
+ const trimmed = namespace.trim();
2932
+ if (!trimmed) return null;
2933
+ const parts = trimmed.split(/\s+/);
2934
+ for (const part of parts) {
2935
+ if (part === "##any" || part === "##other" || part === "##targetNamespace") {
2936
+ continue;
2937
+ }
2938
+ if (!part.includes(":") && part !== "") {
2939
+ return createIssue({
2940
+ code: "INVALID_WILDCARD_NAMESPACE",
2941
+ severity: "warning",
2942
+ message: `Invalid namespace in wildcard constraint: '${part}'. Expected ##any, ##other, ##targetNamespace, or a valid namespace URI.`,
2943
+ path
2944
+ });
2945
+ }
2946
+ }
2947
+ return null;
2948
+ }
2949
+ function validateProcessContents(processContents, path) {
2950
+ if (!processContents) return null;
2951
+ const trimmed = processContents.trim();
2952
+ if (trimmed === "strict" || trimmed === "lax" || trimmed === "skip") {
2953
+ return null;
2954
+ }
2955
+ return createIssue({
2956
+ code: "INVALID_PROCESS_CONTENTS",
2957
+ severity: "error",
2958
+ message: `Invalid processContents value: '${processContents}'. Must be 'strict', 'lax', or 'skip'.`,
2959
+ path
2960
+ });
2961
+ }
2962
+ function validateSingleWildcard(wildcardNode, nodeName) {
2963
+ const issues = [];
2964
+ const nsIssue = validateWildcardNamespace(wildcardNode.namespace, wildcardNode.path);
2965
+ if (nsIssue) {
2966
+ issues.push(nsIssue);
2967
+ }
2968
+ const pcIssue = validateProcessContents(wildcardNode.processContents, wildcardNode.path);
2969
+ if (pcIssue) {
2970
+ issues.push(pcIssue);
2971
+ }
2972
+ if (wildcardNode.notNamespace && wildcardNode.notNamespace.length > 0) {
2973
+ if (wildcardNode.namespace !== "##other" && wildcardNode.namespace !== "##targetNamespace") {
2974
+ issues.push(
2975
+ createIssue({
2976
+ code: "INVALID_NOT_NAMESPACE_USAGE",
2977
+ severity: "warning",
2978
+ message: `notNamespace is only meaningful with ##other or ##targetNamespace namespace constraint.`,
2979
+ path: wildcardNode.path
2980
+ })
2981
+ );
2982
+ }
2983
+ }
2984
+ if (wildcardNode.notQName && wildcardNode.notQName.length > 0) {
2985
+ for (const qname of wildcardNode.notQName) {
2986
+ if (!qname || qname.trim() === "") {
2987
+ issues.push(
2988
+ createIssue({
2989
+ code: "INVALID_NOT_QNAME",
2990
+ severity: "warning",
2991
+ message: `Empty QName in notQName constraint.`,
2992
+ path: wildcardNode.path
2993
+ })
2994
+ );
2995
+ break;
2996
+ }
2997
+ }
2998
+ }
2999
+ return issues;
3000
+ }
3001
+ function findWildcardsInContent(node, wildcards) {
3002
+ if (!node) return;
3003
+ if (node.kind === "any" || node.kind === "anyAttribute") {
3004
+ wildcards.push(node);
3005
+ return;
3006
+ }
3007
+ if (node.children && Array.isArray(node.children)) {
3008
+ for (const child of node.children) {
3009
+ findWildcardsInContent(child, wildcards);
3010
+ }
3011
+ }
3012
+ }
3013
+ function findWildcardsInAttributes(attributes, wildcards) {
3014
+ if (!attributes || !Array.isArray(attributes)) return;
3015
+ for (const attr of attributes) {
3016
+ if (attr.kind === "anyAttribute") {
3017
+ wildcards.push(attr);
3018
+ }
3019
+ }
3020
+ }
3021
+ function runWildcardDiagnostics(schema) {
3022
+ const issues = [];
3023
+ const wildcards = [];
3024
+ for (const elem of Object.values(schema.globals.elements || {})) {
3025
+ if (elem.inlineType?.content) {
3026
+ findWildcardsInContent(elem.inlineType.content, wildcards);
3027
+ }
3028
+ if (elem.inlineType?.attributes) {
3029
+ findWildcardsInAttributes(elem.inlineType.attributes, wildcards);
3030
+ }
3031
+ }
3032
+ for (const complexType of Object.values(schema.globals.complexTypes || {})) {
3033
+ if (complexType.content) {
3034
+ findWildcardsInContent(complexType.content, wildcards);
3035
+ }
3036
+ if (complexType.attributes) {
3037
+ findWildcardsInAttributes(complexType.attributes, wildcards);
3038
+ }
3039
+ }
3040
+ for (const group of Object.values(schema.globals.groups || {})) {
3041
+ if (group.content) {
3042
+ findWildcardsInContent(group.content, wildcards);
3043
+ }
3044
+ }
3045
+ for (const wildcard of wildcards) {
3046
+ const wildcardIssues = validateSingleWildcard(wildcard, wildcard.kind);
3047
+ issues.push(...wildcardIssues);
3048
+ }
3049
+ return issues;
3050
+ }
3051
+
2739
3052
  // src/diagnostics/schemaDiagnostics.js
2740
3053
  function buildStats(schema) {
2741
3054
  return {
@@ -2910,6 +3223,8 @@ function runSchemaDiagnostics(schema, options = {}) {
2910
3223
  const identityIssues = runIdentityConstraintDiagnostics(schema);
2911
3224
  issues.push(...identityIssues);
2912
3225
  emitUnsupportedFeatureWarnings(schema, issues, options);
3226
+ const wildcardIssues = runWildcardDiagnostics(schema);
3227
+ issues.push(...wildcardIssues);
2913
3228
  const facetIssues = runFacetDiagnostics(schema, options);
2914
3229
  issues.push(...facetIssues);
2915
3230
  const restrictionIssues = runRestrictionDiagnostics(schema);
@@ -2930,7 +3245,7 @@ function runSchemaDiagnostics(schema, options = {}) {
2930
3245
  }
2931
3246
 
2932
3247
  // src/version.js
2933
- var ENGINE_VERSION = "v0.2.0";
3248
+ var ENGINE_VERSION = "v0.2.1";
2934
3249
 
2935
3250
  // src/utils/result.js
2936
3251
  function summarizeIssues(issues = []) {
@@ -3818,6 +4133,24 @@ function buildNodesFromContent(schema, contentNode, options, state) {
3818
4133
  function buildComplexTypeContent(schema, complexTypeDecl, options, state) {
3819
4134
  const content = getEffectiveContent(schema, complexTypeDecl);
3820
4135
  const attributes = getEffectiveAttributes(schema, complexTypeDecl);
4136
+ if (state.currentDepth >= options.maxDepth) {
4137
+ return {
4138
+ attributes: buildAttributesObject(schema, attributes, options, state),
4139
+ children: []
4140
+ };
4141
+ }
4142
+ const typeKey = complexTypeDecl.name || complexTypeDecl.qName;
4143
+ if (typeKey && state.visitedTypes.has(typeKey)) {
4144
+ return {
4145
+ attributes: buildAttributesObject(schema, attributes, options, state),
4146
+ children: []
4147
+ };
4148
+ }
4149
+ if (typeKey) {
4150
+ state.visitedTypes.add(typeKey);
4151
+ }
4152
+ const previousDepth = state.currentDepth;
4153
+ state.currentDepth += 1;
3821
4154
  let children = content ? buildNodesFromContent(schema, content, options, state) : [];
3822
4155
  if (options.mode === "minimal" && children.length === 0 && content) {
3823
4156
  children = buildRepresentativeNodesFromContent(
@@ -3827,6 +4160,10 @@ function buildComplexTypeContent(schema, complexTypeDecl, options, state) {
3827
4160
  state
3828
4161
  );
3829
4162
  }
4163
+ state.currentDepth = previousDepth;
4164
+ if (typeKey) {
4165
+ state.visitedTypes.delete(typeKey);
4166
+ }
3830
4167
  return {
3831
4168
  attributes: buildAttributesObject(schema, attributes, options, state),
3832
4169
  children
@@ -3905,7 +4242,10 @@ function selectRoot(schema, options = {}) {
3905
4242
  function generateXmlFromSchema(schema, options = {}, helpers = {}) {
3906
4243
  const normalizedOptions = {
3907
4244
  mode: options.mode === "full" ? "full" : "minimal",
3908
- includeOptionalAttributes: options.includeOptionalAttributes === true
4245
+ includeOptionalAttributes: options.includeOptionalAttributes === true,
4246
+ maxDepth: options.maxDepth ?? 3,
4247
+ maxChoiceBranches: options.maxChoiceBranches ?? 1,
4248
+ expandRepeatingElements: options.expandRepeatingElements ?? 2
3909
4249
  };
3910
4250
  const root = selectRoot(schema, options);
3911
4251
  if (!root) {
@@ -3918,7 +4258,9 @@ function generateXmlFromSchema(schema, options = {}, helpers = {}) {
3918
4258
  const state = {
3919
4259
  resolveAttributeGroup: helpers.resolveAttributeGroup,
3920
4260
  targetPrefix: options.targetPrefix || "tns",
3921
- nsContext
4261
+ nsContext,
4262
+ visitedTypes: /* @__PURE__ */ new Set(),
4263
+ currentDepth: 0
3922
4264
  };
3923
4265
  const [rootNode] = buildElementInstances(
3924
4266
  schema,
@@ -4021,6 +4363,80 @@ function generateSampleXml({ xsdText, options = {} } = {}) {
4021
4363
  });
4022
4364
  }
4023
4365
 
4366
+ // src/validation/wildcardValidator.js
4367
+ function namespaceMatches(elementNamespace, wildcardNamespace, targetNamespace) {
4368
+ if (!wildcardNamespace) return true;
4369
+ if (wildcardNamespace === "##any") return true;
4370
+ if (wildcardNamespace === "##targetNamespace") {
4371
+ return elementNamespace === targetNamespace;
4372
+ }
4373
+ if (wildcardNamespace === "##other") {
4374
+ return elementNamespace !== targetNamespace;
4375
+ }
4376
+ if (Array.isArray(wildcardNamespace)) {
4377
+ return wildcardNamespace.includes(elementNamespace);
4378
+ }
4379
+ return elementNamespace === wildcardNamespace;
4380
+ }
4381
+ function isExcludedByNotNamespace(elementNamespace, notNamespace) {
4382
+ if (!notNamespace || notNamespace.length === 0) return false;
4383
+ return notNamespace.includes(elementNamespace);
4384
+ }
4385
+ function isExcludedByNotQName(qName, notQName) {
4386
+ if (!notQName || notQName.length === 0) return false;
4387
+ return notQName.includes(qName);
4388
+ }
4389
+ function buildQName(localName4, namespaceUri4) {
4390
+ if (!namespaceUri4 || namespaceUri4 === "") {
4391
+ return localName4;
4392
+ }
4393
+ return `{${namespaceUri4}}${localName4}`;
4394
+ }
4395
+ function elementMatchesWildcard(elementLocalName, elementNamespace, wildcardNode, targetNamespace) {
4396
+ if (!wildcardNode || wildcardNode.kind !== "any") {
4397
+ return false;
4398
+ }
4399
+ if (!namespaceMatches(elementNamespace, wildcardNode.namespace, targetNamespace)) {
4400
+ return false;
4401
+ }
4402
+ if (isExcludedByNotNamespace(elementNamespace, wildcardNode.notNamespace)) {
4403
+ return false;
4404
+ }
4405
+ const qName = buildQName(elementLocalName, elementNamespace);
4406
+ if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
4407
+ return false;
4408
+ }
4409
+ return true;
4410
+ }
4411
+ function attributeMatchesWildcard(attrLocalName, attrNamespace, wildcardNode, targetNamespace) {
4412
+ if (!wildcardNode || wildcardNode.kind !== "anyAttribute") {
4413
+ return false;
4414
+ }
4415
+ if (!namespaceMatches(attrNamespace, wildcardNode.namespace, targetNamespace)) {
4416
+ return false;
4417
+ }
4418
+ if (isExcludedByNotNamespace(attrNamespace, wildcardNode.notNamespace)) {
4419
+ return false;
4420
+ }
4421
+ const qName = buildQName(attrLocalName, attrNamespace);
4422
+ if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
4423
+ return false;
4424
+ }
4425
+ return true;
4426
+ }
4427
+ function normalizeProcessContents(processContents) {
4428
+ if (processContents === "lax" || processContents === "skip") {
4429
+ return processContents;
4430
+ }
4431
+ return "strict";
4432
+ }
4433
+ function isStrictWildcardValidation(processContents) {
4434
+ return normalizeProcessContents(processContents) === "strict";
4435
+ }
4436
+ function shouldSkipWildcardValidation(processContents) {
4437
+ return normalizeProcessContents(processContents) === "skip";
4438
+ }
4439
+
4024
4440
  // src/validation/structureValidator.js
4025
4441
  function elementChildren2(xmlNode) {
4026
4442
  return Array.from(xmlNode?.children || []).filter((child) => child.nodeType === 1);
@@ -4090,6 +4506,7 @@ function isSimpleContentComplexType(complexTypeDecl) {
4090
4506
  function validateAttributes(xmlNode, attributes, context) {
4091
4507
  const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts, validateAttributeValue: validateAttributeValue2 } = context;
4092
4508
  const allowed = /* @__PURE__ */ new Map();
4509
+ let anyAttributeWildcard = null;
4093
4510
  for (const attr of attributes || []) {
4094
4511
  if (!attr) continue;
4095
4512
  if (attr.kind === "attribute") {
@@ -4101,6 +4518,8 @@ function validateAttributes(xmlNode, attributes, context) {
4101
4518
  const group = context.resolveAttributeGroup?.(attr.refName);
4102
4519
  if (!group) continue;
4103
4520
  validateAttributes(xmlNode, group.attributes || [], context);
4521
+ } else if (attr.kind === "anyAttribute") {
4522
+ anyAttributeWildcard = attr;
4104
4523
  }
4105
4524
  }
4106
4525
  for (const attrDecl of allowed.values()) {
@@ -4146,6 +4565,15 @@ function validateAttributes(xmlNode, attributes, context) {
4146
4565
  continue;
4147
4566
  }
4148
4567
  if (!allowed.has(attr.name)) {
4568
+ if (anyAttributeWildcard) {
4569
+ const attrLocalName = attr.localName || attr.name.split(":")[1] || attr.name;
4570
+ const attrNamespace = attr.namespaceURI || null;
4571
+ if (attributeMatchesWildcard(attrLocalName, attrNamespace, anyAttributeWildcard, schema.targetNamespace)) {
4572
+ if (!shouldSkipWildcardValidation(anyAttributeWildcard.processContents)) {
4573
+ }
4574
+ continue;
4575
+ }
4576
+ }
4149
4577
  issues.push(
4150
4578
  createIssue2({
4151
4579
  code: ISSUE_CODES2.XML_UNEXPECTED_ATTRIBUTE,
@@ -4563,7 +4991,16 @@ function validateContentModel(children, modelNode, context, pathParts, startInde
4563
4991
  return validateAll(children, startIndex, modelNode, context, pathParts, silent);
4564
4992
  case "any":
4565
4993
  if (startIndex < children.length) {
4566
- return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
4994
+ const childNode = children[startIndex];
4995
+ const childLocalName = localName(childNode);
4996
+ const childNamespace = namespaceUri(childNode);
4997
+ if (elementMatchesWildcard(childLocalName, childNamespace, modelNode, context.schema.targetNamespace)) {
4998
+ if (isStrictWildcardValidation(modelNode.processContents)) {
4999
+ validateElementDecl(childNode, { name: childLocalName, typeName: null }, context, [...pathParts, childLocalName]);
5000
+ } else if (!shouldSkipWildcardValidation(modelNode.processContents)) {
5001
+ }
5002
+ return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
5003
+ }
4567
5004
  }
4568
5005
  return { nextIndex: startIndex, matched: true, matchedAny: false };
4569
5006
  default: