Did some cleanup of the UI and code
This commit is contained in:
parent
8fd2b05b4d
commit
14bad15f4a
@ -9,14 +9,12 @@ namespace XSDVisualiser.Desktop.Converters
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Occurs occ)
|
||||
{
|
||||
if (value is not Occurs occ) return null;
|
||||
|
||||
var min = occ.Min;
|
||||
var max = occ.MaxIsUnbounded ? "*" : occ.Max.ToString(culture);
|
||||
return $"[{min}..{max}]";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
</DockPanel>
|
||||
|
||||
<!-- Body: left tree | splitter | right details -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,Auto,1.6*" RowDefinitions="*">
|
||||
<Grid Grid.Row="1" ColumnDefinitions="2*,Auto,*" RowDefinitions="*">
|
||||
<!-- Left: Tree -->
|
||||
<Border Background="{DynamicResource PanelBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PanelBorderBrush}"
|
||||
@ -30,11 +30,8 @@
|
||||
<TreeDataTemplate DataType="{x:Type m:SchemaNode}" ItemsSource="{Binding Children}">
|
||||
<StackPanel>
|
||||
<!-- Connector line from parent to this node (hidden for roots where ContentModel is null) -->
|
||||
<Grid Margin="0,6,0,2" IsVisible="{Binding ContentModel, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Margin="0,8,8,2" IsVisible="{Binding ContentModel, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
ColumnDefinitions="16,*">
|
||||
<!-- leading small elbow -->
|
||||
<Rectangle Grid.Column="0" Width="16" Height="2" Fill="{DynamicResource SeparatorBrush}" VerticalAlignment="Center"/>
|
||||
<Grid Grid.Column="1">
|
||||
@ -50,7 +47,7 @@
|
||||
<Border CornerRadius="4"
|
||||
BorderBrush="{Binding Cardinality, Converter={StaticResource OptionalToBrush}}"
|
||||
BorderThickness="{Binding Cardinality, Converter={StaticResource OptionalToThickness}}"
|
||||
Padding="8" Margin="0,0,0,6" Background="{DynamicResource PanelBackgroundBrush}">
|
||||
Padding="8" Margin="0,0,8,6" Background="{DynamicResource PanelBackgroundBrush}">
|
||||
<StackPanel Orientation="Vertical" Spacing="2">
|
||||
<!-- Name on its own line, prominent -->
|
||||
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"/>
|
||||
@ -69,7 +66,7 @@
|
||||
|
||||
<!-- Optional: show content model as a subtle hint -->
|
||||
<TextBlock Text="{Binding ContentModel, StringFormat=Model: {0}}"
|
||||
Foreground="{DynamicResource MutedTextBrush}"/>
|
||||
Foreground="{DynamicResource SubtleTextBrush}" FontWeight="SemiBold"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
@ -95,116 +92,31 @@
|
||||
|
||||
<!-- General info -->
|
||||
<Border BorderBrush="{DynamicResource PanelBorderBrush}" BorderThickness="1" CornerRadius="4" Padding="10">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
<TextBlock Text="Name:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Margin="8,0,0,0" Text="{Binding Name}"/>
|
||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Name:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Margin="8,0,0,0" Text="{Binding Name}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Text="Type:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" Margin="8,0,0,0" Text="{Binding TypeName}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Built-in:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Margin="8,0,0,0" Text="{Binding BuiltInType}" FontWeight="Bold"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Text="Built-in:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="2" Margin="8,0,0,0" Text="{Binding BuiltInType}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Model:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Margin="8,0,0,0" Text="{Binding ContentModel}"/>
|
||||
|
||||
<TextBlock Grid.Row="3" Text="Namespace:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="3" Margin="8,0,0,0" Text="{Binding Namespace}"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Namespace:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Margin="8,0,0,0" Text="{Binding Namespace}"/>
|
||||
|
||||
<TextBlock Grid.Row="4" Text="Cardinality:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="4" Margin="8,0,0,0" Text="{Binding Cardinality, Converter={StaticResource CardinalityToLabel}}"/>
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Cardinality:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Margin="8,0,0,0" Text="{Binding Cardinality, Converter={StaticResource CardinalityToLabel}}"/>
|
||||
|
||||
<TextBlock Grid.Column="2" Text="Model:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="3" Margin="8,0,0,0" Text="{Binding ContentModel}"/>
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Text="Nillable:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="5" Grid.Column="1" Margin="8,0,0,0" Text="{Binding IsNillable}"/>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="Type:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Row="6" Grid.Column="1" Margin="8,0,0,0" Text="{Binding TypeName}"/>
|
||||
|
||||
<TextBlock Grid.Row="5" Text="Nillable:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="5" Margin="8,0,0,0" Text="{Binding IsNillable}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Attributes -->
|
||||
<StackPanel>
|
||||
<TextBlock Text="Attributes" FontWeight="SemiBold"/>
|
||||
<ItemsControl ItemsSource="{Binding Attributes}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="m:AttributeInfo">
|
||||
<Border BorderBrush="{DynamicResource PanelBorderBrush}" BorderThickness="1" CornerRadius="4" Padding="8" Margin="0,6,0,0">
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto,*" RowDefinitions="Auto,Auto,Auto">
|
||||
<TextBlock Text="Name:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Margin="8,0,0,0" Text="{Binding Name}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Text="Use:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" Margin="8,0,0,0" Text="{Binding Use}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Text="Type:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="2" Margin="8,0,0,0" Text="{Binding TypeName}"/>
|
||||
|
||||
<TextBlock Grid.Column="2" Text="Built-in:" FontWeight="Bold"/>
|
||||
<TextBlock Grid.Column="3" Margin="8,0,0,0" Text="{Binding BuiltInType}"/>
|
||||
</Grid>
|
||||
|
||||
<StackPanel IsVisible="{Binding Constraints, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Constraints" FontWeight="SemiBold"/>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Enumerations" FontWeight="SemiBold"/>
|
||||
<ItemsControl ItemsSource="{Binding Constraints.Enumerations}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="x:String">
|
||||
<TextBlock Text="{Binding ., StringFormat=• {0}}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Patterns" FontWeight="SemiBold"/>
|
||||
<ItemsControl ItemsSource="{Binding Constraints.Patterns}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="x:String">
|
||||
<TextBlock Text="{Binding ., StringFormat=• {0}}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
<StackPanel IsVisible="{Binding Constraints.Numeric, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Numeric bounds" FontWeight="SemiBold"/>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Numeric.MinInclusive, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Min inclusive:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Numeric.MinInclusive}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Numeric.MaxInclusive, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Max inclusive:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Numeric.MaxInclusive}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Numeric.MinExclusive, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Min exclusive:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Numeric.MinExclusive}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Numeric.MaxExclusive, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Max exclusive:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Numeric.MaxExclusive}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel IsVisible="{Binding Constraints.Length, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="Length bounds" FontWeight="SemiBold"/>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Length.LengthSpecified}">
|
||||
<TextBlock Text="Length:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Length.Length}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Length.MinLengthSpecified}">
|
||||
<TextBlock Text="Min length:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Length.MinLength}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding Constraints.Length.MaxLengthSpecified}">
|
||||
<TextBlock Text="Max length:" FontWeight="Bold"/>
|
||||
<TextBlock Margin="8,0,0,0" Text="{Binding Constraints.Length.MaxLength}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Constraints -->
|
||||
<StackPanel>
|
||||
<TextBlock Text="Constraints" FontWeight="SemiBold"/>
|
||||
|
||||
@ -3,8 +3,8 @@ using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using XSDVisualiser.Core;
|
||||
using XSDVisualiser.Models;
|
||||
using XSDVisualiser.Parsing;
|
||||
|
||||
namespace XSDVisualiser.Desktop
|
||||
{
|
||||
|
||||
@ -12,7 +12,7 @@ namespace XSDVisualiser.Desktop
|
||||
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp() =>
|
||||
private static AppBuilder BuildAvaloniaApp() =>
|
||||
AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.LogToTrace()
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using XSDVisualiser.Models;
|
||||
|
||||
namespace XSDVisualiser.Parsing
|
||||
namespace XSDVisualiser.Core
|
||||
{
|
||||
public class XsdSchemaParser
|
||||
{
|
||||
@ -16,16 +13,16 @@ namespace XSDVisualiser.Parsing
|
||||
_set.XmlResolver = new XmlUrlResolver();
|
||||
using var reader = XmlReader.Create(xsdPath, new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore });
|
||||
var schema = XmlSchema.Read(reader, ValidationCallback);
|
||||
_set.Add(schema);
|
||||
_set.Add(schema!);
|
||||
_set.CompilationSettings = new XmlSchemaCompilationSettings { EnableUpaCheck = true };
|
||||
_set.Compile();
|
||||
|
||||
var model = new SchemaModel
|
||||
{
|
||||
TargetNamespace = schema.TargetNamespace
|
||||
TargetNamespace = schema!.TargetNamespace
|
||||
};
|
||||
|
||||
foreach (XmlSchemaElement globalEl in _set.Schemas().Cast<XmlSchema>()
|
||||
foreach (var globalEl in _set.Schemas().Cast<XmlSchema>()
|
||||
.SelectMany(s => s.Elements.Values.Cast<XmlSchemaElement>()))
|
||||
{
|
||||
var node = BuildNodeForElement(globalEl, parentContentModel: null);
|
||||
@ -58,8 +55,7 @@ namespace XSDVisualiser.Parsing
|
||||
};
|
||||
|
||||
var type = ResolveElementType(element);
|
||||
if (type != null)
|
||||
{
|
||||
if (type == null) return node;
|
||||
node.TypeName = GetQualifiedTypeName(type);
|
||||
if (type.Datatype != null)
|
||||
{
|
||||
@ -76,7 +72,6 @@ namespace XSDVisualiser.Parsing
|
||||
node.Constraints = ExtractConstraints(st);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -84,7 +79,7 @@ namespace XSDVisualiser.Parsing
|
||||
private static string? GetQualifiedTypeName(XmlSchemaType type)
|
||||
{
|
||||
if (!type.QualifiedName.IsEmpty) return type.QualifiedName.ToString();
|
||||
return type.BaseXmlSchemaType != null && !type.BaseXmlSchemaType.QualifiedName.IsEmpty
|
||||
return type.BaseXmlSchemaType is { QualifiedName.IsEmpty: false }
|
||||
? type.BaseXmlSchemaType.QualifiedName.ToString()
|
||||
: type.Name;
|
||||
}
|
||||
@ -96,17 +91,72 @@ namespace XSDVisualiser.Parsing
|
||||
{
|
||||
return _set.GlobalTypes[el.SchemaTypeName] as XmlSchemaType;
|
||||
}
|
||||
if (el.SchemaType != null) return el.SchemaType;
|
||||
return null;
|
||||
|
||||
return el.SchemaType;
|
||||
}
|
||||
|
||||
private void HandleComplexType(SchemaNode node, XmlSchemaComplexType ct)
|
||||
{
|
||||
// Attributes
|
||||
foreach (XmlSchemaAttribute attr in ct.AttributeUses.Values.OfType<XmlSchemaAttribute>())
|
||||
// Collect attributes (ensure uniqueness)
|
||||
var seenAttrKeys = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
// 1) Compiled attribute uses (includes inherited/group attributes after Compile)
|
||||
foreach (var attr in ct.AttributeUses.Values.OfType<XmlSchemaAttribute>())
|
||||
{
|
||||
var qn = attr.QualifiedName.IsEmpty ? attr.RefName : attr.QualifiedName;
|
||||
var key = qn.ToString();
|
||||
if (seenAttrKeys.Add(key))
|
||||
{
|
||||
node.Attributes.Add(ExtractAttribute(attr));
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Uncompiled attributes directly on the type (fallback)
|
||||
foreach (var a in ct.Attributes.OfType<XmlSchemaAttribute>())
|
||||
{
|
||||
var qn = a.QualifiedName.IsEmpty ? a.RefName : a.QualifiedName;
|
||||
var key = qn.ToString();
|
||||
if (seenAttrKeys.Add(key))
|
||||
{
|
||||
node.Attributes.Add(ExtractAttribute(a));
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Attributes from complexContent extension/restriction
|
||||
if (ct.ContentModel is XmlSchemaComplexContent cc)
|
||||
{
|
||||
switch (cc.Content)
|
||||
{
|
||||
case XmlSchemaComplexContentExtension cext:
|
||||
{
|
||||
foreach (var a in cext.Attributes.OfType<XmlSchemaAttribute>())
|
||||
{
|
||||
var qn = a.QualifiedName.IsEmpty ? a.RefName : a.QualifiedName;
|
||||
var key = qn.ToString();
|
||||
if (seenAttrKeys.Add(key))
|
||||
{
|
||||
node.Attributes.Add(ExtractAttribute(a));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case XmlSchemaComplexContentRestriction cres:
|
||||
{
|
||||
foreach (var a in cres.Attributes.OfType<XmlSchemaAttribute>())
|
||||
{
|
||||
var qn = a.QualifiedName.IsEmpty ? a.RefName : a.QualifiedName;
|
||||
var key = qn.ToString();
|
||||
if (seenAttrKeys.Add(key))
|
||||
{
|
||||
node.Attributes.Add(ExtractAttribute(a));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Content model
|
||||
if (ct.ContentTypeParticle is XmlSchemaGroupBase group)
|
||||
@ -158,7 +208,9 @@ namespace XSDVisualiser.Parsing
|
||||
else if (ct.ContentType == XmlSchemaContentType.TextOnly && ct.ContentModel is XmlSchemaSimpleContent simpleContent)
|
||||
{
|
||||
node.ContentModel = "simple";
|
||||
if (simpleContent.Content is XmlSchemaSimpleContentExtension ext)
|
||||
switch (simpleContent.Content)
|
||||
{
|
||||
case XmlSchemaSimpleContentExtension ext:
|
||||
{
|
||||
var baseType = ResolveType(ext.BaseTypeName);
|
||||
if (baseType is XmlSchemaSimpleType st)
|
||||
@ -168,12 +220,19 @@ namespace XSDVisualiser.Parsing
|
||||
node.BuiltInType ??= st.Datatype?.TypeCode.ToString();
|
||||
}
|
||||
|
||||
foreach (XmlSchemaAttribute attr in ext.Attributes.OfType<XmlSchemaAttribute>())
|
||||
foreach (var attr in ext.Attributes.OfType<XmlSchemaAttribute>())
|
||||
{
|
||||
var qn = attr.QualifiedName.IsEmpty ? attr.RefName : attr.QualifiedName;
|
||||
var key = qn.ToString();
|
||||
if (seenAttrKeys.Add(key))
|
||||
{
|
||||
node.Attributes.Add(ExtractAttribute(attr));
|
||||
}
|
||||
}
|
||||
else if (simpleContent.Content is XmlSchemaSimpleContentRestriction res)
|
||||
|
||||
break;
|
||||
}
|
||||
case XmlSchemaSimpleContentRestriction res:
|
||||
{
|
||||
var baseType = ResolveType(res.BaseTypeName);
|
||||
if (baseType is XmlSchemaSimpleType st)
|
||||
@ -184,6 +243,9 @@ namespace XSDVisualiser.Parsing
|
||||
node.TypeName ??= GetQualifiedTypeName(st);
|
||||
node.BuiltInType ??= st.Datatype?.TypeCode.ToString();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,12 +270,10 @@ namespace XSDVisualiser.Parsing
|
||||
else if (!attr.SchemaTypeName.IsEmpty) st = ResolveType(attr.SchemaTypeName) as XmlSchemaSimpleType;
|
||||
else if (attr.SchemaType != null) st = attr.SchemaType;
|
||||
|
||||
if (st != null)
|
||||
{
|
||||
if (st == null) return info;
|
||||
info.TypeName = GetQualifiedTypeName(st);
|
||||
info.BuiltInType = st.Datatype?.TypeCode.ToString();
|
||||
info.Constraints = ExtractConstraints(st);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
@ -225,11 +285,12 @@ namespace XSDVisualiser.Parsing
|
||||
BaseTypeName = GetQualifiedTypeName(st.BaseXmlSchemaType)
|
||||
};
|
||||
|
||||
if (st.Content is XmlSchemaSimpleTypeRestriction restr)
|
||||
switch (st.Content)
|
||||
{
|
||||
case XmlSchemaSimpleTypeRestriction restr:
|
||||
MergeFacets(cons, restr.Facets);
|
||||
}
|
||||
else if (st.Content is XmlSchemaSimpleTypeList list)
|
||||
break;
|
||||
case XmlSchemaSimpleTypeList list:
|
||||
{
|
||||
cons.Patterns.Add("(list)");
|
||||
if (!list.ItemTypeName.IsEmpty)
|
||||
@ -241,18 +302,23 @@ namespace XSDVisualiser.Parsing
|
||||
Merge(cons, sub);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (st.Content is XmlSchemaSimpleTypeUnion union)
|
||||
case XmlSchemaSimpleTypeUnion union:
|
||||
{
|
||||
cons.Patterns.Add("(union)");
|
||||
foreach (var memberType in union.BaseMemberTypes)
|
||||
{
|
||||
if (memberType is XmlSchemaSimpleType mst)
|
||||
if (memberType is { } mst)
|
||||
{
|
||||
var sub = ExtractConstraints(mst);
|
||||
Merge(cons, sub);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cons;
|
||||
@ -261,8 +327,8 @@ namespace XSDVisualiser.Parsing
|
||||
private static void Merge(ConstraintSet target, ConstraintSet? source)
|
||||
{
|
||||
if (source == null) return;
|
||||
foreach (var e in source.Enumerations) if (!target.Enumerations.Contains(e)) target.Enumerations.Add(e);
|
||||
foreach (var p in source.Patterns) if (!target.Patterns.Contains(p)) target.Patterns.Add(p);
|
||||
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);
|
||||
if (source.Numeric != null)
|
||||
{
|
||||
target.Numeric ??= new NumericBounds();
|
||||
@ -271,8 +337,9 @@ namespace XSDVisualiser.Parsing
|
||||
target.Numeric.MinExclusive ??= source.Numeric.MinExclusive;
|
||||
target.Numeric.MaxExclusive ??= source.Numeric.MaxExclusive;
|
||||
}
|
||||
if (source.Length != null)
|
||||
{
|
||||
|
||||
if (source.Length == null) return;
|
||||
|
||||
target.Length ??= new LengthBounds();
|
||||
if (source.Length.LengthSpecified && !target.Length.LengthSpecified)
|
||||
{
|
||||
@ -284,13 +351,12 @@ namespace XSDVisualiser.Parsing
|
||||
target.Length.MinLength = source.Length.MinLength;
|
||||
target.Length.MinLengthSpecified = true;
|
||||
}
|
||||
if (source.Length.MaxLengthSpecified && !target.Length.MaxLengthSpecified)
|
||||
{
|
||||
|
||||
if (!source.Length.MaxLengthSpecified || target.Length.MaxLengthSpecified) return;
|
||||
|
||||
target.Length.MaxLength = source.Length.MaxLength;
|
||||
target.Length.MaxLengthSpecified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void MergeFacets(ConstraintSet cons, XmlSchemaObjectCollection facets)
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using XSDVisualiser.Parsing;
|
||||
using XSDVisualiser.Core;
|
||||
using XSDVisualiser.Utils;
|
||||
|
||||
/*
|
||||
@ -80,6 +80,8 @@ catch (Exception ex)
|
||||
Environment.Exit(3);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
static void PrintHelp()
|
||||
{
|
||||
Console.WriteLine("XSDVisualiser - Parse an XSD and emit a structural model with types, constraints, and cardinality");
|
||||
|
||||
@ -8,6 +8,12 @@ namespace XSDVisualiser.Utils
|
||||
{
|
||||
public static class Serialization
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
|
||||
};
|
||||
|
||||
public static string ToXml<T>(T obj)
|
||||
{
|
||||
var serializer = new XmlSerializer(typeof(T));
|
||||
@ -20,12 +26,7 @@ namespace XSDVisualiser.Utils
|
||||
|
||||
public static string ToJson<T>(T obj)
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
|
||||
};
|
||||
return JsonSerializer.Serialize(obj, options);
|
||||
return JsonSerializer.Serialize(obj, JsonOptions);
|
||||
}
|
||||
|
||||
private sealed class Utf8StringWriter : StringWriter
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user