.Net Add namespace to XML document as default and with a prefix

前端 未结 1 781
面向向阳花
面向向阳花 2021-01-28 00:42

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         


        
1条回答
  •  孤城傲影
    2021-01-28 01:14

    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.

    0 讨论(0)
提交回复
热议问题