Deserializing an XML document with the root being a list - c#

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 {...}

Related

Cannot deserialize sub-elements to list of objects

I am having problems serializing elements of an XML to a list of objects.
This is the XML:
<result>
<stats>
<numitemsfound>1451</numitemsfound>
<startfrom>0</startfrom>
</stats>
<items>
<item>
<id>1</id>
<markedfordeletion>0</markedfordeletion>
<thumbsrc>
</thumbsrc>
<thumbsrclarge>
</thumbsrclarge>
...
<datasource>65</datasource>
<data>
<amount>100</amount>
<kj>389</kj>
<kcal>92.91</kcal>
<fat_gram>0.2</fat_gram>
<fat_sat_gram>-1</fat_sat_gram>
<kh_gram>20.03</kh_gram>
</data>
<servings>
<serving>
<serving_id>386</serving_id>
<weight_gram>150</weight_gram>
</serving>
</servings>
</item>
</result>
The classes I prepared for serialization are
[XmlType("item")]
public class Item
{
[XmlAttribute("id")]
public string id { get; set; }
[XmlAttribute("markedfordeletion")]
public string markedfordeletion { get; set; }
...
[XmlAttribute("datasource")]
public string datasource { get; set; }
[XmlElement("data")]
public Data data { get; set; }
[XmlElement("servings")]
public List<Serving> servings { get; set; }
}
}
This is how I try to serialize the xml
public void ParseSearch(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>), new XmlRootAttribute("item"));
StringReader stringReader = new StringReader(xml);
var productList = (List<Item>)serializer.Deserialize(stringReader);
}
But I get the error ----> System.InvalidOperationException : <result xmlns=''> was not expected. Can you please help me solve this problem?
You have to use a serializer which serializes an instance of result, not of type List:
XmlSerializer serializer = new XmlSerializer(typeof(Result), new XmlRootAttribute("result")); //whatever `Result` actually is as type).
You canĀ“t serialize and de-serialize just parts of a document, either the whole one or nothing at all.
So you need a root-type:
[XmlRoot("result")]
public class Result
{
public Stats Stats {get; set;}
[XmlArray("items")]
[XmlArrayItem("item")]
public List<Item> Items { get; set; }
}

How to deserialize an XML with a nested array elements?

Deserialization of XML file with nested array of elements
I've searched but can't see any helpful examples.
this is my XML sample:
<trans>
<orderNo>0001</orderNo>
<orderDate>08/07/2014</orderDate>
<orders>
<item>
<itemName>item1</itemName>
<itemAmount>200</itemAmount>
<itemMeasures>
<measure>each</measure>
<measure>case</measure>
</itemMeasures>
</item>
<item>
<itemName>item2</itemName>
<itemAmount>100</itemAmount>
<itemMeasures>
<measure>each</measure>
<measure>case</measure>
</itemMeasures>
</item>
</orders>
</trans>
You must create classes for each of the structures you have in the XML and then using XmlSerializer and the method Deserialize of the object from that class you can create nested arrays with the values. If you want code and example, please edit your post with the full xml structure.
See the example below for part of your xml:
[XmlType("trans")]
public class Trans
{
[XmlElement("orderNo")]
public string OrderNo { get; set; }
[XmlElement("orderDate")]
public string OrderDate { get; set; }
[XmlArray("orders")]
public HashSet<Item> Orders { get; set; }
}
[XmlType("item")]
public class Item
{
[XmlElement("itemName")]
public string ItemName { get; set; }
[XmlElement("itemAmount")]
public string ItemAmount { get; set; }
}
The the Deserialization code is:
XmlSerializer mySerializer = new XmlSerializer(typeof(Trans[]), new XmlRootAttribute("trans"));
using (FileStream myFileStream = new FileStream("XmlFile.xml", FileMode.Open))
{
Trans[] r;
r = (Trans[])mySerializer.Deserialize(myFileStream);
}

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>

Deserialize XML to Object Array

