Kristen
Kristen

Reputation: 453

Deserializing complicated xml into objects - Problems creating the objects

Ok so I am working on deserializing an xml document into objects. Basically my xml document will look like this:

<?xml version="1.0"?>
<root>
    <eConnect CUSTNMBR="22222" DATE1="1900-01-01T00:00:00" TABLENAME="RM00101" DBNAME="BOLT" Requester_DOCTYPE="Customer" ACTION="0">
        <Customer>
            <CUSTNMBR>22222</CUSTNMBR>
            <ADDRESS1>123 ABC St</ADDRESS1>
            <ADDRESS2/>
            <ADDRESS3/>
            <ADRSCODE>PRIMARY</ADRSCODE>
            <CITY>Ann Arbor</CITY>
            <CNTCPRSN/>
            <COUNTRY>USA</COUNTRY>
            <CPRCSTNM/>
            <CURNCYID/>
            <CUSTCLAS/>
            <CUSTDISC>0</CUSTDISC>
            <CUSTNAME>Test Customer 2</CUSTNAME>
            <PHONE1>4165551234</PHONE1>
            <PHONE2/>
            <PHONE3/>
            <FAX/>
            <PYMTRMID/>
            <SALSTERR/>
            <SHIPMTHD/>
            <SLPRSNID/>
            <STATE>Micigan</STATE>
            <TAXSCHID/>
            <TXRGNNUM/>
            <UPSZONE/>
            <ZIP>45612</ZIP>
            <STMTNAME>Test Customer 2</STMTNAME>
            <SHRTNAME>Test Customer 2</SHRTNAME>
            <PRBTADCD>PRIMARY</PRBTADCD>
            <PRSTADCD>PRIMARY</PRSTADCD>
            <STADDRCD>PRIMARY</STADDRCD>
            <CHEKBKID/>
            <CRLMTTYP>0</CRLMTTYP>
            <CRLMTAMT>0.00000</CRLMTAMT>
            <CRLMTPER>0</CRLMTPER>
            <CRLMTPAM>0.00000</CRLMTPAM>
            <RATETPID/>
            <PRCLEVEL/>
            <MINPYTYP>0</MINPYTYP>
            <MINPYDLR>0.00000</MINPYDLR>
            <MINPYPCT>0</MINPYPCT>
            <FNCHATYP>0</FNCHATYP>
            <FNCHPCNT>0</FNCHPCNT>
            <FINCHDLR>0.00000</FINCHDLR>
            <MXWOFTYP>0</MXWOFTYP>
            <MXWROFAM>0.00000</MXWROFAM>
            <COMMENT1>test comment</COMMENT1>
            <COMMENT2>another test</COMMENT2>
            <USERDEF1/>
            <USERDEF2/>
            <TAXEXMT1/>
            <TAXEXMT2/>
            <BALNCTYP>0</BALNCTYP>
            <STMTCYCL>5</STMTCYCL>
            <BANKNAME/>
            <BNKBRNCH/>
            <FRSTINDT>1900-01-01T00:00:00</FRSTINDT>
            <INACTIVE>0</INACTIVE>
            <HOLD>0</HOLD>
            <CRCARDID/>
            <CRCRDNUM/>
            <CCRDXPDT>1900-01-01T00:00:00</CCRDXPDT>
            <KPDSTHST>1</KPDSTHST>
            <KPCALHST>1</KPCALHST>
            <KPERHIST>1</KPERHIST>
            <KPTRXHST>1</KPTRXHST>
            <CREATDDT>2015-11-27T00:00:00</CREATDDT>
            <MODIFDT>2015-11-27T00:00:00</MODIFDT>
            <Revalue_Customer>1</Revalue_Customer>
            <Post_Results_To>0</Post_Results_To>
            <FINCHID/>
            <GOVCRPID/>
            <GOVINDID/>
            <DISGRPER>0</DISGRPER>
            <DUEGRPER>0</DUEGRPER>
            <DOCFMTID/>
            <Send_Email_Statements>0</Send_Email_Statements>
            <GPSFOINTEGRATIONID/>
            <INTEGRATIONSOURCE>0</INTEGRATIONSOURCE>
            <INTEGRATIONID/>
            <Address>
                <CUSTNMBR>22222</CUSTNMBR>
                <ADRSCODE>PRIMARY</ADRSCODE>
                <SLPRSNID/>
                <UPSZONE/>
                <SHIPMTHD/>
                <TAXSCHID/>
                <CNTCPRSN/>
                <ADDRESS1>123 ABC St</ADDRESS1>
                <ADDRESS2/>
                <ADDRESS3/>
                <COUNTRY>USA</COUNTRY>
                <CITY>Ann Arbor</CITY>
                <STATE>Micigan</STATE>
                <ZIP>45612</ZIP>
                <PHONE1>4165551234</PHONE1>
                <PHONE2/>
                <PHONE3/>
                <FAX/>
                <GPSFOINTEGRATIONID/>
                <INTEGRATIONSOURCE>0</INTEGRATIONSOURCE>
                <INTEGRATIONID/>
                <Internet_Address/>
            </Address>
        </Customer>
    </eConnect>
