Deserialize an XML file and copy the values into csv - c#

i want to deserialize an xml file and copy those values into csv file.i tried like this.
[Serializable, XmlRoot("Configuration"), XmlType("Configuration")]
public class LabelRequest
{
public string weightoz { get; set; }
public string MailClass { get; set; }
public static void DeSerialization()
{
LabelRequest label = new LabelRequest();
TextReader txtReader = new StreamReader(#"C:\xmlfile.xml");
XmlSerializer xmlSerializer = new XmlSerializer(typeof(LabelRequest));
label = (LabelRequest) xmlSerializer.Deserialize(txtReader);
txtReader.Close();
}
}
and the xml file is as follows
<Labelrequest>
<weightoz>2</weightoz>
<mailclass>abc</mailclass>
</labelrequest>

To write the values to a CSV file shouldn't be too difficult. Your example does not contain any code which writes to a file though. It only deserialises an XML file. Might I suggest something like this.
public static class LabelRequestSerializer
{
public static Label DeserializeXmlFile(string fileName)
{
using (TextReader txtReader = new StreamReader(fileName))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(LabelRequest));
LabelRequest label = (LabelRequest) xmlSerializer.Deserialize(txtReader);
}
}
public static void SerializeToCsv(LabelRequest labelRequest, string fileName)
{
if (labelRequest == null)
throw new ArgumentNullException("labelRequest");
StringBuilder sb = new StringBuilder();
sb.Append(labelRequest.weightoz);
sb.Append(",");
sb.Append(labelRequest.mailclass);
sb.AppendLine();
using (StreamWriter stream = new StreamWriter(fileName))
{
stream.Write(sb.ToString());
}
}
}
Then you can pass the instance of LabelRequest you want to serialize to these static methods. That way LabelRequest does not know about how to serialize itself from files, which is a nice seperation of concerns. Like this
void SomeMethod()
{
LabelRequest labelRequest = new LabelRequest();
LabelRequestSerializer.SerializeToCsv(labelRequest, #"C:\Path\Goes\Here\label.csv");
}
Edit...
If you really don't want to write out every property manually you can use reflection. However there will be a performance hit by using this. Shouldn't be a problem compared to the file IO though.
public static void SerializeToCsv(LabelRequest labelRequest, string fileName)
{
if (labelRequest == null)
throw new ArgumentNullException("labelRequest");
StringBuilder sb = new StringBuilder();
foreach (PropertyInfo info in labelRequest.GetType() .GetProperties())
{
object value = info.GetValue(labelRequest, null);
sb.Append(value);
sb.Append(", ");
}
sb.AppendLine();
using (StreamWriter stream = new StreamWriter(fileName))
{
stream.Write(sb.ToString());
}
}

Related

How to display deserialized Json result on Winform tabPage in C#

Please I need your help here, I could not write the logic to display the deserialized JSON result on tabPage in Winforms C#
public Form1()
{
var path = #"C:\Users\elitebook\source\repos\ExamCBT\question.json";
string jsonFile = File.ReadAllText(path);
Question q = JsonConvert.DeserializeObject<Question>(jsonFile);
InitializeComponent();
}
jsonFile = tabPage2.ToString();
You can use these methods for serializing & deserializing JSON. Just download the Newtonsoft.Json NuGet package.
static class FileHelper
{
public static void JsonSerialize(object obj, string fileName)
{
using (var sw = new System.IO.StreamWriter($"{fileName}.json"))
using (var jw = new Newtonsoft.Json.JsonTextWriter(sw))
{
var serializer = new Newtonsoft.Json.JsonSerializer();
jw.Formatting = Newtonsoft.Json.Formatting.Indented;
serializer.Serialize(jw, obj);
}
}
public static void JsonDeserialize(out string/*object, List<>, or something else*/ obj, string fileName)
{
using (var sr = new System.IO.StreamReader($"{fileName}.json"))
{
using (var jr = new Newtonsoft.Json.JsonTextReader(sr))
{
var serializer = new Newtonsoft.Json.JsonSerializer();
try
{
obj = serializer.Deserialize<string /*object, List<>, or something else...*/>(jr);
}
catch
{
obj = null;
}
}
}
}
}
And you can add JSON data to TabPage like this.
Label label = new Label(); // label can be textbox, button or something else...
FileHelper.JsonDeserialize(out string /*object, List<>, or something else...*/ data, "test");
label.Text = data //data type is string
tabPage1.Controls.Add(label);

How to deserialize xml from the second node

I would like to deserialize part of xml, I tried this, but it does not work.
class Program
{
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(Test), new XmlRootAttribute("Test"));
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("<Root1><Root2><Test><Id>5</Id></Test></Root2></Root1>")))
{
var test = serializer.Deserialize(stream);
}
}
}
public class Test
{
public int Id;
}
How can I say to XmlSerializer to start serialization from <Test>?
Move to desired node with XmlReader.
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("<Root1><Root2><Test><Id>5</Id></Test></Root2></Root1>")))
using (var reader = XmlReader.Create(stream))
{
reader.ReadToFollowing("Test");
var test = (Test)serializer.Deserialize(reader);
}

