c# Deserializing xml to class "xmlns was not expected" - c#

I want to deserialize a XML node to a class, with all the subnodes values into class properties
I got this error
ex {"There is an error in XML document (1, 2)."} System.Exception {System.InvalidOperationException}
and the message of the exception
InnerException {"<LITERALS xmlns=''> was not expected."} // If i use InnerXml it would be REVISION xmlns...
I tried Outer and Inner XML with a lot of solutions that appear in stackoverflow.
I dont know why it adds xmlns
My xml is like that:
<root>
<LITERALS>
<REVISION>Rev.</REVISION>
<SERIE>Serie</SERIE>
</LITERALS>
<MORENODES></MORENODES>
<MORENODES></MORENODES>
</root>
And my class Literals to deserialize the xml node
{
// I tried these options that i saw in a post
// [XmlRoot(ElementName="LITERALS")]
// [Serializable, XmlRoot("LITERALS")]
[XmlRoot(Namespace = "www.idk.com", ElementName = "LITERALS", DataType = "string", IsNullable = true)]
public class Literals
{
[XmlElement(ElementName = "REVISION")]
public string REVISION { get; set; }
[XmlElement(ElementName = "SERIE")]
public string SERIE { get; set; }
}
}
My code
XmlNode literalsNodo = courseNodo.SelectSingleNode("LITERALS");
XmlRootAttribute xRoot = new XmlRootAttribute("LITERALS");
xRoot.ElementName = "LITERALS";
xRoot.Namespace = "http://www.idk.com";
xRoot.IsNullable = true;
if (literalsNodo != null)
{
XmlSerializer xs = new XmlSerializer(typeof(Literals),xRoot);
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(literalsNodo.InnerXml));
literals = (Literals)xs.Deserialize(ms);
}

Related

Unable to deserialize the kml

