What will be the way to read xml here? - c#

I have this below xml file:-
<?xml version="1.0" encoding="utf-8" ?>
<LoanProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Program>
<ProgramID>6</ProgramID>
<Name>Primary Loan</Name>
<InterestRate>0.23</InterestRate>
<StartDate>2018-12-20</StartDate>
<EndDate>2019-03-31</EndDate>
</Program>
<Program>
<ProgramID>6</ProgramID>
<Name>Primary Loan</Name>
<InterestRate>0.25</InterestRate>
<StartDate>2019-04-1</StartDate>
<EndDate>2099-12-31</EndDate>
</Program>
</LoanProduct>
In my class file I have to read from xml file and run some query on it:-
String xml = Server.MapPath("/Resources/LoanProduct.xml");
DataSet dataSet = new DataSet();
dataSet.ReadXml(xml);
Suppose I want to retrieve where ProgramID= 6 and EndDate = '2099-12-31'
How can I achieve that?

You can achieve your desired result by using XDocument under the namespace System.Xml.Linq.
XDocument doc = XDocument.Load(#"Path to your xml file");
var ns = doc.Root.GetDefaultNamespace();
var result = (from program in doc.Descendants(ns + "Program")
where Convert.ToInt32(program.Element(ns + "ProgramID").Value) == 6 && program.Element(ns + "EndDate").Value == "2099-12-31"
select program).FirstOrDefault();
Output: (From Debugger)

You can use serialization. The date should be consistent otherwise you will get an error with this code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication3
{
class Program1
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(LoanProduct));
LoanProduct loanProduct = (LoanProduct)serializer.Deserialize(reader);
}
}
[XmlRoot(ElementName = "LoanProduct", Namespace = "")]
public class LoanProduct
{
[XmlElement("Program", Namespace = "")]
public List<Program> programs { get; set; }
}
[XmlRoot(ElementName = "Program", Namespace = "")]
public class Program
{
public int ProgramID { get; set; }
public string Name { get; set; }
public decimal InterestRate { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
}

Related

How I can deserialize a System.Xml.Linq.XElement?

I tried:
using (XmlReader reader = XmlReader.Create(_xmlPath))
{
while (reader.Read())
{
if (reader.NodeType.Equals(XmlNodeType.Element) && reader.Name.Equals("Obj"))
{
Obj obj = new Obj();
while (reader.Read())
{
if (reader.NodeType.Equals(XmlNodeType.EndElement) && reader.Name.Equals("Obj"))
break;
if (reader.NodeType.Equals(XmlNodeType.Element))
{
switch (reader.Name)
{
case "Code":
obj.Code = reader.ReadElementContentAsString();
break;
case "Data":
XElement el = (XElement) XNode.ReadFrom(reader);
XmlReader r = el.CreateReader();
XmlSerializer serializer = new XmlSerializer(typeof(Data));
Data data = (Data) serializer.Deserialize(r);
obj.Data = data;
break;
}
}
}
}
}
}
Xml :
<Root>
<Obj>
<Code>code</Code>
<Data>
<Date>2020-08-07</Date>
<Amount>1000</Amount>
</Data>
</Obj>
</Root>
Data class :
public class Data{
public DateTime Date {get;set;}
public decimal Amount {get;set;}
}
Normally, it's a large XML file, this is why I try to cut it to fragments and I use XmlReader to parse it.
The deserialization doesn't work, if you have other ways I'm a taker
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Data data = doc.Descendants("Data")
.Select(x => new Data() { Date = (DateTime)x.Element("Date"), Amount = (decimal)x.Element("Amount") }).FirstOrDefault();
}
}
public class Data
{
public DateTime Date { get; set; }
public decimal Amount { get; set; }
}
}
For huge files use following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
List<Data> data = new List<Data>();
while (!reader.EOF)
{
if (reader.Name != "Data")
{
reader.ReadToFollowing("Data");
}
if (!reader.EOF)
{
XElement xData = (XElement)XElement.ReadFrom(reader);
Data newData = new Data() { Date = (DateTime)xData.Element("Date"), Amount = (decimal)xData.Element("Amount") };
data.Add(newData);
}
}
}
}
public class Data
{
public DateTime Date { get; set; }
public decimal Amount { get; set; }
}
}
I simplified your code. It should work.
var serializer = new XmlSerializer(typeof(Obj));
using (XmlReader reader = XmlReader.Create(_xmlPath))
{
while (reader.ReadToFollowing("Obj"))
{
Obj obj = (Obj)serializer.Deserialize(reader);
}
}
If the actual xml has a more complex structure and this code doesn't work, let us know.

