Deserialize rooted XML elements into an array - c#

I need to save multiple fields from an XML into different arrays.
This is what my XML looks like:
<Content>
<Colours>
<Colour name="Strong Red">
<R>255</R>
<G>0</G>
<B>0</B>
<A>255</A>
</Colour>
</Colours>
<Textures>
<Texture name="Character01">
<Path>Path/Folder</Path>
</Texture>
</Textures>
</Content>
Now everything was working fine when <Colours> was my root and i only added colours into one Array.
Now i want to add Textures and later more through the same XML file, thus moving the root one up to <Content>.
This is what my ColourLoader Class looked like with only Colours and <Colour> being the root of my XML:
[Serializable()]
[XmlRoot("Colours")]
public class ColourLoader
{
[XmlElement("Colour")]
public CustomColour[] Colours;
public static ColourLoader Load(string path)
{
var serializer = new XmlSerializer(typeof(ColourLoader));
using (var stream = new FileStream(path, FileMode.Open))
{
return serializer.Deserialize(stream) as ColourLoader;
}
}
}
My CustomColour class works fine, it uses [XmlElement("R")] etc. to read the values from the XML. It's just that i don't know how to read elements from a nested XML.
I somehow have to skip <Content> and add Colours from <Colours> as root and do the same for <Textures> etc.
I don't want to create multiple XML files as i would like to keep all content managing into one spot and only load an XML file once.

I think this is what you're after. I've also included a method that serializes the object. I find this very helpful in diagnosing idiosyncratic issues with XML Serialization...
Please vote as answer if this solved your issue.
[Serializable()]
[XmlRoot("Content")]
public class Content
{
[XmlArray("Colours")]
[XmlArrayItem("Colour")]
public CustomColour[] Colours { get; set; }
[XmlArray("Textures")]
[XmlArrayItem("Texture")]
public CustomTexture[] Textures { get; set; }
}
[Serializable()]
[XmlRoot("Colour")]
public class CustomColour
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("R")]
public int R { get; set; }
[XmlElement("G")]
public int G { get; set; }
[XmlElement("B")]
public int B { get; set; }
[XmlElement("A")]
public int A { get; set; }
}
[Serializable()]
[XmlRoot("Texture")]
public class CustomTexture
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("Path")]
public string Path { get; set; }
}
public static class ContentLoader
{
public static Content Load(TextReader textReader)
{
var serializer = new XmlSerializer(typeof(Content));
var ret = serializer.Deserialize(textReader) as Content;
return ret;
}
public static void Save(TextWriter textWriter, Content content)
{
var serializer = new XmlSerializer(typeof(Content));
serializer.Serialize(textWriter, content);
}
}
public static void XmlSerializing()
{
var xml = #"<?xml version=""1.0"" encoding=""utf-16""?>
<Content xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<Colours>
<Colour name=""Strong Red"">
<R>255</R>
<G>0</G>
<B>0</B>
<A>255</A>
</Colour>
</Colours>
<Textures>
<Texture name=""Character01"">
<Path>Path/Folder</Path>
</Texture>
</Textures>
</Content>";
var reader = new StringReader(xml);
var content = ContentLoader.Load(reader);
Console.WriteLine("Deserialized version:");
Console.WriteLine(" Colours");
foreach (var colour in content.Colours)
{
Console.WriteLine(" R: {0}, G: {1}, B: {2}, A: {3}", colour.R, colour.G, colour.B, colour.A);
}
Console.WriteLine(" Textures");
foreach (var texture in content.Textures)
{
Console.WriteLine(" Path: {0}", texture.Path);
}
var contentObj = new Content()
{
Colours = new[] { new CustomColour() { Name = "StrongRed", R = 255, G = 0, B = 0, A = 255 } },
Textures = new[] { new CustomTexture() { Name = "Character01", Path = "Path/Folder" } }
};
Console.WriteLine(string.Empty);
Console.WriteLine("Serialized version:");
var writer = new StringWriter();
ContentLoader.Save(writer, contentObj);
Console.WriteLine(writer);
}

Related

How to get value inside XML tag?

