When using XMLSerializer to create an XML string of a serialization of a class oXML in vb.net as follows:
Dim x As New Xml.Serialization.XmlSerializer(oXML.GetT
XmlSerializer
has no defined behavior in the case of passing an XmlSerializerNamespaces
with two prefixes for identical namespaces. It could choose either prefix and the result would be semantically identical. Further, from the reference source for the class it appears the namespaces are stored in a hash table so their order is unpredictable. But since the XML would have the same meaning either way, the simplest thing for you to do is to not worry about it.
If for some reason you must have duplicated namespaces in your XML, and must use the default prefix in preference to an equivalent named prefix for elements in that namespace, you could serialize to an XDocument
then add the missing duplicates manually:
Public Module XObjectExtensions
Public Function SerializeToXDocument(Of T)(obj As T, serializer As XmlSerializer, ns As XmlSerializerNamespaces) As XDocument
Dim doc = New XDocument()
Using writer = doc.CreateWriter()
serializer = If(serializer, New XmlSerializer(obj.GetType()))
serializer.Serialize(writer, obj, ns)
End Using
If doc.Root IsNot Nothing AndAlso ns IsNot Nothing Then
' Add missing namespaces
For Each name In ns.ToArray().Except(doc.Root.Attributes().Where(Function(a) a.IsNamespaceDeclaration).Select((Function(a) New XmlQualifiedName(a.Name.LocalName, a.Value))))
doc.Root.Add(New XAttribute("xmlns" + (If(String.IsNullOrEmpty(name.Name), String.Empty, ":" + name.Name)), name.Namespace))
Next
End If
Return doc
End Function
End Module
And then use it like:
Dim xDoc = oXML.SerializeToXDocument(x, xmlns)
Dim xml2 as String
Using sw = New IO.StringWriter()
xDoc.Save(sw)
xml2 = sw.ToString()
End Using
Example dotnetfiddle.
Now, in your case the default namespace was omitted in favor of a duplicated prefixed namespace. If for some reason XmlSerializer
chose to do the opposite (and it's not documented which it will choose), then adding the missing named namespace at the end of the root document's namespace list would cause all elements to be written with the named prefix. That's because it turns out that, when writing an XElement
, name/namespace pairs are pushed onto a stack during serialization and so the lattermost is used. To work around this, you could adapt the code from XDocument Save Removing Node Prefixes and move the default prefix to the end of the attribute list rather than the beginning.