I have the following Kml:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Trains</name>
<description/>
<name>Red Train</name>
</Document>
</kml>
and the following code to deserialize it
private void KmlToObject()
{
var path = #"C:\Users\Downloads\test.kml";
var serializer = new XmlSerializer(typeof(Kml));
using var reader = new StringReader(path);
var obj = serializer.Deserialize(reader) as Kml;
}
[XmlRoot(ElementName = "kml")]
public class Kml
{
[XmlElement(ElementName = "Document")]
public object Document { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
}
And I get the following error:
There is an error in XML document (1, 1).
What am I doing wrong?
StringReader is not the way to read the file.
Initializes a new instance of the StringReader class that reads from the specified string.
Instead, you should look for StreamReader with the ReadToEnd method. Reference: How to: Read text from a file
var path = #"C:\Users\Downloads\test.kml";
var serializer = new XmlSerializer(typeof(Kml));
using (StreamReader sr = new StreamReader(path))
{
var obj = serializer.Deserialize(sr.ReadToEnd()) as Kml;
}
And provide the Namespace to XmlRoot attribute.
[XmlRoot(ElementName = "kml", Namespace = "http://www.opengis.net/kml/2.2")]
public class Kml
{
...
}
Your input file is not valid KML. A Document tag can only contain one name tag, and it looks like yours contains a name, an empty description, and then another name tag. Maybe you intended for the Document to contain a Placemark tag and have that contain the name "Red Train"?

Read xml element while deserializing c#

I have an xml document, where i serialize data dinamically, appending new data if i have a new request. The object properties i serialize are like this
[XmlRoot("LogRecords")]
public class LogRecord
{
public string Message { get; set; }
public DateTime SendTime { get; set; }
public string Sender { get; set; }
public string Recipient { get; set; }
}
Serializing is done in this way :
var stringwriter = new StringWriter();
var serializer = new XmlSerializer(object.GetType());
serializer.Serialize(stringwriter, object);
var smsxmlStr = stringwriter.ToString();
var smsRecordDoc = new XmlDocument();
smsRecordDoc.LoadXml(smsxmlStr);
var smsElement = smsRecordDoc.DocumentElement;
var smsLogFile = new XmlDocument();
smsLogFile.Load("LogRecords.xml");
var serialize = smsLogFile.CreateElement("LogRecord");
serialize.InnerXml = smsElement.InnerXml;
smsLogFile.DocumentElement.AppendChild(serialize);
smsLogFile.Save("LogRecords.xml");
While serializing i use LogFile.CreateElement("LogRecord") and my xml file looks like this :
<LogRecords>
<LogRecord>
<Message>Some messagge</Message>
<SendTime>2017-12-13T22:04:40.1109661+01:00</SendTime>
<Sender>Sender</Sender>
<Recipient>Name</Recipient>
</LogRecord>
<LogRecord>
<Message>Some message too</Message>
<SendTime>2017-12-13T22:05:08.5720173+01:00</SendTime>
<Sender>sender</Sender>
<Recipient>name</Recipient>
</LogRecord>
</LogRecords>
When i try to deserialize like this
XmlSerializer deserializer = new XmlSerializer(typeof(LogRecord));
TextReader reader = new StreamReader("LogRecords.xml");
object obj = deserializer.Deserialize(reader);
LogRecord records = (LogRecord)obj;
reader.Close();
I get null value for each property Message, Sender Recipient and a random value for SendTime, and i know it's because it doesn't recognise the XmlElement LogRecord i added while serializing..
Is there any way to read this xml element so i can take the right property values?
Ps. Sorry if i have messed up the variables, i tried to simplify the code when i added it here and i may have mixed some variables..
Thank you in advance.
You could try to generate POCO classes from XML in Visual Studio as it's described here.
You could serialize/deserialize those POCOs using with simple util methods like:
public static T DeserializeXML<T>(string content)
{
if (content == null)
return default(T);
XmlSerializer xs = new XmlSerializer(typeof(T));
byte[] byteArray = Encoding.ASCII.GetBytes(content);
var contentStream = new MemoryStream(byteArray);
var xml = xs.Deserialize(contentStream);
return (T)xml;
}
public static string SerializeAsXML(object item)
{
if (item == null)
return null;
XmlSerializer xs = new XmlSerializer(item.GetType());
using (var sw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true }))
{
xs.Serialize(writer, item);
return sw.ToString();
}
}
}
LogRecords probably should be a collection (e.g. an array in this POCO):
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Log
{
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute("LogRecords")]
[System.Xml.Serialization.XmlArrayItemAttribute("LogRecord", IsNullable = false)]
public LogRecord[] LogRecords { get; set; }
}
for the next XML format:
<Log>
<LogRecords>
<LogRecord>
<Message>Some messagge</Message>
<SendTime>2017-12-13T22:04:40.1109661+01:00</SendTime>
<Sender>Sender</Sender>
<Recipient>Name</Recipient>
</LogRecord>
<LogRecord>
<Message>Some message too</Message>
<SendTime>2017-12-13T22:05:08.5720173+01:00</SendTime>
<Sender>sender</Sender>
<Recipient>name</Recipient>
</LogRecord>
</LogRecords>
</Log>
You manually add the root element in the xml. Therefore, you must also manually skip it when reading.
XmlSerializer deserializer = new XmlSerializer(typeof(LogRecord));
using (var xmlReader = XmlReader.Create("LogRecords.xml"))
{
// Skip root element
xmlReader.ReadToFollowing("LogRecord");
LogRecord record = (LogRecord)deserializer.Deserialize(xmlReader);
}
Remove the [XmlRoot("LogRecords")] attribute to make it work.
Of course, you will always get the first element in the xml.
As already suggested in the comments, use the list.
List<LogRecord> logRecords = new List<LogRecord>();
var logRecord = new LogRecord { ... };
// Store each new logRecord to list
logRecords.Add(logRecord);
var serializer = new XmlSerializer(typeof(List<LogRecord>));
// Serialization is done with just a couple lines of code.
using (var fileStream = new FileStream("LogRecords.xml", FileMode.Create))
{
serializer.Serialize(fileStream, logRecords);
}
// As well as deserialization
using (var fileStream = new FileStream("LogRecords.xml", FileMode.Open))
{
logRecords = (List<LogRecord>)serializer.Deserialize(fileStream);
}
Thus become unnecessary manipulation using XmlDocument and fuss with manually adding-skipping the root node.

