List of object array from XML - c#

I have a xml that looks like this
<?xml version="1.0" encoding="utf-8" ?>
<Resorces>
<Resource id="3" name="loreum ipsum" downloadcount="5"></Resource>
<Resource id="2" name="loreum ipsum" downloadcount="9"></Resource>
</Resorces>
I have a class
public class Report
{
public int ResourceId {get; set; }
public string ResourceName { get; set; }
public int DownloadCount { get; set; }
}
I want to convert that xml into list of Report objects
I tried the below code
var resourceList = doc.Descendants("Resorces")
.First()
.Elements("Resource")
.ToList();
I get values like this,
How can I get it as list of objects?

Basically what you are missing is the part where you convert the Xml objects into your defined object of Report. This is how you can do it:
var resourceList = doc.Descendants("Resorces")
.First()
.Elements("Resource")
.Select(element => new Report()
{
ResourceId = (int)element.Attribute("id"),
ResourceName = (string)element.Attribute("name"),
DownloadCount = (int)element.Attribute("downloadcount")
})
.ToList();
I kept here the previous linq methods you called to keep it close to the original but as others said you can just get the Elements("Resource") from the doc root

XmlDocument newdoc = new XmlDocument();
newdoc.InnerXml = " <?xml version="1.0" encoding="utf-8" ?>
<Resorces>
<Resource id="3" name="loreum ipsum" downloadcount="5"></Resource>
<Resource id="2" name="loreum ipsum" downloadcount="9"></Resource>
</Resorces>";
List<string> list = new List <string>();
var selectnode = "Resorces/Resource";
var nodes = newdoc.SelectNodes(selectnode);
foreach (XmlNode nod in nodes)
{
string id = nod["id"].InnerText;
string name = nod["name"].InnerText;
string downloadcount = nod["downloadcount"].InnerText;
list.Add(id);
list.Add(name);
list.Add(downloadcount);
}
Console.WriteLine(list.Count);

You could use Elements method to get elements for a given element name.
XDocument doc = XDocument.Load(filepath);
var result = doc.Root
.Elements("Resource")
.Select(x=> new Report()
{
ResourceId = int.Parse( x.Attribute("id").Value),
ResourceName = (string)x.Attribute("name").Value,
DownloadCount = int.Parse( x.Attribute("downloadcount").Value)
})
.ToList();
Check this Demo

You can get by this
XDocument doc = XDocument.Load(xmlpath);
List<Report> resourceList = doc.Descendants("Resorces")
.First()
.Elements("Resource")
.Select(report => new Report()
{
ResourceId = (int)report.Attribute("id"),
ResourceName = (string)report.Attribute("name"),
DownloadCount = (int)report.Attribute("downloadcount")
}).ToList();

Related

How would I parse an XML file into a list

