Deserialize XML doc to .NET list - c#

I have a XML doc that looks like this:
https://gyazo.com/87aef26804136ee0cac49cf8b529f9cd
https://gyazo.com/aeb8c56689da52c67afe9b0bf7c19348
How can I convert this to an .NET List object?
I have tried this:
Deserialization Code:
XmlSerializer serializer = new XmlSerializer(typeof(Person));
using (TextReader reader = new StringReader(xmlString))
{
List<Person> result = (List<Person>)serializer.Deserialize(reader);
}
Person class:
public class Person
{
public int id { get; set; }
public int client_id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public string phone_office { get; set; }
public string phone_mobile { get; set; }
public string fax { get; set; }
public string title { get; set; }
public DateTime createad_at { get; set; }
public DateTime updated_at { get; set; }
public bool isFromHighriseOrHarvest { get; set; }
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
-<people type="array">
-<person>
<author-id type="integer">543801</author-id>
<background>Vi är har jobbat ihop och är vänner / Nathalie</background>
<company-id type="integer">81499881</company-id>
<created-at type="datetime">2011-08-10T08:39:45Z</created-at>
<first-name>Per</first-name>
<group-id type="integer" nil="true"/>
<id type="integer">81500134</id>
<last-name>"Cromwell" (Eriksson)</last-name>
<owner-id type="integer" nil="true"/>
<title>ägare, grafiker</title>
<updated-at type="datetime">2011-08-16T08:17:43Z</updated-at>
<visible-to>Everyone</visible-to>
<company-name>Studio Total</company-name>
<linkedin-url nil="true"/>
< avatar_url>https://secure.highrisehq.com/avatar_proxy/eJxj4Yhmz2SWLWTMZHk2_TYLABiEBDM|9d29b49d8f165ff33f28b7f7fac2926eb8487319</avatar_url>
-<contact-data>
-<web-addresses type="array">
-<web-address>
<id type="integer">70306124</id>
<location>Work</location>
<url>http://www.studiototal.se</url>
</web-address>
</web-addresses>
<twitter-accounts type="array"/>
-<email-addresses type="array">
-<email-address>
<address>per#studiototal.se</address>
<id type="integer">39720318</id>
<location>Work</location>
</email-address>
</email-addresses>
<addresses type="array"/>
-<phone-numbers type="array">
-<phone-number>
<id type="integer">70306123</id>
<location>Work</location>
<number>0703689909</number>
</phone-number>
</phone-numbers>
<instant-messengers type="array"/>
</contact-data>
</person>
-<person>
<author-id type="integer">848257</author-id>
<background/>
<company-id type="integer">153838696</company-id>
<created-at type="datetime">2013-02-18T12:49:37Z</created-at>
<first-name>"Kristofer"</first-name>
<group-id type="integer" nil="true"/>
<id type="integer">153838730</id>
<last-name>"Malmer"</last-name>
<owner-id type="integer" nil="true"/>
<title>Projektledare Online listening</title>
<updated-at type="datetime">2013-02-18T12:49:37Z</updated-at>
<visible-to>Everyone</visible-to>
<company-name>Santa Maria</company-name>
<linkedin-url nil="true"/>
<avatar_url>https://secure.highrisehq.com/avatar_proxy/eJxj4Yhmz2SWLWTMZOlK0eYEABUgAvk|d7e22f72a1a3ae2efa83df54e4184d429120cd9f</avatar_url>
-<contact-data>
<web-addresses type="array"/>
<twitter-accounts type="array"/>
<email-addresses type="array"/>
<addresses type="array"/>
-<phone-numbers type="array">
-<phone-number>
<id type="integer">129346649</id>
<location>Work</location>
<number>031-674151</number>
</phone-number>
</phone-numbers>
<instant-messengers type="array"/>
</contact-data>
</person>
-<person>
<author-id type="integer">848257</author-id>
<background/>
<company-id type="integer">151848665</company-id>
<created-at type="datetime">2013-02-01T10:14:27Z</created-at>
<first-name>"Sorush"</first-name>
<group-id type="integer" nil="true"/>
<id type="integer">151848627</id>
<last-name/>
<owner-id type="integer" nil="true"/>
<title/>
<updated-at type="datetime">2013-02-01T10:16:29Z</updated-at>
<visible-to>Everyone</visible-to>
<company-name>Rancold</company-name>
<linkedin-url nil="true"/>
<avatar_url>https://secure.highrisehq.com/avatar_proxy/eJxj4Yhmz2SWLWTMZNnMxssJABRuAqY|1606d5054fb0e0f0b5ccc657dffcd80966ab9b64</avatar_url>
-<contact-data>
-<web-addresses type="array">
-<web-address>
<id type="integer">127911276</id>
<location>Work</location>
<url>http://www.rancold.com</url>
</web-address>
</web-addresses>
<twitter-accounts type="array"/>
-<email-addresses type="array">
-<email-address>
<address>sa#rancold.com</address>
<id type="integer">76736018</id>
<location>Work</location>
</email-address>
</email-addresses>
<addresses type="array"/>
-<phone-numbers type="array">
-<phone-number>
<id type="integer">127911275</id>
<location>Work</location>
<number>031-7441284</number>
</phone-number>
</phone-numbers>
<instant-messengers type="array"/>
</contact-data>
</person>
The error is System.InvalidOperationException.
Additional message: there is something wrong with your xml document (2, 2).

You should annotate your Person type and its members with XML serialization attributes. See Controlling XML Serialization Using Attributes for more information.

You can build your C# class codefile automatically based on your data. First, clean up your XML (extra whitespace on < avatar_url>, adding the final end tag, getting rid of the stray - characters...
Given good XML, save to a file, and execute the following from a VS command prompt:
xsd.exe people.xml
This creates an XSD file from the XML. Then you need to create your code file:
xsd.exe /c people.xsd
Now you have a C# codefile which has everything configured properly. You can modify this codefile for your needs, but leave all of the attributes and other XML-related stuff alone.

Try xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication7
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Person.people = doc.Descendants("person").Select(x => new Person()
{
id = (int)x.Element("author-id"),
client_id = (int)x.Element("company-id"),
first_name = (string)x.Element("first-name"),
last_name = (string)x.Element("last-name"),
email = (string)x.Descendants("email-addresses").FirstOrDefault(),
phone_office = x.Descendants("phone-number").Where(y => (string)y.Element("location") == "Work").Select(z => (string)x.Descendants("number").FirstOrDefault()).FirstOrDefault(),
phone_mobile = x.Descendants("phone-number").Where(y => (string)y.Element("location") == "Mobile").Select(z => (string)x.Descendants("number").FirstOrDefault()).FirstOrDefault(),
fax = x.Descendants("phone-number").Where(y => (string)y.Element("location") == "Fax").Select(z => (string)x.Descendants("number").FirstOrDefault()).FirstOrDefault(),
title = (string)x.Element("title"),
createad_at = (DateTime)x.Element("created-at"),
updated_at = (DateTime)x.Element("updated-at"),
}).ToList();
}
}
public class Person
{
public static List<Person> people = new List<Person>();
public int id { get; set; }
public int client_id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public string phone_office { get; set; }
public string phone_mobile { get; set; }
public string fax { get; set; }
public string title { get; set; }
public DateTime createad_at { get; set; }
public DateTime updated_at { get; set; }
public bool isFromHighriseOrHarvest { get; set; }
}
}