I have the follow XML structure:
<Document>
<Sectors>
<Sector>
SectorName1
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
<Sector>
SectorName2
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
</Sectors>
</Document>
Also I have classes for deserialize:
public class MetaDataXML
{
public class SectorXML
{
[XmlArrayItem(ElementName = "Sector")]
string SectorName { get; set; }
[XmlArray]
[XmlArrayItem(ElementName = "Subsector")]
public List<string> Subsectors { get; set; }
}
public List<SectorXML> Sectors { get; set; }
}
And part of code which do deserialize:
var xRoot = new XmlRootAttribute { ElementName = "Document", IsNullable = true };
var reader = new XmlSerializer(typeof(MetaDataXML), xRoot);
var data = (MetaDataXML)reader.Deserialize(streamXML);
After deserialization I successfully get subsectors velues, but I didn't get values for SectorName. How I need to organize my structure of class that I'll get values "SectorName1" and "SectorName2" for my string SectorName property?
I found that that this case it's a "Mixed Content". How we can parse this text values?
Whilst I am not entirely sure what it is you're trying to achieve here, I've made a few modifications to your XML class and provided some sample code below that is able to retrieve all of the information about a sector, including its name and the name of all the subsectors inside it.
XML Class:
namespace DocumentXml
{
[XmlRoot("Document")]
public class Document
{
[XmlArray("Sectors")]
[XmlArrayItem("Sector")]
public Sector[] Sectors { get; set; }
}
[XmlRoot("Sector")]
public class Sector
{
[XmlAttribute("SectorName")]
public string SectorName { get; set; }
[XmlArray("Subsectors")]
[XmlArrayItem("Subsector")]
public string[] Subsectors { get; set; }
}
}
Main Program Class:
namespace DocumentXml
{
class Program
{
static void Main(string[] args)
{
var path = #"D:\sandbox\DocumentXml\DocumentXml\Sample.xml";
var serializer = new XmlSerializer(typeof(Document));
var document = serializer.Deserialize(File.OpenRead(path)) as Document;
var sectors = document.Sectors;
foreach (var s in sectors)
{
Console.WriteLine($"Sector Name: {s.SectorName}");
foreach (var ss in s.Subsectors)
{
Console.WriteLine($"Subsector Name: {ss}");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
}
Sample XML:
<Document>
<Sectors>
<Sector SectorName="SectorName1">
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
<Sector SectorName="SectorName2">
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
</Sectors>
</Document>
Output:
EDIT
Since the XML structure cannot be changed, this new class will preserve the structure and also allow you to get the value in question. XmlText returns everything inside the value so a custom set had to be used to ensure that the whitespace was correctly trimmed from it.
[XmlRoot("Document")]
public class MetaDataXml
{
[XmlArray("Sectors")]
[XmlArrayItem("Sector")]
public Sector[] Sectors { get; set; }
}
[XmlRoot("Sector")]
public class Sector
{
[XmlIgnore]
private string _sectorName;
[XmlText]
public string SectorName
{
get
{
return _sectorName;
}
set
{
_sectorName = value.Trim();
}
}
[XmlArray]
[XmlArrayItem(ElementName = "Subsector")]
public List<string> Subsectors { get; set; }
}
Sample Program:
class Program
{
static void Main(string[] args)
{
var path = #"D:\sandbox\DocumentXml\DocumentXml\Sample.xml";
using (var stream = File.OpenRead(path))
{
var deserializer = new XmlSerializer(typeof(MetaDataXml));
var data = (MetaDataXml)deserializer.Deserialize(stream);
foreach (var s in data.Sectors)
{
Console.WriteLine($"Sector Name: {s.SectorName}");
foreach (var ss in s.Subsectors)
{
Console.WriteLine($"Subsector Name: {ss}");
}
Console.WriteLine();
}
}
Console.ReadKey();
}
}

XMLSerializer changes name of elements

I'm trying to serialize object for import to another Software and the issue is, that elements in XML that is to be imported contain ":" (p.e.: < ftr:filter>).
I declared classes overriding those names with [XmlAttribute("ftr:filter")] and [XMLElement(ftr:differentFilter")], but serializer products different nodes. I bet it has something to do with encoding, but I'm not able to change the result (thought I changed encoding).
Example of classes:
public class ListPrijemkaRequest
{
[XmlAttribute("version")]
public string Version { get; set; }
[XmlAttribute("prijemkaVersion")]
public string PrijemkaVersion { get; set; }
[XmlElement("lst:requestPrijemka")]
public List<RequestPrijemka> Requests { get; set; }
}
public class RequestPrijemka
{
[XmlElement("ftr:filter")]
public RequestDateFilter Filter { get; set; }
}
Desired ooutput:
< lst:listPrijemkaRequest version="2.0" prijemkaVersion="2.0">
< lst:requestPrijemka>
< ftr:filter>
< ftr:dateFrom>2013-01-10</ftr:dateFrom>
< ftr:dateTill>2013-03-30</ftr:dateTill>
< /ftr:filter>
< /lst:requestPrijemka>
< /lst:listPrijemkaRequest>
Obtained output:
< lst_x003A_listPrijemkaRequest version="2.0" prijemkaVersion="2.0">
< lst_x003A_requestPrijemka>
< ftr_x003A_filter>
< ftr_x003A_dateFrom>2013-01-10</ftr_x003A_dateFrom>
< ftr_x003A_dateTill>2013-03-30</ftr_x003A_dateTill>
< /ftr_x003A_filter>
< /lst_x003A_requestPrijemka>
< /lst_x003A_listPrijemkaRequest>
If those "tags" ftr / lst are namespaces, there is no need to "hard-code" them, you can setup the serializer to use those namespaces.
http://msdn.microsoft.com/en-us/library/ms163161%28v=vs.110%29.aspx
Example (taken from XML Serialization and namespace prefixes)
[XmlRoot("Node", Namespace="http://your.companies.namespace")]
public class ListPrijemkaRequest {
[XmlElement("requestPrijemka")]
public List<RequestPrijemka> Requests { get; set; }
}
static class Program
{
static void Main()
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("lst", "http://your.companies.namespace");
XmlSerializer xser = new XmlSerializer(typeof(ListPrijemkaRequest));
xser.Serialize(Console.Out, new ListPrijemkaRequest(), ns);
}
}
If not, I don't think it's possible with "default" serialization.
Other options:
Use custom serialization (IXmlSerializable), see: http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly
Do post editing of the serialized file and do a string replace with the desired node names
But like I said in my comment, it is not recommended to use : in node names in the first place!
[XmlRoot("listPrijemkaRequest", Namespace = "http://your.companies.namespace/lst")]
public class ListPrijemkaRequest {
[XmlAttribute("version")]
public string Version { get; set; }
[XmlAttribute("prijemkaVersion")]
public string PrijemkaVersion { get; set; }
[XmlElement("requestPrijemka")]
public List<RequestPrijemka> Requests { get; set; }
}
public class RequestDateFilter
{
[XmlElement(ElementName = "dateFrom")]
public DateTime DateFrom { get; set; }
[XmlElement(ElementName = "dateTill")]
public DateTime DateTill { get; set; }
}
public class RequestPrijemka {
[XmlElement("filter", Namespace = "http://your.companies.namespace/ftr")]
public RequestDateFilter Filter { get; set; }
}
static class Program {
static void Main() {
var ns = new XmlSerializerNamespaces();
ns.Add("lst", "http://your.companies.namespace/lst");
ns.Add("ftr", "http://your.companies.namespace/ftr");
var xser = new XmlSerializer(typeof(ListPrijemkaRequest));
var obj = new ListPrijemkaRequest
{
Version = "2.0",
PrijemkaVersion = "2.0",
Requests = new List<RequestPrijemka>
{
new RequestPrijemka
{
Filter = new RequestDateFilter {DateFrom = DateTime.Now, DateTill = DateTime.Now}
}
}
};
xser.Serialize(Console.Out, obj, ns);
Console.ReadLine();
}
}
Produce this xml:
<?xml version="1.0" encoding="cp866"?>
<lst:listPrijemkaRequest xmlns:ftr="http://your.companies.namespace/ftr" version="2.0" prijemkaVersion="2.0" xmlns:lst="http://your.companies.namespace/lst">
<lst:requestPrijemka>
<ftr:filter>
<ftr:dateFrom>2014-07-17T16:17:47.0601039+03:00</ftr:dateFrom>
<ftr:dateTill>2014-07-17T16:17:47.061104+03:00</ftr:dateTill>
</ftr:filter>
</lst:requestPrijemka>
</lst:listPrijemkaRequest>
Looks similar with what you need.

serialize imageList property

I have an Album class which contains title, description and an integer value of the index of a cover image. It also contains an imageList.
I need to serialize this obj and while the imageList is not serializeable but the imageListStream is...
I'm a complete c# noob so would appreciate what ever guidance available.
The desired result would be somethings like:
<Album>
<Title>Album Title</Title>
<Description>Some explanation.</Description>
<CoverImgIndx>2</CoverImgIdx>
<Images>
<Image>
<indx>0</indx>
<filepath>"C:\Images\file1.jpg"</filepath>
</Image>
<Image>
<indx>1</indx>
<filepath>"C:\Images\file2.png"</filepath>
</Image>
<Image>
<indx>2</indx>
<filepath>"C:\Images\file3.jpg"</filepath>
</Image>
<Image>
<indx>3</indx>
<filepath>"C:\Images\file4.bmp"</filepath>
</Image>
</Images>
</Album>
obviously I need to reconstitute the imageList when deserializing...
Sounds like you simply need to use the XmlSerializer class to serialize your Album class into XML.
Something like this should work: https://dotnetfiddle.net/yE8RAl
Generally speaking you can define your Album / Image like this:
[XmlType(TypeName = "Image")]
public class ImageSerializationContainer
{
[XmlElement(ElementName = "indx")]
public int Index { get; set; }
[XmlElement(ElementName = "filepath")]
public string FilePath { get; set; }
}
[XmlType(TypeName = "Album")]
public class AlbumSerializationContainer
{
public string Title { get; set; }
public string Description { get; set; }
public int CoverImgIndx { get; set; }
public List<ImageSerializationContainer> Images { get; set; }
}
And then use XmlSerializer like this:
XmlSerializer ser = new XmlSerializer(typeof(AlbumSerializationContainer));
StringWriter sw = new StringWriter();
ser.Serialize(sw, yourObjectToSerialize);
return sw.ToString();
However I'm guessing that what you really want is to somehow convert your existing class in a form that you can serialize.
Unfortunately you don't give a lot to go on in your question, so I have to make some assumptions. Now, some of this assumptions are bound to be wrong, but that's to be expected with the level of information you have provided.
I'm going to assume that you are using the ImageList class and that the filenames that you have in your example are stored in a string array that is attached to the ImageList Tag property. Feel free to modify the code to take this value from elsewhere. You did not give information about how you structure your index values. I'm assuming these are indexes in the ImageList.Images collection.
There are several ways to approach your problem. I'm going to show you how to use AutoMapper to convert what could be your class to a class that you can serialize and then serialize it.
Below you can find a complete example. Please note that you might need to update the AutoMapper configuration if your classes are different from presented below.
I'm demonstrating both: serializing an class to XML (example 1) and converting another class to serializable class (example 2).
using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Collections.Generic;
using AutoMapper;
namespace SO24174411
{
class Program
{
static void Main()
{
AlbumSerializationContainer example1 = new AlbumSerializationContainer
{
CoverImgIndx = 2,
Description = "Some explanation.",
Images = new List<ImageSerializationContainer>
{
new ImageSerializationContainer {FilePath = #"C:\Images\file1.jpg", Index = 0},
new ImageSerializationContainer {FilePath = #"C:\Images\file2.png", Index = 1},
new ImageSerializationContainer {FilePath = #"C:\Images\file3.jpg", Index = 2},
new ImageSerializationContainer {FilePath = #"C:\Images\file4.bmp", Index = 3}
},
Title = "Album Title"
};
Console.WriteLine("Example 1");
Console.WriteLine(Serialize(example1));
Album album = new Album
{
CoverImgIndx = 2,
Description = "Some explanation.",
Images = new ImageList(),
Title = "Album Title"
};
SetImages(album.Images, new[]
{
#"C:\Images\file1.jpg",
#"C:\Images\file1.jpg",
#"C:\Images\file2.png",
#"C:\Images\file4.bmp"
});
var example2 = PerformMapping(album);
Console.WriteLine("Example 2");
Console.WriteLine(Serialize(example2));
}
private static AlbumSerializationContainer PerformMapping(Album album)
{
Mapper.CreateMap<Album, AlbumSerializationContainer>();
Mapper.CreateMap<ImageList, List<ImageSerializationContainer>>().ConvertUsing<ImageListconverter>();
AlbumSerializationContainer example2 = Mapper.Map<AlbumSerializationContainer>(album);
return example2;
}
public class ImageListconverter : TypeConverter<ImageList, List<ImageSerializationContainer>>
{
protected override List<ImageSerializationContainer> ConvertCore(ImageList source)
{
if (source == null)
{
return null;
}
List<ImageSerializationContainer> result = new List<ImageSerializationContainer>();
for (int i = 0; i < source.Images.Count; i++)
{
result.Add(new ImageSerializationContainer { FilePath = ((string[])source.Tag)[i], Index = i });
}
return result;
}
}
public static string Serialize(AlbumSerializationContainer a)
{
XmlSerializer ser = new XmlSerializer(typeof(AlbumSerializationContainer));
StringWriter sw = new StringWriter();
ser.Serialize(sw, a);
return sw.ToString();
}
public static void SetImages(ImageList l, string[] names)
{
l.Tag = names;
for(int i=0;i<names.Length;i++)
{
// Aparently you can read names[i] file here if you want
l.Images.Add(new Bitmap(1, 1));
}
}
}
public class Album
{
public string Title { get; set; }
public string Description { get; set; }
public int CoverImgIndx { get; set; }
public ImageList Images { get; set; }
}
[XmlType(TypeName = "Image")]
public class ImageSerializationContainer
{
[XmlElement(ElementName = "indx")]
public int Index { get; set; }
[XmlElement(ElementName = "filepath")]
public string FilePath { get; set; }
}
[XmlType(TypeName = "Album")]
public class AlbumSerializationContainer
{
public string Title { get; set; }
public string Description { get; set; }
public int CoverImgIndx { get; set; }
public List<ImageSerializationContainer> Images { get; set; }
}
}
You will be able to easily de-serialize your xml back to the serialization container class with XmlSerializer.Deserialize. Some more work will be required to map these back to your required class. Since this part depends more than any other on the information you have not provided I leave it as an exercise for the reader.

C# XML Deserialization of array

I have a problem about deserialize an array. Becouse array elements can be of various types. You can see the example:
<?xml version="1.0" encoding="UTF-8"?><export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://zakupki.gov.ru/oos/export/1" xmlns:oos="http://zakupki.gov.ru/oos/types/1">
<notificationZK>
... item 1 data
</notificationZK>
<notificationZK>
... item 2 data
</notificationZK>
<notificationFF>
... item 3 data
</notificationFF>
</export>
All elements extends notificationType
[System.Xml.Serialization.XmlIncludeAttribute(typeof(notificationSZType))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(notificationPOType))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(notificationZKType))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(notificationEFType))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(notificationOKType))]
public partial class notificationType
{
...
So the question is how can I get the collection of notificationType elements from my XML file? I think I cant do something like
[Serializable()]
[System.Xml.Serialization.XmlRoot("export")]
public class NotificationCollection
{
[XmlArray("")] // ???? what I need write here?
[XmlArrayItem("", typeof(notificationType))] // ??? and here?
public notificationType[] notification { get; set; }
}
Regards!
ADDED-------------
So. I make this:
[Serializable()]
[System.Xml.Serialization.XmlRoot("export")]
public class NotificationCollection
{
[XmlElement("notificationSZType", Type = typeof(notificationSZType))]
[XmlElement("notificationPOType", Type = typeof(notificationPOType))]
[XmlElement("notificationZKType", Type = typeof(notificationZKType))]
[XmlElement("notificationEFType", Type = typeof(notificationEFType))]
[XmlElement("notificationOKType", Type = typeof(notificationOKType))]
public notificationType[] notification { get; set; }
}
class Program
{
static void Main(string[] args)
{
NotificationCollection collection = null;
string path = #"E:\notification.xml";
XmlSerializer serializer = new XmlSerializer(typeof(notificationType));
StreamReader reader = new StreamReader(path);
collection = (NotificationCollection) serializer.Deserialize(reader);
reader.Close();
}
}
but have System.InvalidOperationException was unhandled while serializer.Deserialize(reader);
Message=<export xmlns='http://zakupki.gov.ru/oos/export/1'> not expected.
What im doing wrong?
How about moving the type declarations into the collection?
[XmlRoot("export")]
public class NotificationCollection
{
[XmlElement("notificationZK", typeof(NotificationTypeZK))]
[XmlElement("notificationFF", typeof(NotificationTypeFF))]
public List<NotificationType> Notifications { get; set; }
}
public class NotificationType
{
}
public class NotificationTypeZK : NotificationType { }
public class NotificationTypeFF : NotificationType { }
static void Main(string[] args)
{
var data = #"<export><notificationZK /><notificationZK /><notificationFF /></export>";
var serializer = new XmlSerializer(typeof(NotificationCollection));
using (var reader = new StringReader(data))
{
var notifications = serializer.Deserialize(reader);
}
}
This should do the job
[Serializable()]
[System.Xml.Serialization.XmlRoot("export")]
public class NotificationCollection
{
[XmlElement("notificationSZType", Type = typeof(notificationSZType))]
[XmlElement("notificationPOType", Type = typeof(notificationPOType))]
[XmlElement("notificationZKType", Type = typeof(notificationZKType))]
[XmlElement("notificationEFType", Type = typeof(notificationEFType))]
[XmlElement("notificationOKType", Type = typeof(notificationOKType))]
public notificationType[] notification { get; set; }
}
This question is interesting for me as well. I wrote the simplified app to achieve what you ask for:
[Serializable]
[XmlInclude(typeof(ItemA))]
[XmlInclude(typeof(ItemB))]
public class BaseItem
{
public bool Value { get; set; }
}
[Serializable]
public class ItemA : BaseItem
{
public string Text { get; set; }
}
[Serializable]
public class ItemB : BaseItem
{
public int Number { get; set; }
}
[Serializable]
public class ItemsArray
{
public BaseItem[] Items { get; set; }
}
class Program
{
static void Main(string[] args)
{
var array = new ItemsArray
{
Items = new BaseItem[]
{
new ItemA { Value = true, Text = "Test" },
new ItemB { Value = false, Number = 7 }
}
};
ItemsArray output;
using (var stream = new MemoryStream())
{
var serializer = new XmlSerializer(typeof(ItemsArray));
serializer.Serialize(stream, array);
stream.Position = 0;
output = (ItemsArray)serializer.Deserialize(stream);
}
}
}
After deserialization we get exactly what we serialized. The XML inside stream looks like:
<?xml version="1.0"?>
<ItemsArray xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<BaseItem xsi:type="ItemA">
<Value>true</Value>
<Text>Test</Text>
</BaseItem>
<BaseItem xsi:type="ItemB">
<Value>false</Value>
<Number>7</Number>
</BaseItem>
</Items>
</ItemsArray>
As was mentioned in other answer, you can't use different tags inside XML array. However, it's still possible to store different types. Serializer does this by using xsi:type attribute.
In order to solve your problem you probably need to use a bit another scheme of XML.

Deserialize only give me 0 as value

my problem is simple, when I deserialise this file all values are set to 0.
Some code will be more explicit.
Main class :
public partial class MainPage : PhoneApplicationPage
{
Elements file = null;
// Constructor
public MainPage()
{
InitializeComponent();
load_map("clxml.xml");
}
public void load_map(string path)
{
// deserialize xmlfile_config_map
XmlSerializer serializer = new XmlSerializer(typeof(Elements));
StreamReader reader = new StreamReader(path);
try
{
file = (Elements)serializer.Deserialize(reader);
}catch(Exception e){
}
MessageBox.Show((file.listObjet[1].id).ToString());
MessageBox.Show((file.listObjet[2].pos_x).ToString());
reader.Close();
}
}
class that I fill:
//[Serializable]
public class Element
{
[System.Xml.Serialization.XmlElement("id")]
public int id { get; set; }
[System.Xml.Serialization.XmlElement("pos_x")]
public int pos_x { get; set; }
[System.Xml.Serialization.XmlElement("pos_y")]
public int pos_y { get; set; }
[System.Xml.Serialization.XmlElement("rot")]
public int rot { get; set; }
}
//[Serializable()]
[System.Xml.Serialization.XmlRoot("droot")]
public class Elements
{
[XmlElement("Element")]
public List<Element> listObjet { get; set; }
and the xml file :
<Element id="4" pos_x="85" pos_y="43" rot="34"/>
which is line like this, but I don't think the problem comes from here.
The serializer is expecting elements in the XML. Try change [XmlElement] to [XmlAttribute].
The quickest way to find out deserialize issues is by reverting the process. Try serializing a dummy object and verify whether the output is correct.
Elements elements = new Elements
{
listObjet = new List<Element>
{
new Element
{
id = 1,
pos_x = 10,
pos_y = 20,
rot = 8
}
}
};
var serializer = new XmlSerializer(typeof(Elements));
string output;
using (var writer = new StringWriter())
{
serializer.Serialize(writer, elements);
output = writer.ToString();
}
// Todo: check output format
I have changed [XmlElement] to [XmlAttribute] for the id and pos_x properties. This was the output:
<Element id="1" pos_x="10">
<pos_y>20</pos_y>
<rot>8</rot>
</Element>

Categories

Resources