Retrieve fields in key value pair from XML using C#

I have an XML as below:
<test-run>
<test-suite>
<test-suite>
<test-case id="1234" name="ABC" result="Passed">
</test-case>
</test-suite>
</test-suite>
</test-run>
This is an example XML file that I am using.
How to retrieve id,name and Result from this using C#?
Using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<Result> results = doc.Descendants("test-case").Select(x => new Result()
{
id = (string)x.Attribute("id"),
name = (string)x.Attribute("name"),
result = (string)x.Attribute("result")
}).ToList();
}
}
public class Result
{
public string id { get; set; }
public string name { get; set; }
public string result { get; set; }
}
}

Read Elements from XML in c#

I have response from web service and my code looks like following
using (WebResponse response2 = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response2.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
}
}
Now I have my complete response to string soapResult.
My XML looks like following:
soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetResponse xmlns="http://ws.design.americaneagle.com">
<GetResult>
<Distance>0</Distance>
<ID>100</ID>
<Name>Wisconsin</Name>
<Code>WI</Code>
<Address1>202 Las COlinas</Address1>
</GetResult>
</GetResponse>
</soap:Body>
</soap:Envelope>
I want to read ID, Name, and Address1 from the above XML.
How to achieve this? I am new to XML in c#.
Any help? Thanks in advance.
Using xml linq. For testing I'm reading from a file (instead of a webresponse) so you have to make slight changes to go back to your original code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
using (StreamReader rd = new StreamReader(FILENAME))
{
XDocument doc = XDocument.Load(rd);
XElement response = doc.Descendants().Where(x => x.Name.LocalName == "GetResponse").FirstOrDefault();
XNamespace ns = response.GetDefaultNamespace();
var data = response.Descendants(ns + "GetResult").Select(x => new {
distance = (int)x.Element(ns + "Distance"),
id = (int)x.Element(ns + "ID"),
name = (string)x.Element(ns + "Name"),
code = (string)x.Element(ns + "Code"),
addresss = (string)x.Element(ns + "Address1")
}).FirstOrDefault();
}
}
}
}
Use the Xmldocument . With use root statement . It's very to use .. read about it .. or use XPath. Also read about it!
I pasted your XML in XML to Sharp and got this:
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
[XmlRoot(ElementName = "GetResult", Namespace = "http://ws.design.americaneagle.com")]
public class GetResult
{
[XmlElement(ElementName = "Distance", Namespace = "http://ws.design.americaneagle.com")]
public string Distance { get; set; }
[XmlElement(ElementName = "ID", Namespace = "http://ws.design.americaneagle.com")]
public string ID { get; set; }
[XmlElement(ElementName = "Name", Namespace = "http://ws.design.americaneagle.com")]
public string Name { get; set; }
[XmlElement(ElementName = "Code", Namespace = "http://ws.design.americaneagle.com")]
public string Code { get; set; }
[XmlElement(ElementName = "Address1", Namespace = "http://ws.design.americaneagle.com")]
public string Address1 { get; set; }
}
[XmlRoot(ElementName = "GetResponse", Namespace = "http://ws.design.americaneagle.com")]
public class GetResponse
{
[XmlElement(ElementName = "GetResult", Namespace = "http://ws.design.americaneagle.com")]
public GetResult GetResult { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "GetResponse", Namespace = "http://ws.design.americaneagle.com")]
public GetResponse GetResponse { get; set; }
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
[XmlAttribute(AttributeName = "soap", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soap { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsd { get; set; }
}
}
Then you have to deserialize it.
var serializer = new XmlSerializer(typeof(Envelope));
Envelope result;
using (TextReader reader = new StringReader(xml))
{
result = (Envelope)serializer.Deserialize(reader);
}

Deserialize xml into class having string values in xml

Let me explain, there is a database table which has 1 XML column named audits and other common types of column.
so is this possible to deserialize below XML into class.
<?xml version="1.0"?>
<entity type="Order">
<id type="System.Int64">146</id>
<ordernumber type="System.String">OD555</ordernumber>
<audits type='System.String'>
<audit>
<item>
<create timestamp='2017-07-19 10:02:13' userid='23' />
</item>
<invoice>
<create timestamp='2017-07-19 10:03:37' userid='45' />
</invoice>
</audit>
</audits>
</entity>
Class:
public class Order
{
public long id { get; set; }
public string ordernumber { get; set; }
public string audits { get; set; }
}
Modifying your model with the attributes XmlType and XmlAnyElement (requires XmlElement as type)
[XmlType("entity")]
public class Order
{
public long id { get; set; }
public string ordernumber { get; set; }
[XmlAnyElement]
public XmlElement audits { get; set; }
}
allows to deserialize the complete XML string like
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(xmlString);
writer.Flush();
stream.Position = 0;
XmlSerializer serializer = new XmlSerializer(typeof(Order));
Order o = (Order)serializer.Deserialize(stream);
}
Now you are able to get the audits as string like
string auditsString = o.audits.InnerXml;
You can also add a property to your model to simplify the access:
public string auditsString
{
get
{
return audits.InnerXml;
}
}
Try xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication68
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Order order = doc.Descendants("entity").Select(x => new Order()
{
id = (long)x.Element("id"),
ordernumber = (string)x.Element("ordernumber"),
audits = x.Descendants("create").Select(y => (DateTime)y.Attribute("timestamp")).ToList()
}).FirstOrDefault();
}
}
public class Order
{
public long id { get; set; }
public string ordernumber { get; set; }
public List<DateTime> audits { get; set; }
}
}
You can try like this
const string xmlString = #"<columns><column><c1>100</c1><c2>200</c2><cn>300</cn></column><column><c1>111</c1><c2>222</c2><cn>333</cn></column> <column> <c1>MAX Newsletter</c1><c2>OLS Application</c2> <cn>Total funded accounts</cn> </column></columns>";
XDocument doc = XDocument.Parse(xmlString);
if (doc.Root != null)
{
List<Row> items = (from r in doc.Root.Elements("column")
select new Row
{
C1 = (string)r.Element ("C1"),
C2 = (string)r.Element("C2"),
}).ToList();

Read XML from c#

I'm trying to read a xml file from a c# application. so far no luck at all. This is the XML file
<?xml version="1.0" encoding="utf-8"?>
<ExportJobs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<JobList>
<Job Id="555555">
<Comments></Comments>
<DueDate>2017-11-17</DueDate>
<FormattedDueDate>17-Nov-2017 12:00</FormattedDueDate>
<TargetDueDate>2017-11-17</TargetDueDate>
<ServiceTypeId>3</ServiceTypeId>
<ServiceType>Service</ServiceType>
<TenantName>Miss Ash</TenantName>
<Uprn>testUpr</Uprn>
<HouseName></HouseName>
</Job>
<Job Id="666666">
<Comments></Comments>
<DueDate>2018-03-15</DueDate>
<FormattedDueDate>15-Mar-2018 12:00</FormattedDueDate>
<TargetDueDate>2018-03-15</TargetDueDate>
<ServiceTypeId>3</ServiceTypeId>
<ServiceType>Service</ServiceType>
<TenantName>Mr Howard</TenantName>
<Uprn>testUpr2</Uprn>
</Job>
</JobList>
</ExportJobs>
I'm trying to get the job Id and the Uprn from the joblist node and pass the values in to Sql Server DB. I tried this, but I can't get the values,
string costCode;
string uprn;
//File path where the xml is located
string filepath = "C:\\ExportJobs.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filepath);
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
costCode = node.Attributes["Id"].InnerText;
uprn = node.Attributes["Uprn"].InnerText;
}
I really appreciate any help. Thanks
XmlSerializer is your friend:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
public class ExportJobs
{
public List<Job> JobList { get; } = new List<Job>();
}
public class Job
{
[XmlAttribute]
public int Id { get; set; }
public string Comments { get; set; }
public DateTime DueDate { get; set; }
public string FormattedDueDate { get; set; }
public DateTime TargetDueDate{ get; set; }
public int ServiceTypeId { get; set; }
public string ServiceType { get; set; }
public string TenantName { get; set; }
public string Uprn { get; set; }
public string HouseName { get; set; }
}
static class P
{
static void Main()
{
var ser = new XmlSerializer(typeof(ExportJobs));
ExportJobs jobs;
using (var sr = new StringReader(xml))
{
jobs = (ExportJobs) ser.Deserialize(sr);
}
foreach(var job in jobs.JobList)
{
Console.WriteLine($"{job.Id} / {job.Uprn}: {job.DueDate}");
}
}
const string xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<ExportJobs xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<JobList>
<Job Id=""555555"">
<Comments></Comments>
<DueDate>2017-11-17</DueDate>
<FormattedDueDate>17-Nov-2017 12:00</FormattedDueDate>
<TargetDueDate>2017-11-17</TargetDueDate>
<ServiceTypeId>3</ServiceTypeId>
<ServiceType>Service</ServiceType>
<TenantName>Miss Ash</TenantName>
<Uprn>testUpr</Uprn>
<HouseName></HouseName>
</Job>
<Job Id=""666666"">
<Comments></Comments>
<DueDate>2018-03-15</DueDate>
<FormattedDueDate>15-Mar-2018 12:00</FormattedDueDate>
<TargetDueDate>2018-03-15</TargetDueDate>
<ServiceTypeId>3</ServiceTypeId>
<ServiceType>Service</ServiceType>
<TenantName>Mr Howard</TenantName>
<Uprn>testUpr2</Uprn>
</Job>
</JobList>
</ExportJobs>";
}
You are accessing ChildNodes of root element, which contains only Jobs element, which in order does not contains attributes Id and Uprn.
The usual practice is to use XPath query as following:
foreach (XmlNode node in xmlDoc.DocumentElement.SelectNodes("Jobs/Job"))
{
costCode = node.Attributes["Id"].InnerText;
uprn = node.SelectSingleNode("Uprn").InnerText;
}
Note that Uprn is the node and not the node attribute.
Here is tested code. You need the namespace. See code below which is using xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication67
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement exportJobs = doc.Root;
XNamespace ns = exportJobs.GetDefaultNamespace();
var results = exportJobs.Descendants(ns + "Job").Select(x => new {
id = (string)x.Attribute(ns + "Id"),
comment = (string)x.Element(ns + "Comments"),
dueDate = (DateTime)x.Element(ns + "DueDate"),
formattedDueDate = (DateTime)x.Element(ns + "FormattedDueDate"),
targetDueDate = (DateTime)x.Element(ns + "TargetDueDate"),
serviceTypeId = (int)x.Element(ns + "ServiceTypeId"),
serviceType = (string)x.Element(ns + "ServiceType"),
tenantName = (string)x.Element(ns + "TenantName"),
uprn = (string)x.Element(ns + "Uprn"),
houseName = (string)x.Element(ns + "HouseName")
}).ToList();
}
}
}
I think the best way to solve your problem is XDocument class.
XDocument xDoc = XDocument.Load(#"D:\1.xml");
foreach(var node in xDoc.Descendants("Job"))
{
id = node.Attribute("Id");
foreach(var subnode in node.Descendants("Uprn"))
{
uprn = subnode.Value;
}
//or like that. but check it for null before
uprn = node.Descendants("Uprn")?.First().Value
}

Categories