C# XML Serialize object of Array object "There was an error generating the XML document."

I'm having a problem with the c# XML serialization system it's throws an Ambigus exception,
There was an error generating the XML document.
Now i have a Class that contains refferences to other classes and arrays of the other classes
E.G
namespace P2PFileLayout
{
public class p2pfile
{
public FileList FileList;
public StatusServer StatusServer;
public String Hash;
}
}
namespace P2PFileLayout.parts
{
public class StatusServer
{
public Auth Auth;
public Servers Servers;
}
public class Servers
{
public Server[] Server;
}
public class Server
{
public bool AuthRequired = false;
public string Address;
}
public class Files
{
public File[] File;
}
public class File
{
public string FileName = "";
public int BlockSize = 0;
public int BlockCount = 0;
}
public class Directory
{
public string Name;
public Files Files;
public Directory[] Dir;
}
public class Auth
{
public AuthServer[] AuthServer;
}
public class FileList
{
public Files Files;
public Directory[] Directory;
}
}
My Example data
// create the test file
testFile = new p2pfile();
// create a fake fileList
testFile.FileList = new P2PFileLayout.parts.FileList();
testFile.FileList.Directory = new P2PFileLayout.parts.Directory[1];
testFile.FileList.Directory[0] = new P2PFileLayout.parts.Directory();
testFile.FileList.Directory[0].Name = "testFolder";
testFile.FileList.Directory[0].Files = new P2PFileLayout.parts.Files();
testFile.FileList.Directory[0].Files.File = new P2PFileLayout.parts.File[2];
testFile.FileList.Directory[0].Files.File[0] = new P2PFileLayout.parts.File();
testFile.FileList.Directory[0].Files.File[0].FileName = "test.txt";
testFile.FileList.Directory[0].Files.File[0].BlockSize = 64;
testFile.FileList.Directory[0].Files.File[0].BlockCount = 1;
testFile.FileList.Directory[0].Files.File[1] = new P2PFileLayout.parts.File();
testFile.FileList.Directory[0].Files.File[1].FileName = "test2.txt";
testFile.FileList.Directory[0].Files.File[1].BlockSize = 64;
testFile.FileList.Directory[0].Files.File[1].BlockCount = 1;
// create a fake status server
testFile.StatusServer = new P2PFileLayout.parts.StatusServer();
testFile.StatusServer.Servers = new P2PFileLayout.parts.Servers();
testFile.StatusServer.Servers.Server = new P2PFileLayout.parts.Server[1];
testFile.StatusServer.Servers.Server[0] = new P2PFileLayout.parts.Server();
testFile.StatusServer.Servers.Server[0].Address = "http://localhost:8088/list.php";
// create a file hash (real)
HashGenerator.P2PHash hashGen = new HashGenerator.P2PHash();
testFile.Hash = hashGen.getHash();
treeView1.Nodes.Add(new TreeNode("Loading..."));
Classes.CreateTreeView ctv = new Classes.CreateTreeView();
ctv.BuildTreeView(testFile.FileList, treeView1);
treeView1.AfterCheck += new TreeViewEventHandler(treeView1_AfterCheck);
Now that is not as complicated as mine in terms of dept as my i loop objects so dir has support for more dirs but thats just an example
Then i'm serializing to a string var as i want to do a little more than just serialize it but here is my serialization
private string ToXml(object Obj, System.Type ObjType)
{
// instansiate the xml serializer object
XmlSerializer ser = new XmlSerializer(ObjType);
// create a memory stream for XMLTextWriter to use
MemoryStream memStream = new MemoryStream();
// create an XML writer using our memory stream
XmlTextWriter xmlWriter = new XmlTextWriter(memStream, Encoding.UTF8);
// write the object though the XML serializer method using the W3C namespaces
ser.Serialize(xmlWriter, Obj);
// close the XMLWriter
xmlWriter.Close();
// close the memoryStream
memStream.Close();
// get the string from the memory Stream
string xml = Encoding.UTF8.GetString(memStream.GetBuffer());
// remove the stuff before the xml code we care about
xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)));
// clear any thing at the end of the elements we care about
xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1));
// return the XML string
return xml;
}
Can any one see why this is not working or any clues as to why it would not work normally
Why are you doing it manually?
What about this approach?
http://support.microsoft.com/kb/815813
Test test = new Test() { Test1 = "1", Test2 = "3" };
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(test.GetType());
MemoryStream ms = new MemoryStream();
x.Serialize(ms, test);
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
string xml = sr.ReadToEnd();
As for the ambigous message, take a look into the inner exceptions. XML serialization errors use innerexception a lot, and you usually have to look to all levels of InnerExceptions to know what is really happening.

