How to Read Xml in .Net

How to Read XML in .NET?

Load the XML into an XmlDocument and then use xpath queries to extract the data you need.

For example

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlstring);

XmlNode errorNode = doc.DocumentElement.SelectSingleNode("/DataChunk/ResponseChunk/Errors/error");

string errorCode = errorNode.Attributes["code"].Value;
string errorMessage = errorNode.InnerText;

If there is potential for the XML having multiple error elements you can use SelectNodes to get an XmlNodeList that contains all elements at that xpath. For example:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlstring);

XmlNodeList errorNodes = doc.DocumentElement.SelectNodes("/DataChunk/ResponseChunk/Errors/error");

foreach(XmlNode errorNode in errorNodes)
{
string errorCode = errorNode.Attributes["code"].Value;
string errorMessage = errorNode.InnerText;
}

Option 2

If you have a XML schema for the XML you could bind the schema to a class (using the .NET xsd.exe tool). Once you have that you can deserialise the XML into an object and work with it from that object rather than the raw XML. This is an entire subject in itself so if you do have the schema it is worth looking into.

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

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

How to read raw xml from request body in aspnet

First, ASP.NET Core does not support XML serialization/deserialization by default. You must explicitly enable that:

services.AddControllersWithViews().AddXmlSerializerFormatters();

Then, to send raw XML format data to API method, the request's content-Type should be application/xml, and we will receive the xml content from the request body, so we should use the [FromBody] attribute, and we should use the XElement to receive the xml content. Please refer to the following sample:

Create a Values API with the following code:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// POST api/<ValuesController>
[HttpPost]
[Route("/xml")]
public string Post([FromBody]XElement xml)
{
return "Hello" + xml.ToString();
}

Then using Postman to call this API:

Sample Image

Besides, you could also according to the XML elements to create model, then using model class to receive the xml content. Check the following sample:

The XML content as below:

<?xml version="1.0" encoding="UTF-8"?>
<UserViewModel>
<Id>1</Id>
<Name>aa</Name>
</UserViewModel>

Create a UserViewModel

public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}

Then, in the API controller, using the following method to receive data:

    [HttpPost] 
public string Post([FromBody]UserViewModel user)
{
return "Hello" + user.Name.ToString();
}

Using Postman to check it:

Sample Image

The [FromForm] attribute will receive the Form data in the request body. Form data as the name suggests is used to send the data that you are wrapping inside the form like the details you enter when you fill a form. These details are sent by writing them as KEY-VALUE pairs where the key is the "name" of the entry you are sending and value is it’s value. More detail information, you could refer this thread.

Since you are using curl to send request, try to use -H or --header to set the request header, like this:

$ curl -k -X POST https://localhost:5001/xml -d '<foo>bar</foo>' -i -H "Content-Type: text/xml" 

$ curl -k -X POST https://localhost:5001/xml -d '<foo>bar</foo>' -i -H "Content-Type:application/xml"

or

$ curl -k -X POST https://localhost:5001/xml -d '<foo>bar</foo>' -i --header "Content-Type: text/xml" 

$ curl -k -X POST https://localhost:5001/xml -d '<foo>bar</foo>' -i --header "Content-Type:application/xml"

How to read XML data dynamically in C#/.net?

Use LINQ to XML.

Example: to retrieve host with (id = 1):

string id = "1"

XDocument doc = XDocument.Load("data.xml");
var accounts = from elements in doc.Elements("HOSTS").Elements("Host")
where elements.Attribute("id").Value = id
select elements.FirstOrDefault();

How to read xml file having different hierarchy in .net

