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
Reach Control from Another Page. Asp.Net
How to Detect Click/Touch Events on Ui and Gameobjects
What Are the Differences Between a Multidimensional Array and an Array of Arrays in C#
Convert List≪Derivedclass≫ to List≪Baseclass≫
How to Stop Backgroundworker on Form'S Closing Event
Await' Works, But Calling Task.Result Hangs/Deadlocks
Does Json.Net Cache Types' Serialization Information
Best Way to Implement Keyboard Shortcuts in a Windows Forms Application
Sending Email in .Net Through Gmail
Parse String to Datetime in C#