XmlSerializer unreliable or am I doing something wrong?

If you run this code:
public class Program
{
public class MyClass
{
public string Text { get; set; }
}
static MyClass myClass = new MyClass();
static string Desktop = "C:\\Users\\Juan Luis\\Desktop\\";
static void Main(string[] args)
{
myClass.Text = "\r\nhello";
Console.WriteLine((int)myClass.Text[0]);
Save(Desktop + "file.xml", myClass);
myClass = Load(Desktop + "file.xml");
Console.WriteLine((int)myClass.Text[0]);
Console.Read();
}
private static MyClass Load(string fileName)
{
MyClass result = null;
using (Stream stream = File.Open(fileName, FileMode.Open))
{
XmlSerializer xmlFormatter = new XmlSerializer(typeof(MyClass));
result = (MyClass)xmlFormatter.Deserialize(stream);
}
return result;
}
private static void Save(string fileName, MyClass obj)
{
using (Stream tempFileStream = File.Create(fileName))
{
XmlSerializer xmlFormatter = new XmlSerializer(typeof(MyClass));
xmlFormatter.Serialize(tempFileStream, obj);
}
}
}
The output will be 13, 10. The XmlSerializer is removing the carriage return. This is a problem in my case because I need to compare strings for equality in a class that gets serialized and deserialized, and this is causing two strings that are equal before serializing to be unequal after serialized. What would be the best work around?
Edit: After reading answers, this was my solution, in case it will help anyone:
public class SafeXmlSerializer : XmlSerializer
{
public SafeXmlSerializer(Type type) : base(type) { }
public new void Serialize(Stream stream, object o)
{
XmlWriterSettings ws = new XmlWriterSettings();
ws.NewLineHandling = NewLineHandling.Entitize;
using (XmlWriter xmlWriter = XmlWriter.Create(stream, ws))
{
base.Serialize(xmlWriter, o);
}
}
}
I wouldn't call it unreliable exactly: the XmlSerializer strips white space around text inside elements. If it didn't do this then the meaning of XML documents would change according to how you formatted them in the IDE.
You could consider putting the text in a CDATA section, which will preserve the contents exactly. For example, How do you serialize a string as CDATA using XmlSerializer?
Edit: This looks to have a better explanation of where the problem lies, along with a simpler solution - How to keep XmlSerializer from killing NewLines in Strings?

C# - Deserialize a List<String>