.net 4.6 Methods in Serializable class

I am new to serialization and am facing a problem. I have a serializable class, which MUST contain a method. But because of that method I am getting an error during initialization of serializer (when i comment the method, no errors are thrown).
The question - is there a way to mark method in the class so serializer would ignore it and work properly?
This is my serializable class:
[Serializable]
public class Key
{
[XmlAttribute("Id")]
public Guid Id { get; set; }
[XmlAttribute("Kid")]
public Guid Kid { get; set; }
[XmlElement("CEK")]
public string CEK { private get; set; }
public string Foo()
{...}
}
I have a little modified it in terms of privacy of data, but it doesn't influence the topic.
Here is how I do the serialization:
StringReader strReader = null;
XmlSerializer serializer = null;
XmlTextReader xmlReader = null;
Object obj = null;
try
{
strReader = new StringReader(xml);
serializer = new XmlSerializer(objectType,
new XmlRootAttribute
{
ElementName = "someNS",
Namespace = "url.to.some.namespace"
});
xmlReader = new XmlTextReader(strReader);
obj = serializer.Deserialize(xmlReader);
}
Error is thrown at this part:
serializer = new XmlSerializer(objectType,
new XmlRootAttribute
{
ElementName = "someNS",
Namespace = "url.to.some.namespace"
});
UPDATE:
Right, forgot about the error. It is the following:
System.InvalidOperationException:'There was an error reflecting type
'MyProject.Objects.Key'.'
and inner exeptions:
InvalidOperationException: There was an error reflecting property
'Key'.
InvalidOperationException: There was an error reflecting type 'MyProject.Objects.Key'.
Fixed it :
[XmlElement("CEK")]
public string CEK { private get; set; }
This property caused exception; you can't make get a private method in serializable class.

Serializing XML into object - "error in xml document (2,2)

Yes, I have read other threads on this subject but I am missing something:
I am trying to deserialize an XML document that, in part, contains logged SMS messages. The XML file takes the format of:
<reports>
<report>
<sms_messages>
<sms_message>
<number>4155554432</number>
<text>Hi! How are you?</text>
</sms_message>
<sms_message>
<number>4320988876</number>
<text>Hello!</text>
</sms_message>
</sms_messages>
</report>
</reports>
My code looks like:
[XmlType("sms_message")]
public class SMSMessage
{
[XmlElement("number")]
public string Number {get;set;}
[XmlElement("text")]
public string TheText {get;set;}
}
[XmlType("report")]
public class AReport
{
[XmlArray("sms_messages")]
public List<SMSMessage> SMSMessages = new List<SMSMessage>();
}
[XmlRoot(Namespace="www.mysite.com", ElementName="reports", DataType="string", IsNullable=true)]
public class AllReports
{
[XmlArray("reports")]
public List<AReport> AllReports = new List<AReport>();
}
I am trying to serialize it like this:
XmlSerializer deserializer = new XmlSerializer(typeof(AllReports));
TextReader tr = new StreamReader(this.tbXMLPath.text);
List<AllReports> reports;
reports = (List<AllReports>)deserializer.Deserialize(tr);
tr.close();
I get the error: "There is an error in XML document (2,2)" The inner exception states,<reports xmlns=''> was not expected.
I am sure it has something to do with the serializer looking for the namespace of the root node? Is my syntax correct above with the [XmlArray("reports")] ? I feel like something is amiss because "reports" is the root node and it contains a list of "report" items, but the decoration for the root node isn't right? This is my first foray into this area. Any help is greatly appreciated.
With a minimal change to your non-compilable code
XmlSerializer deserializer = new XmlSerializer(typeof(AllReports));
TextReader tr = new StreamReader(filename);
AllReports reports = (AllReports)deserializer.Deserialize(tr);
[XmlType("sms_message")]
public class SMSMessage
{
[XmlElement("number")]
public string Number { get; set; }
[XmlElement("text")]
public string TheText { get; set; }
}
[XmlType("report")]
public class AReport
{
[XmlArray("sms_messages")]
public List<SMSMessage> SMSMessages = new List<SMSMessage>();
}
[XmlRoot("reports")]
public class AllReports
{
[XmlElement("report")]
public List<AReport> Reports = new List<AReport>();
}

