Started working on documentation
This commit is contained in:
parent
e8c30e8a05
commit
aacaaee493
@ -4,6 +4,10 @@ using XSDVisualiser.Core;
|
||||
|
||||
namespace XSDVisualiser.Desktop.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// View model exposing the parsed schema for binding in the main window.
|
||||
/// Provides selection state and information about the currently loaded XSD file.
|
||||
/// </summary>
|
||||
public class MainWindowViewModel(SchemaModel model) : INotifyPropertyChanged
|
||||
{
|
||||
private string? _currentFilePath;
|
||||
@ -11,6 +15,10 @@ public class MainWindowViewModel(SchemaModel model) : INotifyPropertyChanged
|
||||
private SchemaNode? _selectedNode;
|
||||
private SchemaNode? _selectedRootElement;
|
||||
|
||||
/// <summary>
|
||||
/// Parsed schema model currently displayed by the UI.
|
||||
/// Setting this property updates dependent properties and notifies bindings.
|
||||
/// </summary>
|
||||
public SchemaModel Model
|
||||
{
|
||||
get => _model;
|
||||
@ -24,8 +32,14 @@ public class MainWindowViewModel(SchemaModel model) : INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All global elements defined in the loaded schema.
|
||||
/// </summary>
|
||||
public IEnumerable<SchemaNode> RootElements => _model?.RootElements ?? Enumerable.Empty<SchemaNode>();
|
||||
|
||||
/// <summary>
|
||||
/// If set, filters the view to show only this root element and its subtree.
|
||||
/// </summary>
|
||||
public SchemaNode? SelectedRootElement
|
||||
{
|
||||
get => _selectedRootElement;
|
||||
|
||||
@ -15,6 +15,10 @@ using XSDVisualiser.Desktop.ViewModels;
|
||||
|
||||
namespace XSDVisualiser.Desktop.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Left-side tree view control that displays parsed XSD schema nodes and provides actions
|
||||
/// such as copy-as-TSV, validate against XML, and export sample XML.
|
||||
/// </summary>
|
||||
public partial class LeftTreeView : UserControl
|
||||
{
|
||||
public LeftTreeView()
|
||||
@ -24,7 +28,6 @@ public partial class LeftTreeView : UserControl
|
||||
|
||||
private async void OnCopyAsTsvClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
// Determine the node from the menu item's DataContext
|
||||
var node = (sender as MenuItem)?.DataContext as SchemaNode;
|
||||
if (node == null)
|
||||
node =
|
||||
@ -40,7 +43,6 @@ public partial class LeftTreeView : UserControl
|
||||
|
||||
private async void OnValidateAgainstXmlClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
// Resolve node from context
|
||||
var node = (sender as MenuItem)?.DataContext as SchemaNode;
|
||||
if (node == null)
|
||||
node = (sender as Control)?.GetVisualAncestors().OfType<Control>().FirstOrDefault()?.DataContext as SchemaNode;
|
||||
@ -96,7 +98,6 @@ public partial class LeftTreeView : UserControl
|
||||
private static string BuildTsv(SchemaNode root)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
// Header
|
||||
sb.AppendLine(
|
||||
"Depth\tPath\tName\tNamespace\tTypeName\tBuiltInType\tMinOccurs\tMaxOccurs\tContentModel\tConstraints\tIsNillable");
|
||||
var initialPath = root.Name ?? string.Empty;
|
||||
@ -146,7 +147,6 @@ public partial class LeftTreeView : UserControl
|
||||
|
||||
private static async Task<string?> TryGetLocalPathAsync(IStorageFile file)
|
||||
{
|
||||
// Avalonia provides TryGetLocalPath extension for local files; otherwise, we can't access it via System.IO API.
|
||||
return file.TryGetLocalPath();
|
||||
}
|
||||
|
||||
@ -183,10 +183,8 @@ public partial class LeftTreeView : UserControl
|
||||
}
|
||||
};
|
||||
|
||||
// Compose content
|
||||
if (dialog.Content is Grid grid)
|
||||
{
|
||||
// Use a read-only TextBox so users can select text easily
|
||||
var textBox = new TextBox
|
||||
{
|
||||
Text = text,
|
||||
@ -198,7 +196,6 @@ public partial class LeftTreeView : UserControl
|
||||
|
||||
var scroller = new ScrollViewer { Content = textBox };
|
||||
|
||||
// Copy button
|
||||
var copyButton = new Button
|
||||
{
|
||||
Content = "Copy",
|
||||
@ -212,7 +209,6 @@ public partial class LeftTreeView : UserControl
|
||||
if (topLevel?.Clipboard != null)
|
||||
{
|
||||
await topLevel.Clipboard.SetTextAsync(text);
|
||||
// Provide lightweight feedback by changing content briefly
|
||||
if (copyButton.Content is string)
|
||||
copyButton.Content = "Copied";
|
||||
await Task.Delay(1000);
|
||||
|
||||
@ -7,15 +7,33 @@ namespace XSDVisualiser.Core;
|
||||
/// </summary>
|
||||
public class AttributeInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Local name of the attribute.
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Namespace URI of the attribute, if any.
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? Namespace { get; set; }
|
||||
|
||||
[XmlAttribute] public string? Use { get; set; } // optional | required | prohibited
|
||||
/// <summary>
|
||||
/// Usage of the attribute: optional | required | prohibited.
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? Use { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The qualified type name if the attribute has a named type.
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? TypeName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Built-in XML Schema type code name when applicable.
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? BuiltInType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional constraints applied to the attribute's simple type.
|
||||
/// </summary>
|
||||
[XmlElement] public ConstraintSet? Constraints { get; set; }
|
||||
}
|
||||
@ -7,9 +7,14 @@ namespace XSDVisualiser.Core;
|
||||
/// </summary>
|
||||
public class ConstraintSet
|
||||
{
|
||||
/// <summary>
|
||||
/// The qualified name of the base type this constraint set applies to, if any.
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? BaseTypeName { get; set; }
|
||||
|
||||
// Generic catch-all list of constraints for dynamic display and tooling
|
||||
/// <summary>
|
||||
/// A catch-all list of constraint entries for dynamic display and tooling.
|
||||
/// </summary>
|
||||
[XmlArray("Constraints")]
|
||||
[XmlArrayItem("Constraint")]
|
||||
public List<ConstraintEntry> Constraints { get; set; } = new();
|
||||
|
||||
@ -29,7 +29,10 @@ public class SchemaNode
|
||||
[XmlArrayItem("Element")]
|
||||
public List<SchemaNode> Children { get; set; } = new();
|
||||
|
||||
[XmlAttribute] public string? ContentModel { get; set; } // sequence | choice | all | simple
|
||||
/// <summary>
|
||||
/// Content model for this node: sequence | choice | all | simple. For synthetic group nodes, may be "group".
|
||||
/// </summary>
|
||||
[XmlAttribute] public string? ContentModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable documentation extracted from xsd:annotation/xsd:documentation.
|
||||
@ -38,14 +41,13 @@ public class SchemaNode
|
||||
[XmlElement]
|
||||
public string? Documentation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a human-readable name for UI elements (prefers Name, then TypeName).
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
// Used by AutoCompleteBox to get text for filtering and matching
|
||||
// Prefer Name, then TypeName, and fall back to base implementation
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
return Name!;
|
||||
if (!string.IsNullOrEmpty(TypeName))
|
||||
return TypeName!;
|
||||
if (!string.IsNullOrEmpty(Name)) return Name!;
|
||||
if (!string.IsNullOrEmpty(TypeName)) return TypeName!;
|
||||
return base.ToString();
|
||||
}
|
||||
}
|
||||
@ -4,10 +4,18 @@ using System.Xml.Schema;
|
||||
|
||||
namespace XSDVisualiser.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Parses XML Schema (XSD) into a simplified model for visualization and tooling.
|
||||
/// </summary>
|
||||
public class XsdSchemaParser
|
||||
{
|
||||
private readonly XmlSchemaSet _set = new();
|
||||
|
||||
/// <summary>
|
||||
/// Reads and compiles the provided XSD file into a schema set, then produces a simplified schema model.
|
||||
/// </summary>
|
||||
/// <param name="xsdPath">Path to the XSD file.</param>
|
||||
/// <returns>A populated <see cref="SchemaModel"/> representing global elements and their structures.</returns>
|
||||
public SchemaModel Parse(string xsdPath)
|
||||
{
|
||||
_set.XmlResolver = new XmlUrlResolver();
|
||||
@ -34,8 +42,7 @@ public class XsdSchemaParser
|
||||
|
||||
private void ValidationCallback(object? sender, ValidationEventArgs e)
|
||||
{
|
||||
// For now, we do not throw; we capture compiled info best-effort.
|
||||
// Console.Error.WriteLine($"[XSD Validation {e.Severity}] {e.Message}");
|
||||
// Intentionally no-op: schema is parsed best-effort without throwing on compile warnings/errors.
|
||||
}
|
||||
|
||||
private SchemaNode BuildNodeForElement(XmlSchemaElement element, string? parentContentModel)
|
||||
|
||||
@ -11,12 +11,29 @@ namespace XSDVisualiser.Core;
|
||||
/// </summary>
|
||||
public static class XmlValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates an XML document against the global element specified by name and optional namespace
|
||||
/// from the XSD located at <paramref name="xsdPath"/>.
|
||||
/// </summary>
|
||||
/// <param name="xsdPath">Path to the XSD file containing the target element/type definitions.</param>
|
||||
/// <param name="elementName">The local name of the global element to validate against.</param>
|
||||
/// <param name="elementNamespace">The namespace URI of the element; may be null to auto-detect.</param>
|
||||
/// <param name="xmlPath">Path to the XML file to validate.</param>
|
||||
/// <returns>Aggregated validation result with errors/warnings and diagnostics.</returns>
|
||||
public static XmlValidationResult ValidateAgainstElement(string xsdPath, string elementName, string? elementNamespace, string xmlPath)
|
||||
{
|
||||
var set = BuildSchemaSet(xsdPath);
|
||||
return ValidateAgainstElement(set, elementName, elementNamespace, xmlPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates an XML document against a specific global element within an already built <see cref="XmlSchemaSet"/>.
|
||||
/// </summary>
|
||||
/// <param name="schemas">Compiled schema set to use for validation.</param>
|
||||
/// <param name="elementName">The local name of the global element to validate against.</param>
|
||||
/// <param name="elementNamespace">The namespace URI of the element; may be null to auto-detect.</param>
|
||||
/// <param name="xmlPath">Path to the XML file to validate.</param>
|
||||
/// <returns>Aggregated validation result with errors/warnings and diagnostics.</returns>
|
||||
public static XmlValidationResult ValidateAgainstElement(XmlSchemaSet schemas, string elementName, string? elementNamespace, string xmlPath)
|
||||
{
|
||||
var result = new XmlValidationResult();
|
||||
@ -428,15 +445,31 @@ public static class XmlValidator
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggregates XML validation outcomes, including errors, warnings, and overall validity.
|
||||
/// </summary>
|
||||
public sealed class XmlValidationResult
|
||||
{
|
||||
private readonly List<XmlValidationIssue> _issues = new();
|
||||
|
||||
/// <summary>
|
||||
/// True if no validation errors have been recorded.
|
||||
/// </summary>
|
||||
public bool IsValid => _issues.TrueForAll(i => i.Severity != XmlSeverityType.Error);
|
||||
|
||||
/// <summary>
|
||||
/// All recorded validation issues (errors and warnings) in chronological order.
|
||||
/// </summary>
|
||||
public IReadOnlyList<XmlValidationIssue> Issues => _issues;
|
||||
|
||||
/// <summary>
|
||||
/// All recorded validation errors.
|
||||
/// </summary>
|
||||
public IEnumerable<XmlValidationIssue> Errors => _issues.Where(i => i.Severity == XmlSeverityType.Error);
|
||||
|
||||
/// <summary>
|
||||
/// All recorded validation warnings.
|
||||
/// </summary>
|
||||
public IEnumerable<XmlValidationIssue> Warnings => _issues.Where(i => i.Severity == XmlSeverityType.Warning);
|
||||
|
||||
internal void AddError(string message, int? line = null, int? position = null) =>
|
||||
@ -446,6 +479,13 @@ public sealed class XmlValidationResult
|
||||
_issues.Add(new XmlValidationIssue(XmlSeverityType.Warning, message, line ?? 0, position ?? 0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single validation issue (error or warning) with optional location information.
|
||||
/// </summary>
|
||||
/// <param name="Severity">Issue severity (Error or Warning).</param>
|
||||
/// <param name="Message">Human-readable description of the issue.</param>
|
||||
/// <param name="LineNumber">Line number in the XML where the issue occurred, if available.</param>
|
||||
/// <param name="LinePosition">Column position in the XML where the issue occurred, if available.</param>
|
||||
public sealed record XmlValidationIssue(XmlSeverityType Severity, string Message, int LineNumber, int LinePosition);
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user