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
  */
@@ -96,6 +96,8 @@ var UssXsdEngine = (() => {
96
96
  XML_KEY_NULL_VIOLATION: "XML_KEY_NULL_VIOLATION",
97
97
  XML_KEYREF_VIOLATION: "XML_KEYREF_VIOLATION",
98
98
  XML_UNIQUE_VIOLATION: "XML_UNIQUE_VIOLATION",
99
+ XML_ANY_STRICT_VALIDATION_FAILED: "XML_ANY_STRICT_VALIDATION_FAILED",
100
+ XML_ANYATTRIBUTE_STRICT_VALIDATION_FAILED: "XML_ANYATTRIBUTE_STRICT_VALIDATION_FAILED",
99
101
  XML_PATTERN_MISMATCH: "XML_PATTERN_MISMATCH",
100
102
  XML_LENGTH_MISMATCH: "XML_LENGTH_MISMATCH",
101
103
  XML_MIN_LENGTH_VIOLATION: "XML_MIN_LENGTH_VIOLATION",
@@ -122,6 +124,9 @@ var UssXsdEngine = (() => {
122
124
  XSD_RESTRICTION_NOT_SUBSET: "XSD_RESTRICTION_NOT_SUBSET",
123
125
  XSD_RESTRICTION_OCCURS_WIDENED: "XSD_RESTRICTION_OCCURS_WIDENED",
124
126
  XSD_RESTRICTION_ATTRIBUTE_WIDENED: "XSD_RESTRICTION_ATTRIBUTE_WIDENED",
127
+ XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE: "XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
128
+ XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE: "XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
129
+ XSD_RESTRICTION_WILDCARD_INCOMPATIBLE: "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
125
130
  XSD_INCLUDE_NOT_PROVIDED: "XSD_INCLUDE_NOT_PROVIDED",
126
131
  XSD_IMPORT_NOT_PROVIDED: "XSD_IMPORT_NOT_PROVIDED",
127
132
  XSD_INCLUDE_NAMESPACE_MISMATCH: "XSD_INCLUDE_NAMESPACE_MISMATCH",
@@ -507,9 +512,11 @@ var UssXsdEngine = (() => {
507
512
  }
508
513
  function createAnyNode({
509
514
  namespace = null,
510
- processContents = null,
515
+ processContents = "strict",
511
516
  minOccurs = 1,
512
517
  maxOccurs = 1,
518
+ notNamespace = [],
519
+ notQName = [],
513
520
  line = null,
514
521
  column = null,
515
522
  path = null
@@ -517,9 +524,31 @@ var UssXsdEngine = (() => {
517
524
  return {
518
525
  kind: "any",
519
526
  namespace,
520
- processContents,
527
+ processContents: processContents || "strict",
521
528
  minOccurs,
522
529
  maxOccurs,
530
+ notNamespace,
531
+ notQName,
532
+ line,
533
+ column,
534
+ path
535
+ };
536
+ }
537
+ function createAnyAttributeNode({
538
+ namespace = null,
539
+ processContents = "strict",
540
+ notNamespace = [],
541
+ notQName = [],
542
+ line = null,
543
+ column = null,
544
+ path = null
545
+ } = {}) {
546
+ return {
547
+ kind: "anyAttribute",
548
+ namespace,
549
+ processContents: processContents || "strict",
550
+ notNamespace,
551
+ notQName,
523
552
  line,
524
553
  column,
525
554
  path
@@ -844,8 +873,6 @@ var UssXsdEngine = (() => {
844
873
 
845
874
  // src/parser/buildSchemaModel.js
846
875
  var UNSUPPORTED_NODE_FEATURES = /* @__PURE__ */ new Set([
847
- "any",
848
- "anyAttribute",
849
876
  "redefine",
850
877
  "notation"
851
878
  ]);
@@ -1280,6 +1307,10 @@ var UssXsdEngine = (() => {
1280
1307
  issues
1281
1308
  )
1282
1309
  );
1310
+ } else if (child.localName === "anyAttribute") {
1311
+ attributes.push(
1312
+ parseAnyAttribute(child, xsdText, lineStarts, parentPath, schema, issues)
1313
+ );
1283
1314
  }
1284
1315
  }
1285
1316
  return attributes;
@@ -1363,15 +1394,58 @@ var UssXsdEngine = (() => {
1363
1394
  path
1364
1395
  });
1365
1396
  }
1397
+ function parseWildcardNamespace(namespaceStr) {
1398
+ if (!namespaceStr) return null;
1399
+ const trimmed = namespaceStr.trim();
1400
+ if (!trimmed) return null;
1401
+ if (trimmed.includes(" ")) {
1402
+ return trimmed.split(/\s+/).filter((ns) => ns);
1403
+ }
1404
+ return trimmed;
1405
+ }
1406
+ function parseNotNamespace(notNamespaceStr) {
1407
+ if (!notNamespaceStr) return [];
1408
+ const trimmed = notNamespaceStr.trim();
1409
+ if (!trimmed) return [];
1410
+ if (trimmed.includes(" ")) {
1411
+ return trimmed.split(/\s+/).filter((ns) => ns);
1412
+ }
1413
+ return [trimmed];
1414
+ }
1415
+ function parseNotQName(notQNameStr) {
1416
+ if (!notQNameStr) return [];
1417
+ const trimmed = notQNameStr.trim();
1418
+ if (!trimmed) return [];
1419
+ if (trimmed.includes(" ")) {
1420
+ return trimmed.split(/\s+/).filter((qn) => qn);
1421
+ }
1422
+ return [trimmed];
1423
+ }
1366
1424
  function parseAny(node, xsdText, lineStarts, parentPath, schema, issues) {
1367
1425
  const path = buildPath(parentPath, node);
1368
1426
  const loc = locateNodeInSource(xsdText, lineStarts, node);
1369
1427
  collectNodeDiagnostics(schema, issues, node, path, loc);
1370
1428
  return createAnyNode({
1371
- namespace: node.getAttribute("namespace"),
1429
+ namespace: parseWildcardNamespace(node.getAttribute("namespace")),
1372
1430
  processContents: node.getAttribute("processContents"),
1373
1431
  minOccurs: normalizeOccurs(node.getAttribute("minOccurs"), 1),
1374
1432
  maxOccurs: normalizeOccurs(node.getAttribute("maxOccurs"), 1),
1433
+ notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
1434
+ notQName: parseNotQName(node.getAttribute("notQName")),
1435
+ line: loc.line,
1436
+ column: loc.column,
1437
+ path
1438
+ });
1439
+ }
1440
+ function parseAnyAttribute(node, xsdText, lineStarts, parentPath, schema, issues) {
1441
+ const path = buildPath(parentPath, node);
1442
+ const loc = locateNodeInSource(xsdText, lineStarts, node);
1443
+ collectNodeDiagnostics(schema, issues, node, path, loc);
1444
+ return createAnyAttributeNode({
1445
+ namespace: parseWildcardNamespace(node.getAttribute("namespace")),
1446
+ processContents: node.getAttribute("processContents"),
1447
+ notNamespace: parseNotNamespace(node.getAttribute("notNamespace")),
1448
+ notQName: parseNotQName(node.getAttribute("notQName")),
1375
1449
  line: loc.line,
1376
1450
  column: loc.column,
1377
1451
  path
@@ -1794,24 +1868,24 @@ var UssXsdEngine = (() => {
1794
1868
  }
1795
1869
  }
1796
1870
  if (ref?.kind === "import" && ref.namespace) {
1797
- const namespaceMatches = entries.filter((entry) => {
1871
+ const namespaceMatches2 = entries.filter((entry) => {
1798
1872
  const declaredTargetNamespace = getDeclaredTargetNamespaceFromText(
1799
1873
  entry.text
1800
1874
  );
1801
1875
  return (declaredTargetNamespace || null) === (ref.namespace || null);
1802
1876
  });
1803
- if (namespaceMatches.length === 1) {
1877
+ if (namespaceMatches2.length === 1) {
1804
1878
  return {
1805
1879
  kind: "namespace",
1806
- entry: namespaceMatches[0],
1807
- matches: namespaceMatches
1880
+ entry: namespaceMatches2[0],
1881
+ matches: namespaceMatches2
1808
1882
  };
1809
1883
  }
1810
- if (namespaceMatches.length > 1) {
1884
+ if (namespaceMatches2.length > 1) {
1811
1885
  return {
1812
1886
  kind: "ambiguous-namespace",
1813
1887
  entry: null,
1814
- matches: namespaceMatches
1888
+ matches: namespaceMatches2
1815
1889
  };
1816
1890
  }
1817
1891
  }
@@ -2428,6 +2502,115 @@ var UssXsdEngine = (() => {
2428
2502
  }
2429
2503
  }
2430
2504
  }
2505
+ function checkWildcardRestriction(schema, derivedType, baseType, issues) {
2506
+ const derivedContent = getEffectiveContent(schema, derivedType);
2507
+ const baseContent = getEffectiveContent(schema, baseType);
2508
+ const derivedWildcards = [];
2509
+ const baseWildcards = [];
2510
+ function collectWildcards(node, arr) {
2511
+ if (!node) return;
2512
+ if (node.kind === "any") {
2513
+ arr.push(node);
2514
+ return;
2515
+ }
2516
+ if (node.children) {
2517
+ for (const child of asArray(node.children)) {
2518
+ collectWildcards(child, arr);
2519
+ }
2520
+ }
2521
+ }
2522
+ collectWildcards(derivedContent, derivedWildcards);
2523
+ collectWildcards(baseContent, baseWildcards);
2524
+ if (derivedWildcards.length > 0 && baseWildcards.length === 0) {
2525
+ issues.push(
2526
+ buildRestrictionIssue(
2527
+ "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
2528
+ `Restricted type introduces wildcard elements that base type does not have.`,
2529
+ derivedType
2530
+ )
2531
+ );
2532
+ }
2533
+ const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
2534
+ const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
2535
+ const derivedHasAnyAttribute = derivedAttrs.some((a) => a?.kind === "anyAttribute");
2536
+ const baseHasAnyAttribute = baseAttrs.some((a) => a?.kind === "anyAttribute");
2537
+ if (derivedHasAnyAttribute && !baseHasAnyAttribute) {
2538
+ issues.push(
2539
+ buildRestrictionIssue(
2540
+ "XSD_RESTRICTION_WILDCARD_INCOMPATIBLE",
2541
+ `Restricted type introduces anyAttribute that base type does not have.`,
2542
+ derivedType
2543
+ )
2544
+ );
2545
+ }
2546
+ }
2547
+ function checkOccurrenceCompatibility(derived, base, name) {
2548
+ const dMin = typeof derived.minOccurs === "number" ? derived.minOccurs : 1;
2549
+ const bMin = typeof base.minOccurs === "number" ? base.minOccurs : 1;
2550
+ const dMax = maxToNumber(derived.maxOccurs ?? 1);
2551
+ const bMax = maxToNumber(base.maxOccurs ?? 1);
2552
+ return dMin >= bMin && dMax <= bMax;
2553
+ }
2554
+ function checkComplexContentRestriction(schema, derivedType, baseType, issues) {
2555
+ const derivedContent = getEffectiveContent(schema, derivedType);
2556
+ const baseContent = getEffectiveContent(schema, baseType);
2557
+ if (!derivedContent || !baseContent) return;
2558
+ const derivedFlat = flattenContent(derivedContent, []);
2559
+ const baseFlat = flattenContent(baseContent, []);
2560
+ const baseMap = new Map(baseFlat.map((item) => [item.name, item]));
2561
+ for (const item of derivedFlat) {
2562
+ const baseItem = baseMap.get(item.name);
2563
+ if (!baseItem) {
2564
+ issues.push(
2565
+ buildRestrictionIssue(
2566
+ "XSD_RESTRICTION_NOT_SUBSET",
2567
+ `Restricted type contains element '${item.name}' not in base type.`,
2568
+ item
2569
+ )
2570
+ );
2571
+ continue;
2572
+ }
2573
+ if (!checkOccurrenceCompatibility(item, baseItem, item.name)) {
2574
+ issues.push(
2575
+ buildRestrictionIssue(
2576
+ "XSD_RESTRICTION_OCCURRENCE_INCOMPATIBLE",
2577
+ `Restricted type has incompatible occurrence constraints for '${item.name}'.`,
2578
+ item
2579
+ )
2580
+ );
2581
+ }
2582
+ }
2583
+ }
2584
+ function checkSimpleContentRestriction(schema, derivedType, baseType, issues) {
2585
+ if (baseType.contentModel !== "simple") {
2586
+ issues.push(
2587
+ buildRestrictionIssue(
2588
+ "XSD_RESTRICTION_NOT_SUBSET",
2589
+ `SimpleContent restriction requires base type to have simple content.`,
2590
+ derivedType
2591
+ )
2592
+ );
2593
+ }
2594
+ const derivedAttrs = asArray(getEffectiveAttributes(schema, derivedType));
2595
+ const baseAttrs = asArray(getEffectiveAttributes(schema, baseType));
2596
+ const baseAttrMap = new Map(
2597
+ baseAttrs.filter((attr) => attr?.kind === "attribute").map((attr) => [localDeclName(attr), attr])
2598
+ );
2599
+ for (const attr of derivedAttrs) {
2600
+ if (attr?.kind !== "attribute") continue;
2601
+ const name = localDeclName(attr);
2602
+ const baseAttr = baseAttrMap.get(name);
2603
+ if (!baseAttr && !baseAttrs.some((a) => a?.kind === "anyAttribute")) {
2604
+ issues.push(
2605
+ buildRestrictionIssue(
2606
+ "XSD_RESTRICTION_ATTRIBUTE_INCOMPATIBLE",
2607
+ `SimpleContent restricted type adds attribute '${name}' not in base type.`,
2608
+ attr
2609
+ )
2610
+ );
2611
+ }
2612
+ }
2613
+ }
2431
2614
  function runRestrictionDiagnostics(schema) {
2432
2615
  const issues = [];
2433
2616
  for (const complexType of Object.values(schema.globals.complexTypes || {})) {
@@ -2437,6 +2620,12 @@ var UssXsdEngine = (() => {
2437
2620
  if (!baseType) continue;
2438
2621
  checkRestrictedContentSubset(schema, complexType, baseType, issues);
2439
2622
  checkRestrictedAttributes(schema, complexType, baseType, issues);
2623
+ checkWildcardRestriction(schema, complexType, baseType, issues);
2624
+ if (complexType.contentModel === "complex" && baseType.contentModel === "complex") {
2625
+ checkComplexContentRestriction(schema, complexType, baseType, issues);
2626
+ } else if (complexType.contentModel === "simple" && baseType.contentModel === "simple") {
2627
+ checkSimpleContentRestriction(schema, complexType, baseType, issues);
2628
+ }
2440
2629
  }
2441
2630
  return issues;
2442
2631
  }
@@ -2763,6 +2952,130 @@ var UssXsdEngine = (() => {
2763
2952
  return issues;
2764
2953
  }
2765
2954
 
2955
+ // src/diagnostics/schemaWildcardDiagnostics.js
2956
+ function validateWildcardNamespace(namespace, path) {
2957
+ if (!namespace) return null;
2958
+ const trimmed = namespace.trim();
2959
+ if (!trimmed) return null;
2960
+ const parts = trimmed.split(/\s+/);
2961
+ for (const part of parts) {
2962
+ if (part === "##any" || part === "##other" || part === "##targetNamespace") {
2963
+ continue;
2964
+ }
2965
+ if (!part.includes(":") && part !== "") {
2966
+ return createIssue({
2967
+ code: "INVALID_WILDCARD_NAMESPACE",
2968
+ severity: "warning",
2969
+ message: `Invalid namespace in wildcard constraint: '${part}'. Expected ##any, ##other, ##targetNamespace, or a valid namespace URI.`,
2970
+ path
2971
+ });
2972
+ }
2973
+ }
2974
+ return null;
2975
+ }
2976
+ function validateProcessContents(processContents, path) {
2977
+ if (!processContents) return null;
2978
+ const trimmed = processContents.trim();
2979
+ if (trimmed === "strict" || trimmed === "lax" || trimmed === "skip") {
2980
+ return null;
2981
+ }
2982
+ return createIssue({
2983
+ code: "INVALID_PROCESS_CONTENTS",
2984
+ severity: "error",
2985
+ message: `Invalid processContents value: '${processContents}'. Must be 'strict', 'lax', or 'skip'.`,
2986
+ path
2987
+ });
2988
+ }
2989
+ function validateSingleWildcard(wildcardNode, nodeName) {
2990
+ const issues = [];
2991
+ const nsIssue = validateWildcardNamespace(wildcardNode.namespace, wildcardNode.path);
2992
+ if (nsIssue) {
2993
+ issues.push(nsIssue);
2994
+ }
2995
+ const pcIssue = validateProcessContents(wildcardNode.processContents, wildcardNode.path);
2996
+ if (pcIssue) {
2997
+ issues.push(pcIssue);
2998
+ }
2999
+ if (wildcardNode.notNamespace && wildcardNode.notNamespace.length > 0) {
3000
+ if (wildcardNode.namespace !== "##other" && wildcardNode.namespace !== "##targetNamespace") {
3001
+ issues.push(
3002
+ createIssue({
3003
+ code: "INVALID_NOT_NAMESPACE_USAGE",
3004
+ severity: "warning",
3005
+ message: `notNamespace is only meaningful with ##other or ##targetNamespace namespace constraint.`,
3006
+ path: wildcardNode.path
3007
+ })
3008
+ );
3009
+ }
3010
+ }
3011
+ if (wildcardNode.notQName && wildcardNode.notQName.length > 0) {
3012
+ for (const qname of wildcardNode.notQName) {
3013
+ if (!qname || qname.trim() === "") {
3014
+ issues.push(
3015
+ createIssue({
3016
+ code: "INVALID_NOT_QNAME",
3017
+ severity: "warning",
3018
+ message: `Empty QName in notQName constraint.`,
3019
+ path: wildcardNode.path
3020
+ })
3021
+ );
3022
+ break;
3023
+ }
3024
+ }
3025
+ }
3026
+ return issues;
3027
+ }
3028
+ function findWildcardsInContent(node, wildcards) {
3029
+ if (!node) return;
3030
+ if (node.kind === "any" || node.kind === "anyAttribute") {
3031
+ wildcards.push(node);
3032
+ return;
3033
+ }
3034
+ if (node.children && Array.isArray(node.children)) {
3035
+ for (const child of node.children) {
3036
+ findWildcardsInContent(child, wildcards);
3037
+ }
3038
+ }
3039
+ }
3040
+ function findWildcardsInAttributes(attributes, wildcards) {
3041
+ if (!attributes || !Array.isArray(attributes)) return;
3042
+ for (const attr of attributes) {
3043
+ if (attr.kind === "anyAttribute") {
3044
+ wildcards.push(attr);
3045
+ }
3046
+ }
3047
+ }
3048
+ function runWildcardDiagnostics(schema) {
3049
+ const issues = [];
3050
+ const wildcards = [];
3051
+ for (const elem of Object.values(schema.globals.elements || {})) {
3052
+ if (elem.inlineType?.content) {
3053
+ findWildcardsInContent(elem.inlineType.content, wildcards);
3054
+ }
3055
+ if (elem.inlineType?.attributes) {
3056
+ findWildcardsInAttributes(elem.inlineType.attributes, wildcards);
3057
+ }
3058
+ }
3059
+ for (const complexType of Object.values(schema.globals.complexTypes || {})) {
3060
+ if (complexType.content) {
3061
+ findWildcardsInContent(complexType.content, wildcards);
3062
+ }
3063
+ if (complexType.attributes) {
3064
+ findWildcardsInAttributes(complexType.attributes, wildcards);
3065
+ }
3066
+ }
3067
+ for (const group of Object.values(schema.globals.groups || {})) {
3068
+ if (group.content) {
3069
+ findWildcardsInContent(group.content, wildcards);
3070
+ }
3071
+ }
3072
+ for (const wildcard of wildcards) {
3073
+ const wildcardIssues = validateSingleWildcard(wildcard, wildcard.kind);
3074
+ issues.push(...wildcardIssues);
3075
+ }
3076
+ return issues;
3077
+ }
3078
+
2766
3079
  // src/diagnostics/schemaDiagnostics.js
2767
3080
  function buildStats(schema) {
2768
3081
  return {
@@ -2937,6 +3250,8 @@ var UssXsdEngine = (() => {
2937
3250
  const identityIssues = runIdentityConstraintDiagnostics(schema);
2938
3251
  issues.push(...identityIssues);
2939
3252
  emitUnsupportedFeatureWarnings(schema, issues, options);
3253
+ const wildcardIssues = runWildcardDiagnostics(schema);
3254
+ issues.push(...wildcardIssues);
2940
3255
  const facetIssues = runFacetDiagnostics(schema, options);
2941
3256
  issues.push(...facetIssues);
2942
3257
  const restrictionIssues = runRestrictionDiagnostics(schema);
@@ -2957,7 +3272,7 @@ var UssXsdEngine = (() => {
2957
3272
  }
2958
3273
 
2959
3274
  // src/version.js
2960
- var ENGINE_VERSION = "v0.2.0";
3275
+ var ENGINE_VERSION = "v0.2.1";
2961
3276
 
2962
3277
  // src/utils/result.js
2963
3278
  function summarizeIssues(issues = []) {
@@ -3845,6 +4160,24 @@ var UssXsdEngine = (() => {
3845
4160
  function buildComplexTypeContent(schema, complexTypeDecl, options, state) {
3846
4161
  const content = getEffectiveContent(schema, complexTypeDecl);
3847
4162
  const attributes = getEffectiveAttributes(schema, complexTypeDecl);
4163
+ if (state.currentDepth >= options.maxDepth) {
4164
+ return {
4165
+ attributes: buildAttributesObject(schema, attributes, options, state),
4166
+ children: []
4167
+ };
4168
+ }
4169
+ const typeKey = complexTypeDecl.name || complexTypeDecl.qName;
4170
+ if (typeKey && state.visitedTypes.has(typeKey)) {
4171
+ return {
4172
+ attributes: buildAttributesObject(schema, attributes, options, state),
4173
+ children: []
4174
+ };
4175
+ }
4176
+ if (typeKey) {
4177
+ state.visitedTypes.add(typeKey);
4178
+ }
4179
+ const previousDepth = state.currentDepth;
4180
+ state.currentDepth += 1;
3848
4181
  let children = content ? buildNodesFromContent(schema, content, options, state) : [];
3849
4182
  if (options.mode === "minimal" && children.length === 0 && content) {
3850
4183
  children = buildRepresentativeNodesFromContent(
@@ -3854,6 +4187,10 @@ var UssXsdEngine = (() => {
3854
4187
  state
3855
4188
  );
3856
4189
  }
4190
+ state.currentDepth = previousDepth;
4191
+ if (typeKey) {
4192
+ state.visitedTypes.delete(typeKey);
4193
+ }
3857
4194
  return {
3858
4195
  attributes: buildAttributesObject(schema, attributes, options, state),
3859
4196
  children
@@ -3932,7 +4269,10 @@ var UssXsdEngine = (() => {
3932
4269
  function generateXmlFromSchema(schema, options = {}, helpers = {}) {
3933
4270
  const normalizedOptions = {
3934
4271
  mode: options.mode === "full" ? "full" : "minimal",
3935
- includeOptionalAttributes: options.includeOptionalAttributes === true
4272
+ includeOptionalAttributes: options.includeOptionalAttributes === true,
4273
+ maxDepth: options.maxDepth ?? 3,
4274
+ maxChoiceBranches: options.maxChoiceBranches ?? 1,
4275
+ expandRepeatingElements: options.expandRepeatingElements ?? 2
3936
4276
  };
3937
4277
  const root = selectRoot(schema, options);
3938
4278
  if (!root) {
@@ -3945,7 +4285,9 @@ var UssXsdEngine = (() => {
3945
4285
  const state = {
3946
4286
  resolveAttributeGroup: helpers.resolveAttributeGroup,
3947
4287
  targetPrefix: options.targetPrefix || "tns",
3948
- nsContext
4288
+ nsContext,
4289
+ visitedTypes: /* @__PURE__ */ new Set(),
4290
+ currentDepth: 0
3949
4291
  };
3950
4292
  const [rootNode] = buildElementInstances(
3951
4293
  schema,
@@ -4048,6 +4390,80 @@ ${writeNode(rootNode, 0)}`;
4048
4390
  });
4049
4391
  }
4050
4392
 
4393
+ // src/validation/wildcardValidator.js
4394
+ function namespaceMatches(elementNamespace, wildcardNamespace, targetNamespace) {
4395
+ if (!wildcardNamespace) return true;
4396
+ if (wildcardNamespace === "##any") return true;
4397
+ if (wildcardNamespace === "##targetNamespace") {
4398
+ return elementNamespace === targetNamespace;
4399
+ }
4400
+ if (wildcardNamespace === "##other") {
4401
+ return elementNamespace !== targetNamespace;
4402
+ }
4403
+ if (Array.isArray(wildcardNamespace)) {
4404
+ return wildcardNamespace.includes(elementNamespace);
4405
+ }
4406
+ return elementNamespace === wildcardNamespace;
4407
+ }
4408
+ function isExcludedByNotNamespace(elementNamespace, notNamespace) {
4409
+ if (!notNamespace || notNamespace.length === 0) return false;
4410
+ return notNamespace.includes(elementNamespace);
4411
+ }
4412
+ function isExcludedByNotQName(qName, notQName) {
4413
+ if (!notQName || notQName.length === 0) return false;
4414
+ return notQName.includes(qName);
4415
+ }
4416
+ function buildQName(localName4, namespaceUri4) {
4417
+ if (!namespaceUri4 || namespaceUri4 === "") {
4418
+ return localName4;
4419
+ }
4420
+ return `{${namespaceUri4}}${localName4}`;
4421
+ }
4422
+ function elementMatchesWildcard(elementLocalName, elementNamespace, wildcardNode, targetNamespace) {
4423
+ if (!wildcardNode || wildcardNode.kind !== "any") {
4424
+ return false;
4425
+ }
4426
+ if (!namespaceMatches(elementNamespace, wildcardNode.namespace, targetNamespace)) {
4427
+ return false;
4428
+ }
4429
+ if (isExcludedByNotNamespace(elementNamespace, wildcardNode.notNamespace)) {
4430
+ return false;
4431
+ }
4432
+ const qName = buildQName(elementLocalName, elementNamespace);
4433
+ if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
4434
+ return false;
4435
+ }
4436
+ return true;
4437
+ }
4438
+ function attributeMatchesWildcard(attrLocalName, attrNamespace, wildcardNode, targetNamespace) {
4439
+ if (!wildcardNode || wildcardNode.kind !== "anyAttribute") {
4440
+ return false;
4441
+ }
4442
+ if (!namespaceMatches(attrNamespace, wildcardNode.namespace, targetNamespace)) {
4443
+ return false;
4444
+ }
4445
+ if (isExcludedByNotNamespace(attrNamespace, wildcardNode.notNamespace)) {
4446
+ return false;
4447
+ }
4448
+ const qName = buildQName(attrLocalName, attrNamespace);
4449
+ if (isExcludedByNotQName(qName, wildcardNode.notQName)) {
4450
+ return false;
4451
+ }
4452
+ return true;
4453
+ }
4454
+ function normalizeProcessContents(processContents) {
4455
+ if (processContents === "lax" || processContents === "skip") {
4456
+ return processContents;
4457
+ }
4458
+ return "strict";
4459
+ }
4460
+ function isStrictWildcardValidation(processContents) {
4461
+ return normalizeProcessContents(processContents) === "strict";
4462
+ }
4463
+ function shouldSkipWildcardValidation(processContents) {
4464
+ return normalizeProcessContents(processContents) === "skip";
4465
+ }
4466
+
4051
4467
  // src/validation/structureValidator.js
4052
4468
  function elementChildren2(xmlNode) {
4053
4469
  return Array.from(xmlNode?.children || []).filter((child) => child.nodeType === 1);
@@ -4117,6 +4533,7 @@ ${writeNode(rootNode, 0)}`;
4117
4533
  function validateAttributes(xmlNode, attributes, context) {
4118
4534
  const { schema, createIssue: createIssue2, ISSUE_CODES: ISSUE_CODES2, issues, pathParts, validateAttributeValue: validateAttributeValue2 } = context;
4119
4535
  const allowed = /* @__PURE__ */ new Map();
4536
+ let anyAttributeWildcard = null;
4120
4537
  for (const attr of attributes || []) {
4121
4538
  if (!attr) continue;
4122
4539
  if (attr.kind === "attribute") {
@@ -4128,6 +4545,8 @@ ${writeNode(rootNode, 0)}`;
4128
4545
  const group = context.resolveAttributeGroup?.(attr.refName);
4129
4546
  if (!group) continue;
4130
4547
  validateAttributes(xmlNode, group.attributes || [], context);
4548
+ } else if (attr.kind === "anyAttribute") {
4549
+ anyAttributeWildcard = attr;
4131
4550
  }
4132
4551
  }
4133
4552
  for (const attrDecl of allowed.values()) {
@@ -4173,6 +4592,15 @@ ${writeNode(rootNode, 0)}`;
4173
4592
  continue;
4174
4593
  }
4175
4594
  if (!allowed.has(attr.name)) {
4595
+ if (anyAttributeWildcard) {
4596
+ const attrLocalName = attr.localName || attr.name.split(":")[1] || attr.name;
4597
+ const attrNamespace = attr.namespaceURI || null;
4598
+ if (attributeMatchesWildcard(attrLocalName, attrNamespace, anyAttributeWildcard, schema.targetNamespace)) {
4599
+ if (!shouldSkipWildcardValidation(anyAttributeWildcard.processContents)) {
4600
+ }
4601
+ continue;
4602
+ }
4603
+ }
4176
4604
  issues.push(
4177
4605
  createIssue2({
4178
4606
  code: ISSUE_CODES2.XML_UNEXPECTED_ATTRIBUTE,
@@ -4590,7 +5018,16 @@ ${writeNode(rootNode, 0)}`;
4590
5018
  return validateAll(children, startIndex, modelNode, context, pathParts, silent);
4591
5019
  case "any":
4592
5020
  if (startIndex < children.length) {
4593
- return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
5021
+ const childNode = children[startIndex];
5022
+ const childLocalName = localName(childNode);
5023
+ const childNamespace = namespaceUri(childNode);
5024
+ if (elementMatchesWildcard(childLocalName, childNamespace, modelNode, context.schema.targetNamespace)) {
5025
+ if (isStrictWildcardValidation(modelNode.processContents)) {
5026
+ validateElementDecl(childNode, { name: childLocalName, typeName: null }, context, [...pathParts, childLocalName]);
5027
+ } else if (!shouldSkipWildcardValidation(modelNode.processContents)) {
5028
+ }
5029
+ return { nextIndex: startIndex + 1, matched: true, matchedAny: true };
5030
+ }
4594
5031
  }
4595
5032
  return { nextIndex: startIndex, matched: true, matchedAny: false };
4596
5033
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uss-xsd-engine",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Browser-first XSD engine for schema diagnostics, tree extraction, sample XML generation, and XML validation.",
5
5
  "type": "module",
6
6
  "main": "dist/uss-xsd-engine.esm.js",