Deserialization Xml Document Error - c#

I have a problem when I deserialize the xml into List of Objects. I searched it on the net this morning, but my problem isn't resolved.
Deserialization method
public static List<FileAction> DeSerialization()
{
XmlRootAttribute xRoot=new XmlRootAttribute();
xRoot.ElementName="ArrayOfSerializeClass";
xRoot.IsNullable=true;
XmlSerializer serializer = new XmlSerializer(typeof(List<FileAction>),xRoot);//, new XmlRootAttribute("ArrayOfSerializeClass")
using (Stream streamReader = File.OpenRead(#"C:\serialization\SerializationWithFileWatcher\Output\XmlSerialize.xml"))//FileStream fs =new FileStream(xmlPath,FileMode.Open)
{
using (XmlReader reader = XmlReader.Create(streamReader))
{
int count =0;
List<FileAction> serialList2 = (List<FileAction>)serializer.Deserialize(reader);
return (List<FileAction>)serializer.Deserialize(reader);
}
}
Calling Method
String resultPath = #"C:\serialization\SerializationWithFileWatcher\Output\XmlSerialize.xml";
if (!File.Exists(resultPath))
{
XmlSerializer xs = new XmlSerializer(typeof(List<SerializeClass>));
using (FileStream fileStream = new FileStream(#"C:\serialization\SerializationWithFileWatcher\Output\XmlSerialize.xml", FileMode.Create))
{
xs.Serialize(fileStream, serializeList);//seri
fileStream.Close();
}
Console.WriteLine("Succesfully serialized to XML");
}
else
{
//string path= #"C:\serialization\SerializationWithFileWatcher\Output\XmlSerialize.xml";
DeSerialization();
XmlSerializer xs = new XmlSerializer(typeof(List<SerializeClass>));
FileStream fs = new FileStream(#"C:\serialization\SerializationWithFileWatcher\Output\XmlSerialize.xml", FileMode.Append, FileAccess.Write);
using (XmlWriter xwr = XmlWriter.Create(fs))//TextWriter xwr = new StreamWriter
{
xs.Serialize(xwr, serializeList);//seri
//fs.Close();
}
Console.WriteLine("Succesfully serialized to XML");
}
return serializeList;
The reason why I am calling it here is that I want to add this object again to the xml file.
THe error is that here is an error in XML document (15,27).
My Xml structure
<?xml version="1.0"?>
<ArrayOfSerializeClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SerializeClass>
<creationTime>2013-11-25T09:53:25.3325289+05:30</creationTime>
<fileAction>Renamed</fileAction>
<Properties>
<FileAttributes fileName="validate json.txt">
<fileSize>307</fileSize>
<extension>.txt</extension>
<lastAccessTime>2013-11-25T09:53:25.3325289+05:30</lastAccessTime
<fullPath>C:\serialization\SerializationWithFileWatcher\SerializationWithFileWatcherProj\validate json.txt</fullPath>
</FileAttributes>
</Properties>
</SerializeClass>
</ArrayOfSerializeClass>

What I understand from the code above is that you are trying to extend the current XML, by first reading it as a FileStream and then using an XmlWriter to add some more content to it.
If my understanding is correct, then you are trying to write to the end of an existing XML file, which is not allowed since any XML document can have only one root node. In your case, that root node is ArrayOfSerializeClass.
So, in order to successfully achieve your task, you must append your XML within the root node.
Update:
Possible solution here: how to append a xml file in c#?

Related

Converting xml to stream and disabling dtd breaking Deserialization

I have created the following wrapper method to disable DTD
public class Program
{
public static void Main(string[] args)
{
string s = #"<?xml version =""1.0"" encoding=""utf-16""?>
<ArrayOfSerializingTemplateItem xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<SerializingTemplateItem>
</SerializingTemplateItem>
</ArrayOfSerializingTemplateItem >";
try
{
XmlReader reader = XmlWrapper.CreateXmlReaderObject(s);
XmlSerializer sr = new XmlSerializer(typeof(List<SerializingTemplateItem>));
Object ob = sr.Deserialize(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
Console.ReadLine();
}
}
public class XmlWrapper
{
public static XmlReader CreateXmlReaderObject(string sr)
{
byte[] byteArray = Encoding.UTF8.GetBytes(sr);
MemoryStream stream = new MemoryStream(byteArray);
stream.Position = 0;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.None;
settings.DtdProcessing = DtdProcessing.Ignore;
return XmlReader.Create(stream, settings);
}
}
public class SerializingTemplateItem
{
}
The above throws exception "There is no Unicode byte order mark. Cannot switch to Unicode." (Demo fiddle here: https://dotnetfiddle.net/pGxOE9).
But if I use the following code to create the XmlReader instead of calling the XmlWrapper method. It works fine.
StringReader stringReader = new StringReader( xml );
XmlReader reader = new XmlTextReader( stringReader );
But I need to use the wrapper method as a security requirement to disable DTD. I don't know why I am unable to deserialize after calling my wrapper method. Any help will be highly appreciated.
Your problem is that you have encoded the XML into a MemoryStream using Encoding.UTF8, but the XML string itself claims to be encoded in UTF-16 in the encoding declaration in its XML text declaration:
<?xml version ="1.0" encoding="utf-16"?>
<ArrayOfSerializingTemplateItem>
<!-- Content omitted -->
</ArrayOfSerializingTemplateItem >
Apparently when the XmlReader encounters this declaration, it tries honor the declaration and switch from UTF-8 to UTF-16 but fails for some reason - possibly because the stream really is encoded in UTF-8. Conversely when the deprecated XmlTextReader encounters the declaration, it apparently just ignores it as not implemented, which happens to cause things to work successfully in this situation.
The simplest way to resolve this is to read directly from the string using a StringReader using XmlReader.Create(TextReader, XmlReaderSettings):
public class XmlWrapper
{
public static XmlReader CreateXmlReaderObject(string sr)
{
var settings = new XmlReaderSettings
{
ValidationType = ValidationType.None,
DtdProcessing = DtdProcessing.Ignore,
};
return XmlReader.Create(new StringReader(sr), settings);
}
}
Since a c# string is always encoded internally in UTF-16 the encoding statement in the XML will be ignored as irrelevant. This will also be more performant as the conversion to an intermediate byte array is completely skipped.
Incidentally, you should dispose of your XmlReader via a using statement:
Object ob;
using (var reader = XmlWrapper.CreateXmlReaderObject(s))
{
XmlSerializer sr = new XmlSerializer(typeof(List<SerializingTemplateItem>));
ob = sr.Deserialize(reader);
}
Working sample fiddle here.
Related questions:
Meaning of - <?xml version="1.0" encoding="utf-8"?>
Ignoring specified encoding when deserializing XML

Trouble deserialising xml file using DataContractSerializer

It's been awhile since i've used DataContractSerializer and i'm having a little trouble deserializing a xml file.
<?xml version="1.0" encoding="utf-8"?>
<SoftwareLicense xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
The error i'm getting is:
{"Error in line 1 position 117. Expecting element 'SoftwareLicense' from namespace 'http://schemas.datacontract.org/2004/07/Solentim.Modules.Licensing.Activation'..
Encountered 'Element' with name 'SoftwareLicense', namespace ''. "}
[DataContract(Name = "SoftwareLicense")]
public class SoftwareLicense : ISoftwareLicense
{
...
}
I've tried specifying the namespace which also doesn't work.
var serializer = new DataContractSerializer(typeof(SoftwareLicense));
using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (var reader =
XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas()))
{
return (SoftwareLicense) serializer.ReadObject(reader);
}
}
The namespace of the file has recently changed and an interface added to the class. I've resolved all other issues i just can't seem to get around this one.
I prefer to use the DatacontractSerializer as the class now has interface properties and XMLSerializer won't deserialise it
This answer may help you to solve your problem.
If you prefer to use XmlSerializer. Here is the simple implementation below:
private T Deserialize<T>(string path) where T : class
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
T result = null;
using (XmlReader reader = XmlReader.Create(path))
{
result = (T)serializer.Deserialize(reader);
}
return result;
}

Most efficient way to determine how class use to Deserialize XML

I have many .xsd files for many xml schemas
example
XML 1.0 - xml_1_0.xml
<?xml version="1.0" encoding="UTF-8"?>
<cars version="1.00">
<car>Honda</car>
<car>Ferrari</car>
</cars>
XML 2.0 - xml_2_0.xml
<?xml version="1.0" encoding="UTF-8"?>
<cars version="2.00">
<car>
<name>Honda</name>
<color>White</color>
</car>
<car>
<name>Honda</name>
<color>Red</color>
</car>
</cars>
I create my classes from .xsd like this
xsd.exe cars_1_0.xsd /c
xsd.exe cars_2_0.xsd /c
And Deserialize like this:
foreach(string file in files) {
XmlDocument doc = new XmlDocument();
doc.Load(file);
string version = doc.SelectSingleNode("/Cars/#version").Value;
if(version == "1.00")
{
Stream reader = new FileStream(file, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(v1.Cars));
v1.Cars XML = new v1.Cars();
XML = (v1.Cars)serializer.Deserialize(reader);
}
else if(version == "2.00")
{
Stream reader = new FileStream(file, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof(v2.Cars));
v2.Cars XML = new v2.Cars();
XML = (v2.Cars)serializer.Deserialize(reader);
}
}
Does anyone know a better way to do this, or have a better performance?
You have several options, depending on how far you want to take this. One fairly non invasive option would be to not use XmlDocument and avoid loading the stream more than once. For example, your existing code could be simplified/streamlined to :
foreach (string file in files)
{
using (var stream = new FileStream(file, FileMode.Open))
{
var settings = new XmlReaderSettings();
settings.CloseInput = false;
string version = "";
using (var xmlReader = XmlReader.Create(stream))
{
if (xmlReader.ReadToFollowing("Cars"))
{
version = xmlReader.GetAttribute("version");
}
else
{
throw new XmlException("Could not get 'version' attribute of 'Cars' root element!");
}
}
stream.Position = 0;
if (version == "1.00")
{
XmlSerializer serializer = new XmlSerializer(typeof(v1.Cars));
v1.Cars XML = new v1.Cars();
XML = (v1.Cars)serializer.Deserialize(stream);
}
else if (version == "2.00")
{
XmlSerializer serializer = new XmlSerializer(typeof(v2.Cars));
v2.Cars XML = new v2.Cars();
XML = (v2.Cars)serializer.Deserialize(stream);
}
}
}
Since you're just reading off the root element, you might even be able to get away with deserializing from the XmlReader and not have to reset the position on the FileStream.
This avoids the overhead of loading the entire file twice (once for XmlDocument, then again for XmlSerializer) - and particularly avoids the memory overhead of creating a DOM for each document.
A more nuclear option would be implementing IXmlSerializable on a set of custom classes, which would have custom logic in the ReadXml methods to parse the version attribute and instantiate the correct child type(s) - e.g. a CarCollection class that has a List<Car> property, where Car is an abstract class that has CarV1 and CarV2 as descendants. This would be about as efficient as you could get (and offer very fine grained control over your class hierarchy design), but would eliminate the possibility of using xsd.exe to generate your classes.

Encoding attribute from XML file Declaration turns to lower case when the file is created by a MemoryStream

I have to generate a XML file using "ISO-8859-1" encoding from my Asp.Net Web API application but MemoryStream lowercases the encoding attribute from the generated XML definition to "iso-8859-1".
This method generates a XML file based on a object which has been created by a XSD.
public static MemoryStream GenerateXml<T>(T entity) where T : class
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
//Add an empty namespace and empty value
ns.Add("", "");
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream, Encoding.GetEncoding("ISO-8859-1"));
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(streamWriter, entity, ns);
return memoryStream;
}
Then I need to use XDocument to replace the prefix definition of XML elements (Its a prerequisite that all elements should be only named with their own tags). So I had to do this:
public MemoryStream GenerateXmlOpening<T>(T entity) where T : class
{
var xmlMemStream = XmlHelper.GenerateXml(entity);
xmlMemStream.Position = 0;
XDocument doc = XDocument.Load(xmlMemStream, LoadOptions.PreserveWhitespace);
//Removes the namespace declaration as prefix on elements
doc.Descendants().Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
//the memory stream retreived from 'xmlMemStream' is already with "iso-8859-1 in lowercase, so im trying to override it
doc.Declaration.Encoding = "ISO-8859-1";
MemoryStream stream = new MemoryStream();
// when i save the xdoc to the new memorystream, the encoding goes from "ISO-8859-1" to "iso-8859-1" again.
doc.Save(stream);
stream.Position = 0;
return stream;
}
This is the beginning of the returned generated XML file:
<?xml version="1.0" encoding="iso-8859-1"?>
... content
How it's supposed to be:
<?xml version="1.0" encoding="ISO-8859-1"?>
... content
Ps.* Im writing the XML using a MemoryStream because I have to write a .zip file and return a response of all generated XML files within this zip. This .Zip generator receives a list of MemoryStreams.

XML deserialize iso 20022 pain.001.001.03 from xsd using c#

I want to get an object from an xml file. In my example I am using iso 2002 pain.001.001.03
I have downloaded the schema from
pain.001.001.03.xsd
and the xml file from
pain.001.001.03.xml
I have validated my xml against the xsd using this tool
Validate XML
I have generated a class using xsd
and I am using the code below in order to deserialize
XmlSerializer ser = new XmlSerializer(typeof(CustomerCreditTransferInitiationV03), new XmlRootAttribute
{
ElementName = "Document",
Namespace = "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03",
});
FileStream myFileStream = new FileStream("C:\\001.001.03\\pain.001.001.03.xml", FileMode.Open);
CustomerCreditTransferInitiationV03 myObject = (CustomerCreditTransferInitiationV03) ser.Deserialize(myFileStream);
The code return null values but my xml has values
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
<CstmrCdtTrfInitn>
The root element is an Document, and not a CstmrCdtTrfInitn :
var serializer = new XmlSerializer(typeof(Document));
using (var file = File.OpenRead(path))
{
var document = (Document)serializer.Deserialize(file);
var transfer = document.CstmrCdtTrfInitn;
}

Categories