Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize XML String into Class

Tags:

c#

I am trying to deserialize an XML String into my class which is derived from another class but I am having a problem in doing so, I am getting the following error:

{"The specified type is abstract: name='DeviceRequest', namespace='', at <DeviceRequest xmlns=''>."}

I assume i am missing some decorator attribute that will inform the serializer how to deserialize this xml into the class?

Here is my code:

//Usage
DeviceRequest dreq = DeviceRequest.ParseRequest(e.XML);


//Base Class
public abstract class IFSFRequestBase
{
    private string m_ApplicationSender = "";
    private int m_WorkStationID = 0;
    private string m_RequestID = "";

    [XmlAttribute()]
    public abstract string RequestType { get; set; }

    public abstract byte[] Message();

    [XmlAttribute()]
    public string ApplicationSender
    {
        get
        {
            return m_ApplicationSender;
        }
        set
        {
            m_ApplicationSender = value;
        }
    }

    [XmlAttribute()]
    public int WorkStationID
    {
        get
        {
            return m_WorkStationID;
        }
        set
        {
            m_WorkStationID = value;
        }
    }

    [XmlAttribute()]
    public string RequestID
    {
        get
        {
            return m_RequestID;
        }
        set
        {
            m_RequestID = value;
        }
    }

}


//Derived Class
public abstract class DeviceRequest : IFSFRequestBase
{
    private string m_TerminalID = "";
    private string m_SequenceID = "";
    private Output m_OutputField = null;

    [XmlAttribute(), DefaultValue("")]
    public string TerminalID
    {
        get
        {
            return m_TerminalID;
        }
        set
        {
            m_TerminalID = value;
        }
    }

    [XmlAttribute(), DefaultValue("")]
    public string SequenceID
    {
        get
        {
            return m_SequenceID;
        }
        set
        {
            m_SequenceID = value;
        }
    }

    [XmlElement("Output")]
    public Output OutputField
    {
        get
        {
            return m_OutputField;
        }
        set
        {
            m_OutputField = value;
        }
    }

    public static DeviceRequest ParseRequest(string sXML)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(DeviceRequest));

        StringReader sr = new StringReader(sXML);

        NamespaceIgnorantXmlTextReader XMLWithoutNamespace = new NamespaceIgnorantXmlTextReader(sr);

        return (DeviceRequest)serializer.Deserialize(XMLWithoutNamespace);
    }
}


// helper class to ignore namespaces when de-serializing
public class NamespaceIgnorantXmlTextReader : XmlTextReader
{
    public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader) : base(reader) { }

    public override string NamespaceURI
    {
        get { return ""; }
    }
}

UPDATE:

OK based on the answers here. I have updated the code, I now have a class Display that derives from DeviceRequest. I now get the following error:

{"There is an error in XML document (2, 2)."}, {"<DeviceRequest xmlns=''> was not expected."}


public class Display : DeviceRequest
{
    public static Display ParseRequest(string sXML)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Display));

        StringReader sr = new StringReader(sXML);

        NamespaceIgnorantXmlTextReader XMLWithoutNamespace = new NamespaceIgnorantXmlTextReader(sr);

        return (Display)serializer.Deserialize(XMLWithoutNamespace);
    }

    [XmlAttribute()]
    public override string RequestType
    {
        get { return "Output"; } set { } 
    }

    public override byte[] Message()
    {
        throw new NotImplementedException();
    }
}

DeviceRequest dreq = Display.ParseRequest(e.XML);
like image 323
KF-SoftwareDev Avatar asked Dec 15 '14 12:12

KF-SoftwareDev


2 Answers

As DeviceRequest is an abstract type, it cannot be instantiated directly. It is impossible to directly deserialize into instances of Device-Request. That said, if there are some non-abstract classes derived from it, please show some of them.

like image 130
Codor Avatar answered Sep 18 '22 14:09

Codor


OK, I have resolved this issue now. Thanks for the input guys.

I needed to add:

[System.Xml.Serialization.XmlRootAttribute(ElementName = "DeviceRequest")]

to the Display Class

[System.Xml.Serialization.XmlRootAttribute(ElementName = "DeviceRequest")]
public class Display : DeviceRequest
{
    public static Display ParseRequest(string sXML)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Display));

        StringReader sr = new StringReader(sXML);

        NamespaceIgnorantXmlTextReader XMLWithoutNamespace = new NamespaceIgnorantXmlTextReader(sr);

        return (Display)serializer.Deserialize(XMLWithoutNamespace);
    }

    [XmlAttribute()]
    public override string RequestType
    {
        get { return "O"; } set { } 
    }

    public override byte[] Message()
    {
        throw new NotImplementedException();
    }
}
like image 32
KF-SoftwareDev Avatar answered Sep 20 '22 14:09

KF-SoftwareDev