From 32dfff177337b7886a2b4b47e0a9c8a47288e74b Mon Sep 17 00:00:00 2001 From: Michael Ganss Date: Thu, 5 Aug 2021 13:11:41 +0200 Subject: [PATCH] Create individual classes for all root elements that derive from the same type (see #273) --- XmlSchemaClassGenerator/ModelBuilder.cs | 48 +++++++++++++++++++++++-- XmlSchemaClassGenerator/TypeModel.cs | 2 ++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/XmlSchemaClassGenerator/ModelBuilder.cs b/XmlSchemaClassGenerator/ModelBuilder.cs index 38ddf6eb..23cd1435 100644 --- a/XmlSchemaClassGenerator/ModelBuilder.cs +++ b/XmlSchemaClassGenerator/ModelBuilder.cs @@ -137,7 +137,7 @@ private void CreateSubstitutes() private void AddXmlRootAttributeToAmbiguousTypes() { - var ambiguousTypes = Types.Values.Where(t=>t.RootElementName == null && !(t is InterfaceModel)).GroupBy(t => t.Name); + var ambiguousTypes = Types.Values.Where(t => t.RootElementName == null && !t.IsAbstractRoot && !(t is InterfaceModel)).GroupBy(t => t.Name); foreach (var ambiguousTypeGroup in ambiguousTypes) { var types = ambiguousTypeGroup.ToList(); @@ -253,7 +253,7 @@ private void CreateElements(IEnumerable elements) var type = CreateTypeModel(typeSource, rootElement.ElementSchemaType, qualifiedName); ClassModel derivedClassModel = null; - if (type.RootElementName != null) + if (type.RootElementName != null || type.IsAbstractRoot) { if (type is ClassModel classModel) { @@ -283,6 +283,49 @@ private void CreateElements(IEnumerable elements) ((ClassModel)derivedClassModel.BaseClass).DerivedTypes.Add(derivedClassModel); derivedClassModel.RootElementName = rootElement.QualifiedName; + + if (!type.IsAbstractRoot) + { + // Also create an empty derived class for the original root element + + var originalClassModel = new ClassModel(_configuration) + { + Name = _configuration.NamingProvider.RootClassNameFromQualifiedName(type.RootElementName), + Namespace = classModel.Namespace + }; + + originalClassModel.Documentation.AddRange(classModel.Documentation); + classModel.Documentation.Clear(); + + if (originalClassModel.Namespace != null) + { + originalClassModel.Name = originalClassModel.Namespace.GetUniqueTypeName(originalClassModel.Name); + originalClassModel.Namespace.Types[originalClassModel.Name] = originalClassModel; + } + + if (classModel.XmlSchemaName != null && !classModel.XmlSchemaName.IsEmpty) + { + key = BuildKey(classModel.RootElement, classModel.XmlSchemaName); + Types[key] = originalClassModel; + } + + originalClassModel.BaseClass = classModel; + ((ClassModel)originalClassModel.BaseClass).DerivedTypes.Add(originalClassModel); + + originalClassModel.RootElementName = type.RootElementName; + + if (classModel.RootElement.SubstitutionGroup != null + && SubstitutionGroups.TryGetValue(classModel.RootElement.SubstitutionGroup, out var substitutes)) + { + foreach (var substitute in substitutes.Where(s => s.Element == classModel.RootElement)) + { + substitute.Type = originalClassModel; + } + } + + classModel.RootElementName = null; + classModel.IsAbstractRoot = true; + } } else { @@ -297,6 +340,7 @@ private void CreateElements(IEnumerable elements) classModel.Documentation.AddRange(GetDocumentation(rootElement)); } + type.RootElement = rootElement; type.RootElementName = rootElement.QualifiedName; } diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index dc482be0..50162593 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -111,7 +111,9 @@ public abstract class TypeModel protected static readonly CodeDomProvider CSharpProvider = CodeDomProvider.CreateProvider("CSharp"); public NamespaceModel Namespace { get; set; } + public XmlSchemaElement RootElement { get; set; } public XmlQualifiedName RootElementName { get; set; } + public bool IsAbstractRoot { get; set; } public string Name { get; set; } public XmlQualifiedName XmlSchemaName { get; set; } public XmlSchemaType XmlSchemaType { get; set; }