diff --git a/XmlSchemaClassGenerator.Tests/XmlTests.cs b/XmlSchemaClassGenerator.Tests/XmlTests.cs index 279b9631..4660bf32 100644 --- a/XmlSchemaClassGenerator.Tests/XmlTests.cs +++ b/XmlSchemaClassGenerator.Tests/XmlTests.cs @@ -186,40 +186,65 @@ public void TestGuid() [Fact, TestPriority(1)] [UseCulture("en-US")] - public void TestUnion() - { - var assembly = Compiler.Generate("Union", UnionPattern, new Generator - { - NamespacePrefix = "Union", - IntegerDataType = typeof(int), - MapUnionToWidestCommonType = true - }); - - Assert.NotNull(assembly); - - SharedTestFunctions.TestSamples(Output, "Union", UnionPattern); - - var snapshotType = assembly.GetType("Union.Snapshot"); - Assert.NotNull(snapshotType); - - var date = snapshotType.GetProperty("Date"); - Assert.NotNull(date); - Assert.Equal(typeof(DateTime), date.PropertyType); - - var count = snapshotType.GetProperty("Count"); - Assert.NotNull(count); - Assert.Equal(typeof(int), count.PropertyType); - - var num = snapshotType.GetProperty("Num"); - Assert.NotNull(num); - Assert.Equal(typeof(decimal), num.PropertyType); - } - - [Fact, TestPriority(1)] - [UseCulture("en-US")] - public void TestList() - { - Compiler.Generate("List", ListPattern); + public void TestUnion() + { + var assembly = Compiler.Generate("Union", UnionPattern, new Generator + { + NamespacePrefix = "Union", + IntegerDataType = typeof(int), + MapUnionToWidestCommonType = true + }); + + Assert.NotNull(assembly); + + SharedTestFunctions.TestSamples(Output, "Union", UnionPattern); + + var snapshotType = assembly.GetType("Union.Snapshot"); + Assert.NotNull(snapshotType); + + var date = snapshotType.GetProperty("Date"); + Assert.NotNull(date); + Assert.Equal(typeof(DateTime), date.PropertyType); + + var count = snapshotType.GetProperty("Count"); + Assert.NotNull(count); + Assert.Equal(typeof(int), count.PropertyType); + + var num = snapshotType.GetProperty("Num"); + Assert.NotNull(num); + Assert.Equal(typeof(decimal), num.PropertyType); + } + + [Fact, TestPriority(1)] + [UseCulture("en-US")] + public void TestSimpleContentEnum() + { + var assembly = Compiler.Generate("SimpleContentEnum", "xsd/simple/simplecontent-enum.xsd"); + + const string ns = "SimpleContentEnum.Simplecontent"; + + var enumType = assembly.GetType($"{ns}.TransConfirmationCodeTypeEnum"); + if (enumType == null) + { + var names = string.Join(", ", assembly.GetTypes().Select(t => t.FullName)); + Assert.Fail($"Enum type not found. Available types: {names}"); + } + + var type = assembly.GetType($"{ns}.TransConfirmationCodeType"); + Assert.NotNull(type); + + var baseType = assembly.GetType($"{ns}.CodeType"); + Assert.Equal(baseType, type.BaseType); + + var valueProperty = type.GetProperties().Single(p => p.PropertyType == enumType); + Assert.Equal("Value", valueProperty.Name); + } + + [Fact, TestPriority(1)] + [UseCulture("en-US")] + public void TestList() + { + Compiler.Generate("List", ListPattern); SharedTestFunctions.TestSamples(Output, "List", ListPattern); } diff --git a/XmlSchemaClassGenerator.Tests/xsd/simple/simplecontent-enum.xsd b/XmlSchemaClassGenerator.Tests/xsd/simple/simplecontent-enum.xsd new file mode 100644 index 00000000..4e62daf7 --- /dev/null +++ b/XmlSchemaClassGenerator.Tests/xsd/simple/simplecontent-enum.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/XmlSchemaClassGenerator/ModelBuilder.cs b/XmlSchemaClassGenerator/ModelBuilder.cs index 34c35477..d995c01a 100644 --- a/XmlSchemaClassGenerator/ModelBuilder.cs +++ b/XmlSchemaClassGenerator/ModelBuilder.cs @@ -551,6 +551,15 @@ private TypeModel CreateTypeModel(XmlSchemaComplexType complexType) } } + if (complexType.ContentModel?.Content is XmlSchemaSimpleContentRestriction simpleContentRestriction) + { + var enumFacets = simpleContentRestriction.Facets?.OfType().ToList(); + if (enumFacets?.Count > 0 && !_configuration.EnumAsString) + { + classModel.TextValueType = CreateSimpleContentEnumModel(classModel, enumFacets); + } + } + XmlSchemaParticle xmlParticle = null; if (classModel.BaseClass != null) { @@ -723,6 +732,49 @@ private static List EnsureEnumValuesUnique(List return enumModelValues; } + private EnumModel CreateSimpleContentEnumModel(ClassModel classModel, List enumFacets) + { + var enumNamespace = namespaceModel?.Key.XmlSchemaNamespace ?? qualifiedName.Namespace; + var enumQualifiedName = qualifiedName.IsEmpty + ? new XmlQualifiedName($"{classModel.Name}Enum", enumNamespace) + : new XmlQualifiedName($"{qualifiedName.Name}Enum", enumNamespace); + + var enumName = $"{classModel.Name}Enum"; + if (namespaceModel != null) + enumName = namespaceModel.GetUniqueTypeName(enumName); + + var enumModel = new EnumModel(_configuration) + { + Name = enumName, + Namespace = namespaceModel, + XmlSchemaName = enumQualifiedName, + IsAnonymous = false, + }; + + foreach (var facet in enumFacets.DistinctBy(f => f.Value)) + { + var value = new EnumValueModel + { + Name = _configuration.NamingProvider.EnumMemberNameFromValue(enumModel.Name, facet.Value, facet), + Value = facet.Value + }; + + var valueDocs = GetDocumentation(facet); + value.Documentation.AddRange(valueDocs); + + value.IsDeprecated = facet.Annotation?.Items.OfType() + .Any(a => Array.Exists(a.Markup, m => m.Name == "annox:annotate" && m.HasChildNodes && m.FirstChild.Name == "jl:Deprecated")) == true; + + enumModel.Values.Add(value); + } + + enumModel.Values = EnsureEnumValuesUnique(enumModel.Values); + if (namespaceModel != null) + namespaceModel.Types[enumModel.Name] = enumModel; + + return enumModel; + } + private EnumModel CreateEnumModel(XmlSchemaSimpleType simpleType, List enumFacets) { // we got an enum diff --git a/XmlSchemaClassGenerator/Models/ClassModel.cs b/XmlSchemaClassGenerator/Models/ClassModel.cs index 5695082d..801c93dd 100644 --- a/XmlSchemaClassGenerator/Models/ClassModel.cs +++ b/XmlSchemaClassGenerator/Models/ClassModel.cs @@ -17,6 +17,7 @@ public class ClassModel(GeneratorConfiguration configuration) : ReferenceTypeMod public bool IsMixed { get; set; } public bool IsSubstitution { get; set; } public TypeModel BaseClass { get; set; } + public TypeModel TextValueType { get; set; } public List DerivedTypes { get; set; } = []; public override bool IsSubtype => BaseClass != null; @@ -95,6 +96,46 @@ public override CodeTypeDeclaration Generate() if (BaseClass is ClassModel) { classDeclaration.BaseTypes.Add(BaseClass.GetReferenceFor(Namespace)); + + if (TextValueType != null && !string.IsNullOrEmpty(Configuration.TextValuePropertyName)) + { + var textName = Configuration.TextValuePropertyName; + var enableDataBinding = Configuration.EnableDataBinding; + var typeReference = TextValueType.GetReferenceFor(Namespace); + + CodeMemberField backingFieldMember = null; + if (enableDataBinding) + { + backingFieldMember = new CodeMemberField(typeReference, textName.ToBackingField(Configuration.PrivateMemberPrefix)) + { + Attributes = MemberAttributes.Private + }; + classDeclaration.Members.Add(backingFieldMember); + } + + CodeMemberField text = new(typeReference, textName + PropertyModel.GetAccessors(backingFieldMember, enableDataBinding, TextValueType.GetPropertyValueTypeCode())) + { + Attributes = MemberAttributes.Public | MemberAttributes.New, + }; + + var docs = new List { + new() { Language = English, Text = "Gets or sets the text value." }, + new() { Language = German, Text = "Ruft den Text ab oder legt diesen fest." } + }; + + docs.AddRange(TextValueType.Documentation); + + var attribute = AttributeDecl(); + + text.Comments.AddRange(GetComments(docs).ToArray()); + + text.CustomAttributes.Add(attribute); + classDeclaration.Members.Add(text); + + var valuePropertyModel = new PropertyModel(Configuration, textName, TextValueType, this); + + Configuration.MemberVisitor(text, valuePropertyModel); + } } else if (!string.IsNullOrEmpty(Configuration.TextValuePropertyName)) {