I can serialize a list really easy:
List<String> fieldsToNotCopy =new List<String> {"Iteration Path","Iteration ID"};
fieldsToNotCopy.SerializeObject("FieldsToNotMove.xml");
Now I need a method like this:
List<String> loadedList = new List<String();
loadedList.DeserializeObject("FieldsToNotMove.xml");
Is there such a method? Or am I going to need to create an XML reader and load it in that way?
EDIT: Turns out there is no built in SerialzeObject. I had made one earlier in my project and forgot about it. When I found it I thought it was built in. In case you are curious this is the SerializeObject that I made:
// Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
TextWriter textWriter = new StreamWriter(filename);
xmlSerializer.Serialize(textWriter, toSerialize);
textWriter.Close();
}
There is no such builtin method as SerializeObject but it's not terribly difficult to code one up.
public void SerializeObject(this List<string> list, string fileName) {
var serializer = new XmlSerializer(typeof(List<string>));
using ( var stream = File.OpenWrite(fileName)) {
serializer.Serialize(stream, list);
}
}
And Deserialize
public void Deserialize(this List<string> list, string fileName) {
var serializer = new XmlSerializer(typeof(List<string>));
using ( var stream = File.OpenRead(fileName) ){
var other = (List<string>)(serializer.Deserialize(stream));
list.Clear();
list.AddRange(other);
}
}
These are my serialize/deserialize extension methods that work quite well
public static class SerializationExtensions
{
public static XElement Serialize(this object source)
{
try
{
var serializer = XmlSerializerFactory.GetSerializerFor(source.GetType());
var xdoc = new XDocument();
using (var writer = xdoc.CreateWriter())
{
serializer.Serialize(writer, source, new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") }));
}
return (xdoc.Document != null) ? xdoc.Document.Root : new XElement("Error", "Document Missing");
}
catch (Exception x)
{
return new XElement("Error", x.ToString());
}
}
public static T Deserialize<T>(this XElement source) where T : class
{
try
{
var serializer = XmlSerializerFactory.GetSerializerFor(typeof(T));
return (T)serializer.Deserialize(source.CreateReader());
}
catch //(Exception x)
{
return null;
}
}
}
public static class XmlSerializerFactory
{
private static Dictionary<Type, XmlSerializer> serializers = new Dictionary<Type, XmlSerializer>();
public static XmlSerializer GetSerializerFor(Type typeOfT)
{
if (!serializers.ContainsKey(typeOfT))
{
System.Diagnostics.Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT));
var newSerializer = new XmlSerializer(typeOfT);
serializers.Add(typeOfT, newSerializer);
}
return serializers[typeOfT];
}
}
You just need to define a type for your list and use it instead
public class StringList : List<String> { }
Oh, and you don't NEED the XmlSerializerFactory, it's just there since creating a serializer is slow, and if you use the same one over and over this speeds up your app.
I'm not sure whether this will help you but I have dome something which I believe to be similar to you.
//A list that holds my data
private List<Location> locationCollection = new List<Location>();
public bool Load()
{
//For debug purposes
Console.WriteLine("Loading Data");
XmlSerializer serializer = new XmlSerializer(typeof(List<Location>));
FileStream fs = new FileStream("CurrencyData.xml", FileMode.Open);
locationCollection = (List<Location>)serializer.Deserialize(fs);
fs.Close();
Console.WriteLine("Data Loaded");
return true;
}
This allows me to deserialise all my data back into a List<> but i'd advise putting it in a try - catch block for safety. In fact just looking at this now is going to make me rewrite this in a "using" block too.
I hope this helps.
EDIT:
Apologies, just noticed you're trying to do it a different way but i'll leave my answer there anyway.
I was getting error while deserializing to object. The error was "There is an error in XML document (0, 0)". I have modified the Deserialize function originally written by #JaredPar to resolve this error. It may be useful to someone:
public static void Deserialize(this List<string> list, string fileName)
{
XmlRootAttribute xmlRoot = new XmlRootAttribute();
xmlRoot.ElementName = "YourRootElementName";
xmlRoot.IsNullable = true;
var serializer = new XmlSerializer(typeof(List<string>), xmlRoot);
using (var stream = File.OpenRead(fileName))
{
var other = (List<string>)(serializer.Deserialize(stream));
list.Clear();
list.AddRange(other);
}
}
Create a list of products be serialized
List<string> Products = new List<string>
{
new string("Product 1"),
new string("Product 2"),
new string("Product 3"),
new string("Product 4")
};
Serialization
using (FileStream fs = new FileStream(#"C:\products.txt", FileMode.Create))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, Products);
}
Deserialization
using (FileStream fs = new FileStream(#"C:\products.txt", FileMode.Open))
{
BinaryFormatter bf = new BinaryFormatter();
var productList = (List<string>)bf.Deserialize(fs);
}

Categories

Resources