List:
List<string> list = new List<string>();
XML File:
<memberlist>
<member>
<name>Name</name>
<status>Status</status>
</member>
</memberlist>
How would I go about parsing this file, lets say (file.xml) into the list?
I've tried many ways but none of them seem to be working.
I want to check to see if the status is 'gold', and if it is, I would like to put the name of that member into the list.
Load the xml into an XDocument. You can do this from a file, I have demonstrated from a string.
Do a linq query for elements named "status" (within "member") that also have a value of "gold".
Of those, grab the value of the "name" element.
Use AddRange on your list of strings.
List<string> lstGolds = new List<string>();
string xml ="<memberlist><member><name>Name</name><status>gold</status></member></memberlist>";
XDocument doc = XDocument.Parse(xml);
var goldStatus = doc.Descendants("member")
.Where(d => d.Element("status").Value == "gold")
.Select(d => d.Element("name").Value);
lstGolds.AddRange(goldStatus);
You should use using System.Xml.Linq;
using (FileStream fileStramWrite = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader streamReader = new StreamReader(fileStramWrite))
{
var xdoc = XDocument.Load(streamReader);
var xElement = xdoc.Element("memberlist");
var xElement2 = xElement.Element("member");
var name = xElement2.Element("name").Value;
var status = xElement2.Element("status").Value;
}
Convert your XML to a list of objects....
Use these two mehods:
public static string Serialize<T>(T dataToSerialize)
{
try
{
var stringwriter = new ISOEncodingStringWriter();
var serializer = new XmlSerializer(typeof(T));
var xns = new XmlSerializerNamespaces();
xns.Add(string.Empty, string.Empty);
serializer.Serialize(stringwriter, dataToSerialize, xns);
return stringwriter.ToString();
}
catch
{
throw;
}
}
public static T Deserialize<T>(string xmlText)
{
try
{
var stringReader = new System.IO.StringReader(xmlText);
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
catch
{
throw;
}
}
Make the following Class where you give the following attributes
[XmlRoot(ElementName = "Members", Namespace = "")]
public class Members
{
[XmlElement("Member")]
public Member[] member { get; set; }
}
public class Member
{
[XmlElementAttribute("Name")]
public string Name { get; set; }
[XmlElementAttribute("Status")]
public string Status { get; set; }
}
Then deserialize your data.
Members result = Deserialize<Members>(XML_String);
You got your members in a array and you ca convert that to a list if you want.
You can use LINQ
XElement xml = XElement.Load("locationToYourXmlFile");
var members = xml.Elements("member");
var list = members.Where(member => member.Element("status")?.Value == "Gold")
.Select(member => member.Element("name")?.Value)
.ToList();
Assuming your XML has a bunch of member elements under the root memberlist element, each with a name and status element inside that.
<?xml version="1.0" encoding="utf-8"?>
<memberlist>
<member>
<name>John</name>
<status>Gold</status>
</member>
<member>
<name>Sam</name>
<status>Silver</status>
</member>
<member>
<name>Sara</name>
<status>Gold</status>
</member>
</memberlist>

xml not parsing correctly

I'm trying to parse xml but certain elements aren't returning anything. the first block returns good data but the artist nodes and venue nodes all return null. im not sure what im doing wrong.
XDocument xml = XDocument.Parse(data);
var events = xml.Descendants("events");
foreach(var e in events)
{
foreach(var attribute in e.Descendants("event"))
{
string id = (string)attribute.Element("id");
string Title = (string)attribute.Element("title");
DateTime date = DateTime.Parse(((string)attribute.Element("datetime")), null, DateTimeStyles.RoundtripKind);
string TicketUrl = (string)attribute.Element("ticket_url");
TicketType TicketType = (TicketType)Enum.Parse(typeof(TicketType), (string)attribute.Element("ticket_type"));
TicketAvailability TicketAvailability = (TicketAvailability)Enum.Parse(typeof(TicketAvailability), (string)attribute.Element("ticket_status"));
DateTime TicketSaleDate = DateTime.Parse(((string)attribute.Element("on_sale_datetime")), null, DateTimeStyles.RoundtripKind);
DateTime LastAvailabilityCheck = DateTime.Now;
string FacebookRsvpUrl = (string)attribute.Element("facebook_rsvp_url");
string Description = (string)attribute.Element("description");
List<Artist> artistData = new List<Artist>();
Venue venue = new Venue();
foreach (var artistNode in attribute.Descendants("artist"))
{
var artistName = (string)artistNode.Attribute("name");
var junk = (string)artistNode.Attribute("mbid");
var ImageUrl = (string)artistNode.Attribute("image_url");
var ThumbnailUrl = (string)artistNode.Attribute("thumb_url");
var FaceBookUrl = (string)artistNode.Attribute("facebook_tour_dates_url");
artistData.Add(new Artist(artistName, ThumbnailUrl, ImageUrl, FaceBookUrl));
}
foreach (var venueNode in attribute.Descendants("venue"))
{
var VenueName = (string)venueNode.Element("name");
var City = (string)attribute.Element("city");
var Region = (string)venueNode.Attribute("region");
var Country = (string)venueNode.Attribute("country");
var GpsLocation = (string)venueNode.Attribute("latitude") + ", " + (string)attribute.Attribute("longitude");
venue = new Venue(VenueName, City, Region, Country, GpsLocation);
}
concerts.Add(new Concert(id, artistData, venue, date, TicketSaleDate, Description, FacebookRsvpUrl, Title, TicketUrl, TicketType, TicketAvailability, LastAvailabilityCheck));
}
}
sample data:
<?xml version="1.0" encoding="UTF-8"?>
<events>
<event>
<id>9203898</id>
<title>Fall Out Boy # DTE Energy Music Theatre in Clarkston, MI</title>
<datetime>2015-07-10T19:00:00</datetime>
<formatted_datetime>Friday, July 10, 2015 at 7:00PM</formatted_datetime>
<formatted_location>Clarkston, MI</formatted_location>
<ticket_url>http://www.bandsintown.com/event/9203898/buy_tickets?app_id=BandJunkieForWindows&artist=Fall+Out+Boy</ticket_url>
<ticket_type>Tickets</ticket_type>
<ticket_status>available</ticket_status>
<on_sale_datetime>2015-01-23T10:00:00</on_sale_datetime>
<facebook_rsvp_url>http://www.bandsintown.com/event/9203898?app_id=BandJunkieForWindows&artist=Fall+Out+Boy&came_from=67</facebook_rsvp_url>
<description></description>
<artists>
<artist>
<name>Fall Out Boy</name>
<mbid>516cef4d-0718-4007-9939-f9b38af3f784</mbid>
<image_url>http://www.bandsintown.com/FallOutBoy/photo/medium.jpg</image_url>
<thumb_url>http://www.bandsintown.com/FallOutBoy/photo/small.jpg</thumb_url>
<facebook_tour_dates_url>http://bnds.in/1n0W0qQ</facebook_tour_dates_url>
</artist>
</artists>
<venue>
<name>name</name>
<city>place</city>
<region>state</region>
<country>United States</country>
<latitude>142.748783</latitude>
<longitude>-183.380201</longitude>
</venue>
</event>
</events>
You're using Attribute, but your XML contains elements. Use Element instead...
foreach (var artistNode in attribute.Descendants("artist"))
{
var artistName = (string)artistNode.Element("name");
// etc...
Also as a sidenote, you can cast XElement and XAttribute to DateTime instead of calling DateTime.Parse:
DateTime TicketSaleDate = DateTime.Parse(((string)attribute.Element("on_sale_datetime")), null, DateTimeStyles.RoundtripKind);
can be
DateTime TicketSaleDate = (DateTime)attribute.Element("on_sale_datetime");

Cant get list from received XML file

This is xml that I receive:
<?xml version="1.0" encoding="UTF-8"?>
<mdpr:Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mdpr="http://...">
<mdpr:contactList>
<mdpr:contact ID="{123456}" classID="Customer">
<mdpr:Name>data1</mdpr:Name>
<mdpr:TransportCode>data2</mdpr:TransportCode>
<mdpr:ZipCode>data3</mdpr:ZipCode>
<mdpr:City>data4</mdpr:City>
</mdpr:contact>
<mdpr:contact ID="{234567}" classID="Customer">
<mdpr:Name>data5</mdpr:Name>
<mdpr:TransportCode>data6</mdpr:TransportCode>
<mdpr:ZipCode>data7</mdpr:ZipCode>
<mdpr:City>data8</mdpr:City>
</mdpr:contact>
</mdpr:contactList>
...
Here is how I try to get all contacts:
public class Contact
{
public string Name { get; set; }
public string TransportCode { get; set; }
}
...
XDocument xdoc = XDocument.Load(doc.CreateNavigator().ReadSubtree());
List<Contact> contacts = (from xml in xdoc.Elements("contactList").Elements("contact")
select new Contact
{
Name = xml.Element("Name").Value,
TransportCode = xml.Element("TransportCode").Value
}).ToList();
But I get nothing. What am I doing wrong here?
You have mdpr namespace declared in your xml:
xmlns:mdpr="http://..."
but you are providing only local name of elements in query. E.g. you provide contactList name, but full name of element is mdpr:contactList. That's why nothing is found.
You should define XNamespace for your namespace and use it to create full names of elements:
XNamespace mdpr = "http://...";
var contacts = from c in xdoc.Root.Element(mdpr + "contactList")
.Elements(mdpr + "contact")
select new Contact {
TransportCode = (string)c.Element(mdpr + "TransportCode"),
Name = (string)c.Element(mdpr + "Name")
};
Also contactList is not the root of document. You should search it under Root.
XDocument xdoc = XDocument.Load(doc.CreateNavigator().ReadSubtree());
var ns = xdoc.Root.Name.Namespace;
List<Contact> contacts = (from xml in xdoc.Root.Elements(ns +"contactList").Elements(ns +"contact")
select new Contact
{
Name = xml.Element(ns +"Name").Value,
TransportCode = xml.Element(ns +"TransportCode").Value
}).ToList();
try to specify namespace
string nmsp = "http://www.w3.org/2001/XMLSchema-instance/"
from xml in xdoc.Elements(nmsp+"contactList").Elements(nmsp + "contact")

Select number of data based of a specific node

I have the following piece of code
XmlDocument docu = new XmlDocument();
docu.Load(file);
XmlNodeList lst = docu.GetElementsByTagName("name");
foreach (XmlNode n in lst)
{
string text = n.InnerText;
var types = doc.Element("program").Element("program-function").Element("function").Descendants("type").Where(x => x.Value == text).Select(c => c.Value).ToArray();
}
my xml is as follows
<program>
<program-function>
<function>
<name>add</name>
<return-type>double</return-type>
<params>
<type>double</type>
<type-value>a</type-value>
<type>double</type>
<type-value>b</type-value>
<type>string</type>
<type-value>c</type-value>
</params>
<body> return a + b + c; </body>
</function>
<function>
<name>test</name>
<return-type>int</return-type>
<params>
<type>double</type>
<type-value>a</type-value>
<type>double</type>
<type-value>b</type-value>
</params>
<body> return a + b; </body>
</function>
</program-function>
</program>
i need to be able to get the number of <type> for each <name>
result for add should be 3 = types.count() = 3
result for test should be 2 = types.count() = 2
any advice?
EDIT : If i want to retrieve each value inside types? ie. add should contain a,b,c and test should contain a,b. Would love to store it in an array for easier retrieval
How about using Linq to Xml
var xDoc = XDocument.Parse(xml);
var functions = xDoc.Descendants("function")
.Select(f => new
{
Name = f.Element("name").Value,
Types = f.Descendants("type").Select(t=>t.Value).ToList(),
//Types = f.Descendants("type").Count()
TypeValues = f.Descendants("type-value").Select(t=>t.Value).ToList()
})
.ToList();
Try this:
XDocument doc = XDocument.Load(your file);
var vals = doc.Element("program").Element("program-function").Elements("function");
var result = vals.Select(i =>
new { name = i.Element("name"),
count = i.Elements("type").Count() }

Writing XML Files in C#?

How would I go about doing this:
for( var i = 0; i < emp; i++ )
{
Console.WriteLine("Name: ");
var name = Console.ReadLine();
Console.WriteLine("Nationality:");
var country = Console.ReadLine();
employeeList.Add( new Employee(){
Name = name,
Nationality = country
} );
}
I want a test run of, for example:
Imran Khan
Pakistani
to generate an XML File:
<employee>
<name> Imran Khan </name>
<nationality> Pakistani </nationality>
</employee>
Any suggestions?
My suggestion is to use xml serialization:
[XmlRoot("employee")]
public class Employee {
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("nationality")]
public string Nationality { get; set; }
}
void Main() {
// ...
var serializer = new XmlSerializer(typeof(Employee));
var emp = new Employee { /* properties... */ };
using (var output = /* open a Stream or a StringWriter for output */) {
serializer.Serialize(output, emp);
}
}
There are several ways, but the one I like is using the class XDocument.
Here's a nice example on how to do it.
How can I build XML in C#?
If you have any questions, just ask.
To give you an idea of how XDocument works based on your loop, you would do this:
XDocument xdoc = new XDocument();
xdoc.Add(new XElement("employees"));
for (var i = 0; i < 3; i++)
{
Console.WriteLine("Name: ");
var name = Console.ReadLine();
Console.WriteLine("Nationality:");
var country = Console.ReadLine();
XElement el = new XElement("employee");
el.Add(new XElement("name", name), new XElement("country", country));
xdoc.Element("employees").Add(el);
}
After running, xdoc would be something like:
<employees>
<employee>
<name>bob</name>
<country>us</country>
</employee>
<employee>
<name>jess</name>
<country>us</country>
</employee>
</employees>
<employee>
<name> Imran Khan </name>
<nationality> Pakistani </nationality>
</employee>
XElement x = new XElement ("employee",new XElement("name",e.name),new XElement("nationality",e.nationality) );

Categories