I have classes as follows
namespace Coverage {
public class ClassInfo {
public string ClassName;
public int BlocksCovered;
public int BlocksNotCovered;
public ClassInfo() {}
public ClassInfo(string ClassName, int BlocksCovered, int BlocksNotCovered)
{
this.ClassName = ClassName;
this.BlocksCovered = BlocksCovered;
this.BlocksNotCovered = BlocksNotCovered;
}
}
public class Module {
public List<ClassInfo> ClassInfoList;
public int BlocksCovered;
public int BlocksNotCovered;
public string moduleName;
public Module()
{
ClassInfoList = new List<ClassInfo>();
BlocksCovered = 0;
BlocksNotCovered = 0;
moduleName = "";
}
With the following serializer code
XmlSerializer SerializerObj = new XmlSerializer(typeof(Module));
// Create a new file stream to write the serialized object to a file
TextWriter WriteFileStream = new StreamWriter(#"test.xml");
SerializerObj.Serialize(WriteFileStream, report);
WriteFileStream.Close();
I can get the following XML file.
<?xml version="1.0" encoding="utf-8"?>
<Module xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ClassInfoList>
<ClassInfo>
<ClassName>Fpga::TestMe</ClassName>
<BlocksCovered>4</BlocksCovered>
<BlocksNotCovered>8</BlocksNotCovered>
</ClassInfo>
<ClassInfo>
<ClassName>Fpga::TestMe2</ClassName>
<BlocksCovered>4</BlocksCovered>
<BlocksNotCovered>8</BlocksNotCovered>
</ClassInfo>
</ClassInfoList>
<BlocksCovered>8</BlocksCovered>
<BlocksNotCovered>16</BlocksNotCovered>
<moduleName>helloclass.exe</moduleName>
</Module>
Q1 : How can I remove the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://... to have simple element <Module>..</Module>?
Q2 : The XML element name is exactly the same as the class name or variable name. Can I replace it with my own?
Q3 : Can I remove the outer <ClassInfoList>?
For example, how can I generate the XML as follows:
<?xml version="1.0" encoding="utf-8"?>
<Module>
<Class>
<ClassName>Fpga::TestMe</ClassName>
<BlocksCovered>4</BlocksCovered>
<BlocksNotCovered>8</BlocksNotCovered>
</Class>
<Class>
<ClassName>Fpga::TestMe2</ClassName>
<BlocksCovered>4</BlocksCovered>
<BlocksNotCovered>8</BlocksNotCovered>
</Class>
<BlocksCovered>8</BlocksCovered>
<BlocksNotCovered>16</BlocksNotCovered>
<moduleName>helloclass.exe</moduleName>
</Module>
(btw, it doesn't tie to the question, but you should aim to avoid public fields, for lots of reasons covered in many stackoverflow questions)
Q3: Simply:
[XmlElement("Class")]
public List<ClassInfo> ClassInfoList;
Q2 re the top level name; you can use
[XmlRoot("somethingFun")]
public class Module { ... }
Q2 re member names:
[XmlElement("blocks")]
public int BlocksCovered;
(see also [XmlAttribute(...)])
Q1 Removing the xsi etc can be done with XmlSerializerNamespaces:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var ser = new XmlSerializer(typeof(Module));
ser.Serialize(destination, module, ns);
Related
I have XML file which have some tags with dot(.), now i am using "StringWriter"
to Map XML data with C#, but i am not able to handle XML tags which have dot(.) in tag name like:- "Customer.Name", how can i map this with C# class.
I had give XmlElement with my class model, but still i am not getting values map with my class.
Can any one give me suggestion.
[XmlElement(ElementName = "PARENTNAME")]
public string PARENTNAME { get; set; } //This is perfect mapped
[XmlElement(ElementName = "DISPLAYCONTACT.CONTACTNAME")]
public string DISPLAYCONTACTCONTACTNAME { get; set; } // This is not mapped
[XmlElement(ElementName = "DISPLAYCONTACT.COMPANYNAME")]
public string DISPLAYCONTACTCOMPANYNAME { get; set; }
Convert XML to C#
XmlDocument doc = new XmlDocument();
doc.LoadXml(customerString);
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
doc.WriteTo(xw);
String XmlString = sw.ToString();
string xmlToJson = JsonConvert.SerializeXmlNode(doc);
var deserialized = JsonConvert.SerializeXmlNode(doc);
var customer = new CusGetResIn();
customer= JsonConvert.DeserializeObject<CusGetResIn>(deserialized);
Also Tried:-
XmlSerializer serializer = new XmlSerializer(typeof(CusGetResIn));
MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(XmlString));
CusGetResIn resultingMessage = (CusGetResIn)serializer.Deserialize(memStream);
XML:-
<?xml version="1.0" encoding="UTF-8"?>
<response>
<control>
<status>success</status>
<senderid>Intacct_ISB</senderid>
<controlid>17/12/2018</controlid>
<uniqueid>false</uniqueid>
<dtdversion>3.0</dtdversion>
</control>
<operation>
<authentication>
<status>success</status>
<userid>vinit1</userid>
<companyid>FASTMORE-trial</companyid>
<locationid></locationid>
<sessiontimestamp>2018-12-19T00:41:15-08:00</sessiontimestamp>
</authentication>
<result>
<status>success</status>
<function>readByQuery</function>
<controlid>testFunctionId</controlid>
<data listtype="customer" count="31" totalcount="31" numremaining="0" resultId="">
<customer>
<RECORDNO>5</RECORDNO>
<CUSTOMERID>CUST-00101</CUSTOMERID>
<NAME>Sun Microsystems - EBC</NAME>
<ENTITY>CCUST-00101</ENTITY>
<PARENTKEY></PARENTKEY>
<PARENTID></PARENTID>
<PARENTNAME></PARENTNAME>
<DISPLAYCONTACT.CONTACTNAME>Sun Microsystems - EBC(CCUST-00101)</DISPLAYCONTACT.CONTACTNAME>
<DISPLAYCONTACT.COMPANYNAME>Sun Microsystems - EBC</DISPLAYCONTACT.COMPANYNAME>
<DISPLAYCONTACT.PREFIX></DISPLAYCONTACT.PREFIX>
<DISPLAYCONTACT.FIRSTNAME></DISPLAYCONTACT.FIRSTNAME>
<DISPLAYCONTACT.LASTNAME></DISPLAYCONTACT.LASTNAME>
<DISPLAYCONTACT.INITIAL></DISPLAYCONTACT.INITIAL>
<DISPLAYCONTACT.PRINTAS>Sun Microsystems - Executive Briefing Center</DISPLAYCONTACT.PRINTAS>
<DISPLAYCONTACT.TAXABLE>true</DISPLAYCONTACT.TAXABLE>
<DISPLAYCONTACT.TAXGROUP></DISPLAYCONTACT.TAXGROUP>
<DISPLAYCONTACT.PHONE1></DISPLAYCONTACT.PHONE1>
<DISPLAYCONTACT.PHONE2></DISPLAYCONTACT.PHONE2>
<DISPLAYCONTACT.CELLPHONE></DISPLAYCONTACT.CELLPHONE>
<DISPLAYCONTACT.PAGER></DISPLAYCONTACT.PAGER>
<DISPLAYCONTACT.FAX></DISPLAYCONTACT.FAX>
<DISPLAYCONTACT.EMAIL1>sevans#intacct.com</DISPLAYCONTACT.EMAIL1>
<DISPLAYCONTACT.EMAIL2></DISPLAYCONTACT.EMAIL2>
<DISPLAYCONTACT.URL1></DISPLAYCONTACT.URL1>
<DISPLAYCONTACT.URL2></DISPLAYCONTACT.URL2>
<DISPLAYCONTACT.VISIBLE>true</DISPLAYCONTACT.VISIBLE>
<DISPLAYCONTACT.MAILADDRESS.ADDRESS1>1245 Williams Lane</DISPLAYCONTACT.MAILADDRESS.ADDRESS1>
<DISPLAYCONTACT.MAILADDRESS.ADDRESS2></DISPLAYCONTACT.MAILADDRESS.ADDRESS2>
<DISPLAYCONTACT.MAILADDRESS.CITY>San Jose</DISPLAYCONTACT.MAILADDRESS.CITY>
<DISPLAYCONTACT.MAILADDRESS.STATE>CA</DISPLAYCONTACT.MAILADDRESS.STATE>
<DISPLAYCONTACT.MAILADDRESS.ZIP>95112</DISPLAYCONTACT.MAILADDRESS.ZIP>
<DISPLAYCONTACT.MAILADDRESS.COUNTRY>USA</DISPLAYCONTACT.MAILADDRESS.COUNTRY>
<DISPLAYCONTACT.MAILADDRESS.COUNTRYCODE></DISPLAYCONTACT.MAILADDRESS.COUNTRYCODE>
<DISPLAYCONTACT.MAILADDRESS.LATITUDE></DISPLAYCONTACT.MAILADDRESS.LATITUDE>
<DISPLAYCONTACT.MAILADDRESS.LONGITUDE></DISPLAYCONTACT.MAILADDRESS.LONGITUDE>
<DISPLAYCONTACT.STATUS>active</DISPLAYCONTACT.STATUS>
<TERMNAME>2/10 Net30</TERMNAME>
<TERMVALUE>2:10:1#30#1%:W:</TERMVALUE>
<CUSTREPID>EMP-002</CUSTREPID>
<CUSTREPNAME>Joanna Drake</CUSTREPNAME>
<RESALENO></RESALENO>
<TAXID></TAXID>
<CREDITLIMIT></CREDITLIMIT>
<TOTALDUE>3525172.72</TOTALDUE>
<COMMENTS></COMMENTS>
<ACCOUNTLABEL></ACCOUNTLABEL>
<ARACCOUNT>4000</ARACCOUNT>
<ARACCOUNTTITLE>Sales</ARACCOUNTTITLE>
<LAST_INVOICEDATE>10/01/2012</LAST_INVOICEDATE>
<LAST_STATEMENTDATE></LAST_STATEMENTDATE>
<DELIVERY_OPTIONS>Print#~#E-Mail</DELIVERY_OPTIONS>
<TERRITORYID></TERRITORYID>
<SHIPPINGMETHOD>Delivery</SHIPPINGMETHOD>
<CUSTTYPE>Corporate</CUSTTYPE>
<GLGRPKEY></GLGRPKEY>
<GLGROUP></GLGROUP>
<PRICESCHEDULE></PRICESCHEDULE>
<DISCOUNT></DISCOUNT>
<PRICELIST></PRICELIST>
<VSOEPRICELIST></VSOEPRICELIST>
<CURRENCY></CURRENCY>
<CONTACTINFO.CONTACTNAME></CONTACTINFO.CONTACTNAME>
<CONTACTINFO.PREFIX></CONTACTINFO.PREFIX>
<CONTACTINFO.FIRSTNAME></CONTACTINFO.FIRSTNAME>
<CONTACTINFO.INITIAL></CONTACTINFO.INITIAL>
<CONTACTINFO.LASTNAME></CONTACTINFO.LASTNAME>
<CONTACTINFO.COMPANYNAME></CONTACTINFO.COMPANYNAME>
<CONTACTINFO.PRINTAS></CONTACTINFO.PRINTAS>
<CONTACTINFO.PHONE1></CONTACTINFO.PHONE1>
<CONTACTINFO.PHONE2></CONTACTINFO.PHONE2>
<CONTACTINFO.CELLPHONE></CONTACTINFO.CELLPHONE>
<CONTACTINFO.PAGER></CONTACTINFO.PAGER>
<CONTACTINFO.FAX></CONTACTINFO.FAX>
<CONTACTINFO.EMAIL1></CONTACTINFO.EMAIL1>
<CONTACTINFO.EMAIL2></CONTACTINFO.EMAIL2>
<CONTACTINFO.URL1></CONTACTINFO.URL1>
<CONTACTINFO.URL2></CONTACTINFO.URL2>
<CONTACTINFO.VISIBLE></CONTACTINFO.VISIBLE>
<CONTACTINFO.MAILADDRESS.ADDRESS1></CONTACTINFO.MAILADDRESS.ADDRESS1>
<CONTACTINFO.MAILADDRESS.ADDRESS2></CONTACTINFO.MAILADDRESS.ADDRESS2>
<CONTACTINFO.MAILADDRESS.CITY></CONTACTINFO.MAILADDRESS.CITY>
<CONTACTINFO.MAILADDRESS.STATE></CONTACTINFO.MAILADDRESS.STATE>
<CONTACTINFO.MAILADDRESS.ZIP></CONTACTINFO.MAILADDRESS.ZIP>
<CONTACTINFO.MAILADDRESS.COUNTRY></CONTACTINFO.MAILADDRESS.COUNTRY>
<CONTACTINFO.MAILADDRESS.COUNTRYCODE></CONTACTINFO.MAILADDRESS.COUNTRYCODE>
<SHIPTO.CONTACTNAME></SHIPTO.CONTACTNAME>
<SHIPTO.PREFIX></SHIPTO.PREFIX>
<SHIPTO.FIRSTNAME></SHIPTO.FIRSTNAME>
<SHIPTO.INITIAL></SHIPTO.INITIAL>
<SHIPTO.LASTNAME></SHIPTO.LASTNAME>
<SHIPTO.COMPANYNAME></SHIPTO.COMPANYNAME>
<SHIPTO.PRINTAS></SHIPTO.PRINTAS>
<SHIPTO.TAXABLE></SHIPTO.TAXABLE>
<SHIPTO.TAXGROUP></SHIPTO.TAXGROUP>
<SHIPTO.PHONE1></SHIPTO.PHONE1>
<SHIPTO.PHONE2></SHIPTO.PHONE2>
<SHIPTO.CELLPHONE></SHIPTO.CELLPHONE>
<SHIPTO.PAGER></SHIPTO.PAGER>
<SHIPTO.FAX></SHIPTO.FAX>
<SHIPTO.EMAIL1></SHIPTO.EMAIL1>
<SHIPTO.EMAIL2></SHIPTO.EMAIL2>
<SHIPTO.URL1></SHIPTO.URL1>
<SHIPTO.URL2></SHIPTO.URL2>
<SHIPTO.VISIBLE></SHIPTO.VISIBLE>
<SHIPTO.MAILADDRESS.ADDRESS1></SHIPTO.MAILADDRESS.ADDRESS1>
<SHIPTO.MAILADDRESS.ADDRESS2></SHIPTO.MAILADDRESS.ADDRESS2>
<SHIPTO.MAILADDRESS.CITY></SHIPTO.MAILADDRESS.CITY>
<SHIPTO.MAILADDRESS.STATE></SHIPTO.MAILADDRESS.STATE>
<SHIPTO.MAILADDRESS.ZIP></SHIPTO.MAILADDRESS.ZIP>
<SHIPTO.MAILADDRESS.COUNTRY></SHIPTO.MAILADDRESS.COUNTRY>
<SHIPTO.MAILADDRESS.COUNTRYCODE></SHIPTO.MAILADDRESS.COUNTRYCODE>
<BILLTO.CONTACTNAME></BILLTO.CONTACTNAME>
<BILLTO.PREFIX></BILLTO.PREFIX>
<BILLTO.FIRSTNAME></BILLTO.FIRSTNAME>
<BILLTO.INITIAL></BILLTO.INITIAL>
<BILLTO.LASTNAME></BILLTO.LASTNAME>
<BILLTO.COMPANYNAME></BILLTO.COMPANYNAME>
<BILLTO.PRINTAS></BILLTO.PRINTAS>
<BILLTO.TAXABLE></BILLTO.TAXABLE>
<BILLTO.TAXGROUP></BILLTO.TAXGROUP>
<BILLTO.PHONE1></BILLTO.PHONE1>
<BILLTO.PHONE2></BILLTO.PHONE2>
<BILLTO.CELLPHONE></BILLTO.CELLPHONE>
<BILLTO.PAGER></BILLTO.PAGER>
<BILLTO.FAX></BILLTO.FAX>
<BILLTO.EMAIL1></BILLTO.EMAIL1>
<BILLTO.EMAIL2></BILLTO.EMAIL2>
<BILLTO.URL1></BILLTO.URL1>
<BILLTO.URL2></BILLTO.URL2>
<BILLTO.VISIBLE></BILLTO.VISIBLE>
<BILLTO.MAILADDRESS.ADDRESS1></BILLTO.MAILADDRESS.ADDRESS1>
<BILLTO.MAILADDRESS.ADDRESS2></BILLTO.MAILADDRESS.ADDRESS2>
<BILLTO.MAILADDRESS.CITY></BILLTO.MAILADDRESS.CITY>
<BILLTO.MAILADDRESS.STATE></BILLTO.MAILADDRESS.STATE>
<BILLTO.MAILADDRESS.ZIP></BILLTO.MAILADDRESS.ZIP>
<BILLTO.MAILADDRESS.COUNTRY></BILLTO.MAILADDRESS.COUNTRY>
<BILLTO.MAILADDRESS.COUNTRYCODE></BILLTO.MAILADDRESS.COUNTRYCODE>
<STATUS>active</STATUS>
<ONETIME>false</ONETIME>
<CUSTMESSAGEID></CUSTMESSAGEID>
<ONHOLD>false</ONHOLD>
<PRCLST_OVERRIDE>C</PRCLST_OVERRIDE>
<OEPRCLSTKEY></OEPRCLSTKEY>
<OEPRICESCHEDKEY></OEPRICESCHEDKEY>
<ENABLEONLINECARDPAYMENT>true</ENABLEONLINECARDPAYMENT>
<ENABLEONLINEACHPAYMENT>true</ENABLEONLINEACHPAYMENT>
<VSOEPRCLSTKEY></VSOEPRCLSTKEY>
<WHENMODIFIED>12/18/2018 16:07:40</WHENMODIFIED>
<ARINVOICEPRINTTEMPLATEID></ARINVOICEPRINTTEMPLATEID>
<OEQUOTEPRINTTEMPLATEID></OEQUOTEPRINTTEMPLATEID>
<OEORDERPRINTTEMPLATEID></OEORDERPRINTTEMPLATEID>
<OELISTPRINTTEMPLATEID></OELISTPRINTTEMPLATEID>
<OEINVOICEPRINTTEMPLATEID></OEINVOICEPRINTTEMPLATEID>
<OEADJPRINTTEMPLATEID></OEADJPRINTTEMPLATEID>
<OEOTHERPRINTTEMPLATEID></OEOTHERPRINTTEMPLATEID>
<WHENCREATED>01/01/1970 00:00:00</WHENCREATED>
<CREATEDBY></CREATEDBY>
<MODIFIEDBY>1</MODIFIEDBY>
<OBJECTRESTRICTION>Unrestricted</OBJECTRESTRICTION>
<DISPLAYCONTACTKEY>38</DISPLAYCONTACTKEY>
<CONTACTKEY></CONTACTKEY>
<SHIPTOKEY></SHIPTOKEY>
<BILLTOKEY></BILLTOKEY>
<CUSTREPKEY>2</CUSTREPKEY>
<SHIPVIAKEY>1</SHIPVIAKEY>
<TERRITORYKEY></TERRITORYKEY>
<TERMSKEY>1</TERMSKEY>
<ACCOUNTLABELKEY></ACCOUNTLABELKEY>
<ACCOUNTKEY>25</ACCOUNTKEY>
<CUSTTYPEKEY>1</CUSTTYPEKEY>
<PRICESCHEDULEKEY></PRICESCHEDULEKEY>
<OFFSETGLACCOUNTNO></OFFSETGLACCOUNTNO>
<OFFSETGLACCOUNTNOTITLE></OFFSETGLACCOUNTNOTITLE>
<ADVBILLBY></ADVBILLBY>
<ADVBILLBYTYPE></ADVBILLBYTYPE>
<SUPDOCID></SUPDOCID>
<MEGAENTITYKEY></MEGAENTITYKEY>
<MEGAENTITYID></MEGAENTITYID>
<MEGAENTITYNAME></MEGAENTITYNAME>
<RESTRICTEDLOCATIONS></RESTRICTEDLOCATIONS>
<RESTRICTEDDEPARTMENTS></RESTRICTEDDEPARTMENTS>
</customer></data>
</result>
</operation>
</response>
Please help me.
Quick test shows XmlSerializer can handle this pretty easily
Test class:
[XmlRoot]
public class Test
{
[XmlElement(ElementName="Foo.Alpha")]
public string Alpha {get;set;}
[XmlElement(ElementName="Foo.Beta")]
public string Beta {get;set;}
}
Example method:
private static void Main()
{
var src = #"<Test>
<Foo.Alpha>value 1</Foo.Alpha>
<Foo.Beta>value 2</Foo.Beta>
</Test>";
using (var sreader = new StringReader(src))
using (var reader = XmlReader.Create(sreader))
{
var serializer = new XmlSerializer(typeof(Test));
var test = (Test)serializer.Deserialize(reader);
Console.WriteLine(test.Alpha);
Console.WriteLine(test.Beta);
}
}
Update: since the XML document you are processing is very large, you should consider what you actually need to do. If you need to manipulate the entire document as objects then the approach taken in JP Hellemons's answer may be the way to go. If you are only interested in certain fields, then it may be better to load the XML into an XDocument or XmlDocument and extract the fields you are interested in from that, or even write a forward-only parser using XmlReader to do the same thing.
I have pasted your XML in an XMLFile1.xml and pasted it in Visual Studio to generate classes, so this will be a lot of autogenerated code... warning
could not fit auto gen code...
Body is limited to 30000 characters; you entered 93977
Full code here:
https://pastebin.com/VxzNUjsv
Smaller version:
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<RECORDNO>5</RECORDNO>
<CUSTOMERID>CUST-00101</CUSTOMERID>
<PARENTNAME>parent</PARENTNAME>
<DISPLAYCONTACT.CONTACTNAME>Sun Microsystems - EBC(CCUST-00101)</DISPLAYCONTACT.CONTACTNAME>
<DISPLAYCONTACT.COMPANYNAME>Sun Microsystems - EBC</DISPLAYCONTACT.COMPANYNAME>
</customer>
and C# code:
class Program
{
static void Main(string[] args)
{
using (var sreader = new StringReader(File.ReadAllText(#"C:\Users\JP\source\repos\soXmlParsing\soXmlParsing\XMLFile1.xml")))
using (var reader = XmlReader.Create(sreader))
{
var serializer = new XmlSerializer(typeof(customer));
var test = (customer)serializer.Deserialize(reader);
Console.WriteLine(test.PARENTNAME);
Console.WriteLine(test.DISPLAYCONTACTCONTACTNAME);
}
}
}
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class customer
{
private byte rECORDNOField;
private string cUSTOMERIDField;
private string pARENTNAMEField;
private string dISPLAYCONTACTCONTACTNAMEField;
private string dISPLAYCONTACTCOMPANYNAMEField;
/// <remarks/>
public byte RECORDNO
{
get
{
return this.rECORDNOField;
}
set
{
this.rECORDNOField = value;
}
}
/// <remarks/>
public string CUSTOMERID
{
get
{
return this.cUSTOMERIDField;
}
set
{
this.cUSTOMERIDField = value;
}
}
/// <remarks/>
public string PARENTNAME
{
get
{
return this.pARENTNAMEField;
}
set
{
this.pARENTNAMEField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DISPLAYCONTACT.CONTACTNAME")]
public string DISPLAYCONTACTCONTACTNAME
{
get
{
return this.dISPLAYCONTACTCONTACTNAMEField;
}
set
{
this.dISPLAYCONTACTCONTACTNAMEField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DISPLAYCONTACT.COMPANYNAME")]
public string DISPLAYCONTACTCOMPANYNAME
{
get
{
return this.dISPLAYCONTACTCOMPANYNAMEField;
}
set
{
this.dISPLAYCONTACTCOMPANYNAMEField = value;
}
}
}
I have a class that could be serialized on its own, for example:
[XmlRoot("NameOfMyRoot", Namespace = "myNamespace")]
public class Inner
{
public Inner(){}
public string SomeString { get; set; }
}
Which is perfectly serializing into (I am using ns alias for myNamespace, see full demo)
<?xml version="1.0" encoding="utf-16"?>
<NameOfMyRoot xmlns:ns="myNamespace">
<ns:SomeString></ns:SomeString>
</NameOfMyRoot>
Now I want this object to be part of another one (the wrapper):
[XmlRoot("Root")]
public class Outer<T>
{
public T Property{ get; set; }
public Outer(){}
public Outer(T inner)
{
Property = inner;
}
}
Which gives me this:
<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:ns="myNamespace">
<Property>
<ns:SomeString></ns:SomeString>
</Property>
</Root>
What I want is just embedding inner object as-is into its parent, like so:
<?xml version="1.0" encoding="utf-16"?>
<Root>
<NameOfMyRoot xmlns:ns="myNamespace">
<ns:SomeString></ns:SomeString>
</NameOfMyRoot>
</Root>
Notice that namespace should not move to root, and I can't specify element's name, since there will be many different types.
Fiddle with full example.
Of cource, I can just serialize them separately and combine through some nasty string manipulation, but I hope there is a neat way to achieve this somehow.
There's no easy way to do that. You can do it at runtime, though:
// perhaps discover these details at runtime
var attribs = new XmlAttributeOverrides();
attribs.Add(typeof(Outer<Inner>), "Property", new XmlAttributes
{
XmlElements = { new XmlElementAttribute {ElementName = "NameOfMyRoot" } }
});
attribs.Add(typeof(Inner), "SomeString", new XmlAttributes
{
XmlElements = { new XmlElementAttribute { Namespace = "myNamespace"} }
});
var ser = new XmlSerializer(typeof(Outer<Inner>), attribs);
var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
ser.Serialize(Console.Out, obj);
Note that you must store and re-use such a serializer; for simple new XmlSerializer() examples, the serializer is cached internally and re-used; however, for non-trivial cases like this, a new dynamic type is emitted each time, so you will leak memory (it won't be unloaded).
That gives you:
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<NameOfMyRoot>
<SomeString xmlns="myNamespace">abc</SomeString>
</NameOfMyRoot>
</Root>
If you don't want the two xmlns alias declaration, those can be removed separately, but they do not change the meaning, at least to a compliant reader. Likewise, the ns can be added as an alias:
var obj = new Outer<Inner> { Property = new Inner { SomeString = "abc" } };
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ns.Add("ns", "myNamespace");
ser.Serialize(Console.Out, obj, ns);
which gives:
<Root xmlns:ns="myNamespace">
<NameOfMyRoot>
<ns:SomeString>abc</ns:SomeString>
</NameOfMyRoot>
</Root>
As an alternative approach:
using System;
using System.Xml;
using System.Xml.Serialization;
[XmlRoot("NameOfMyRoot")]
public class Inner
{
public Inner() { }
[XmlElement(Namespace = "myNamespace")]
public string SomeString { get; set; }
}
static class Program
{
static void Main()
{
using (XmlWriter writer = XmlWriter.Create(Console.Out))
{
writer.WriteStartDocument(false);
writer.WriteStartElement("Root");
var ser = new XmlSerializer(typeof(Inner));
var obj = new Inner { SomeString = "abc" };
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ns.Add("ns", "myNamespace");
ser.Serialize(writer, obj, ns);
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
}
What I've done here is to manually write the root node, and only get the XmlSerializer to write the inner content. Note that I had to change the attributes aroung SomeString to make it work in the way you expect (where it is the string that has the namespace, not the object).
I have two classes. The base class has a public property with a DataMember. Now, I do not want this property to be serialized in the child class. I have no control over the parent class, and several other classes do inherit from it.
Is there a way to "hide" this attribute from the XmlSerializer that's used by WCF ? (the context here is a WCF RESTful web service).
Yes, it is possible using the XmlAttributeOverrides class, and the XmlIgnore property. Here is the example based on the one from MSDN:
public class GroupBase
{
public string GroupName;
public string Comment;
}
public class GroupDerived : GroupBase
{
}
public class Test
{
public static void Main()
{
Test t = new Test();
t.SerializeObject("IgnoreXml.xml");
}
public XmlSerializer CreateOverrider()
{
XmlAttributeOverrides xOver = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes();
attrs.XmlIgnore = true; //Ignore the property on serialization
xOver.Add(typeof(GroupDerived), "Comment", attrs);
XmlSerializer xSer = new XmlSerializer(typeof(GroupDerived), xOver);
return xSer;
}
public void SerializeObject(string filename)
{
XmlSerializer xSer = CreateOverrider();
GroupDerived myGroup = new GroupDerived();
myGroup.GroupName = ".NET";
myGroup.Comment = "My Comment...";
TextWriter writer = new StreamWriter(filename);
xSer.Serialize(writer, myGroup);
writer.Close();
}
Result:
<?xml version="1.0" encoding="utf-8"?>
<GroupDerived xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GroupName>.NET</GroupName>
</GroupDerived>
Result with XmlIgnore = false;:
<?xml version="1.0" encoding="utf-8"?>
<GroupDerived xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GroupName>.NET</GroupName>
<Comment>My Comment...</Comment>
</GroupDerived>
I am doing the program in convert XML file to List Objects. I have successfully done serialization from List to XML .but I have an problem on doing deserialization. Please anyone tell me what's the wrong i have done in this code.
This is my XML code.
<?xml version="1.0"?>
<Contact_x0020_Form xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Contact>
<Contact>
<Id>1</Id>
<Name>vicky1kumar</Name>
<Phone>248847227</Phone>
</Contact>
<Contact>
<Id>2</Id>
<Name>vicky1kumar2kumar</Name>
<Phone>725228355</Phone>
</Contact>
<Contact>
<Id>3</Id>
<Name>vicky1kumar2kumar3kumar</Name>
<Phone>2032848116</Phone>
</Contact>
<Contact>
<Id>4</Id>
<Name>vicky1kumar2kumar3kumar4kumar</Name>
<Phone>853938969</Phone>
</Contact>
<Contact>
<Id>5</Id>
<Name>vicky1kumar2kumar3kumar4kumar5kumar</Name>
<Phone>530646891</Phone>
</Contact>
</Contact>
<Id>0</Id>
</Contact_x0020_Form>
This is my Class for convert XML to List Object
public class Converter
{
public static T XmlToObject<T>(string xml)
{
using (var xmlStream = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(XmlReader.Create(xmlStream));
}
}
public static List<T> XmlToObjectList<T>(string xml, string nodePath)
{
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
var returnItemsList = new List<T>();
foreach (XmlNode xmlNode in xmlDocument.SelectNodes(nodePath))
{
returnItemsList.Add(XmlToObject<T>(xmlNode.OuterXml));
}
return returnItemsList;
}
}
And this is my DEserialization code...
List<string> decont = new List<string>();
decont = Converter.XmlToObjectList<string>(#"C:\vignesh\serialization\xmlserialize\XmlSerializeContact.xml","//Contact");
foreach (var item in decont)
{
Console.WriteLine(decont);
}
I got this error:
Data at the root level is invalid. Line 1, position 1.
Data at the root level is invalid. Line 1, position 1.
To address this first error, you must understand the cause. The issue is LoadXml accepts an xml string; whereas you are passing a path to an Xml file. You need to use Load instead of LoadXml.
That said, there are a lot of other things you need to correct. The serialized XML provided in your question seems to be incorrect--e.g. the Contact node is its own parent. Thus, your node selection is giving you the entire Xml. (Did you mean to define Contacts node to be the parent of the Contact list?)
<Contacts>
.. <Contact>
First, your xml should look like this:
<?xml version="1.0"?>
<Contact_x0020_Form>
<Contacts>
<Contact>
<Id>1</Id>
<Name>vicky1kumar</Name>
<Phone>248847227</Phone>
</Contact>
<Contact>
<Id>2</Id>
<Name>vicky1kumar2kumar</Name>
<Phone>725228355</Phone>
</Contact>
</Contacts>
</Contact_x0020_Form>
Second, define serialization classes something like :
[XmlRoot(ElementName = "Contact_x0020_Form")]
public class Root
{
[XmlElement("Contacts")]
public Contacts contacts{get;set;}
}
public class Contacts
{
public List<Contact> contacts {get;set;}
}
public class Contact
{
[XmlElement("Id")]
public int Id {get;set;}
[XmlElement("Name")]
public string Name {get;set;}
[XmlElement("Phone")]
public string Phone {get;set;}
}
and your helper classes
public static class serialize
{
public static T Deserialize<T>(string path)
{
T result;
using (var stream = File.Open(path, FileMode.Open))
{
result = Deserialize<T>(stream);
}
return result;
}
public static void Serialize<T>(T root, string path)
{
using (var stream = File.Open(path, FileMode.Create))
{
var xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(stream, root);
}
}
public static T Deserialize<T>(Stream stream)
{
var xmlSerializer = new XmlSerializer(typeof(T));
return (T)xmlSerializer.Deserialize(stream);
}
}
And, finally your func:
static void Main()
{
var a = serialize.Deserialize<Root>("input.xml"); //xml file name given here.
Console.WriteLine(a.contacts);
}
This is how you should proceed. Then on, you can get the list of objects that you want.
use this before calling xml data in deserialization
xml = Regex.Replace(xml, "<\\?xml.*?>", String.Empty);
here xml is your xml data.
I have a class which contain an interface member variable.How can i deserialize this class
interface ISensor { }
[Serializable]
class Sensor: ISensor { }
[Serializable]
class Root
{
[XmlElement("Sensor")]
public List<ISensor> SensorList{ get; set; }
}
My XML will be like this
<?xml version="1.0" encoding="us-ascii"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Sensor >
<SensorName>Name1</SensorName>
<SensorValue>0.0</SensorValue>
</Sensor>
<Sensor>
<SensorName>Name2</SensorName>
<SensorValue>148.00</SensorValue>
</Sensor>
</Root>
Assuming you are using XmlSerializer, there are two changes required for both serialization and deserialization:
Tell the serializer the list of types that can appear, in other words the types that inherit from Sensor.
Use a class for the List rather than an interface, in other words replace List<ISensor> with List<Sensor>.
Unfortunately, the XmlSerializer does not handle interfaces in the way you want. See XmlSerializer serialize generic List of interface for more information.
If using a base class is not an option You could write your own XML serializer by implementing IXmlSerializable. Override ReadXml and parse the XML manually.
For example:
public interface ISensor { }
[Serializable]
public class Sensor : ISensor { }
[Serializable]
public class Root
{
// Changed List<ISensor> to List<Sensor>. I also changed
// XmlElement to XmlArray so it would appear around the list.
[XmlArray("Sensor")]
public List<Sensor> SensorList { get; set; }
}
[Serializable]
public class SensorA : Sensor
{
[XmlElement("A")]
public string A { get; set; }
}
[Serializable]
public class SensorB : Sensor
{
[XmlElement("B")]
public string B { get; set; }
}
class Program
{
public static void Main(string[] args)
{
XmlSerializer xmlSerializer;
Root root = new Root();
root.SensorList = new List<Sensor>();
root.SensorList.Add(new SensorA() {A = "foo"});
root.SensorList.Add(new SensorB() {B = "bar"});
// Tell the serializer about derived types
xmlSerializer = new XmlSerializer(typeof (Root),
new Type[]{typeof (SensorA), typeof(SensorB)});
StringBuilder stringBuilder = new StringBuilder();
using (StringWriter stringWriter = new StringWriter(stringBuilder))
{
xmlSerializer.Serialize(stringWriter, root);
}
// Output the serialized XML
Console.WriteLine(stringBuilder.ToString());
Root root2;
using (StringReader stringReader = new StringReader(stringBuilder.ToString()))
{
root2 = (Root) xmlSerializer.Deserialize(stringReader);
}
}
}
The output from the Console.WriteLine statement is:
<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Sensor>
<Sensor xsi:type="SensorA">
<A>foo</A>
</Sensor>
<Sensor xsi:type="SensorB">
<B>bar</B>
</Sensor>
</Sensor>
</Root>