I want final xml as follows...
<Programs>
<Program><id>4</id><isRead>true</isRead><isWrite>false</isWrite></Program>
<Program><id>8</id><isRead>true</isRead><isWrite>true</isWrite></Program>
</programs>
now following is the code written
XmlDocument xmlDoc = new XmlDocument();
XmlNode rootNode = xmlDoc.CreateNode(XmlNodeType.Element,"programs",null);
xmlDoc.AppendChild(rootNode);
foreach (dynamic item in access)
{
XmlNode myXmlNode = JsonConvert.DeserializeXmlNode(item.ToString(), "program");
rootNode.AppendChild(myXmlNode); //error
}
where in myXmlNode.InnerXml, I am already getting following
<Program><id>4</id><isRead>true</isRead><isWrite>false</isWrite></Program>
And so, running the loop for all children to add in which is parent. But I am getting error for line //error as marked above. Error is:
The specified node cannot be inserted as the valid child of this node,
because the specified node is the wrong type.
You are trying to insert different type of xml node. You could use ImportNode to apply it.
foreach (dynamic item in access)
{
XmlNode myXmlNode = JsonConvert.DeserializeXmlNode(item.ToString(), "program");
rootNode.AppendChild(rootNode.OwnerDocument.ImportNode(myXmlNode.FirstChild,true));
}
I would recommend you create a model for what you are looking to create in XML, then serialize a list of the model to XML.
The reason being that you will end up with something far more maintainable.
Your model would be something like this:
public class Program
{
public int Id { get; set; }
public bool IsRead { get; set; }
public bool IsWrite { get; set; }
}
And you can serialize it by following this article:
https://support.microsoft.com/en-gb/help/815813/how-to-serialize-an-object-to-xml-by-using-visual-c
I've used the XmlSerializer library myself a few times.
public class Program
{
public int Id { get; set; }
public bool IsRead { get; set; }
public bool IsWrite { get; set; }
}
public class XmlTemplate
{
public List<Program> Programs { get; set; }
}
class MainProgram
{
static void Main(string[] args)
{
var xmlTemplate = new XmlTemplate();
xmlTemplate.Programs = new List<Program>();
xmlTemplate.Programs.Add(new Program() { Id = 123, IsRead = true, IsWrite = false });
xmlTemplate.Programs.Add(new Program() { Id = 456, IsRead = false, IsWrite = true });
var serializer = new XmlSerializer(typeof(XmlTemplate));
var stream = new StringWriter();
serializer.Serialize(stream, xmlTemplate);
Console.WriteLine(stream.ToString());
Console.ReadKey();
}
}
This outputs the XML in the following format:
<XmlTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Programs>
<Program>
<Id>123</Id>
<IsRead>true</IsRead>
<IsWrite>false</IsWrite>
</Program>
<Program>
<Id>456</Id>
<IsRead>false</IsRead>
<IsWrite>true</IsWrite>
</Program>
</Programs>
</XmlTemplate>
Related
I am trying to find if an element value exists then get a element value below it. i.e.
<Reply>
<customer id="1223">
<group>A</group>
<class>
<custclass>AB</custclass>
<custval>1</custval>
</class>
<class>
<custclass>CD</custclass>
<custval>2</custval>
</class>
</customer>
</Reply>
I need to get the custval element value if the custclass = "CD". What is the best way to set this into a string in C# "2"? So I am looking for if custclass element value of "CD" exists then return the custval element value of 2.
Thanks for any info.
We can read the property value using various ways-
Method 1 - using XmlDocument
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList xnl = doc.SelectNodes("/Reply/customer/class");
foreach (XmlNode node in xnl)
{
if (node.ChildNodes[0].InnerText == "CD")
{
Console.WriteLine(node.ChildNodes[1].InnerText);
}
}
Method 2 - using XDcoument and LINQ
XDocument xml = XDocument.Load(xmlFile);
var result = xml.Root.DescendantsAndSelf("class")
.Where(r => (string)r.Element("custclass").Value == "CD")
.Select(s=> (string)s.Element("custval").Value).Single();
Console.WriteLine(result);
Method 3 - using XDocument and XPathSelectElement
var custval = xml.XPathSelectElement("Reply/customer/class[custclass='CD']/custval").Value;
Console.WriteLine(custval);
Method 4 - using XmlSerializer
Create C# classes using xmltocsharp & use Deserialize to convert the xml to object
[XmlRoot(ElementName = "class")]
public class Class
{
[XmlElement(ElementName = "custclass")]
public string Custclass { get; set; }
[XmlElement(ElementName = "custval")]
public string Custval { get; set; }
}
[XmlRoot(ElementName = "customer")]
public class Customer
{
[XmlElement(ElementName = "group")]
public string Group { get; set; }
[XmlElement(ElementName = "class")]
public List<Class> Class { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "Reply")]
public class Reply
{
[XmlElement(ElementName = "customer")]
public Customer Customer { get; set; }
}
static async System.Threading.Tasks.Task Main(string[] args)
{
string xmlFile = #"xxxxxx.xml";
using (StreamReader r = new StreamReader(xmlFile))
{
string xmlString = r.ReadToEnd();
XmlSerializer ser = new XmlSerializer(typeof(Reply));
using (TextReader reader = new StringReader(xmlString))
{
var result = (Reply)ser.Deserialize(reader);
var custvalue = result.Customer.Class.Where(i => i.Custclass == "CD").Select(a => a.Custval).Single();
Console.WriteLine(custvalue);
}
}
}
This question already has answers here:
How do I stop an empty tag from being emitted by XmlSerializer?
(4 answers)
Closed 4 years ago.
[XmlRoot("SAPInformationInterchangeXML")]
public class EWayBillResponseXML
{
[XmlElement(ElementName = "SAPBusinessNetworkCustomerID")]
public string SAPBusinessNetworkCustomerID { get; set; }
[XmlElement(ElementName = "INVOIC")]
public ResponseINVOIC Invoice { get; set; }
}
public class ResponseINVOIC
{
[XmlElement(ElementName = "HeaderInformation")]
public string HeaderInformation { get; set; }
[XmlElement(ElementName = "AuthorizationInformation")]
public string AuthorizationInformation { get; set; }
}
var encoding = Encoding.GetEncoding("ISO-8859-1");
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = false,
Encoding = encoding
};
string requestHeaderInformation = null, requestAuthorizationInformation = null;
EWayBillResponseXML obj = new EWayBillResponseXML
{
SAPBusinessNetworkCustomerID = "1",
Invoice = new ResponseINVOIC
{
HeaderInformation = requestHeaderInformation,
AuthorizationInformation = requestAuthorizationInformation
}
};
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(obj.GetType());
using (var stream = new MemoryStream())
{
using (var xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
{
x.Serialize(xmlWriter, obj);
}
Console.WriteLine(encoding.GetString(stream.ToArray()));
}
I have created 2 objects named EWayBillResponseXML and ResponseINVOIC. I tried to serialize using above code snippet. It gives me serialized XML but it returns null object element too. I don't need null object in serialized XML. Can you Please help me out.
Currently getting output:
<?xml version="1.0" encoding="iso-8859-1"?>
<SAPInformationInterchangeXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SAPBusinessNetworkCustomerID>1</SAPBusinessNetworkCustomerID>
<INVOIC />
</SAPInformationInterchangeXML>
Expected output:
<?xml version="1.0" encoding="iso-8859-1"?>
<SAPInformationInterchangeXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SAPBusinessNetworkCustomerID>1</SAPBusinessNetworkCustomerID>
</SAPInformationInterchangeXML>
You can add the following method to your serializable class (EWayBillResponseXML):
public bool ShouldSerializeInvoice()
{
return Invoice != null;
}
You can read more about that here.
As #gmiley said, you should make method named like this ShouldSerialize___ where ___ is the name of property that should or not be serialized. That method needs to be in class where is said property
So, in your case, make ShouldSerializeResponseINVOIC method in your EWayBillResponseXML class
[XmlRoot("SAPInformationInterchangeXML")]
public class EWayBillResponseXML
{
[XmlElement(ElementName = "SAPBusinessNetworkCustomerID")]
public string SAPBusinessNetworkCustomerID { get; set; }
[XmlElement(ElementName = "INVOIC")]
public ResponseINVOIC Invoice { get; set; }
public book ShouldSerializeInvoice()
{
return Invoice != null;
}
}
Edit:
Dbc correctly said in comment that Invoice is not actually null but empty, so you should handle that.
I am creating XML to send data. The data contains multiple datatypes as string, integer and decimal. My XML format and c# code to create it as follows.
<root>
<data>
<struct>
<PartnerCD></PartnerCD>
<UserName> </UserName>
<Password> </Password>
<Action> </Action>
<OfficeCD></OfficeCD>
<ChannelCD></ChannelCD>
<Token></Token>
<Notes> </Notes>
<Products>
<Product>
<ProductID></ProductID>
<SVA></SVA>
<Amount></Amount>
</Product>
</Products>
</struct>
</data>
</root>
And my c# code is
public static string CreateRequestXML(string partnerCd, string userName, string password, string action, string productId, string token, string sva, string amount)
{
XmlDocument doc = new XmlDocument();
XmlElement elemRoot = doc.CreateElement("root");
XmlElement elemData = doc.CreateElement("data");
XmlElement elemStruct = doc.CreateElement("struct");
XmlElement elemProducts = doc.CreateElement("Products");
XmlElement elemProduct = doc.CreateElement("Product");
doc.AppendChild(elemRoot);
elemRoot.AppendChild(elemData);
elemData.AppendChild(elemStruct);
//Insert data here
InsertDataNode(doc, elemStruct, "PartnerCD", partnerCd);
InsertDataNode(doc, elemStruct, "UserName", userName);
InsertDataNode(doc, elemStruct, "Password", password);
InsertDataNode(doc, elemStruct, "Action", action);
InsertDataNode(doc, elemStruct, "Token", token);
elemStruct.AppendChild(elemProducts);
elemProducts.AppendChild(elemProduct);
InsertDataNode(doc, elemProduct, "ProductID", productId);
InsertDataNode(doc, elemProduct, "SVA", sva);
InsertDataNode(doc, elemProduct, "Amount", amount);
return doc.OuterXml;
}
private static void InsertDataNode(XmlDocument doc, XmlElement parentElem, string nodeName, string nodeValue)
{
XmlElement elem = doc.CreateElement(nodeName);
elem.InnerText = nodeValue;
parentElem.AppendChild(elem);
}
and am getting the result as
<root>
<data>
<struct>
<PartnerCD>123</PartnerCD>
<UserName>api</UserName>
<Password>pass</Password>
<Action>token</Action>
<Token>4847898</Token>
<Products>
<Product>
<ProductID>123</ProductID>
<SVA>e8a8227c-bba3-4f32-a2cd-15e8f246344b</SVA>
<Amount>700</Amount>
</Product>
</Products>
</struct>
</data>
</root>
I want the PartnerCD and ProductId elements as integer and Amount element as decimal. I have tried XMLNodeType but no use.
Well the data type is irrelevant in the XML as such, it's all defined in the schema it uses, that's where the declaration of expected data types are stored.
So if you have a XSD that says that /root/data/struct/PartnerCD is of type xs:int then you will get validation errors upon validating the file. The XML itself is just a container of all data, it doesn't include the meta information. You CAN define it manually, but the Point is beyond me in about 99.99% of the cases, and it's more or less a bastard of XML, like MSXML that will understand what you're up to.
Xml has no concept of "data type" natively, the XmlNodeType you refer to is what type of Node it is (such as element, attribute etc), not what type of data is contained within it.
Personally I would create an object and Serialize\Deserialize to\from XML like so.....
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.IO;
namespace _37321906
{
class Program
{
static void Main(string[] args)
{
Root root = new Root();
root.Data.Struct.PartnerCD = 123;
root.Data.Struct.UserName = "api";
root.Data.Struct.Password = "pass";
root.Data.Struct.Action = "token";
root.Data.Struct.Token = 4847898;
root.Data.Struct.Products.Product.Add(new Product { ProductID = 123, SVA = "e8a8227c-bba3-4f32-a2cd-15e8f246344b", Amount = 700.0001 });
// Serialize the root object to XML
Serialize<Root>(root);
// Deserialize from XML
Root DeserializeRoot = Deserialize<Root>();
}
private static void Serialize<T>(T data)
{
// Use a file stream here.
using (TextWriter WriteFileStream = new StreamWriter("test.xml"))
{
// Construct a SoapFormatter and use it
// to serialize the data to the stream.
XmlSerializer SerializerObj = new XmlSerializer(typeof(T));
try
{
// Serialize EmployeeList to the file stream
SerializerObj.Serialize(WriteFileStream, data);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Failed to serialize. Reason: {0}", ex.Message));
}
}
}
private static T Deserialize<T>() where T : new()
{
//List<Employee> EmployeeList2 = new List<Employee>();
// Create an instance of T
T ReturnListOfT = CreateInstance<T>();
// Create a new file stream for reading the XML file
using (FileStream ReadFileStream = new FileStream("test.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Construct a XmlSerializer and use it
// to serialize the data from the stream.
XmlSerializer SerializerObj = new XmlSerializer(typeof(T));
try
{
// Deserialize the hashtable from the file
ReturnListOfT = (T)SerializerObj.Deserialize(ReadFileStream);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Failed to serialize. Reason: {0}", ex.Message));
}
}
// return the Deserialized data.
return ReturnListOfT;
}
// function to create instance of T
public static T CreateInstance<T>() where T : new()
{
return (T)Activator.CreateInstance(typeof(T));
}
}
[XmlRoot(ElementName = "Product")]
public class Product
{
[XmlElement(ElementName = "ProductID")]
public int ProductID { get; set; }
[XmlElement(ElementName = "SVA")]
public string SVA { get; set; }
[XmlElement(ElementName = "Amount")]
public double Amount { get; set; }
}
[XmlRoot(ElementName = "Products")]
public class Products
{
public Products()
{
this.Product = new List<Product>();
}
[XmlElement(ElementName = "Product")]
public List<Product> Product { get; set; }
}
[XmlRoot(ElementName = "struct")]
public class Struct
{
public Struct()
{
this.Products = new Products();
}
[XmlElement(ElementName = "PartnerCD")]
public int PartnerCD { get; set; }
[XmlElement(ElementName = "UserName")]
public string UserName { get; set; }
[XmlElement(ElementName = "Password")]
public string Password { get; set; }
[XmlElement(ElementName = "Action")]
public string Action { get; set; }
[XmlElement(ElementName = "OfficeCD")]
public string OfficeCD { get; set; }
[XmlElement(ElementName = "ChannelCD")]
public string ChannelCD { get; set; }
[XmlElement(ElementName = "Token")]
public int Token { get; set; }
[XmlElement(ElementName = "Notes")]
public string Notes { get; set; }
[XmlElement(ElementName = "Products")]
public Products Products { get; set; }
}
[XmlRoot(ElementName = "data")]
public class Data
{
public Data()
{
this.Struct = new Struct();
}
[XmlElement(ElementName = "struct")]
public Struct Struct { get; set; }
}
[XmlRoot(ElementName = "root")]
public class Root
{
public Root()
{
this.Data = new Data();
}
[XmlElement(ElementName = "data")]
public Data Data { get; set; }
}
}
find your XML in the build folder called test.xml
I am having trouble deserializing a list of objects. I can get just one object to serialize into an object but cannot get the list. I get no error it just returns an empty List. This is the XML that gets returned:
<locations>
<location locationtype="building" locationtypeid="1">
<id>1</id>
<name>Building Name</name>
<description>Description of Building</description>
</location>
</locations>
This is the class I have and I am deserializing in the GetAll method:
[Serializable()]
[XmlRoot("location")]
public class Building
{
private string method;
[XmlElement("id")]
public int LocationID { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("mubuildingid")]
public string MUBuildingID { get; set; }
public List<Building> GetAll()
{
var listBuildings = new List<Building>();
var building = new Building();
var request = WebRequest.Create(method) as HttpWebRequest;
var response = request.GetResponse() as HttpWebResponse;
var streamReader = new StreamReader(response.GetResponseStream());
TextReader reader = streamReader;
var serializer = new XmlSerializer(typeof(List<Building>),
new XmlRootAttribute() { ElementName = "locations" });
listBuildings = (List<Building>)serializer.Deserialize(reader);
return listBuildings;
}
}
Try this:
[XmlRoot("locations")]
public class BuildingList
{
public BuildingList() {Items = new List<Building>();}
[XmlElement("location")]
public List<Building> Items {get;set;}
}
Then deserialize the whole BuildingList object.
var xmlSerializer = new XmlSerializer(typeof(BuildingList));
var list = (BuildingList)xmlSerializer.Deserialize(xml);
I know this is an old(er) question, but I struggled with this today, and found an answer that doesn't require encapsulation.
Assumption 1: You have control over the source Xml and how it is constructed.
Assumption 2: You are trying to serialise the Xml directly into a List<T> object
You must name the Root element in the Xml as ArrayOfxxx where xxx is the name of your class (or the name specified in XmlType (see 2.))
If you wish your xml Elements to have a different name to the class, you should use XmlType on the class.
NB: If your Type name (or class name) starts with a lowercase letter, you should convert the first character to uppercase.
Example 1 - Without XmlType
class Program
{
static void Main(string[] args)
{
//String containing the xml array of items.
string xml =
#"<ArrayOfItem>
<Item>
<Name>John Doe</Name>
</Item>
<Item>
<Name>Martha Stewart</Name>
</Item>
</ArrayOfItem>";
List<Item> items = null;
using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml)))
using (var stream = new StreamReader(mem))
{
var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item>
items = (List<Item>)ser.Deserialize(stream);
}
if (items != null)
{
items.ForEach(I => Console.WriteLine(I.Name));
}
else
Console.WriteLine("No Items Deserialised");
}
}
public class Item
{
public string Name { get; set; }
}
Example 2 - With XmlType
class Program
{
static void Main(string[] args)
{
//String containing the xml array of items.
//Note the Array Name, and the Title case on stq.
string xml =
#"<ArrayOfStq>
<stq>
<Name>John Doe</Name>
</stq>
<stq>
<Name>Martha Stewart</Name>
</stq>
</ArrayOfStq>";
List<Item> items = null;
using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml)))
using (var stream = new StreamReader(mem))
{
var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item>
items = (List<Item>)ser.Deserialize(stream);
}
if (items != null)
{
items.ForEach(I => Console.WriteLine(I.Name));
}
else
Console.WriteLine("No Items Deserialised");
}
}
[XmlType("stq")]
public class Item
{
public string Name { get; set; }
}
Not sure how Building corresponds with the location you have in your xml, but to me it makes more sense if they're named equivalently. Instead of using a List use a LocationList, and it becomes:
[Serializable()]
[XmlRoot("locations")]
public class LocationCollection{
[XmlElement("location")]
public Location[] Locations {get;set;}
}
[Serializable()]
[XmlRoot("location")]
public class Location
{
[XmlElement("id")]
public int LocationID { get; set; }
[XmlAttribute("locationtype")]
public string LocationType {get;set;}
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("mubuildingid")]
public string MUBuildingID { get; set; }
}
You can then deserialize as follows:
var request = WebRequest.Create(method) as HttpWebRequest;
var response = request.GetResponse() as HttpWebResponse;
var streamReader = new StreamReader(response.GetResponseStream());
TextReader reader = streamReader;
var serializer = new XmlSerializer(typeof(LocationCollection),
new XmlRootAttribute() { ElementName = "locations" });
var listBuildings = (LocationCollection)serializer.Deserialize(reader);
return listBuildings;
I know, old question, but came across it when faced by a similar issue.
Building on #ricovox's answer and in context of the OP's question, this is the model I would use to serialize his xml:
[Serializable, XmlRoot("locations")]
public class BuildingList
{
[XmlArrayItem("location", typeof(Building))]
public List<Building> locations { get; set; }
}
[Serializable]
public class Building
{
public int LocationID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string MUBuildingID { get; set; }
public List<Building> GetAll()
{
...
}
}
The OP's mistake was to create the list item as the root
Use [XMLArray] for collection properties.
I want to process certain elements of an XML string into an object based on the properties in the object matching up to the names of elements in the XML.
An example structure of the XML is as follows:
<Bar>
<Body>
<Header>
<A>Value</A>
<B>true</B>
</Header>
<Data>
<D>Value</D>
</Data>
<Data>
<D>Value2</D>
<Data>
</Body>
</Bar>
There can be MANY <Data> elements in the XML, however <Header> only exists once. The class I have set up is as so:
public class Foo
{
public string A { get; set; }
public bool B { get; set; }
public List<FooData> { get; set; }
public void ProcessXml(string xml)
{
XDocument xDoc = XDocument.Load(new StringReader(xml));
var propVals = (from ele in xDoc.Descendants()
join prop in this.GetType().GetProperties() on ele.Name.LocalName equals prop.Name
select new
{
prop = prop,
val = new Func<object>(() =>
{
object objValue = null;
prop.PropertyType.TryParse(ele.Value, ref objValue);
return objValue;
}).Invoke()
});
propVals.ToList().ForEach(x => x.prop.SetValue(this, x.val, null));
}
}
public class FooData
{
public string D { get; set; }
}
I came up with the method ProcessXml which starts to set things up, however at the minute I am only ever setting Header values (A, B), any ideas on how I can add many FooData items into the List from within the same method easily?
public static class TypeExtensions
{
public static void TryParse(this Type t, object valIn, ref object valOut)
{
//Do some parsing logic
try{
out = TypeDescriptor.GetConverter(t).ConvertFromInvariantString(valIn);
return true;
} catch(Exception) { return false; }
}
}
I went along a similar line as what I did with the header stuff as there isn't an easy way to combine this into one line.
var dataElements = (from dataDescendants in (from ele2 in xDoc.Descendants()
Where ele2.Name.LocalName == "Data"
select ele2.Descendants())
from dataDescendant in dataDescendants
join prop in typeof(FooItem).GetProperties() on prop.Name equals dataDescendant.Name.LocalName
select Element = dataDescendant, Property = prop, dataDescendants
group by dataDescendants into g = group
select g).ToList();
dataElements.ForEach(dataElement =>
{
FooItem fi = new FooItem();
dataElement.ToList.ForEach(x =>
{
object objVal = null;
x.Property.PropertyType.TryParse(x.Element.Value, objVal);
x.Property.SetValue(fi, objVal, null);
}
DataItems.Add(fi);
}
If your XML is really that simple, you can use Serialization to get this dynamic/self loading behavior, by decorating your model classes with the appropriate XML Serialization attributes though you will need at least 1 class for each level of indentation in the document:
void Main()
{
var xml = #"<Bar>
<Body>
<Header>
<A>Value</A>
<B>true</B>
</Header>
<Data>
<D>Value</D>
</Data>
<Data>
<D>Value2</D>
</Data>
</Body>
</Bar>";
var serializer = new XmlSerializer(typeof(Bar));
serializer.Deserialize( new MemoryStream( Encoding.ASCII.GetBytes( xml ) ) ).Dump();
}
public class Bar
{
public Body Body { get; set; }
}
public class Body
{
public Header Header { get; set; }
[XmlElement]
public Data[] Data { get; set; }
}
public class Header
{
public string A { get; set; }
public string B { get; set; }
}
public class Data
{
public string D { get; set; }
}
(Edited: I missed that there's only 1 Header element)