diff --git a/XSDVisualiser.Desktop/Views/RightDetailsView.axaml b/XSDVisualiser.Desktop/Views/RightDetailsView.axaml index 98faab9..a2f06c1 100644 --- a/XSDVisualiser.Desktop/Views/RightDetailsView.axaml +++ b/XSDVisualiser.Desktop/Views/RightDetailsView.axaml @@ -116,6 +116,23 @@ + + + + + + + + + + + + + + + + + diff --git a/XSDVisualiser/Models/XsdSchemaModel.cs b/XSDVisualiser/Models/XsdSchemaModel.cs index bb1c322..1ffae00 100644 --- a/XSDVisualiser/Models/XsdSchemaModel.cs +++ b/XSDVisualiser/Models/XsdSchemaModel.cs @@ -137,6 +137,19 @@ namespace XSDVisualiser.Models [XmlElement] public LengthBounds? Length { get; set; } + + // Generic catch-all list of facets for dynamic display and tooling + [XmlArray("Facets")] + [XmlArrayItem("Facet")] + public List AllFacets { get; set; } = new(); + } + + public class FacetEntry + { + [XmlAttribute] + public string? Name { get; set; } + [XmlAttribute] + public string? Value { get; set; } } public class NumericBounds diff --git a/XSDVisualiser/Parsing/XsdSchemaParser.cs b/XSDVisualiser/Parsing/XsdSchemaParser.cs index a2c9a31..363aeaf 100644 --- a/XSDVisualiser/Parsing/XsdSchemaParser.cs +++ b/XSDVisualiser/Parsing/XsdSchemaParser.cs @@ -347,6 +347,24 @@ namespace XSDVisualiser.Core if (source == null) return; foreach (var e in source.Enumerations.Where(e => !target.Enumerations.Contains(e))) target.Enumerations.Add(e); foreach (var p in source.Patterns.Where(p => !target.Patterns.Contains(p))) target.Patterns.Add(p); + + // Merge generic facets + if (source.AllFacets != null) + { + foreach (var sf in source.AllFacets) + { + var exists = false; + foreach (var tf in target.AllFacets) + { + if (string.Equals(tf.Name, sf.Name, StringComparison.Ordinal) && string.Equals(tf.Value, sf.Value, StringComparison.Ordinal)) + { + exists = true; break; + } + } + if (!exists) target.AllFacets.Add(new FacetEntry { Name = sf.Name, Value = sf.Value }); + } + } + if (source.Numeric != null) { target.Numeric ??= new NumericBounds(); @@ -380,6 +398,7 @@ namespace XSDVisualiser.Core { foreach (var f in facets) { + // Map known facets to strongly-typed buckets for backward compatibility switch (f) { case XmlSchemaEnumerationFacet enumFacet: @@ -429,8 +448,41 @@ namespace XSDVisualiser.Core } break; } + + // Always capture all facets generically for dynamic display + if (f is XmlSchemaFacet baseFacet) + { + var name = GetFacetName(f); + var value = baseFacet.Value; + if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) + { + var exists = false; + foreach (var entry in cons.AllFacets) + { + if (string.Equals(entry.Name, name, StringComparison.Ordinal) && string.Equals(entry.Value, value, StringComparison.Ordinal)) + { + exists = true; break; + } + } + if (!exists) + { + cons.AllFacets.Add(new FacetEntry { Name = name, Value = value }); + } + } + } } } + + private static string GetFacetName(XmlSchemaObject facet) + { + var typeName = facet.GetType().Name; // e.g., XmlSchemaMinInclusiveFacet + if (typeName.StartsWith("XmlSchema", StringComparison.Ordinal)) + typeName = typeName.Substring("XmlSchema".Length); + if (typeName.EndsWith("Facet", StringComparison.Ordinal)) + typeName = typeName.Substring(0, typeName.Length - "Facet".Length); + if (typeName.Length == 0) return typeName; + return char.ToLowerInvariant(typeName[0]) + typeName.Substring(1); + } private static string? ExtractDocumentation(XmlSchemaAnnotated? annotated) { if (annotated?.Annotation == null) return null;