I'm trying to deserialize an XML file to an object array, but I'm receiving empty objects.
My question looks similar to this: How to Deserialize xml to an array of objects? but I can't seem to create a class which inherits IXmlSerializable. That said, I don't think that approach is necessary.
Am I doing something wrong?
File Object
[XmlType("file")]
public class File
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("company_name")]
public string Company_Name { get; set; }
[XmlElement("docs")]
public HashSet<doc> Docs { get; set; }
}
Doc Object
[XmlType("doc")]
public class Doc
{
[XmlElement("valA")]
public string ValA { get; set; }
[XmlElement("valB")]
public string ValB { get; set; }
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<files>
<file>
<id>12345</id>
<company_name>Apple</company_name>
<docs>
<doc>
<valA>Info</valA>
<valB>More Info</valB>
</doc>
</docs>
</file>
<file>
<id>12345</id>
<company_name>Microsoft</company_name>
<docs>
<doc>
<valA>Even More Info</valA>
<valB>Lots of it</valB>
</doc>
</docs>
</file>
</files>
Deserialization code
XmlSerializer mySerializer = new XmlSerializer(typeof(File[]), new XmlRootAttribute("files"));
using (FileStream myFileStream = new FileStream("Files.xml", FileMode.Open))
{
File[] r;
r = (File[])mySerializer.Deserialize(myFileStream);
}
You have decorated your properties with XMLAttribute but they are elements in your XML. So, change all XMLAttribute to XmlElement.
[XmlType("file")]
public class File
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("company_name")]
public string Company_Id { get; set; }
[XmlArray("docs")]
public HashSet<Doc> Docs { get; set; }
}
[XmlType("doc")]
public class Doc
{
[XmlElement("valA")]
public string ValA { get; set; }
[XmlElement("valB")]
public string ValB { get; set; }
}
Also you XML is not well formed. I guess this is typo though -
<company_name>Apple</company_id>
<company_name>Microsoft</company_id>
Ending tag should be company_name -
<company_name>Apple</company_name>
<company_name>Microsoft</company_name>
I would use xml parser..
XDocument doc=XDocument.Load(url);
File[] r=doc.Elements("file")
.Select(f=>
new File
{
Id=f.Element("id").Value,
Company_Id=f.Element("company_name").Value,
Docs=new HashSet<Docs>(
f.Elements("docs")
.Elements("doc")
.Select(d=>
new Doc
{
ValA=d.Element("valA").Value,
ValB=d.Element("valB").Value
}))
}).ToArray();

Get null by deserialize in C# from XML if string between tags

i need some help, i get allways null if i will deserialize a string between two xml tags.
The following example xml file:
<?xml version="1.0" encoding="utf-8" ?>
<item name='First Item' size='1'>
<Bits value='0'>
1st String
</Bits>
<Bits value='1'>
2nd String
</Bits>
</item>
And i write the following classes:
[Serializable()]
public class Bits
{
[XmlElement(ElementName = "Bits")]
public String entryString { get; set; }
[XmlAttribute("value")]
public int entryValue { get; set; }
}
[Serializable()]
[XmlRoot("item")]
public class itemsReader
{
public itemsReader()
{
_bitList = new List<Bits>();
}
[XmlElement("Bits")]
public List<Bits> _bitList { get; set; }
[XmlAttribute("name")]
public String entryName { get; set; }
[XmlAttribute("size")]
public int entrySize { get; set; }
}
Only the entryString is always null!
To readout the XML file i use the following:
itemsReader ireader = null;
String path = #"PathtoString";
XmlSerializer serializer = new XmlSerializer(typeof(itemsReader));
var reader = File.OpenText(path);
ireader = (itemsReader)serializer.Deserialize(reader);
Thanks for help!
You have decorated entryString with XmlElement attribute which will search for an element Bits inside Bits itself.
But you want inner text of Bits element. For that we have another attribute called XmlText.
So change this
[XmlElement(ElementName = "Bits")]
public String entryString { get; set; }
to
[XmlText]
public String entryString { get; set; }
i ran your code on your input and got the output, but the i saw, in the Bits class, that the property entryString has an attribute
[XmlElement(ElementName = "Bits")]
but in your xml file there is no <Bits> tags around 1st String. so i added them and got:
<?xml version="1.0"?>
<item name="First Item" size="2">
<Bits value="1">
<Bits>firstOne</Bits>
</Bits>
<Bits value="2">
<Bits>secOne</Bits>
</Bits>
</item>
and then your code worked
so you can change the xml file or get rid of the attribute. your call

Categories