Getting InvalidOperationException when Deserializing in C# - c#

I'm using an XML based .config file for storing some records.
my XML is below:
<?xml version="1.0" encoding="utf-8"?>
<Data_List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Configuration>
<Name>1st Week</Name>
<Binary>
<Field>field1</Field>
<Version>1.0</Version>
</Binary>
<Binary>
<Field>field2</Field>
<Version>2.0</Version>
</Binary>
</Configuration>
<Configuration>
<Name>2nd Week</Name>
<Binary>
<Field>field1</Field>
<Version>2.0</Version>
</Binary>
<Binary>
<Field>field2</Field>
<Version>4.0</Version>
</Binary>
</Configuration>
</Data_List>
I'm using C# code as follows:
public Binary
{
public String Field;
public String Version;
}
public Configuration
{
public String Name;
public List<Binary> Binary_List = new List<Binary>();
public GetfromXML()
{
List<Configuration> lists = new List<Configuration>();
TextReader reader = new StreamReader("Data_List.config");
XmlSerializer serializer = new XmlSerializer(typeof(List<Configuration>));
lists=(List<Configuration>)serializer.Deserialize(reader);
reader.Close();
}
I'm getting an exception saying "There's an error in XML document(2,2)".
Can anyone pls help?

I think the problem is that your model is not well structurized. In other words, serializer does not know how to read your .xml.
Your xml is wrong. When you have List< T > there would be an:
<ArrayOfT></ArrayOfT>
in .XML. Here is how you need to do it!
First, try using xml attributes from System.Xml.Serialization(i.e. [XmlArray()])
It would be better that you use FileStream instead of just pointing out URI
using(var filestream = new FileStream(//your uri, FIleMode.Open)
{
}
Use properties instead of variables. Because later on you may want to bind.
Example of my code how i managed to solve that issue:
public ServiceMap Deserialize()
{
ServiceMap serviceMap = new ServiceMap();
try
{
using (var fileStream = new FileStream(Settings.ServiceMapPath, FileMode.Open))
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;
using (XmlReader reader = XmlReader.Create(fileStream, settings))
{
serviceMap = _serializer.Deserialize(reader) as ServiceMap;
}
}
}
catch (FileNotFoundException)
{
MessageBox.Show("File 'ServiceMap.xml' could not be found!");
}
return serviceMap;
}
My ServiceMap class:
[XmlRoot("ServiceMap")]
public class ServiceMap
{
[XmlArray("Nodes")]
[XmlArrayItem("Node")]
public List<Node> Nodes = new List<Node>();
[XmlArray("Groups")]
[XmlArrayItem("Group")]
public List<Group> Groups = new List<Group>();
[XmlArray("Categories")]
[XmlArrayItem("Category")]
public List<Category> Categories = new List<Category>();
}
EDIT: My XML:
<?xml version="1.0" encoding="utf-8"?>
<ServiceMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http:// www.w3.org/2001/XMLSchema">
<Nodes>
<Node Name="Predrag">
<Children>
<Child>dijete1</Child>
<Child>dijete2</Child>
<Child>dijete3</Child>
<Child>dijete4</Child>
</Children>
<Parents>
<Parent>roditelj1</Parent>
<Parent>roditelj2</Parent>
<Parent>roditelj3</Parent>
</Parents>
<Group Name="Grupa" />
<Category Name="Kategorija" />
</Node>
<Node Name="Tami">
<Children>
<Child>dijete1</Child>
<Child>dijete2</Child>
</Children>
<Parents>
<Parent>roditelj1</Parent>
</Parents>
<Group Name="Grupa2" />
<Category Name="Kategorija2" />
</Node>

Related

XML error during deserialize

I have problem when I'm trying to deserialize an XML to object. My XML look like:
<?xml version="1.0" encoding="utf-16"?>
<Products
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AllProducts>
<Product>
<ID>8</ID>
<GID>51280</GID>
<Kod>RNIKAKC1.6</Kod>
<Name>SB-800</Name>
<Ean>0018208048014</Ean>
<CommodityGroup>
<ID>86</ID>
<Name>AKCESORIA FOTO</Name>
<Path>
<Category>
<ID>60798</ID>
<Name>ARCHIWALNE</Name>
</Category>
</Path>
</CommodityGroup>
</Product>
....
Next products
...
My method code:
var MemoryStream = APIAccess.DownloadFileToStream("example.xml", "exampleContainer");
using (MemoryStream)
{
MemoryStream.Position = 0;
using (StreamReader StreamReader = new StreamReader(MemoryStream))
{
XmlSerializer serializer = new XmlSerializer(typeof(CommodityGroup));
var products = serializer.Deserialize(StreamReader);
}
}
Method DownloadFileToStream is working good, because it is useful in other classes.
I'm geting error:
InvalidOperationException: Products xmlns='' was not expected.
I want to create object of a Node CommodityGroup. I've created class selecting this node, coping it and pasting in the new class like Paste Special -> XML
Attributes of this class looks like:
[Serializable()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "CommodityGroup", IsNullable = false)]
I don't know to fix it. When I'm adding into XML Serializer param new XmlRootAttribute("Products"), I'm getting "0" values.
Do you have any suggestions?
If you want to deserialize only part of an xml document, you should skip unnecessary nodes.
Do it using XmlReader.
using (StreamReader StreamReader = new StreamReader(MemoryStream))
using (var xmlReader = XmlReader.Create(StreamReader))
{
xmlReader.ReadToFollowing("CommodityGroup");
XmlSerializer serializer = new XmlSerializer(typeof(CommodityGroup));
var commodityGroup = (CommodityGroup)serializer.Deserialize(xmlReader);
}

Xml .NET : Remove ArrayOfXmlElement and XmlElement

I created a .NET class for XML serialization
[Serializable()]
[XmlRoot("documents")]
public class BdfXmlData
{
[XmlElement("document")]
public List<XmlElement> Documents { get; set; }
public BdfXmlData()
{
Documents = new List<XmlElement>();
}
}
When I try to serialize an object, I get with this tree:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfXmlElement xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<XmlElement>
<documents>
<document>
...
<document>
<documents>
</XmlElement>
</ArrayOfXmlElement>
How can I have the following three?
<?xml version="1.0" encoding="utf-8"?>
<documents>
<document>
...
<document>
<documents>
Thanks in advance.
The code to serialize my class is the following:
public static string GetSerializedObject<T>(T t)
{
using (MemoryStream stream = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, t);
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream))
return reader.ReadToEnd();
}
}
I think you can at least simplify your xml-code:
<ArrayOfdocuments xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<documents>
<document>
...
<document>
<documents>
</ArrayOfdocuments>
The "XmlElement" element can be left out.
Surely you are serialising an array of BdfXmlData
in pseudo code
BdfXmlData[] dataInArray = new [] {new BdfXmlData()};
GetSerializedObject(dataInArray)
would produce what you have whereas,
in pseudo code..
BdfXmlData data = new BdfXmlData();
GetSerializedObject(data)
should give you what you want!
Exact, I serialise the Documents collection :
SerializationHelper.GetSerializedObject(xmlRootData.Documents);
In fact, I receive some XmlElement with this tree :
<document>
...
<document>
and I add these elements to my List "Documents".
xmlRootData.Documents.Add(xmlData);
When I serialise my final object (BdfXmlData), the xml contains 2 documents tags and 2 document tags
string xmlData = SerializationHelper.GetSerializedObject(xmlRootData);
<documents xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<document>
<documents>
<document>
</document>
<documents>
</document>
</documents>

