I am using the code below in order to serialize Topology class to xml:
public static bool WriteTopologyFile(string path)
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(Topology));
using (StreamWriter reader = new StreamWriter(path))
{
serializer.Serialize(reader, Runtime.Topology);
}
return true;
}
catch (Exception ex)
{
Log.WriteEventLog(ex, EventLogEntryType.Error);
}
return false;
}
In Topology class, there are some DateTime fields and i want to serialize these DateTime fields in
System.Xml.XmlDateTimeSerializationMode.RoundtripKind
mode. How can i do that?
[XmlIgnore]
public DateTime Time { get; set; }
[XmlElement("Time")]
public string strTime
{
get { return Time.ToString("o"); }
set { Time = DateTime.Parse(value); }
}
Related
I am trying to serializing a XML file using the following code,
using System;
using System.Xml;
using System.Xml.Serialization;
namespace TestXML
{
[Serializable]
[XmlRootAttribute("Test")]
public class Test100
{
[XmlElementAttribute("StartDate")]
public DateTime StartDate { get; set; }
[XmlElementAttribute("EndDate")]
public DateTime EndDate { get; set; }
}
class Program
{
static void Main(string[] args)
{
Test100 obj = new Test100();
try
{
XmlSerializer serializer = new XmlSerializer(typeof(Test100));
XmlReader reader = XmlReader.Create(#"C:\MyProjects\TestXML\TestXML\Test.xml");
obj = (Test100)serializer.Deserialize(reader);
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
The XML file:
<?xml version="1.0"?>
<Test>
<StartDate>2020-01-19T00:00:00Z</StartDate>
<EndDate></EndDate>
</Test>
Exception : The string '' is not a valid AllXsd value.
Thanks in advance for your help.
I updated the code as below
public string EndDate { get; set; }
[XmlIgnore]
public bool? _EndDate
{
get
{
if (!string.IsNullOrWhiteSpace(EndDate))
{
return bool.Parse(EndDate);
}
return null;
}
}
The above code is handling the null issue.
I have an XML file which has nodes,
I need to deserialize it to the class
[Serializable]
public class MasterSettingsFile
{
public string version { get; set; }
public bool IsEncrypted { get; set; }
public string settingsString { get; set; }
public string GetSettingsString()
{
if(IsEncrypted)
{
// return decrypted string
}
return settingsString;
}
}
I need to get the whole text under <settingString> as string
I tried normal deserialization. But gives error. Tried adding the whole node to "value" but still '<' causes problem.
protected bool WriteConfigFile(string fileName, Type type, object obj)
{
bool retValue = true;
FileStream fileStream = null;
XmlSerializer xmlSerializer = null;
try
{
this.BackupFile(fileName);
fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
xmlSerializer = new XmlSerializer(type);
xmlSerializer.Serialize(fileStream, obj);
}
catch (Exception ex)
{
retValue = false;
//LogManager.SingleInstance.WriteLog(this, ex.ToString());
}
finally
{
if (fileStream != null)
{
fileStream.Close();
}
if (retValue== false)
{
this.RestoreBackupFile(fileName);
}
this.DeleteBackupFile(fileName);
}
return retValue;
}
The main issue was that the xml was not formed using Serialization. Once I did that, this deserialization worked fine. When serialized, it will automatically save using escape symbols.
Currently I am trying to write a set of two classes: one (BackgroundManagerSettings) which will hold all the variables that I wish to save when the program is closed, and another (BackgroundManager) which contains methods and variables that will only be needed during the runtime.
Code:
public class BackgroundManager : BackgroundManagerSettings
{
//Example
private string _LastName;
public string LastName
{
get
{
return this._LastName;
}
set
{
this._LastName = value;
}
}
public BackgroundManager()
{
this.LastName = "Smith";
}
public static BackgroundManager Load(string filename)
{
XmlSerializer Serializer = new XmlSerializer(typeof(BackgroundManager));
LoopAgain:
try
{
using (StreamReader Reader = new StreamReader(filename))
{
return Serializer.Deserialize(Reader) as BackgroundManager;
}
}
catch (FileNotFoundException)
{
using (StreamWriter Writer = new StreamWriter(filename))
{
Serializer.Serialize(Writer, new BackgroundManager() as BackgroundManagerSettings);
Writer.Close();
}
goto LoopAgain;
}
catch (InvalidOperationException)
{
File.Delete(filename);
goto LoopAgain;
}
}
public void Save(string filename)
{
XmlSerializer Serializer = new XmlSerializer(typeof(BackgroundManager));
using (StreamWriter Writer = new StreamWriter(filename))
{
Serializer.Serialize(Writer, this as BackgroundManagerSettings);
Writer.Close();
}
}
}
public abstract class BackgroundManagerSettings
{
//Example
private string _FirstName;
[XmlElement("FirstName")]
public string FirstName
{
get
{
return this._FirstName;
}
set
{
this._FirstName = value;
}
}
public BackgroundManagerSettings()
{
this.FirstName = "Joe";
}
}
Usage:
BackgroundManager Manager = BackgroundManager.Load("temp.Xml");
Manager.Save("temp.Xml");
Output:
<?xml version="1.0" encoding="UTF-8"?>
<BackgroundManager xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FirstName>Joe</FirstName>
<LastName>Smith</LastName>
</BackgroundManager>
My current problem is that when I use the Save() Method it serializes the fields of BackgroundManager as well as the fields of BackgroundManagerSettings. How do I make it so it only serializes the fields of BackgroundManagerSettings? Any help or links to point me in the right direction would be much appreciated.
Mark all the public members of the base class that you don't want to be serialized with XmlIgnore attribute.
I would do it like this:
[DataContract]
public class BackgroundManager : BackgroundManagerSettings
{
[DataMember]
public int PropertyToSerialize { get; set; }
}
Add the DataMember decoration to all of the properties that you want included.
After some more research I found a method that works how I want it to thanks for the advice.
public static BackgroundManager Load(string filename)
{
XmlSerializer Serializer = new XmlSerializer(typeof(BackgroundManager));
LoopAgain:
try
{
using (StreamReader Reader = new StreamReader(filename))
{
return Serializer.Deserialize(Reader) as BackgroundManager;
}
}
catch (FileNotFoundException)
{
XmlSerializer BaseSerializer = new XmlSerializer(typeof(BackgroundManagerSettings));
using (StreamWriter Writer = new StreamWriter(filename))
{
BaseSerializer.Serialize(Writer, new BackgroundManager().ToBase());
Writer.Close();
}
goto LoopAgain;
}
catch (InvalidOperationException)
{
File.Delete(filename);
goto LoopAgain;
}
}
public void Save(string filename)
{
XmlSerializer Serializer = new XmlSerializer(typeof(BackgroundManagerSettings));
using (StreamWriter Writer = new StreamWriter(filename))
{
Serializer.Serialize(Writer, this.ToBase());
Writer.Close();
}
}
private dynamic ToBase()
{
var Temp = Activator.CreateInstance(typeof(BackgroundManagerSettings));
FieldInfo[] Fields = Temp.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo x in Fields)
{
x.SetValue(Temp, x.GetValue(this));
}
return Temp;
}
I have to two simple serialize/desirialize methods,
Mapping:
[System.Runtime.Serialization.DataContract(Namespace = "", Name = "PARAMS")]
public sealed class CourseListRequest {
[DataMember(Name = "STUDENTID")]
public int StudentId { get; set; }
[DataMember(Name = "YEAR")]
public string Year { get; set; }
[DataMember(Name = "REQUESTTYPE")]
public int RequestType { get; set; }
}
public static string Serialize<T>(this T value) {
if (value == null) throw new ArgumentNullException("value");
try {
var dcs = new DataContractSerializer(typeof (T));
string xml;
using (var ms = new MemoryStream()) {
dcs.WriteObject(ms, value);
xml = Encoding.UTF8.GetString(ms.ToArray());
}
return xml;
}
catch (Exception e) {
throw;
}
}
public static T Deserialize<T>(this string xml) where T : class {
if (string.IsNullOrEmpty(xml)) {
return default(T);
}
try {
var dcs = new DataContractSerializer(typeof (T));
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml))) {
ms.Position = 0;
return dcs.ReadObject(ms) as T;
}
}
catch (Exception e) {
throw;
}
}
result:
<PARAMS xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><REQUESTTYPE>36</REQUESTTYPE><STUDENTID>0</STUDENTID><YEAR>תשע</YEAR></PARAMS>
How to remove xmlns:i="http://www.w3.org/2001/XMLSchema-instance" ?? On serializing
Switch to using XmlSerializer
System.Xml.Serialization.XmlSerializer
This will generate plain XML with no namespaces
please help. I have this code, it's my class to serialize\deserialize application settings.
[XmlRoot("EvaStartupData")]
[Serializable]
public class MyConfigClass
{
public string ServerName { get; set; }
public string Database { get; set; }
public string UserName { get; set; }
public string UserLogin { get; set; }
public static void MyConfigLoad()
{
FileInfo fi = new FileInfo(myConfigFileName);
if (fi.Exists)
{
XmlSerializer mySerializer = new XmlSerializer(myConfigClass.GetType());
StreamReader myXmlReader = new StreamReader(myConfigFileName);
try
{
myConfigClass = (MyConfigClass)mySerializer.Deserialize(myXmlReader);
myXmlReader.Close();
}
catch (Exception e)
{
MessageBox.Show("Ошибка сериализации MyConfigLoad\n" + e.Message);
}
finally
{
myXmlReader.Dispose();
}
}
}
public static void MyConfigSave()
{
XmlSerializer mySerializer = new XmlSerializer(myConfigClass.GetType());
StreamWriter myXmlWriter = new StreamWriter(myConfigFileName);
try
{
mySerializer.Serialize(myXmlWriter, myConfigClass);
}
catch (Exception e)
{
MessageBox.Show("Ошибка сериализации MyConfigSave\n" + e.Message);
}
finally
{
myXmlWriter.Dispose();
}
}
}
Serialization give's me simple xml-structure:
<ServerName>navuhodonoser</ServerName>
<Database>matrix</Database>
<UserName>Mr.Smith</UserName>
<UserLogin>neo</UserLogin>
How must i modify my class to get this xml structure ?:
<Connection ServerName="navuhodonoser" Database="matrix" ....>
By default the XmlSerializer will serialize all public properties as elements; to override that you'll need to tag each property with [XmlAttribute] (from System.Xml.Serialization namespace) which will give you your desired output.
For example:
[XmlAttribute]
public string ServerName { get; set; }
[XmlAttribute]
public string Database { get; set; }
[XmlElement]
public string UserName { get; set; }
// Note: no attribute
public string UserLogin { get; set; }
will produce something like:
<xml ServerName="Value" Database="Value">
<UserName>Value</UserName> <!-- Note that UserName was tagged with XmlElement, which matches the default behavior -->
<UserLogin>Value</UserLogin>
</xml>
I have a couple of suggestions. Try code more like this:
public static void MyConfigLoad()
{
if (!File.Exists(myConfigFileName))
{
return;
}
XmlSerializer mySerializer = new XmlSerializer(myConfigClass.GetType());
using (StreamReader myXmlReader = new StreamReader(myConfigFileName))
{
try
{
myConfigClass = (MyConfigClass)mySerializer.Deserialize(myXmlReader);
}
catch (Exception e)
{
MessageBox.Show("Ошибка сериализации MyConfigLoad\n" + e.ToString());
}
}
}
public static void MyConfigSave()
{
XmlSerializer mySerializer = new XmlSerializer(myConfigClass.GetType());
using (StreamWriter myXmlWriter = new StreamWriter(myConfigFileName))
{
try
{
mySerializer.Serialize(myXmlWriter, myConfigClass);
}
catch (Exception e)
{
MessageBox.Show("Ошибка сериализации MyConfigSave\n" + e.ToString());
}
}
}
You should put the StreamReader and StreamWriter in using blocks so that they will be disposed even if an exception occurs. Also, I suggest you always display e.ToString() instead of just e.Message, as it will display the entire exception, including any inner exceptions.
Also, File.Exists works just like FileInfo.Exists, but doesn't require you to create an instance before using it.
One final note is that you should look into using the Settings feature instead of creating your own configuration classes. That allows you to easily create type-safe settings that can be used throughout your application, and which can be per-user or per-application.