Related

How to read XML elements c# (sample code provided)

I have the following XML sample that I want to read the data. I only provided one "project" element but this can have many "project" inside the "projects" root.
<?xml version="1.0" encoding="utf-8"?>
<projects>
<project>
<details>
<projectName><![CDATA[CxWtGZxYT]]></projectName>
<uniqueID>Pt144</uniqueID>
<collaboratingList>
<collaboratingOrganisation id="5318" value="EpCyxCv RvGxrXAYXGpA xCxWtGZxYT"/>
<collaboratingOrganisation id="0000" value="EpCyxCv RvGxrXAYXGpA xCxWtGZxYTd"/>
</collaboratingList>
<researchOutputList>
<item>
<pubDate>2014-02-04T00:00:00+00:00</pubDate>
<title><![CDATA[rGDEZ]]></title>
<link>link</link>
<guid>guid</guid>
<description><![CDATA[uGDB BDstA rGDEZ]]></description>
</item>
<item>
<pubDate>2015-08-04T00:00:00+00:00</pubDate>
<title><![CDATA[AERx CApCYZ.]]></title>
<link>link</link>
<guid>guid</guid>
<description><![CDATA[vwtpY]]></description>
</item>
</researchOutputList>
</details>
</project>
</projects>
I can read the <projectName> and <uniqueId> but cannot <researchOutputList> and <collaboratingList>. I am not sure what I am missing or if my XML structure is correct. My codes below:
[Serializable]
[XmlRoot("projects")]
public class BulkProjectRoot
{
public BulkProjectRoot()
{
BulkProjectDetails = new List<BulkProjectData>();
}
[XmlArray("project")]
[XmlArrayItem("details")]
public List<BulkProjectData> BulkProjectDetails { get; set; }
}
[Serializable]
[XmlRoot("details")]
public class BulkProjectData
{
public BulkProjectData()
{
ProjectResearches = new List<ProjectResearchOutputs>();
}
[XmlElement("projectName")]
public string Name { get; set; }
[XmlElement("uniqueID")]
public string ProjectUniqueId { get; set; }
[XmlElement("researchOutputList")]
public List<ProjectResearchOutputs> ProjectResearches { get; set; }
}
[Serializable]
[XmlRoot("researchOutputList")]
public class ProjectResearchOutputs
{
public ProjectResearchOutputs()
{
ResearchItemsList = new List<ResearchOutputItems>();
}
[XmlElement("item")]
public List<ResearchOutputItems> ResearchItemsList { get; set; }
}
[Serializable]
[XmlRoot("item")]
public class ResearchOutputItems
{
[XmlElement("pubDate")]
public DateTime? PublishDate { get; set; }
[XmlElement("title")]
public string ResearchTitle { get; set; }
[XmlElement("link")]
public string ResearchLink { get; set; }
[XmlElement("guid")]
public string ResearchGuid { get; set; }
[XmlElement("description")]
public string ResearchDescription { get; set; }
}
The reasearchlist deserializes fine with Linqpad, but you are missing the collaboration information in your BulkProjectData class.
void Main()
{
var xml = #"<?xml version=""1.0"" encoding=""utf - 8""?>
<projects>
<project>
<details>
<projectName><![CDATA[CxWtGZxYT]]></projectName>
<uniqueID> Pt144 </uniqueID>
<collaboratingList>
<collaboratingOrganisation id = ""5318"" value = ""EpCyxCv RvGxrXAYXGpA xCxWtGZxYT"" />
<collaboratingOrganisation id = ""0000"" value = ""EpCyxCv RvGxrXAYXGpA xCxWtGZxYTd"" />
</collaboratingList>
<researchOutputList>
<item>
<pubDate>2014-02-04T00:00:00+00:00</pubDate>
<title><![CDATA[rGDEZ]]></title>
<link> link </link>
<guid> guid </guid>
<description><![CDATA[uGDB BDstA rGDEZ]]></description>
</item>
<item>
<pubDate>2015-08-04T00:00:00+00:00</pubDate>
<title><![CDATA[AERx CApCYZ.]]></title>
<link> link </link>
<guid> guid </guid>
<description><![CDATA[vwtpY]]></description>
</item>
</researchOutputList>
</details>
</project>
</projects>";
var serializer = new XmlSerializer(typeof(BulkProjectRoot));
var result = (BulkProjectRoot)serializer.Deserialize(new StringReader(xml));
result.Dump();
Jsut make this change -
[Serializable]
[XmlRoot("details")]
public class BulkProjectData
{
public BulkProjectData()
{
// Not a list
ProjectResearches = new ProjectResearchOutputs();
}
[XmlElement("projectName")]
public string Name { get; set; }
[XmlElement("uniqueID")]
public string ProjectUniqueId { get; set; }
[XmlElement("researchOutputList")]
public ProjectResearchOutputs ProjectResearches { get; set; }
}

unable to deserialize all elements of this xml

Few elements of this XML does not deserialize and but it does not throw any errors either.
<?xml version="1.0" encoding="utf-8"?>
<TrialMWordsRecord xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyList>
<MWords>
<Id>0</Id>
<Name>ListMWords1</Name>
<Type>LIST</Type>
<MyOutput>true</MyOutput>
<WordsElements>
<Words>
<Name>ListMWords1</Name>
<Value>Apple</Value>
<Type>STRING</Type>
</Words>
<Words>
<Name>ListMWords1</Name>
<Value>Mango</Value>
<Type>STRING</Type>
</Words>
<Words>
<Name>ListMWords1</Name>
<Value>Chickoo</Value>
<Type>STRING</Type>
</Words>
</WordsElements>
</MWords>
<MWords>
<Id>1</Id>
<Type>RANDOM</Type>
<MyOutput>true</MyOutput>
<WordsElements>
<Name>Limit</Name>
<Value>3,8</Value>
<Type>NUMERIC</Type>
</WordsElements>
</MWords>
</TrialMWordsList>
</MyListRecord>
Below are my classes:
[Serializable()]
[XmlRootAttribute("MyListRecord")]
public class MyList
{
[XmlArray("MyList")]
public List<MWords> MWords
{
get;
set;
}
public static MyList Deserialize()
{
XmlSerializer deserializer = new XmlSerializer(typeof(MyList));
TextReader textReader = new StreamReader(Application.StartupPath + "\\MyList.xml");
MyList resultList = (MyList)deserializer.Deserialize(textReader);
textReader.Close();
return resultList;
}
}
[Serializable()]
public class MWords
{
public int Id
{
get;
set;
}
public MWordsType Type
{
get;
set;
}
public bool MyOutput
{
get;
set;
}
public string Requirement
{
get;
set;
}
[XmlArrayItem("WordsElements")]
public List<Words> WordList
{
get;
set;
}
public static MWords Deserialize()
{
XmlSerializer deserializer = new XmlSerializer(typeof(MWords));
TextReader textReader = new StreamReader(Application.StartupPath + "\\MWords.xml");
MWords mwords = (MWords)deserializer.Deserialize(textReader);
textReader.Close();
return mwords;
}
}
public class Words
{
public string Value
{
get;
set;
}
public TYPE Type
{
get;
set;
}
public string Name
{
get;
set;
}
}
Now when I deserialize this XML, if Type is LiST, the WordList gets updated, e.g. here count for WordList will be 3 but if Type is RANDOM, WordList is 0 which should actually be 1 and not 0.
Really don't know what could be the reason.
The problem is in your XML. Look at what it's like for your working case:
<WordsElements>
<Words>
<Name>ListMWords1</Name>
<Value>Apple</Value>
<Type>STRING</Type>
</Words>
<Words>
...
</Words>
<Words>
...
</Words>
</WordsElements>
Now compare that with your broken case:
<WordsElements>
<Name>Limit</Name>
<Value>3,8</Value>
<Type>NUMERIC</Type>
</WordsElements>
You've got no Words element in there - it should be:
<WordsElements>
<Words>
<Name>Limit</Name>
<Value>3,8</Value>
<Type>NUMERIC</Type>
</Words>
</WordsElements>
If you can't change the XML, you may need to deserialize it by hand - which probably wouldn't be too hard.
As an aside, you might want to look into writing your automatically implemented properties on one line - it's a lot more compact to write
public string Name { get; set; }
than
public string Name
{
get;
set;
}
... and it's no harder to read, IMO.
The contents of element WordsElements for type RANDOM does not wrap in <Words></Words>:
<MWords>
<Id>1</Id>
<Type>RANDOM</Type>
<MyOutput>true</MyOutput>
<WordsElements>
<Words>
<Name>Limit</Name>
<Value>3,8</Value>
<Type>NUMERIC</Type>
</Words>
</WordsElements>
</MWords>

Deserialization of XML list objects in C#

I am trying to deserialize an xml in c# which looks like this (shortened version):
<?xml version="1.0" encoding="UTF-8"?>
<map>
<parts>
<part name="default part">
<objects count="1597">
<object type="1" symbol="6">
<coords count="130">
<coord x="-221595" y="-109687" flags="1"/>
<coord x="-221625" y="-109744"/>
<coord x="-221640" y="-109785"/>
<coord x="-221640" y="-109841" flags="1"/>
<coord x="-221655" y="-109969"/>
<coord x="-221655" y="-110040"/>
<coord x="-221640" y="-110164" flags="1"/>
<coord x="-221640" y="-110209"/>
<coord x="-221655" y="-110265"/>
</coords>
<pattern rotation="0">
<coord x="0" y="0"/>
</pattern>
</object>
</objects>
</part>
</parts>
</map>
Using the classes below:
[XmlRoot("map")]
public class Map {
[XmlElement(ElementName = "parts")]
public List<Part> parts { get; set; }
public Map()
{
parts = new List<Part>();
}
public class Part {
[XmlElement(ElementName = "objects")]
public List<KdToPostGISProject.Object> objects { get; set; }
public Part()
{
objects = new List<KdToPostGISProject.Object>();
}
[XmlAttribute(AttributeName = "name")]
public String name { get; set; }
}
public class Object
{
[XmlElement(ElementName = "coords")]
public List<Coord> coords { get; set; }
public Object()
{
coords = new List<Coord>();
}
}
public class Coord
{
[XmlAttribute]
public int x { get; set; }
[XmlAttribute]
public int y { get; set; }
}
And the main function:
var serializer = new XmlSerializer(typeof(Map), new XmlRootAttribute("map"));
Map resultingMessage = (Map)serializer.Deserialize(new FileStream(#"myXml.xml", FileMode.Open));
For some reason which I've been trying to figure out I keep getting zero objects (and null name) in my part-class. Right now I'm stuck, anyone who has any input?
For List<T> members, you have to mark them as e.g.:
[XmlArray(ElementName = "parts")]
[XmlArrayItem(ElementName = "part")]
public List<Part> parts { get; set; }
Not:
[XmlElement(ElementName = "parts")]
Change for all List<T> members then it should work fine.

deserializing a nested list in xml

I am c# silverlight beginner i am under a situation that i have thios xml code:
string xmlstring = #"<?xml version='1.0' encoding='utf-8' ?>
<par>
<name>amount</name>
<label>Amount</label>
<unit>Hundred</unit >
<comp>
<type>Combo</type>
<attributes>
<type>Integer</type>
<displayed>4</displayed>
<selected>0</selected>
<item>5</item>
</attributes>
</comp>
</par>";
** Now what is the problem ?**
In the last line when i try to debug "item" which is asssigned several value like 5 on line Debug.WriteLine(attrib.item);i just see only "5" on debugging it dont show other values. I guess i need to implement a list for it. But how to do it here that i don't know. Could some one please help me so that i will be able to have all the assigned values to item in this c# code because after this step i havce to create a GUI of it. Woudl be a big help.
Note: I cannot use ArrayList because silverligth dont support it any other lastertnative please ?
This is what you need:
[XmlRoot(ElementName = "parameter")]
public class Parameter
{
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("label")]
public string Label { get; set; }
[XmlElement("unit")]
public string Unit { get; set; }
[XmlElement("component")]
public Component Component { get; set; }
}
[XmlRoot(ElementName = "component")]
public class Component {
[XmlElement("type")]
public string Type { get; set; }
[XmlElement("attributes")]
public Attributes Attributes { get; set; }
}
[XmlRoot(ElementName = "attributes")]
public class Attributes
{
[XmlElement("type")]
public string Type { get; set; }
[XmlElement("displayed")]
public string Displayed { get; set; }
[XmlElement("selected")]
public string Selected { get; set; }
[XmlArray("items")]
[XmlArrayItem("item", typeof(string))]
public List<string> Items { get; set; }
}
class Program
{
static void Main(string[] args)
{
string xmlstring = #"<?xml version='1.0' encoding='utf-8' ?>
<parameter>
<name>max_amount</name>
<label>Max Amount</label>
<unit>Millions</unit>
<component>
<type>Combo</type>
<attributes>
<type>Integer</type>
<displayed>4</displayed>
<selected>0</selected>
<items>
<item>5</item>
<item>10</item>
<item>20</item>
<item>50</item>
</items>
</attributes>
</component >
</parameter>";
XmlSerializer deserializer = new XmlSerializer(typeof(Parameter));
XmlReader reader = XmlReader.Create(new StringReader(xmlstring));
Parameter parameter = (Parameter)deserializer.Deserialize(reader);
Console.WriteLine("Type: {0}", parameter.Component.Attributes.Type);
Console.WriteLine("Displayed: {0}", parameter.Component.Attributes.Displayed);
Console.WriteLine("Selected: {0}", parameter.Component.Attributes.Selected);
Console.WriteLine("Items: ");
foreach (var item in parameter.Component.Attributes.Items)
{
Console.WriteLine("\t{0}", item);
}
Console.ReadLine();
}
}
Note small change in xmlstring, now every <item></item> is inside container:
<items>
<item>5</item>
<item>10</item>
<item>20</item>
<item>50</item>
</items>

Deserializing an XML document with the root being a list

I have an XML document provided to me externally that I need to import into my application. The document is badly written, but not something I can really do much about.
<?xml version="1.0" encoding="iso-8859-1"?>
<xml>
<Items>
<Property1 />
<Property2 />
...
</Items>
<Items>
<Property1 />
<Property2 />
...
</Items>
...
</xml>
How should I go about using the XmlSerializer for this?
It doesn't seem to matter what class setup I use, or wether I put XmlRoot(ElementName="xml") on my base class it always says that the <xml xmlns=''> is unexpected.
Edit: Added the C# code I am using
[XmlRoot(ElementName = "xml")]
public class Container
{
public List<Items> Items { get; set; }
}
public class Items
{
public short S1 { get; set; }
public short S2 { get; set; }
public short S3 { get; set; }
public short S4 { get; set; }
public short S5 { get; set; }
public short S6 { get; set; }
public short S7 { get; set; }
}
public class XMLImport
{
public Container Data{ get; private set; }
public static XMLImport DeSerializeFromFile(string fileName)
{
XMLImport import = new XMLImport();
XmlSerializer serializer = new XmlSerializer(typeof(Container));
using (StreamReader reader = new StreamReader(fileName))
import.Data = (Container)serializer.Deserialize(reader);
return import;
}
}
Say you have a class Items maps to each <Items> node:
public class Items
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
You can deserialize your list of Items like this:
var doc = XDocument.Parse(
#"<?xml version=""1.0"" encoding=""iso-8859-1""?>
<xml>
<Items>
<Property1 />
<Property2 />
</Items>
<Items>
<Property1 />
<Property2 />
</Items>
</xml>");
var serializer = new XmlSerializer(typeof(List<Items>), new XmlRootAttribute("xml"));
List<Items> list = (List<Items>)serializer.Deserialize(doc.CreateReader());
The root of your XML is not a List, the root of your xml is the <xml> node I think you are just confused by its name :)
please visit the following link, It has many good answers voted by many people.
Here is the link: How to Deserialize XML document
Error Deserializing Xml to Object - xmlns='' was not expected
Simply take off the Namespace =:
[XmlRoot("xml"), XmlType("xml")]
public class RegisterAccountResponse {...}

Categories