From 0996162d0385b40f08f030dca9e654305dfa23cd Mon Sep 17 00:00:00 2001 From: Alexander Titov Date: Sat, 2 May 2020 18:29:27 +0300 Subject: [PATCH] Resolve type naming ambiguity with XmlRootAttribute For any type with non unique name without XmlRootAttribute SGEN.exe fails to generate xml serialization assembly with error: The top XML element 'XXX' from namespace '' references distinct types Test.Namespace.XXX and Test.Another.Namespace.XXX. Use XML attributes to specify another XML name or namespace for the element or types. This commit defines RootElementName for all types without RootElementName (except interfaces) if type name is not unique --- XmlSchemaClassGenerator.Tests/XmlTests.cs | 58 +++++++++++++++++++++++ XmlSchemaClassGenerator/ModelBuilder.cs | 19 ++++++++ 2 files changed, 77 insertions(+) diff --git a/XmlSchemaClassGenerator.Tests/XmlTests.cs b/XmlSchemaClassGenerator.Tests/XmlTests.cs index 1980fadf..17445fc9 100644 --- a/XmlSchemaClassGenerator.Tests/XmlTests.cs +++ b/XmlSchemaClassGenerator.Tests/XmlTests.cs @@ -1665,5 +1665,63 @@ public void GenerateXmlRootAttributeForEnumTest() Assert.Equal("EnumTestType", xmlRootAttribute.ElementName); Assert.Equal("http://test.namespace", xmlRootAttribute.Namespace); } + + [Fact] + public void AmbiguousTypesTest() + { + const string xsd1 = @" + + + + + + + + + + + "; + const string xsd2 = @" + + + + + + + + + + + "; + var generator = new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key =>key.XmlSchemaNamespace + } + }; + var contents1 = ConvertXml(nameof(GenerateXmlRootAttributeForEnumTest), xsd1, generator); + var contents2 = ConvertXml(nameof(GenerateXmlRootAttributeForEnumTest), xsd2, generator); + var content1 = Assert.Single(contents1); + var content2 = Assert.Single(contents2); + + var assembly = Compiler.Compile(nameof(GenerateXmlRootAttributeForEnumTest), content1, content2); + + var testType = assembly.GetType("Test_NS1.EnumTestType"); + Assert.NotNull(testType); + var xmlRootAttribute = testType.GetCustomAttributes().FirstOrDefault(); + Assert.NotNull(xmlRootAttribute); + Assert.Equal("EnumTestType", xmlRootAttribute.ElementName); + Assert.Equal("Test_NS1", xmlRootAttribute.Namespace); + + testType = assembly.GetType("Test_NS2.EnumTestType"); + Assert.NotNull(testType); + xmlRootAttribute = testType.GetCustomAttributes().FirstOrDefault(); + Assert.NotNull(xmlRootAttribute); + Assert.Equal("EnumTestType", xmlRootAttribute.ElementName); + Assert.Equal("Test_NS2", xmlRootAttribute.Namespace); + } } } diff --git a/XmlSchemaClassGenerator/ModelBuilder.cs b/XmlSchemaClassGenerator/ModelBuilder.cs index c281f361..3a64b00b 100644 --- a/XmlSchemaClassGenerator/ModelBuilder.cs +++ b/XmlSchemaClassGenerator/ModelBuilder.cs @@ -68,6 +68,25 @@ public ModelBuilder(GeneratorConfiguration configuration, XmlSchemaSet set) RenameInterfacePropertiesIfRenamedInDerivedClasses(); RemoveDuplicateInterfaceProperties(); } + + AddXmlRootAttributeToAmbiguousTypes(); + } + + private void AddXmlRootAttributeToAmbiguousTypes() + { + var ambiguousTypes = Types.Values.Where(t=>t.RootElementName == null && !(t is InterfaceModel)).GroupBy(t => t.Name); + foreach (var ambiguousTypeGroup in ambiguousTypes) + { + var types = ambiguousTypeGroup.ToList(); + if (types.Count == 1) + { + continue; + } + foreach (var typeModel in types) + { + typeModel.RootElementName = typeModel.GetQualifiedName(); + } + } } private void RemoveDuplicateInterfaceProperties()