Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET XML Deserialization ignore namespaces

I got thousands of XML files following all the same schema/structure. I implemented IXmlSerializable and thus am reading the elements and attributes myself.

My problem is that these files each use a different phony namespace. These files come from an other source so I cannot change that :D Also, there are too many of those namespaces for me to just build an array of the possible namespaces and pass it along to the xmlserializer.

Right now, if I don't specify a namespace, it throws a [xmlns:ns0="http://tempuri.org/abcd.xsd" was not expected] error.

I would like to be able to tell the serializer to simply ignore the namespace when deserializing my object and just fire ReadXML. Or just be able to tell it to accept any "http://tempuri.org/" namespace.

Is that possible?

I would like to avoid modifying the files as much as possible.

Thank you!

like image 813
user1698428 Avatar asked Sep 25 '12 20:09

user1698428


1 Answers

Yes, it is possible. When you call the Deserialize method of your XmlSerializer, you can specify an XmlTextReader instance.

This answer by Cheeso on a related C# question shows how to create an XmlTextReader which ignores any namespaces occurring in the XML file. I have taken the liberty to translate his idea to VB and create a simple proof-of-concept example based on your requirements:

Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Xml.Serialization

' Helper class
Class NamespaceIgnorantXmlTextReader
    Inherits XmlTextReader

    Public Sub New(stream As Stream)
        MyBase.New(stream)
    End Sub

    Public Overrides ReadOnly Property NamespaceURI As String
        Get
            Return ""
        End Get
    End Property
End Class

' Serializable class
Public Class ExampleClass
    Public Property MyProperty As String
End Class

' Example
Module Module1
    Sub Main()
        Dim testXmlStream = New MemoryStream(Encoding.UTF8.GetBytes(
            "<ExampleClass xmlns=""http://tempuri.org/SomePhonyNamespace1.xsd"" 
                           xmlns:ph2=""http://tempuri.org/SomePhonyNamespace2.xsd"">
                 <ph2:MyProperty>SomeValue</ph2:MyProperty>
             </ExampleClass>"))

        Dim serializer As New XmlSerializer(GetType(ExampleClass))
        Dim reader As New NamespaceIgnorantXmlTextReader(testXmlStream)
        Dim example = DirectCast(serializer.Deserialize(reader), ExampleClass)

        Console.WriteLine(example.MyProperty)   ' prints SomeValue
    End Sub
End Module

Note: If it's just the document's default namespace which is different (i.e., the individual tags don't have different namespaces), using a standard TextXmlReader with the Namespaces property set to False suffices.

Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Xml.Serialization

' Serializable Class
Public Class ExampleClass
    Public Property MyProperty As String
End Class

' Example
Module Module1
    Sub Main()
        Dim testXmlStream = New MemoryStream(Encoding.UTF8.GetBytes(
            "<ExampleClass xmlns=""http://tempuri.org/SomePhonyNamespace1.xsd"">
                 <MyProperty>SomeValue</MyProperty>
             </ExampleClass>"))

        Dim serializer As New XmlSerializer(GetType(ExampleClass))
        Dim reader As New XmlTextReader(testXmlStream)
        reader.Namespaces = False
        Dim example = DirectCast(serializer.Deserialize(reader), ExampleClass)

        Console.WriteLine(example.MyProperty)   ' prints SomeValue
    End Sub
End Module
like image 196
Heinzi Avatar answered Oct 14 '22 13:10

Heinzi