Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 59 additions & 34 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
22 changes: 22 additions & 0 deletions XmlSchemaClassGenerator.Tests/xsd/simple/simplecontent-enum.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com/simplecontent" targetNamespace="http://example.com/simplecontent" elementFormDefault="qualified">
<xs:complexType name="CodeType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="listID" type="xs:string" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>

<xs:complexType name="TransConfirmationCodeType">
<xs:simpleContent>
<xs:restriction base="CodeType">
<xs:enumeration value="Always"/>
<xs:enumeration value="Never"/>
<xs:enumeration value="OnError"/>
</xs:restriction>
</xs:simpleContent>
</xs:complexType>

<xs:element name="Root" type="TransConfirmationCodeType"/>
</xs:schema>
52 changes: 52 additions & 0 deletions XmlSchemaClassGenerator/ModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,15 @@ private TypeModel CreateTypeModel(XmlSchemaComplexType complexType)
}
}

if (complexType.ContentModel?.Content is XmlSchemaSimpleContentRestriction simpleContentRestriction)
{
var enumFacets = simpleContentRestriction.Facets?.OfType<XmlSchemaEnumerationFacet>().ToList();
if (enumFacets?.Count > 0 && !_configuration.EnumAsString)
{
classModel.TextValueType = CreateSimpleContentEnumModel(classModel, enumFacets);
}
}

XmlSchemaParticle xmlParticle = null;
if (classModel.BaseClass != null)
{
Expand Down Expand Up @@ -723,6 +732,49 @@ private static List<EnumValueModel> EnsureEnumValuesUnique(List<EnumValueModel>
return enumModelValues;
}

private EnumModel CreateSimpleContentEnumModel(ClassModel classModel, List<XmlSchemaEnumerationFacet> 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<XmlSchemaAppInfo>()
.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<XmlSchemaEnumerationFacet> enumFacets)
{
// we got an enum
Expand Down
41 changes: 41 additions & 0 deletions XmlSchemaClassGenerator/Models/ClassModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ClassModel> DerivedTypes { get; set; } = [];
public override bool IsSubtype => BaseClass != null;

Expand Down Expand Up @@ -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<DocumentationModel> {
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<XmlTextAttribute>();

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))
{
Expand Down