XML Deserialization without specifying XmlRootAttribute

here is my xml :
<connections total="2" >
<person>
<id>ohKiUAZWz2</id>
<first-name>ミ★нιяαℓ</first-name>
<last-name>§|-|ä|-|»♥«</last-name>
<headline>--</headline>
</person>
<person>
<id>LmgYe-Nl2a</id>
<first-name>kunal</first-name>
<last-name>b</last-name>
<headline>Student at MscIT,Surat</headline>
</person>
</connection>
from code behind :
List<LinkWall> LinkWallList = new List<LinkWall>();
XmlNodeList xmlnode = doc.GetElementsByTagName("person");
foreach (XmlElement ele in xmlnode)
{
XmlRootAttribute xr = new XmlRootAttribute("person");
XmlSerializer mySerializer = new XmlSerializer(typeof(LinkWall),xr);
StringReader re = new StringReader(ele.InnerXml);
LinkWallList.Add((LinkWall)mySerializer.Deserialize(re));
}
here is my class definition :
[XmlRoot("person")]
public class LinkWall
{
public LinkWall()
{ }
[XmlElement(ElementName = "id")]
public string id { get; set; }
[XmlElement(ElementName = "first-name")]
public string firstName { get; set; }
[XmlElement(ElementName = "last-name")]
public string lastName { get; set; }
[XmlElement(ElementName = "headline", IsNullable=true)]
public string headline { get; set; }
}
but when i try to deserialize. it show me error like : {"There are multiple root elements."}
is there any solution or alternative for specifying XmlRootAttribute ?
thanks in advance, Milan Mendpara
I think your issue is with this line:
StringReader re = new StringReader(ele.InnerXml);
Change it to:
StringReader re = new StringReader(ele.OuterXml);
The reason is the InnerXml property will return all of the child nodes but not the parent node. OuterXml will include your parent person node too.
i.e. InnerXml has no root element (well, it has many!):
<id>ohKiUAZWz2</id>
<first-name>?????al</first-name>
<last-name>§|-|ä|-|»?«</last-name>
<headline>--</headline>
OuterXml is as expected:
<person>
<id>ohKiUAZWz2</id>
<first-name>?????al</first-name>
<last-name>§|-|ä|-|»?«</last-name>
<headline>--</headline>
</person>
There is also no real need to use the XmlSerializer constructor you are using. Try:
XmlSerializer mySerializer = new XmlSerializer(typeof(LinkWall));
Instead.
Try OuterXml instead of InnerXML
StringReader re = new StringReader(ele.OuterXml);
I believe you should make a class structured like your xml file and deserialize your xml file into an instance of this class.
MyClass myObject = new MyClass;
XmlSerializer ser = new XmlSerializer(myObject.GetType());
using (FileStream fs = new FileStream(FilePath, FileMode.Open))
{
XmlTextReader reader = new XmlTextReader(fs);
myObject = (MyClass)ser.Deserialize(reader);
}
This code runs faster and then you will be able to do wathever you want with the data inside your object.

Categories

Resources