Skip to content

Commit

Permalink
Resolve type naming ambiguity with XmlRootAttribute
Browse files Browse the repository at this point in the history
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
  • Loading branch information
AVTit committed May 2, 2020
1 parent 03a997d commit 0996162
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
58 changes: 58 additions & 0 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""Test_NS1""
elementFormDefault=""qualified"" attributeFormDefault=""unqualified"">
<xs:element name=""EnumTestType"">
<xs:simpleType>
<xs:restriction base=""xs:string"">
<xs:enumeration value=""EnumValue""/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>";
const string xsd2 = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""Test_NS2""
elementFormDefault=""qualified"" attributeFormDefault=""unqualified"">
<xs:element name=""EnumTestType"">
<xs:simpleType>
<xs:restriction base=""xs:string"">
<xs:enumeration value=""EnumValue""/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>";
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<XmlRootAttribute>().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<XmlRootAttribute>().FirstOrDefault();
Assert.NotNull(xmlRootAttribute);
Assert.Equal("EnumTestType", xmlRootAttribute.ElementName);
Assert.Equal("Test_NS2", xmlRootAttribute.Namespace);
}
}
}
19 changes: 19 additions & 0 deletions XmlSchemaClassGenerator/ModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 0996162

Please sign in to comment.