Added documentation to the view

This commit is contained in:
Frederik Jacobsen 2025-10-18 21:37:44 +02:00
parent e442e1c89a
commit c4b26fd2a0
3 changed files with 74 additions and 0 deletions

View File

@ -39,6 +39,14 @@
</Grid> </Grid>
</Border> </Border>
<!-- Documentation -->
<StackPanel IsVisible="{Binding Documentation, Converter={x:Static ObjectConverters.IsNotNull}}">
<TextBlock Text="Documentation" FontWeight="SemiBold"/>
<Border BorderBrush="{DynamicResource PanelBorderBrush}" BorderThickness="1" CornerRadius="4" Padding="10">
<TextBlock Text="{Binding Documentation}" TextWrapping="Wrap"/>
</Border>
</StackPanel>
<!-- Constraints --> <!-- Constraints -->
<StackPanel> <StackPanel>
<TextBlock Text="Constraints" FontWeight="SemiBold"/> <TextBlock Text="Constraints" FontWeight="SemiBold"/>

View File

@ -55,6 +55,13 @@ namespace XSDVisualiser.Models
[XmlAttribute] [XmlAttribute]
public string? ContentModel { get; set; } // sequence | choice | all | simple public string? ContentModel { get; set; } // sequence | choice | all | simple
/// <summary>
/// Human-readable documentation extracted from xsd:annotation/xsd:documentation.
/// Prefer element-level documentation; falls back to type-level documentation.
/// </summary>
[XmlElement]
public string? Documentation { get; set; }
public override string ToString() public override string ToString()
{ {
// Used by AutoCompleteBox to get text for filtering and matching // Used by AutoCompleteBox to get text for filtering and matching

View File

@ -1,5 +1,6 @@
using System.Xml; using System.Xml;
using System.Xml.Schema; using System.Xml.Schema;
using System.Text;
using XSDVisualiser.Models; using XSDVisualiser.Models;
namespace XSDVisualiser.Core namespace XSDVisualiser.Core
@ -54,6 +55,9 @@ namespace XSDVisualiser.Core
ContentModel = parentContentModel ContentModel = parentContentModel
}; };
// Prefer element-level documentation
node.Documentation = ExtractDocumentation(element);
var type = ResolveElementType(element); var type = ResolveElementType(element);
if (type == null) return node; if (type == null) return node;
node.TypeName = GetQualifiedTypeName(type); node.TypeName = GetQualifiedTypeName(type);
@ -62,6 +66,20 @@ namespace XSDVisualiser.Core
node.BuiltInType = type.Datatype.TypeCode.ToString(); node.BuiltInType = type.Datatype.TypeCode.ToString();
} }
// Fallback to type-level documentation if none on element
if (string.IsNullOrWhiteSpace(node.Documentation))
{
switch (type)
{
case XmlSchemaComplexType ctDoc:
node.Documentation = ExtractDocumentation(ctDoc);
break;
case XmlSchemaSimpleType stDoc:
node.Documentation = ExtractDocumentation(stDoc);
break;
}
}
switch (type) switch (type)
{ {
case XmlSchemaComplexType ct: case XmlSchemaComplexType ct:
@ -413,5 +431,46 @@ namespace XSDVisualiser.Core
} }
} }
} }
private static string? ExtractDocumentation(XmlSchemaAnnotated? annotated)
{
if (annotated?.Annotation == null) return null;
var sb = new StringBuilder();
foreach (var item in annotated.Annotation.Items)
{
if (item is not XmlSchemaDocumentation doc) continue;
if (doc.Markup is { Length: > 0 })
{
var pieceBuilder = new StringBuilder();
foreach (var node in doc.Markup)
{
try
{
var text = node?.InnerText;
if (!string.IsNullOrWhiteSpace(text))
{
pieceBuilder.Append(text);
}
}
catch
{
// ignore malformed nodes
}
}
var piece = pieceBuilder.ToString().Trim();
if (string.IsNullOrWhiteSpace(piece)) continue;
if (sb.Length > 0) sb.AppendLine().AppendLine();
sb.Append(piece);
}
else if (!string.IsNullOrWhiteSpace(doc.Source))
{
// If there is a source but no markup, skip; we only render text.
}
}
return sb.Length == 0 ? null : sb.ToString();
}
} }
} }