Search code examples
xmlvb.netxml-deserialization

Deserializing an element with different xsi:style


I need to deserialize a XML file that contains an element with two different types.
Example:

<loop xsi:type="loopDynamicLengthType">
...
<loop xsi:type="loopTerminatedType">
...

In my source the class is defined as:

<XmlElement("loop")> Public prLoop() As PosResponseLoop

The second one is defined as:

<XmlInclude(GetType(loopTerminatedType))> _
Public Class PosResponseLoop

The first one could be defined in a similar way and the same name,

<XmlInclude(GetType(loopDynamicLengthType))> _
Public Class PosResponseLoop

but the compiler says:

class 'PosResponseLoop' and class 'PosResponseLoop' conflict in namespace 'WindowsApplication1'.

How can i solve it?


Solution

  • The standard attribute xsi:type allows an XML element to explicitly assert its type. In this case, the element <loop> can have two types, loopDynamicLengthType and loopTerminatedType. As explained here, XmlSerializer uses the xsi:type information to map the XML element to a specific .Net type. Thus what you need to do is have a single base class (possibly though not necessarily abstract) to represent any possible type of loop, with two subclasses, each corresponding to the two possible xsi:type values:

    <XmlInclude(GetType(LoopTerminatedType))> _
    <XmlInclude(GetType(LoopDynamicLengthType))> _
    Public MustInherit Class PosResponseLoop
    End Class
    
    <XmlType("loopTerminatedType")> _
    Public Class LoopTerminatedType
        Inherits PosResponseLoop
    End Class
    
    <XmlType("loopDynamicLengthType")> _
    Public Class LoopDynamicLengthType
        Inherits PosResponseLoop
    End Class
    

    The <XmlInclude> attributes on the base class specify the set of possible subtypes that might be encountered. The <XmlType(String)> attributes on the derived classes specify the name that will appear as the value of the corresponding xsi:type attribute.

    Then your containing type should look like:

    Public Class RootObject
        <XmlElement("loop")> Public prLoop() As PosResponseLoop 
    End Class
    

    Sample fiddle.