Click here to Skip to main content
15,888,521 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,

I need to develop an application, which takes an XML file as an input and returns a .NET object.

I have tried this using the Deserialize method, but the problem is Deserialize method expects us to know the type of the object we want to create, my problem is that I will get different XML's and I want a generic code, which can take any XML and returns a .NET object.

I dont know whether it is possible or not.

Can some please help me in this?

A code sample will be highly appreciated.

Thanks
Posted

If your XML structure is completely arbitrary (I mean, it could have any structure having any hierarchy with any nesting level), I am sorry, it is not possible to generate a .NET object on the fly.

If you need to return a typed .NET object for each different XML (Of different structure), you surely need to know the structure of the XML, parse it accordingly and populate the object. There is no alternative.
 
Share this answer
 
I'm not quite sure what you've meant. But you cannot convert ANY xml into ANY .Net object.
First your app have to know what types should be xml's attributes/elements.
You should have xsd schema for this purpose.
Let's suppose you have the following xml:

XML
<BillsOutList>
  <BillOut Account="5"
           Destination="RUFBESTQWY"
           Created="2010-12-14T11:34:48.297"
           Modified="2010-12-14T11:34:48.297"
           Amount="10.0000"
           PageNumber="0" />
  <BillOut Account="5"
           Destination="RUFBESTQWY"
           Created="2010-11-22T17:41:25.330"
           Modified="2010-11-22T17:41:25.330"
           Amount="10.0000"  />
</BillsOutList>


The xsd should be:

XML
<xs:schema
  id="IncomeList" xmlns=""
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="BillsOutList"
              msdata:Locale="en-US">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="1">
        <xs:element name="BillOut">
          <xs:complexType>
            <xs:attribute name="Account" type="xs:string" />
            <xs:attribute name="Destination" type="xs:string" />
            <xs:attribute name="Created" type="xs:string" />
            <xs:attribute name="Modified" type="xs:string" />
            <xs:attribute name="Amount" type="xs:decimal" />
            <xs:attribute name="PageNumber" type="xs:int" />
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>


And the corresponding class:

C#
public class BillOut : IEntity
 {
     private string msAccount = String.Empty;
     private decimal mdAmount;
     private DateTime moModified;
     private DateTime moCreated;
     private string msDestination = String.Empty;
     private int miPage;

     [XmlAttribute]
     public string Destination
     {
         get { return msDestination; }
         set { msDestination = value; }
     }

     [XmlAttribute]
     public DateTime Created
     {
         get { return moCreated; }
         set { moCreated = value; }
     }

     [XmlAttribute]
     public DateTime Modified
     {
         get { return moModified; }
         set { moModified = value; }
     }

     [XmlAttribute]
     public decimal Amount
     {
         get { return mdAmount; }
         set { mdAmount = value; }
     }

     [XmlAttribute]
     public string Account
     {
         get { return msAccount; }
         set { msAccount = value; }
     }

     [XmlAttribute]
     public int PageNumber
     {
         get { return miPage; }
         set { miPage = value; }
     }
     public string GetXSD()
     {
         return "BillsOutList.xsd";
     }
 }



Here is the IEntity:

C#
public interface IEntity
{
    string GetXSD();
}



And to convert it:

C#
Type TType = typeof(T);
if (TType.GetInterface("IEntity") == null)
{
    RowCount = 0;
    throw new CPException(TType.ToString() + " must be iherited from IEntity!");
}
string lsXSDFile = String.Empty;

try
{
    T t = Activator.CreateInstance<T>();
    lsXSDFile = (string)TType.InvokeMember("GetXSD", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, t, null);
}
catch (Exception)
{
    RowCount = 0;
    throw new CPNullException(TType.ToString() + " no XSD!");
}

// check resources
DataSet loDataSet = new DataSet();
Stream schema = Assembly.GetExecutingAssembly().GetManifestResourceStream("yourappnamespaces.Schemas." + lsXSDFile);
if (schema == null)
{
    RowCount = 0;
    throw new CPNullException(lsXSDFile + " No schema in resources!");
}

loDataSet.ReadXmlSchema(schema);


//fill the data
XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = "\t";
            MemoryStream loResultStream = new MemoryStream();
            XmlWriter writer = XmlWriter.Create(loResultStream, settings);
            yourxmlelement.WriteTo(writer);
            writer.Close();
            loResultStream.Position = 0;
            loDataSet.ReadXml(loResultStream, XmlReadMode.IgnoreSchema);
            loResultStream.Close();


But if you can use .Net 4 you can use CodeDOM/Reflection.Emit to create an object dynamically but still you need xsd to know types of properties.
 
Share this answer
 
Comments
Abhinav S 20-Dec-10 4:34am    
Good answer.
maheshk_blr 20-Dec-10 4:56am    
Thank you very much for a very nice explanatory answer.
You can't directly convert xml to strong typed .net objects.
Solutions:
1) Use XmlSerializer class, which, deserializes your xml to objects, but, it has to be properly formated.
2) Write your own parsing, and object creation.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900