I'm trying to use XDocument to read in XML and deserialize it to objects.
I want to take the following XML:
<r25:spaces xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xl="http://www.w3.org/1999/xlink" xmlns:r25="http://www.collegenet.com/r25" pubdate="2019-07-15T14:51:16-07:00" engine="accl">
<r25:space crc="00000022" status="est" xl:href="space.xml?space_id=200">
<r25:space_id>200</r25:space_id>
<r25:space_name>LRN 0001</r25:space_name>
<r25:formal_name>Learning Commons -Test Scheduling Room</r25:formal_name>
<r25:partition_id xl:href="rmpart.xml?partition_id=2">2</r25:partition_id>
<r25:last_mod_dt>2019-07-11T08:01:00-07:00</r25:last_mod_dt>
</r25:space>
</r25:spaces>
and deserialize it to a List of spaces (where Space has the following definition):
public class Space
{
public long space_id { get; set; }
public string space_name { get; set; }
public string formal_name { get; set; }
public long partition_id { get ; set; }
public DateTime last_mod_dt { get; set; }
}
I've only gotten so far as to get the XElement. It dies on the serializer
var doc = XDocument.Parse(result.Content);
XNamespace ns = "http://www.collegenet.com/r25";
XElement el = doc.Element(ns + "spaces");
foreach (var space in el.Elements())
{
var serializer = new XmlSerializer(typeof(Space));
var s = (Space)serializer.Deserialize(space.CreateReader());
}
You can simply use LINQ to XML here. e.g.
using System;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApp22
{
public class Space
{
public long space_id { get; set; }
public string space_name { get; set; }
public string formal_name { get; set; }
public long partition_id { get; set; }
public DateTime last_mod { get; set; }
}
class Program
{
static void Main(string[] args)
{
var xml = #"
<r25:spaces xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xl=""http://www.w3.org/1999/xlink"" xmlns:r25=""http://www.collegenet.com/r25"" pubdate=""2019-07-15T14:51:16-07:00"" engine=""accl"">
<r25:space crc=""00000022"" status=""est"" xl:href=""space.xml?space_id=200"">
<r25:space_id>200</r25:space_id>
<r25:space_name>LRN 0001</r25:space_name>
<r25:formal_name>Learning Commons -Test Scheduling Room</r25:formal_name>
<r25:partition_id xl:href=""rmpart.xml?partition_id=2"">2</r25:partition_id>
<r25:last_mod_dt>2019-07-11T08:01:00-07:00</r25:last_mod_dt>
</r25:space>
</r25:spaces>
";
var doc = XDocument.Parse(xml);
XNamespace ns = "http://www.collegenet.com/r25";
var q = from e in doc.Element(ns + "spaces").Elements()
select new Space
{
space_id = (int)e.Element(ns + "space_id"),
space_name = (string)e.Element(ns + "space_name"),
formal_name = (string)e.Element(ns + "formal_name"),
partition_id = (long)e.Element(ns + "partition_id"),
last_mod = (DateTime)e.Element(ns + "last_mod_dt")
};
var space = q.First();
}
}
}
You can add the XmlRoot to your class to declare the namespace for that element:
[XmlRoot("space", Namespace = "http://www.collegenet.com/r25")]
public class Space
{
public long space_id { get; set; }
public string space_name { get; set; }
public string formal_name { get; set; }
public long partition_id { get; set; }
public DateTime last_mod { get; set; }
}
The deserializer will now correctly read the XML as an object.
Use the the XSD tool to generate the class and then use XmlSerializer to populate the class. Like this.
MyClass myClass;
using (var stream = new FileStream("myClass.xml", FileMode.Open))
{
var serializer = new XmlSerializer(typeof(MyClass));
myClass = serializer.Deserialize(stream);
}
I found a website that will take XML and create the proper deserialization classes. Xml2CSharp, which created the following classes that allowed the deserialization to work:
[XmlRoot(ElementName="partition_id", Namespace="http://www.collegenet.com/r25")]
public class Partition_id {
[XmlAttribute(AttributeName="href", Namespace="http://www.w3.org/1999/xlink")]
public string Href { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="space", Namespace="http://www.collegenet.com/r25")]
public class Space {
[XmlElement(ElementName="space_id", Namespace="http://www.collegenet.com/r25")]
public string Space_id { get; set; }
[XmlElement(ElementName="space_name", Namespace="http://www.collegenet.com/r25")]
public string Space_name { get; set; }
[XmlElement(ElementName="formal_name", Namespace="http://www.collegenet.com/r25")]
public string Formal_name { get; set; }
[XmlElement(ElementName="partition_id", Namespace="http://www.collegenet.com/r25")]
public Partition_id Partition_id { get; set; }
[XmlElement(ElementName="last_mod_dt", Namespace="http://www.collegenet.com/r25")]
public string Last_mod_dt { get; set; }
[XmlAttribute(AttributeName="crc")]
public string Crc { get; set; }
[XmlAttribute(AttributeName="status")]
public string Status { get; set; }
[XmlAttribute(AttributeName="href", Namespace="http://www.w3.org/1999/xlink")]
public string Href { get; set; }
}
[XmlRoot(ElementName="spaces", Namespace="http://www.collegenet.com/r25")]
public class Spaces {
[XmlElement(ElementName="space", Namespace="http://www.collegenet.com/r25")]
public Space Space { get; set; }
[XmlAttribute(AttributeName="xsi", Namespace="http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName="xl", Namespace="http://www.w3.org/2000/xmlns/")]
public string Xl { get; set; }
[XmlAttribute(AttributeName="r25", Namespace="http://www.w3.org/2000/xmlns/")]
public string R25 { get; set; }
[XmlAttribute(AttributeName="pubdate")]
public string Pubdate { get; set; }
[XmlAttribute(AttributeName="engine")]
public string Engine { get; set; }
}
Related
I run query against DB which returns me 1 row 2 columns. Each column has XML(script) inside which I need to retrieve into (ideally string) and then execute against DB.
I need the retrieved string to have lines and formatting as if i would copy if from SQL management studio.
Part of XMLresult from SQL management studio I need this format. replacement: XXXXXX
<message>
<header>
<meta version="02" type="OrMessageUdalost_Int" />
<sender name="XXXXXX" appid="XXXXXX" netid="XXXXXX" />
<receiver name="XXXXXX" appid="XXXXXX" netid="XXXXXX" />
<timestamp date="XXXXXX" time="10:11:00" gmt="+XXXXXX" />
<options priority="4" props="XXXXXX" limit="100" />
</header>
<content>
<q1:orMessageUdalost_Int xmlns:q1="XXXXXX" verze="v_2.11">
<hlavicka>
<idDatovaVeta>XXXXXX</idDatovaVeta>
<datumVytvoreni>XXXXXX</datumVytvoreni>
<ciselnikAktualizace>false</ciselnikAktualizace>
<ostrovniRezim>false</ostrovniRezim>
<puvodceDV>
<id>XXXXXX</id>
<kod>XXXXXX</kod>
</puvodceDV>
<idPuvodniDV>XXXXXX</idPuvodniDV>
<puvodniDatumVytvoreni>XXXXXX</puvodniDatumVytvoreni>
<stavUdalosti>XXXXXX</stavUdalosti>
<stavSlozky>
<slozka>
<id>XXXXXX</id>
<kod>XXXXXX</kod>
</slozka>
<isStav>XXXXXX</isStav>
</stavSlozky>
</hlavicka>
<teloFull>
Thanks for any advice.
So the key is to get the proper indentation?
In that case, I would recommend taking a look at the following SO thread:
Format XML string to print friendly XML string
The key is that you need indentation, which can be achieved through the XmlTextWrite.Formatting = Formatting.Indented option.
Use XML serializer. See code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication193
{
class Program
{
const string INPUT_FILENAME = #"c:\temp\test.xml";
const string OUTPUT_FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(INPUT_FILENAME);
StringReader sReader = new StringReader(xml);
XmlReader reader = XmlReader.Create(sReader);
XmlSerializer serializer = new XmlSerializer(typeof(Message));
Message message = (Message)serializer.Deserialize(reader);
//write
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("q1", "XXXXXX");
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
serializer.Serialize(writer,message,names);
byte[] buffer = new byte[stream.Length];
stream.Position = 0;
stream.Read(buffer, 0, (int)stream.Length);
string output = Encoding.UTF8.GetString(buffer);
}
}
[XmlRoot("message")]
public class Message
{
public Header header { get; set; }
public Content content { get; set; }
}
public class Header
{
public Meta meta { get; set; }
public Sender sender { get; set; }
public Receiver receiver { get; set; }
public Timestamp timestamp { get; set; }
public Options options { get; set; }
}
public class Meta
{
[XmlAttribute("version")]
public string version { get; set; }
[XmlAttribute("type")]
public string type { get; set; }
}
public class Sender
{
[XmlAttribute()]
public string name { get; set; }
[XmlAttribute()]
public string appid { get; set; }
[XmlAttribute()]
public string netid { get; set; }
}
public class Receiver
{
[XmlAttribute()]
public string name { get; set; }
[XmlAttribute()]
public string appid { get; set; }
[XmlAttribute()]
public string netid { get; set; }
}
public class Timestamp
{
[XmlAttribute()]
public string date { get; set; }
[XmlAttribute()]
public DateTime timespan { get; set; }
[XmlAttribute()]
public string gmt { get; set; }
}
public class Options
{
[XmlAttribute()]
public int priority { get; set; }
[XmlAttribute()]
public string props { get; set; }
[XmlAttribute()]
public int limit { get; set; }
}
public class Content
{
[XmlElement(Namespace = "XXXXXX")]
public OrMessageUdalost_Int orMessageUdalost_Int { get; set; }
}
public class OrMessageUdalost_Int
{
[XmlAttribute()]
public string verze { get; set; }
[XmlElement(Namespace = "")]
public Hlavicka hlavicka { get; set; }
}
public class Hlavicka
{
public string idDatovaVeta { get; set; }
public string datumVytvoreni { get; set; }
public string ciselnikAktualizace { get; set; }
public Boolean ostrovniRezim { get; set; }
public PuvodceDV puvodceDV { get; set; }
public string idPuvodniDV { get; set; }
public string puvodniDatumVytvoreni { get; set; }
public string stavUdalosti { get; set; }
[XmlArray("stavSlozky")]
[XmlArrayItem("slozka")]
public List<Slozka> slozka { get; set; }
public TeloFull teloFull { get; set; }
}
public class PuvodceDV
{
public string id { get; set; }
public string kod { get; set; }
}
public class Slozka
{
public string id { get; set; }
public string kod { get; set; }
}
public class TeloFull
{
}
}
I'm currently working on an application through WPF and wonder what's the better option in my case. I have a web based API that originally prints it's own XML and fills in the elements with it's data, but since this'll eventually be on a live server I thought it might seem a bit more convenient if the executable creates an XML file and parses API data into it.
If my option seems better, how do I write designated data to XML elements? I'm sorry if my question is a bit vague.
My JSON classes
[DataContract]
public class ShipmentDetails
{
[DataMember(Name="salutationCode")]
public string salutationCode { get; set; }
[DataMember(Name="firstName")]
public string firstName { get; set; }
[DataMember(Name="surName")]
public string surName { get; set; }
[DataMember(Name="streetName")]
public string streetName { get; set; }
[DataMember(Name="houseNumber")]
public string houseNumber { get; set; }
[DataMember(Name="zipCode")]
public string zipCode { get; set; }
[DataMember(Name="city")]
public string city { get; set; }
[DataMember(Name="countryCode")]
public string countryCode { get; set; }
[DataMember(Name="email")]
public string email { get; set; }
[DataMember(Name="language")]
public string language { get; set; }
}
[DataContract]
public class BillingDetails
{
[DataMember(Name="salutationCode")]
public string salutationCode { get; set; }
[DataMember(Name="firstName")]
public string firstName { get; set; }
[DataMember(Name="surName")]
public string surName { get; set; }
[DataMember(Name="streetName")]
public string streetName { get; set; }
[DataMember(Name="houseNumber")]
public string houseNumber { get; set; }
[DataMember(Name="zipCode")]
public string zipCode { get; set; }
[DataMember(Name="city")]
public string city { get; set; }
[DataMember(Name="countryCode")]
public string countryCode { get; set; }
[DataMember(Name="email")]
public string email { get; set; }
}
[DataContract]
public class CustomerDetails
{
[DataMember(Name="shipmentDetails")]
public ShipmentDetails shipmentDetails { get; set; }
[DataMember(Name="billingDetails")]
public BillingDetails billingDetails { get; set; }
}
[DataContract]
public class OrderItem
{
[DataMember(Name="orderItemId")]
public string orderItemId { get; set; }
[DataMember(Name="offerReference")]
public string offerReference { get; set; }
[DataMember(Name="ean")]
public string ean { get; set; }
[DataMember(Name="title")]
public string title { get; set; }
[DataMember(Name="quantity")]
public int quantity { get; set; }
[DataMember(Name="offerPrice")]
public double offerPrice { get; set; }
[DataMember(Name="offerId")]
public string offerId { get; set; }
[DataMember(Name="transactionFee")]
public double transactionFee { get; set; }
[DataMember(Name="latestDeliveryDate")]
public string latestDeliveryDate { get; set; }
[DataMember(Name="expiryDate")]
public string expiryDate { get; set; }
[DataMember(Name="offerCondition")]
public string offerCondition { get; set; }
[DataMember(Name="cancelRequest")]
public bool cancelRequest { get; set; }
[DataMember(Name="fulfilmentMethod")]
public string fulfilmentMethod { get; set; }
}
[DataContract]
public class Example
{
[DataMember(Name="orderId")]
public string orderId { get; set; }
[DataMember(Name="pickUpPoint")]
public bool pickUpPoint { get; set; }
[DataMember(Name="dateTimeOrderPlaced")]
public DateTime dateTimeOrderPlaced { get; set; }
[DataMember(Name="customerDetails")]
public CustomerDetails customerDetails { get; set; }
[DataMember(Name="orderItems")]
public IList<OrderItem> orderItems { get; set; }
}
My XML
using (XmlWriter writer = XmlWriter.Create("Orders.xml"))
{
writer.WriteStartElement("start");
writer.WriteElementString("customer_id", "935933");
writer.WriteStartElement("orders");
writer.WriteStartElement("order");
writer.WriteElementString("order_id", "");
writer.WriteElementString("order_ref", "");
writer.WriteElementString("order_dropshipment", "");
writer.WriteElementString("order_dlv_adr_name", "");
writer.WriteElementString("order_dlv_adr_street", "");
writer.WriteElementString("order_dlv_adr_housenr", "");
writer.WriteElementString("order_dlv_adr_zipcode", "");
writer.WriteElementString("order_dlv_adr_city", "");
writer.WriteElementString("order_dlv_adr_email", "");
writer.WriteElementString("order_dlv_adr_phone", "");
writer.WriteElementString("order_dlv_adr_country_isocode", "");
writer.WriteStartElement("orderrows");
writer.WriteStartElement("orderrow");
writer.WriteElementString("orderrow_sku", "");
writer.WriteElementString("orderrow_qty", "");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.Flush();
}
XML mapping in PHP
$order->addChild('order_id',$info['orderId']);
$order->addChild('order_ref',$info['orderId']);// order_ref is usually the same as the order_id
$order->addChild('order_dropshipment',"Y"); // Yes and No if there's no dropshipment needed
$order->addChild('order_dlv_adr_name',$info['customerDetails']['shipmentDetails']['firstName'].' '.$info['customerDetails']['shipmentDetails']['surName']);
$order->addChild('order_dlv_adr_street',$info['customerDetails']['shipmentDetails']['streetName']);
$order->addChild('order_dlv_adr_housenr',$info['customerDetails']['shipmentDetails']['houseNumber']);
$order->addChild('order_dlv_adr_zipcode',$info['customerDetails']['shipmentDetails']['zipCode']);
$order->addChild('order_dlv_adr_city',$info['customerDetails']['shipmentDetails']['city']);
$order->addChild('order_dlv_adr_email',COMPANY_EMAIL);
$order->addChild('order_dlv_adr_phone',COMPANY_PHONE);
$order->addChild('order_dlv_adr_country_isocode',$info['customerDetails']['shipmentDetails']['countryCode']);
Desired output
<start>
<customer_id>935933</customer_id>
<orders>
<order>
<order_id>11864523</order_id>
<order_ref>11864523</order_ref>
<order_dropshipment>Y</order_dropshipment>
<order_dlv_adr_name>Fred Bellens</order_dlv_adr_name>
<order_dlv_adr_street>Elisabetaelaan</order_dlv_adr_street>
<order_dlv_adr_housenr>2</order_dlv_adr_housenr>
<order_dlv_adr_zipcode>3200</order_dlv_adr_zipcode>
<order_dlv_adr_city>Aarschot</order_dlv_adr_city>
<order_dlv_adr_email>*our mail*</order_dlv_adr_email>
<order_dlv_adr_phone>077 396 814</order_dlv_adr_phone>
<order_dlv_adr_country_isocode>BE</order_dlv_adr_country_isocode>
<orderrows>
<orderrow>
<orderrow_sku>KA0 14315 21_122</orderrow_sku>
<orderrow_qty>1</orderrow_qty>
</orderrow>
</orderrows>
</order>
</orders>
</start>
There are several ways how you can achieve that desired XML.
Let me show you two different ways:
XElement
Instead of relying on the XmlWriter we can construct the desired structure with XElement.
In your case the initialization of the tree could look similar to this:
var order = //...;
var shipment = order.customerDetails.billingDetails;
var xml = new XElement("start",
new XElement("customer_id", 935933),
new XElement("orders",
new XElement("order",
new XElement("order_id", order.orderId),
new XElement("order_ref", order.orderId),
new XElement("order_dropshipment", "Y"),
new XElement("order_dlv_adr_name", $"{shipment.firstName} {shipment.surName}"),
new XElement("order_dlv_adr_street", shipment.streetName),
new XElement("order_dlv_adr_housenr", shipment.houseNumber),
new XElement("order_dlv_adr_zipcode", shipment.zipCode),
new XElement("order_dlv_adr_city", shipment.city),
new XElement("order_dlv_adr_email", "TBD"),
new XElement("order_dlv_adr_phone", "TBD"),
new XElement("order_dlv_adr_country_isocode", shipment.countryCode)
)));
Then the persistence logic would look like this:
using var sampleXml = new FileStream("sample.xml", FileMode.CreateNew, FileAccess.Write);
using var fileWriter = new StreamWriter(sampleXml);
fileWriter.Write(xml.ToString());
fileWriter.Flush();
And that's it.
JsonConvert
As an alternative if you already have the desired structure in json then you can easily convert it to XML via JsonConvert's DeserializeXmlNode:
var orderInJson = JsonConvert.SerializeObject(data);
XmlDocument orderInXml = JsonConvert.DeserializeXmlNode(orderInJson);
And here is the persistence logic:
using var sampleXml = new XmlTextWriter("sample2.xml", Encoding.UTF8);
using var fileWriter = XmlWriter.Create(sampleXml);
orderInXml.WriteTo(fileWriter);
fileWriter.Flush();
This is my xml File i want to read the all the inner test of all the child element of the exp
<TreasuryExp xmlns="http://page.com/Exp" MsgDtTm="2020-06-08T12:30:35.283"
MessageId="11EXP080620201" Source="11" Destination="CPSMS" Name="user1" RecordsCount="1861"
NetAmountSum="4440306976.00">
<Exp>
<Year1>2018</Year1>
<Year2>2019</Year2>
<Code>11</Code>
<Budget>205500101638352</Budget>
<ObjectHeadCode>52_400</ObjectHeadCode>
<DDOCode>300008</DDOCode>
<VoucherNumber>5994</VoucherNumber>
<Date>31/03/2019</Date>
<GrossAmount>51200.00</GrossAmount>
<DeductionAmount>0.00</DeductionAmount>
<NetAmount>51200.00</NetAmount>
<UniqueID>3392430</UniqueID>
<PayeeCount>0</PayeeCount>
<PayDetail>N</PayDetail>
<PayeeDetails />
</Exp>
<Exp>
<Year1>2018</Year1>
<Year2>2019</Year2>
<Code>11</Code>
<Budget>205500101638352</Budget>
<ObjectHeadCode>52_400</ObjectHeadCode>
<DDOCode>300008</DDOCode>
<VoucherNumber>5995</VoucherNumber>
<Date>31/03/2019</Date>
<GrossAmount>4400.00</GrossAmount>
<DeductionAmount>0.00</DeductionAmount>
<NetAmount>4400.00</NetAmount>
<UniqueID>3303530</UniqueID>
<PayeeCount>0</PayeeCount>
<PayDetail>N</PayDetail>
<PayeeDetails />
</Exp>
</TreasuryExp>
i and reading it and running it on loop but m getting returned same items every time
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load("E:/trial/Expenditure.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmldoc.NameTable);
XmlAttributeCollection attrColl = xmldoc.DocumentElement.Attributes;
var xmlnsattribute = attrColl.GetNamedItem("xmlns").Value;
XmlNodeList xmlnodli = xmldoc.SelectNodes("//ab:Expenditure", nsmgr);
List<Expenditure> strli = new List<Expenditure>();
here i am running a loop to load in list to get the value of the xml nodes or u can say values of each nodes
foreach (XmlNode xm in xmlnodli)
{
fin_year1 = Convert.ToInt32(xm.SelectSingleNode("//ab:Year1", nsmgr).InnerText),
fin_year2 = Convert.ToInt32(xm.SelectSingleNode("//ab:Year2", nsmgr).InnerText),
statecode = Convert.ToInt32(xm.SelectSingleNode("//ab:Code", nsmgr).InnerText),
budgetcode = Convert.ToInt64(xm.SelectSingleNode("//ab:Budget", nsmgr).InnerText),
objectheadcode = (xm.SelectSingleNode("//ab:ObjectHeadCode", nsmgr).InnerText).ToString(),
ddocode = xm.SelectSingleNode("//ab:DDOCode", nsmgr).InnerText.ToString(),
vouchernumber = Convert.ToInt32(xm.SelectSingleNode("//ab:VoucherNumber", nsmgr).InnerText),
date = Convert.ToDateTime(xm.SelectSingleNode("//ab:Date", nsmgr).InnerText),
grossamount = Convert.ToDecimal(xm.SelectSingleNode("//ab:GrossAmount", nsmgr).InnerText),
deductionamount = Convert.ToDecimal(xm.SelectSingleNode("//ab:DeductionAmount", nsmgr).InnerText),
netamount = Convert.ToDecimal(xmlnodli[i].SelectSingleNode("NetAmount", nsmgr).InnerText.ToString()),
objectheadcode = Convert.ToString(xm.SelectNodes("//ab:NetAmount", nsmgr)),
stateexpuniqueid = Convert.ToInt32(xm.SelectSingleNode("//ab:StateExpUniqueID", nsmgr).InnerText),
payeecount = Convert.ToInt32(xm.SelectSingleNode("//ab:PayeeCount", nsmgr).InnerText),
paydetail = Convert.ToString(xm.SelectSingleNode("//ab:PayDetail", nsmgr).InnerText),
}
return strli;
here is my DTO
public class Expenditure
{
public int year1 { get; set; }
public int year2 { get; set; }
public int code { get; set; }
public long budget { get; set; }
public string objectheadcode { get; set; }
public string ddocode { get; set; }
public int vouchernumber { get; set; }
public DateTime date { get; set; }
public decimal grossamount { get; set; }
public decimal deductionamount { get; set; }
public decimal netamount { get; set; }
public int stateexpuniqueid { get; set; }
public int payeecount { get; set; }
public string paydetail { get; set; }
public string payeedetails { get; set; }
public string xmlns { get; set; }
public string MsgDtTm { get; set; }
public string MessageId { get; set; }
public string Source { get; set; }
public string Destination { get; set; }
public string StateName { get; set; }
public string RecordsCount { get; set; }
public string NetAmountSum { get; set; }
}
Thank You
Use following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializier = new XmlSerializer(typeof(TreasuryExp));
TreasuryExp treasuryExp = (TreasuryExp)serializier.Deserialize(reader);
}
}
[XmlRoot(ElementName = "TreasuryExp", Namespace = "http://page.com/Exp")]
public class TreasuryExp
{
[XmlElement("Exp")]
public List<Expenditure> Expenditure { get; set; }
}
public class Expenditure
{
[XmlElement("Year1")]
public int year1 { get; set; }
[XmlElement("Year2")]
public int year2 { get; set; }
[XmlElement("Code")]
public int code { get; set; }
[XmlElement("Budget")]
public long budget { get; set; }
[XmlElement("ObjectHeadCode")]
public string objectheadcode { get; set; }
[XmlElement("DDOCode")]
public string ddocode { get; set; }
[XmlElement("VpucherNumber")]
public int vouchernumber { get; set; }
private DateTime _date { get; set; }
[XmlElement("Date")]
public string date
{
get{ return _date.ToString("dd/MM/yyyy");}
set{ _date = DateTime.ParseExact(value, "dd/MM/yyyy", CultureInfo.InvariantCulture);}
}
[XmlElement("GrossAmount")]
public decimal grossamount { get; set; }
[XmlElement("DectionAmount")]
public decimal deductionamount { get; set; }
[XmlElement("NetAmount")]
public decimal netamount { get; set; }
[XmlElement("UniqueID")]
public int stateexpuniqueid { get; set; }
[XmlElement("PayeeCount")]
public int payeecount { get; set; }
[XmlElement("PayeeDetail")]
public string paydetail { get; set; }
[XmlElement("PayeeDetails")]
public string payeedetails { get; set; }
[XmlElement("")]
public string xmlns { get; set; }
[XmlElement("")]
public string MsgDtTm { get; set; }
[XmlElement("")]
public string MessageId { get; set; }
[XmlElement("")]
public string Source { get; set; }
[XmlElement("")]
public string Destination { get; set; }
[XmlElement("")]
public string StateName { get; set; }
[XmlElement("")]
public string RecordsCount { get; set; }
[XmlElement("")]
public string NetAmountSum { get; set; }
}
}
I am trying to serialise a piece of XML that is being returned from a third party API. However when doing so i am only retrieving part of the object upon serialisation. And only some of the values seem to exist. I thought this could be a input type problem, however all the types seem to be correct. I think it may have something to do with how my model is constructed.After debugging the code i have narrowed it down to be a problem with the conversion of the xml into the object.
C# CODE:
//[Route("api/AvailabiliyCheck/GetAvailability/{CSSDistrictCode}/{GoldAddressKey}")]
public EADAvailabilityDetails GetAvailabilityEAD([FromUri] string CSSDistrictCode, [FromUri] string GoldAddressKey)
{
//Load the request xml template
XmlDocument doc = new XmlDocument();
string path = HttpContext.Current.Server.MapPath("~/XML/Availability/GetAvailabilityEAD.xml");
doc.Load(path);
//Assign incoming paramaters to xml template
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
manager.AddNamespace("stupid_xmlns", "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService");
XmlNode CSSDistrictCodeNode = doc.SelectSingleNode("soap:Envelope/soap:Body/stupid_xmlns:GetAvailability/stupid_xmlns:request/stupid_xmlns:RequestDetails/stupid_xmlns:CSSDistrictCode", manager);
CSSDistrictCodeNode.InnerXml = CSSDistrictCode;
XmlNode GoldAddressKeyNode = doc.SelectSingleNode("soap:Envelope/soap:Body/stupid_xmlns:GetAvailability/stupid_xmlns:request/stupid_xmlns:RequestDetails/stupid_xmlns:GoldAddressKey", manager);
GoldAddressKeyNode.InnerXml = GoldAddressKey;
//Send Request To API
string _url = "https://b2b.api.talktalkgroup.com/api/v2/partners/AvailabilityCheckers/NPAC/v45";
string _action = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService/NetworkProductAvailabilityCheckerService/GetAvailability";
string xml = doc.InnerXml;
var soapResult = WebService.ApiRequest(_url, _action, xml);
XmlDocument xmlToFormat = new XmlDocument();
xmlToFormat.LoadXml(soapResult);
string Outerxml = xmlToFormat.FirstChild.FirstChild.FirstChild.FirstChild.ChildNodes[2].InnerXml;
//Remove all namespaces
var xmlToBeStripped = XElement.Parse(Outerxml);
string finalXml = XmlFormatter.stripNS(xmlToBeStripped).ToString();
EADAvailabilityDetails result;
// Deserialises xlm into an object
XmlSerializer serializer = new XmlSerializer(typeof(EADAvailabilityDetails));
using (TextReader reader = new StringReader(finalXml))
{
result = (EADAvailabilityDetails)serializer.Deserialize(reader);
}
return result;
}
XML being returned:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetAvailabilityResponse xmlns="http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService">
<GetAvailabilityResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Status xmlns="http://schemas.datacontract.org/2004/07/InHouse.SharedLibraries.ServiceBase.BaseTypes">
<Errors/>
<HasErrors>false</HasErrors>
</Status>
<CSSDistrictCode>lv</CSSDistrictCode>
<EADAvailability>
<AvailabilityDetails i:type="EADAvailabilityDetails">
<Status xmlns="http://schemas.datacontract.org/2004/07/InHouse.SharedLibraries.ServiceBase.BaseTypes">
<Errors/>
<HasErrors>false</HasErrors>
</Status>
<EADAvailability>
<EADAvailabilityResult>
<CollectorNodeExchangeCode>NDMAI</CollectorNodeExchangeCode>
<CollectorNodeExchangeName>Maidstone</CollectorNodeExchangeName>
<Distance>0</Distance>
<EADBandwidth xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>100M</a:string>
</EADBandwidth>
<EADSubType>EAD-LA</EADSubType>
<FibreExchangeCode>NDACO</FibreExchangeCode>
<FibreExchangename>Archers Court</FibreExchangename>
<IndicativeECC>Within tariff</IndicativeECC>
<IndicativeOrderCategory>Category 2.1</IndicativeOrderCategory>
<LocalExchangeCode>NDACO</LocalExchangeCode>
<LocalExchangeName>Archers Court</LocalExchangeName>
<ORLeadTime>40</ORLeadTime>
<OrderCategoryExplanation>There is a T node within 1km (or 650m in London) with spare capacity and ducting is in place, however some additional cabling is required between the premises and the T node.</OrderCategoryExplanation>
<TTLeadTime>56</TTLeadTime>
<Zone>0</Zone>
</EADAvailabilityResult>
<EADAvailabilityResult>
<CollectorNodeExchangeCode>NDMAI</CollectorNodeExchangeCode>
<CollectorNodeExchangeName>Maidstone</CollectorNodeExchangeName>
<Distance>0</Distance>
<EADBandwidth xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>LOW 1GB</a:string>
</EADBandwidth>
<EADSubType>EAD-LA</EADSubType>
<FibreExchangeCode>NDACO</FibreExchangeCode>
<FibreExchangename>Archers Court</FibreExchangename>
<IndicativeECC>Within tariff</IndicativeECC>
<IndicativeOrderCategory>Category 2.1</IndicativeOrderCategory>
<LocalExchangeCode>NDACO</LocalExchangeCode>
<LocalExchangeName>Archers Court</LocalExchangeName>
<ORLeadTime>40</ORLeadTime>
<OrderCategoryExplanation>There is a T node within 1km (or 650m in London) with spare capacity and ducting is in place, however some additional cabling is required between the premises and the T node.</OrderCategoryExplanation>
<TTLeadTime>56</TTLeadTime>
<Zone>0</Zone>
</EADAvailabilityResult>
<EADAvailabilityResult>
<CollectorNodeExchangeCode>NDCAN</CollectorNodeExchangeCode>
<CollectorNodeExchangeName>Canterbury</CollectorNodeExchangeName>
<Distance>20656</Distance>
<EADBandwidth xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>HIGH 1GB</a:string>
</EADBandwidth>
<EADSubType>EAD-NonLA</EADSubType>
<FibreExchangeCode>NDCAN</FibreExchangeCode>
<FibreExchangename>Canterbury</FibreExchangename>
<IndicativeECC>Within tariff</IndicativeECC>
<IndicativeOrderCategory>Category 2.1</IndicativeOrderCategory>
<LocalExchangeCode>NDACO</LocalExchangeCode>
<LocalExchangeName>Archers Court</LocalExchangeName>
<ORLeadTime>40</ORLeadTime>
<OrderCategoryExplanation>There is a T node within 1km (or 650m in London) with spare capacity and ducting is in place, however some additional cabling is required between the premises and the T node.</OrderCategoryExplanation>
<TTLeadTime>56</TTLeadTime>
<Zone>B</Zone>
</EADAvailabilityResult>
</EADAvailability>
<LeadTime>10</LeadTime>
</AvailabilityDetails>
</EADAvailability>
<GoldAddressKey>A00009292752</GoldAddressKey>
<Postcode/>
</GetAvailabilityResult>
</GetAvailabilityResponse>
</s:Body>
</s:Envelope>
Model:
[Serializable, XmlRoot("AvailabilityDetails")]
public class EADAvailabilityDetails
{
[XmlElement("EADAvailability")]
public EADAvailability EADAvailability { get; set; }
}
public class EADAvailability
{
[XmlElement("EADAvailabilityResult")]
public List<EADAvailabilityResult> EADAvailabilityResult { get; set; }
}
public class EADAvailabilityResult
{
[XmlElement("CollectorNodeExchangeCode")]
public string CollectorNodeExchangeCode { get; set; }
[XmlElement("CollectorNodeExchangeName")]
public string CollectorNodeExchangeName { get; set; }
[XmlElement("Distance")]
public int Distance { get; set; }
[XmlElement("EADBandwidth")]
public string EADBandwidth { get; set; }
[XmlElement("EADSubType")]
public string EADSubType { get; set; }
[XmlElement("FibreExchangeCode")]
public string FibreExchangeCode { get; set; }
[XmlElement("FibreExchangename")]
public string FibreExchangename { get; set; }
[XmlElement("IndicativeECC")]
public string IndicativeECC { get; set; }
[XmlElement("IndicativeOrderCategory")]
public string IndicativeOrderCategory { get; set; }
[XmlElement("LocalExchangeCode")]
public string LocalExchangeCode { get; set; }
[XmlElement("LocalExchangeName")]
public string LocalExchangeName { get; set; }
[XmlElement("ORLeadTime")]
public int ORLeadTime { get; set; }
[XmlElement("OrderCategoryExplanation")]
public string OrderCategoryExplanation { get; set; }
[XmlElement("TTLeadTime")]
public int TTLeadTime { get; set; }
[XmlElement("Zone")]
public int Zone { get; set; }
}
XML after serialisation:
{
"<EADAvailability>k__BackingField": {
"EADAvailabilityResult": [
{
"CollectorNodeExchangeCode": "NDMAI",
"CollectorNodeExchangeName": "Maidstone",
"Distance": 0,
"EADBandwidth": "100M",
"EADSubType": null,
"FibreExchangeCode": null,
"FibreExchangename": null,
"IndicativeECC": null,
"IndicativeOrderCategory": null,
"LocalExchangeCode": null,
"LocalExchangeName": null,
"ORLeadTime": 0,
"OrderCategoryExplanation": null,
"TTLeadTime": 0,
"Zone": 0
}
]
}
}
The code below works :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication139
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(reader);
}
}
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement (Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
}
public class Body
{
[XmlElement(Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
public GetAvailabilityResponse GetAvailabilityResponse { get; set; }
}
public class GetAvailabilityResponse
{
[XmlElement(Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
public GetAvailabilityResult GetAvailabilityResult { get; set; }
}
public class GetAvailabilityResult
{
[XmlArray("EADAvailability", Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
[XmlArrayItem("AvailabilityDetails", Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
public AvailabilityDetails[] AvailabilityDetails { get; set; }
}
[XmlInclude(typeof(EADAvailabilityDetails))]
[Serializable, XmlRoot("AvailabilityDetails", Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
public class AvailabilityDetails
{
}
[Serializable, XmlRoot("EADAvailabilityDetails", Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
public class EADAvailabilityDetails : AvailabilityDetails
{
[XmlArray("EADAvailability", Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
[XmlArrayItem("EADAvailabilityResult", Namespace = "http://webservices.talktalkplc.com/NetworkProductAvailabilityCheckerService")]
public EADAvailabilityResult[] EADAvailabilityResult { get; set; }
}
public class EADAvailabilityResult
{
public string CollectorNodeExchangeCode { get; set; }
public string CollectorNodeExchangeName { get; set; }
public int Distance { get; set; }
public EADBandwidth EADBandwidth { get; set; }
public string EADSubType { get; set; }
public string FibreExchangeCode { get; set; }
public string FibreExchangename { get; set; }
public string IndicativeECC { get; set; }
public string IndicativeOrderCategory { get; set; }
public string LocalExchangeCode { get; set; }
public string LocalExchangeName { get; set; }
public int ORLeadTime { get; set; }
public string OrderCategoryExplanation { get; set; }
public int TTLeadTime { get; set; }
public string Zone { get; set; }
}
public class EADBandwidth
{
[XmlElement(ElementName = "string", Type = typeof(string), Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
public string String { get; set; }
}
}
I am trying to deserialize the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<jobInfo
xmlns="http://www.force.com/2009/06/asyncapi/dataload">
<id>750x0000000005LAAQ</id>
<operation>insert</operation>
<object>Contact</object>
<createdById>005x0000000wPWdAAM</createdById>
<createdDate>2009-09-01T16:42:46.000Z</createdDate>
<systemModstamp>2009-09-01T16:42:46.000Z</systemModstamp>
<state>Open</state>
<concurrencyMode>Parallel</concurrencyMode>
<contentType>CSV</contentType>
<numberBatchesQueued>0</numberBatchesQueued>
<numberBatchesInProgress>0</numberBatchesInProgress>
<numberBatchesCompleted>0</numberBatchesCompleted>
<numberBatchesFailed>0</numberBatchesFailed>
<numberBatchesTotal>0</numberBatchesTotal>
<numberRecordsProcessed>0</numberRecordsProcessed>
<numberRetries>0</numberRetries>
<apiVersion>28.0</apiVersion>
</jobInfo>
I have created this object:
public class JobInfo
{
public string xmlns { get; set; }
public string id { get; set; }
public string operation { get; set; }
public string #object { get; set; }
public string createdById { get; set; }
public string createdDate { get; set; }
public string systemModstamp { get; set; }
public string state { get; set; }
public string concurrencyMode { get; set; }
public string contentType { get; set; }
public string numberBatchesQueued { get; set; }
public string numberBatchesInProgress { get; set; }
public string numberBatchesCompleted { get; set; }
public string numberBatchesFailed { get; set; }
public string numberBatchesTotal { get; set; }
public string numberRecordsProcessed { get; set; }
public string numberRetries { get; set; }
public string apiVersion { get; set; }
}
public class RootObject
{
public JobInfo jobInfo { get; set; }
}
And, I am using this code:
XmlSerializer serializer = new XmlSerializer(typeof(RootObject));
StringReader rdr = new StringReader(response);
RootObject resultingMessage = (RootObject)serializer.Deserialize(rdr);
However, I get this error:
There is an error in XML document (1, 40).
{"<jobInfo xmlns='http://www.force.com/2009/06/asyncapi/dataload'> was not expected."}
How can I account for the xmlns attribute? My code has it as a property (thus, it fails)...
Currently your code is expecting the xmlns as element, not the attribute.
You should add the XmlSerialization attributes to your class, like this:
[XmlRoot("jobInfo", Namespace="http://www.force.com/2009/06/asyncapi/dataload"]
public class JobInfo
{
[XmlAttribute]
public string xmlns { get; set; }
[XmlElement(ElementName = "id")]
public string id { get; set; }
....
}
You can find more information in MSDN articles:
Controlling XML Serialization Using Attributes
Examples of XML Serialization
Try using the XmlRootAttribute to specify the Namespace.
[XmlRoot("jobInfo", Namespace = "http://www.force.com/2009/06/asyncapi/dataload")]
public class JobInfo
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("operation")]
public string Operation { get; set; }
[XmlElement("object")]
public string Object { get; set; }
[XmlElement("createdById")]
public string CreatedById { get; set; }
[XmlElement("createdDate")]
public DateTime CreatedDate { get; set; }
[XmlElement("systemModstamp")]
public DateTime SystemModstamp { get; set; }
[XmlElement("state")]
public string State { get; set; }
[XmlElement("concurrencyMode")]
public string ConcurrencyMode { get; set; }
[XmlElement("contentType")]
public string ContentType { get; set; }
[XmlElement("numberBatchesQueued")]
public string NumberBatchesQueued { get; set; }
[XmlElement("numberBatchesInProgress")]
public string NumberBatchesInProgress { get; set; }
[XmlElement("numberBatchesCompleted")]
public string NumberBatchesCompleted { get; set; }
[XmlElement("numberBatchesFailed")]
public string NumberBatchesFailed { get; set; }
[XmlElement("numberBatchesTotal")]
public string NumberBatchesTotal { get; set; }
[XmlElement("numberRecordsProcessed")]
public string numberRecordsProcessed { get; set; }
[XmlElement("numberRetries")]
public string NumberRetries { get; set; }
[XmlElement("apiVersion")]
public string ApiVersion { get; set; }
}
Code:
var xml = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<jobInfo xmlns=""http://www.force.com/2009/06/asyncapi/dataload"">
<id>750x0000000005LAAQ</id>
<operation>insert</operation>
<object>Contact</object>
<createdById>005x0000000wPWdAAM</createdById>
<createdDate>2009-09-01T16:42:46.000Z</createdDate>
<systemModstamp>2009-09-01T16:42:46.000Z</systemModstamp>
<state>Open</state>
<concurrencyMode>Parallel</concurrencyMode>
<contentType>CSV</contentType>
<numberBatchesQueued>0</numberBatchesQueued>
<numberBatchesInProgress>0</numberBatchesInProgress>
<numberBatchesCompleted>0</numberBatchesCompleted>
<numberBatchesFailed>0</numberBatchesFailed>
<numberBatchesTotal>0</numberBatchesTotal>
<numberRecordsProcessed>0</numberRecordsProcessed>
<numberRetries>0</numberRetries>
<apiVersion>28.0</apiVersion>
</jobInfo>";
var serializer = new XmlSerializer(typeof(JobInfo));
JobInfo jobInfo;
using(var stream = new StringReader(xml))
using(var reader = XmlReader.Create(stream))
{
jobInfo = (JobInfo)serializer.Deserialize(reader);
}
Add the namespace
[XmlRoot("jobInfo",Namespace = "http://www.force.com/2009/06/asyncapi/dataload")]
public class JobInfo
{
// get rid of the xmlns property
// other properties stay
}
// there is no rootobject, JobInfo is your root
XmlSerializer serializer = new XmlSerializer(typeof(JobInfo));
StringReader rdr = new StringReader(response);
JobInfo resultingMessage = (JobInfo)serializer.Deserialize(rdr);