How to Read and Parse an Xml File in C#

Reading the XML file in c#

nodeList is a list of <InvoiceHeader> nodes. One method to solve this problem would be to iterate through the ChildNodes of nodeList and use the property Name to create the Details class in each iteration.

Your code was almost there... I've just updated it slightly so it correctly adds the <Number> elements to the list:

List<Details> detailsList = new List<Details>();
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNodeList nodeList = doc.SelectNodes("/Invoice/InvoiceHeader");
foreach (XmlNode node in nodeList)
{
// create details class for each InvoiceHeader
Details detail = new Details();
detail.Number = new List<string>();

// loop over child nodes to get Name and all Number elements
foreach (XmlNode child in node.ChildNodes)
{
// check node name to decide how to handle the values
if (child.Name == "Name")
{
detail.Name = child.InnerText;
}
else if (child.Name == "Number")
{
detail.Number.Add(child.InnerText);
}
}
detailsList.Add(detail);
}

Then you can display the results like this:

foreach (var details in detailsList)
{
Console.WriteLine($"{details.Name}: {string.Join(",", details.Number)}");
}

// output
cust1: 5689
cust1: 5689,5459
cust1: 5689,5645,5879

Another method you could consider is Linq-to-Xml. The below code produces the same output as that above:

XDocument doc = XDocument.Load(path);
var details = doc.Descendants("Invoice")
.Elements()
.Select(node => new Details()
{
Name = node.Element("Name").Value,
Number = node.Elements("Number").Select(child => child.Value).ToList()
})
.ToList();

C# parse XML file to object

Here are the classes:

public class Config
{
public UI UI { get; set; }
public Output Output { get; set; }
}

public struct UI
{
public string Colour { get; set; }
public string Size { get; set; }
}

public struct Output
{
public string Mode { get; set; }
public int Version { get; set; }
}

The Deserialize function:

    public static T Deserialize<T>(string xmlString)
{
if (xmlString == null) return default;
var serializer = new XmlSerializer(typeof(T));
using (var reader = new StringReader(xmlString))
{
return (T) serializer.Deserialize(reader);
}
}

And here's a working version:

        Config cfg = Deserialize<Config>(xmlString);
Console.WriteLine(cfg.Output.Mode);

How does one parse XML files?

I'd use LINQ to XML if you're in .NET 3.5 or higher.

Read XML from c#

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>";
}

C# Parse XML file into object from given tag

You might try read Xml up the point you find your node and then retrieve it's outer xml and put that into XmlSerializer. Let's say you have a simple XML file like this one:

<rootnode>
<!-- some nodes inside -->
<uselessNode>
<thatsWhatIWant>
<!-- some fields inside -->
<uselessNodeInside/>
<usefullNodeInside/>
</thatsWhatIWant>
</uselessNode>
</rootnode>

What you could do is open up XmlReader:

XmlReader reader = XmlReader.Create("path/to/myfile.xml");

Then read contents up to your POI and store that in some variable:

string wantedNodeContents = string.Empty;
while (reader.Read())
{
if(reader.NodeType == XmlNodeType.Element && reader.Name == "thatsWhatIWant")
{
wantedNodeContents = reader.ReadOuterXml();
break;
}
}

Having this you should be able to use XmlSerializer like so:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(ClassToDeserialize));
System.IO.TextReader textReader = System.IO.StringReader(wantedNodeContents);
ClassToDeserialize loadedObjectXml = xmlSerializer.Deserialize(textReader) as ClassToDeserialize;

You can alternatively (or in addition to that) try to add some handlers for UnknownNode and UnknownAttribute:

xmlSerializer.UnknownNode+= new XmlNodeEventHandler(UnknownNode);
xmlSerializer.UnknownAttribute+= new XmlAttributeEventHandler(UnknownAttribute);

void UnknownNode(object sender, XmlNodeEventArgs e) { }
void UnknownAttribute(object sender, XmlAttributeEventArgs e) { }

Unable to parse and read xml data

I corrected the xml file and used xml linq (XDocument) to get values

<source xml:base="https://google.com/api/v1" xmlns="http://www.w3.org/2005/Atom" xmlns:x="abc" xmlns:n="def" >
<id>s1</id>
<value>
<id>value1</id>
<version>1.90</version>
<content type="application/xml">
<x:products>
<n:Productname>3M</n:Productname>
<n:ProductId n:type="Int32">97</n:ProductId>
</x:products>
<x:products>
<n:Productname>HD</n:Productname>
<n:ProductId n:type="Int32">99</n:ProductId>
</x:products>
</content>
</value>
</source>

Here is the code :

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);
XElement value = doc.Descendants().Where(x => x.Name.LocalName == "value").FirstOrDefault();
XNamespace ns = value.GetDefaultNamespace();
XNamespace xNs = value.GetNamespaceOfPrefix("x");
XNamespace nNs = value.GetNamespaceOfPrefix("n");

var values = doc.Descendants(ns + "value").Select(x => new
{
id = (string)x.Element(ns + "id"),
products = x.Descendants(xNs + "products").Select(y => new
{
name = (string)y.Element(nNs + "Productname"),
id = (string)y.Element(nNs + "ProductId")
}).ToList()
}).ToList();
}
}
}

How to read this XML in C#?

You could do something like this: get the <ROWDATA> node, then its first (and only) descendant, and from that node, extract the info from the attributes with this code:

var field = xml.Root.Descendants("ROWDATA").Descendants().FirstOrDefault();

if (field != null)
{
string dateJoined = field.Attribute("dateJoined").Value;
decimal total = decimal.Parse(field.Attribute("totals").Value);
decimal partials = decimal.Parse(field.Attribute("partials").Value);

int status = int.Parse(field.Attribute("status").Value);
int counter = int.Parse(field.Attribute("counter").Value);
}

UPDATE: as @KlausGütter has noted in comments - if your .NET culture you're using uses something other than a dot (.) as its decimal separator, then this code won't properly convert the strings representing the decimal values.

To check what the decimal separator is, use this:

CultureInfo.CurrentCulture.Number.CurrencyDecimalSeparator

To properly convert the XML data to decimal in such a case, use:

    decimal total = (decimal)field.Attribute("totals");
decimal partials = (decimal)field.Attribute("partials");


Related Topics



Leave a reply



Submit