Read XML from c#

13,966

Solution 1

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

Solution 2

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.

Solution 3

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();

        }
    }
}

Solution 4

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
    }
Share:
13,966
KMR
Author by

KMR

I'm C# ASP.NET Developer who is enthusiastic to build .NET/MVC Applications. I have done my Bachelors in BSc Business Information Systems and my Masters in MSc Big Data and Business Intelligence. I'm very keen on learning new technologies, Languages to keep up with the trend

Updated on June 04, 2022

Comments

  • KMR
    KMR almost 2 years

    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

  • Mikhail Tulubaev
    Mikhail Tulubaev almost 7 years
    However, Marc Gravell♦'s answer is more applicable :)
  • Marc Gravell
    Marc Gravell almost 7 years
    BTW: there is an "Edit" => "Paste Special" => "Past XML As Classes" menu option in Visual Studio, but if you use it, you'll see why I usually don't... (compare the generated code with the code in the answer above)
  • KMR
    KMR almost 7 years
    Thanks a lot. I'll test this.