You have a very large file so it is best to use XmlReader. Try this code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication16
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
enum State
{
GET_SUBNETWORK,
GET_MECONTEXT,
GET_CONTAINERS,
GET_SUBNETWORK_OR_MECONTEXT
}
static void Main(string[] args)
{
XmlReaderSettings settings = new XmlReaderSettings() { IgnoreWhitespace = true };
XmlReader reader = XmlReader.Create(FILENAME, settings);

reader.ReadToFollowing("SubNetwork", "generic.xsd");
Network.network.name = reader.GetAttribute("id");
Network.network.subnetworks = new List<SubNetwork>();

string xnNameSpace = reader.LookupNamespace("xn");
reader.ReadToFollowing("SubNetwork", xnNameSpace);

Sites newSite = null;
SubNetwork subNetWork = null;
Boolean endElement = false;

State state = State.GET_SUBNETWORK;
while (!reader.EOF)
{
switch (state)
{
case State.GET_SUBNETWORK:
if (reader.Name != "xn:SubNetwork")
{
reader.ReadToFollowing("SubNetwork", xnNameSpace);
}
if (!reader.EOF)
{
subNetWork = new SubNetwork();
Network.network.subnetworks.Add(subNetWork);
subNetWork.name = reader.GetAttribute("id");
subNetWork.sites = new List<Sites>();

state = State.GET_MECONTEXT;
}
break;

case State.GET_MECONTEXT :
if (reader.Name != "xn:MeContext")
{
if (reader.NodeType == XmlNodeType.EndElement)
{
endElement = true;
state = State.GET_SUBNETWORK;
}
else
{
endElement = false;
reader.ReadToFollowing("MeContext", xnNameSpace);
}
}
if (!reader.EOF && !endElement)
{
state = State.GET_CONTAINERS;
newSite = new Sites();
subNetWork.sites.Add(newSite);
newSite.sitename = reader.GetAttribute("id");
reader.ReadToFollowing("ManagedElement", xnNameSpace);
reader.ReadToFollowing("VsDataContainer", xnNameSpace);
}
break;

case State.GET_CONTAINERS:

if (!reader.EOF)
{
switch (reader.NodeType)
{
case XmlNodeType.EndElement:
state = State.GET_SUBNETWORK_OR_MECONTEXT;
break;
case XmlNodeType.Text:
string text = reader.ReadContentAsString();
break;

case XmlNodeType.Element:

string elementName = reader.Name;
XElement element = (XElement)XElement.ReadFrom(reader);
if (elementName == "xn:VsDataContainer")
{
XElement vsDataENodeBFunction = element.Descendants().Where(a => a.Name.LocalName == "vsDataENodeBFunction").FirstOrDefault();
if (vsDataENodeBFunction != null)
{
XElement eNBId = element.Descendants().Where(a => a.Name.LocalName == "eNBId").FirstOrDefault();
if (eNBId != null)
{
newSite.eNBId = (int)eNBId;
}
}
List<XElement> vsDataContainers = element.Descendants().Where(a => a.Name.LocalName == "VsDataContainer").ToList();
List<XElement> vsDataEUtranCellFDD = vsDataContainers.Where(x => x.Descendants().Where(a => (a.Name.LocalName == "vsDataType") && ((string)a == "vsDataEUtranCellFDD")).Any()).ToList();
if (vsDataEUtranCellFDD.Any())
{
List<CellName> cells = vsDataEUtranCellFDD.Select(x => new CellName()
{
id = (string)x.Attribute("id"),
earfcndl = (int)x.Descendants().Where(a => a.Name.LocalName == "earfcndl").FirstOrDefault(),
earfcnul = (int)x.Descendants().Where(a => a.Name.LocalName == "earfcnul").FirstOrDefault()
}).ToList();
if (newSite.cellName == null)
{
newSite.cellName = new List<CellName>();
}
newSite.cellName.AddRange(cells);
}
}
break;

default:
Console.WriteLine("Unexpected Results");
string elementText = reader.ReadContentAsString();
Console.ReadLine();
break;
}
}
break;

case State.GET_SUBNETWORK_OR_MECONTEXT :
switch(reader.NodeType)
{
case XmlNodeType.Element :
switch(reader.Name)
{
case "xn:MeContext" :
state = State.GET_MECONTEXT;
break;
case "xn:SubNetwork" :
state = State.GET_SUBNETWORK;
break;
default :
reader.ReadStartElement();
break;
}
break;

case XmlNodeType.Text:
string text = reader.ReadContentAsString();
break;

case XmlNodeType.EndElement:
reader.ReadEndElement();
break;

default:
Console.WriteLine("Unexpected Results");
string elementText = reader.ReadContentAsString();
Console.ReadLine();
break;

}
break;
}
}
}

}
public class Network
{
public static Network network = new Network();
public string name { get; set; }
public List<SubNetwork> subnetworks { get; set; }
}
public class SubNetwork
{
public string name { get; set; }
public List<Sites> sites { get; set; }

}
public class Sites
{
public string sitename { get; set; }
public int eNBId { get; set; }
public List<CellName> cellName { get; set; }
}
public class CellName
{
public string id { get; set; }
public int earfcndl { get; set; }
public int earfcnul { get; set; }
}
}


Related Topics



Leave a reply



Submit