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.
Related
I need to deserialize bellow XML. The chapter element can have multiple child chapter element in it.I have tried to deserialize the XML using XmlSerializer.
All the elements are deserializing as expected but the issue is that the child Chapter array is not deserializing, am I missing something here? Please help.
<Survey>
<SurveyResults>
<Subject>
<Chapter>
<ChapterIterationName />
<Questions />
<Chapter>
<ChapterName>CHAPTER 1</ChapterName>
<ChapterIterationName />
<Questions>
<Question>
<Text>Question 1</Text>
</Question>
<Question>
<Text>Question 2</Text>
</Question>
</Questions>
<Chapter>
<ChapterName>CHAPTER 1.1</ChapterName>
<ChapterIterationName />
<Questions>
<Question>
<Text>Questoin 1</Text>
</Question>
<Question>
<Text>Questoin 2</Text>
</Question>
</Questions>
</Chapter>
<Chapter>
<ChapterName>CHAPTER 1.2</ChapterName>
<ChapterIterationName />
<Questions>
<Question>
<Text>Questoin 1</Text>
</Question>
<Question>
<Text>Questoin 2</Text>
</Question>
</Questions>
</Chapter>
</Chapter>
</Chapter>
</Subject>
</SurveyResults>
</Survey>
Here is the code I have tried.
public class Survey
{
public SurveyResults SurveyResults { get; set; }
}
public class SurveyResults
{
public Subject Subject { get; set; }
}
public class Subject
{
public List<Chapter> Chapter { get; set; }
}
public class Chapter
{
public string ChapterName { get; set; }
public string ChapterIterationName { get; set; }
[XmlArray("Chapter")]
public List<Chapter> Chapters { get; set; }
public List<Questions> Questions { get; set; }
}
public class Questions
{
public List<Question> Question { get; set; }
}
public class Question
{
public string Text { get; set; }
}
public class Serializer
{
public T Deserialize<T>(string input) where T : class
{
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));
using (StringReader sr = new StringReader(input))
{
return (T)ser.Deserialize(sr);
}
}
}
Serializer ser = new Serializer();
Survey survey = ser.Deserialize<Survey>(xlString);
Result
[Edit]
After so many edits, I found the simple way to solve this:
Copy you XML file contents.
From Visual Studio Menus select Edit -> Paste Special -> Paste XML as Classes.
Use the deserialize code.
string path = #"G:\Projects\StackOverFlow\WpfApp1\Survey.xml";
FileStream reader = File.OpenRead(path);
XmlSerializer ser = new XmlSerializer(typeof(Survey));
Survey survey = (Survey)ser.Deserialize(reader);
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; }
}
}
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; }
}
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>
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 {...}