</root>

When I try to deserialize this, I get an "Object reference not set to instance of an object" exception. My classes look like this:

    [XmlRoot("root")]
    public class eConnect
    {
        public Customer customer;
    }

    public class Customer
    {
        public string CUSTNMBR { get; set; }
        public string CUSTNAME { get; set; }

    }

Am I getting the exception because I have to have variables for all the nodes in the xml document? Is there a way to only use the nodes I need?

Also am I creating my classes the right way, because basically the xml will have a root node called root and the root can contain multiple eConnect nodes, but each eConnect node will only contain one customer node.

Upvotes: 1

Views: 180

Answers (2)

Hans Vonn
Hans Vonn

Reputation: 4079

Use Visual Studio's Paste XML as Classes feature.

To do this: Open Visual Studio > Edit Menu > Paste Special > Paste XML as Classes.

The resulting classes may need clean up (e.g. change type from ushort to int etc.). This feature handles the necessary attributes for serialization. Here is an example for your xml:

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class root
{

    private rootEConnect eConnectField;

    /// <remarks/>
    public rootEConnect eConnect
    {
        get
        {
            return this.eConnectField;
        }
        set
        {
            this.eConnectField = value;
        }
    }
}

// Intermediate Xml nodes ...

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class rootEConnectCustomer
{

    private ushort cUSTNMBRField;

    private string aDDRESS1Field;

    private object aDDRESS2Field;

    private object aDDRESS3Field;

    private string aDRSCODEField;

    // rest of class ...
}

Upvotes: 0

DHP
DHP

Reputation: 251

Try adding the Serializable attribute on your classes and using the XmlElement tag inside your classes to define how the objects are mapped. I would also make a separate class for your root.

[XmlRoot("root")]
[Serializable]
public class Root
{
    public Root() 
    {
        eConnects = new List<eConnect>();
    }

    [XmlElement("eConnect")]
    public List<eConnect> eConnects { get; set; }
}

[XmlRoot("eConnect")]
[Serializable]
public class eConnect
{
    [XmlElement("Customer")]
    public Customer customer { get; set; }
}

[XmlRoot("Customer")]
[Serializable]
public class Customer
{
    [XmlElement("CUSTNMBR")]
    public string CUSTNMBR { get; set; }
    [XmlElement("CUSTNAME")]
    public string CUSTNAME { get; set; }

}

Using the XmlElement tag also gives you the freedom to name your variables friendlier names. For example you could switch

[XmlElement("CUSTNAME")]
public string CUSTNAME { get; set; }

to

[XmlElement("CUSTNAME")]
public string CustomerName { get; set; }

Upvotes: 2

Related Questions