trying to update xml file but it puts everything in one tag

im trying to update this xml page:
<?xml version="1.0" encoding="utf-8"?>
<news>
<report>
<user></user>
<date></date>
<content></content>
</report>
</news>
with this method:
public static void InsetXML(string user, string date, string content, string Xmlfile)
{
string XMLfile;
XmlElement reportEle, userEle, dateEle, contentEle;
XmlDocument doc = new XmlDocument();
XMLfile = Xmlfile;
doc.Load(XMLfile);
reportEle = doc.CreateElement("report");
userEle = doc.CreateElement("user");
dateEle = doc.CreateElement("date");
contentEle = doc.CreateElement("content");
userEle.InnerText = user;
dateEle.InnerText = date;
contentEle.InnerText = content;
reportEle.AppendChild(userEle);
reportEle.AppendChild(dateEle);
reportEle.AppendChild(contentEle);
doc.DocumentElement.InsertAfter(reportEle, doc.DocumentElement.FirstChild);
FileStream fsxml = new FileStream(XMLfile, FileMode.Truncate, FileAccess.Write, FileShare.ReadWrite);
doc.Save(fsxml);
fsxml.Close();
}
take into consideration, string Xmlfile = Server.MapPath("news.xml");
(copied the method from a book that i'm using) but every time i try it it just writes everything into the user tag like this:
<?xml version="1.0" encoding="utf-8"?>
<news>
<report>
<user>
</user>
<date>
</date>
<content>
</content>
</report>
<report>
<user>dsfdsfg,10.10.1999,sdfas</user>
<date>
</date>
<content>
</content>
</report>
</news>
thanks to all helpers :D
Give this a try.. and I'll leave this link for further reference.
public static void InsetXML(string user, string date, string content, string Xmlfile)
{
XmlDocument xmlDoc = new XmlDocument();
XmlNode rootNode = xmlDoc.CreateElement("news");
xmlDoc.AppendChild(rootNode);
XmlNode parent = xmlDoc.CreateElement("report");
rootNode.AppendChild(parent);
XmlNode child1 = xmlDoc.CreateElement("user");
child1.InnerText = user;
parent.AppendChild(child1);
XmlNode child2 = xmlDoc.CreateElement("date");
child2.InnerText = date;
parent.AppendChild(child2);
XmlNode child3 = xmlDoc.CreateElement("content");
child3.InnerText = content;
parent.AppendChild(child3);
FileStream fsxml = new FileStream(Xmlfile, FileMode.Truncate, FileAccess.Write, FileShare.ReadWrite);
xmlDoc.Save(fsxml);
fsxml.Close();
}
I tested this and wrote the XML to an existing .xml file on my drive.
This was the result:
<news>
<report>
<user>dsfdsfg</user>
<date>10.10.1999</date>
<content>sdfas</content>
</report>
</news>

Deserialization XML in a List

The Application serializes a List to xml:
<?xml version="1.0"?>
<Tools xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Tool>
<Name>test1</Name>
<Path>C:\Program Files\FreePDF_XP\fpmailer.exe</Path>
</Tool>
<Tool>
<Name>test2</Name>
<Path>C:\Program Files\FreePDF_XP\fpassist.exe</Path>
</Tool>
<Tool>
<Name>test3</Name>
<Path>C:\Program Files\FreePDF_XP\ShellMail.exe</Path>
</Tool>
</Tools>
If I'm don't on the wrong way I must create new Objects and add them to a list:
Tool tool = new Tool();
XmlSerializer deserializer = new XmlSerializer(typeof(List<Tool>));
using (var reader = new StreamReader(#Start.userConfigurePath + "\\config.xml"))
{
tool = (Tool)deserializer.Deserialize(reader);
reader.Close();
}
toolList.Add(tool);
}
In the result there isn't a Object in the List. How can I deserialize the serialized objects in the xml in a List? Could it be that there is something wrong at the code for derisalization?
Edit:
Something seems to be wrong with my xml declaration (XML File Error 2,2). That I don't understand because i create the xml document on this way:
XmlDocument toolConfig = new XmlDocument();
XmlNode myRoot;
myRoot = toolConfig.CreateElement("Tool");
toolConfig.AppendChild(myRoot);
It should be
toolList = (List<Tool>)deserializer.Deserialize(reader);

How to write an xml attribute without replace all attributes?

I'm using this:
public void WriteSettings(string key, string value)
{
XmlWriterSettings xmlSettings = new XmlWriterSettings();
xmlSettings.Indent = true;
xmlSettings.NewLineOnAttributes = true;
XmlWriter writer = XmlWriter.Create(TMP_FULLPATH, xmlSettings);
writer.WriteStartElement("settings");
writer.WriteAttributeString(key, value);
writer.WriteEndAttribute();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
But any modification replaces all attributes with only the last remaining attribute that I am trying to add. For example:
current XML:
<?xml version="1.0" encoding="utf-8"?>
<settings TitleFormat="name:%name% date:%date%" />
when I do:
WriteSettings("foo", "baa");
the XML is:
<?xml version="1.0" encoding="utf-8"?>
<settings foo="baa" />
instead of:
<?xml version="1.0" encoding="utf-8"?>
<settings TitleFormat="name:%name% date:%date%" foo="baa" />
How can I fix that?
You are writing a new file, with no consideration at all of the old. To update a document, you must load it into a DOM, edit the DOM, and save the DOM:
var doc = new XmlDocument();
doc.Load(path);
doc.DocumentElement.SetAttribute(key, value);
doc.Save(path);
you are creating new file each time you call XmlWriter.Create(), do something like this.

Categories