Convert List<Object> to XML - c#

I have a very simple application. MainUI has the List of CustomClass. I pass this list to WCF service. WCF Service further needs to save these objects in database.
I am using Open XML in our sql stored procedure to get better performnace. But i don't know how to convert my List of Objects to XML.
If i have a datatable, it'll be easy as datatables have methods to get the XML out of them. But how to use for List of objects.
I completly understand that if my List is coming over the WCF, it is getting serialized properly. But what should i exactly need to do.

IMO, look into Controlling XML Serialization with Attributes and the XmlSerializer class and possibly create container classes parallel to your CustomClass. While List<> can't be automatically serialized by the default XML serializer, an array can be.

Thera are two ways: use XmlSerializer or DataContractSerializer.

Code for convert list to xml : List name GridDetails
void ConvertToXml()
{
string xmlString = ConvertObjectToXMLString(GridDetails);
// Save C# class object into Xml file
XElement xElement = XElement.Parse(xmlString);
xElement.Save(#"C:\Users\user\Downloads\userDetail.xml");
}
static string ConvertObjectToXMLString(object classObject)
{
string xmlString = null;
XmlSerializer xmlSerializer = new XmlSerializer(classObject.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
xmlSerializer.Serialize(memoryStream, classObject);
memoryStream.Position = 0;
xmlString = new StreamReader(memoryStream).ReadToEnd();
}
return xmlString;
}

Related

Read multiple XML files into a XML class structure

I would like to Read and Deserialize more than one XML file into my XML class structure given a list of strings consisting of file names.
Obviously when reading ONE xml file, you can go like this:
XmlRoot file = null;
XmlSerializer ser = new XmlSerializer(typeof(XmlRoot));
using (XmlReader read = XmlReader.Create(FileName))
{
file = (XmlRoot)ser.Deserialize(read);
{
Which will deserialize the XML file into the class structure?
It is not possible to have a list with file names and use a foreach loop to iterate over them, reading and deserializing one by one as it would theoretically result into multiple root elements being read, deserialized and replicated in the class structure.
So in general I would like to deserialize each file and append the required master elements to a root object.
Does anyone know how to accomplish this? It would be of great help.
Thanks in advance!
PS: Excuse me for my English, as I am not a native speaker. If you need further information, just tell me!
I managed to solve the problem for myself.
First i created a XDocument for the first file i read, afterwards i iterate through the other documents creating a new XDocument for every xml file and try to get the elements after the root (Language in my case) and add it to the root of the XDocument created outside the loop.
XDocument lDoc = new XDocument();
int counter = 0;
foreach (var fileName in multipleFileNames)
{
try
{
counter++;
if (lCounter <= 1)
{
doc = XDocument.Load(fileName);
}
else
{
XDocument doc2 = XDocument.Load(fileName);
IEnumerable<XElement> elements = doc2.Element("Language")
.Elements();
doc.Root.Add(elements);
}
}
return Deserialize(lDoc);
Afterwards i call the Deserialize method, deserializing my created XDocument like this:
public static XmlLanguage Deserialize(XDocument doc)
{
XmlSerializer ser = new XmlSerializer(typeof(XmlLanguage));
return (XmlLanguage)ser.Deserialize(doc.CreateReader());
}

Serializing a generic binary search tree with a bunch of child objects, including a binary tree

I've got a very complex binary search tree. It's node data should keep an object of custom KeyValue class. As a key there should be a string, and value is another tree, which data field contains an object of custom KeyValue class, where key is a string and value is string[].
I need to serialize and deserialize it, using XML serializer.
The problem is that serialization isn't done properly. XML file does not contain Nodes as elements, only their data.
Therefore, it can't be deserialized, a new tree's root is null.
Here is how I perform serialization.
XmlSerializer XMLserializer = new XmlSerializer(typeof(RecursiveKeyValueTree<string, RecursiveKeyValueTree<string, string[]>>), extraTypes);
XmlSerializerNamespaces myNamespace = new XmlSerializerNamespaces();
myNamespace.Add("", "");
using (FileStream serializationStream = File.Create("dictionaryTreeExample.xml"))
XMLserializer.Serialize(serializationStream, dictionaryTree, myNamespace);
RecursiveKeyValueTree<string, RecursiveKeyValueTree<string, string[]>> dictionaryTreeDeserialized;
using (FileStream deserializationStream = File.OpenRead("dictionaryTreeExample.xml"))
{
dictionaryTreeDeserialized = (RecursiveKeyValueTree<string, RecursiveKeyValueTree<string, string[]>>)XMLserializer.Deserialize(deserializationStream);
}
XML file:
My Add() method in the binary tree had an unnecessary check before inserting elements, thus, it prevented elements of the outer tree from being inserted.

passing xml data into a string to be used as a parameter

Having trouble dealing with xml and to properly use it for my purpose. So i am creating a test method and one of the parameters is xml data and i am not sure how to pass it in.
Service
public IEnumerable<Submissions> CheckingOutForUserReview(string data)
{
var _submissions = DataContextManager.StoredProcs.CheckingOutForUserReview<SSubmissions>(data, s => new Submissions
{
QRCodeGUID = SubmissionsColumnMap.QRCodeGUID(s),
StoragePath = SubmissionsColumnMap.StoragePath(s),
UploadedByUsersID = SubmissionsColumnMap.UploadedByUsersID(s)
});
return _submissions;
}
Stored Proc:
public virtual IEnumerable<T> CheckingOutForUserReview<T>(string data, Func<IDataRecord, T> modelBinder)
{
SqlCommand _command = new SqlCommand("dbo.CheckingOutForUserReview");
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.Add(new SqlParameter { ParameterName = "Data", SqlDbType = SqlDbType.Xml, Value = data });
return DbInstance.ExecuteAs<T>(_command, modelBinder);
}
This is my TestMethod:
public void CheckingOutForUserReview()
{
string _data = #"<CheckingOutForUserReview xmlns:i=""www.w3.org/2001/XMLSchema-instance"" xmlns=""schemas.name.com/2013/03/Malt.Models"">
<Record>
<QRCodeID>2FAC636E-F96C-4465-9272-760BAF73C0DF</QRCodeID>
<SubmissionID>10B5236C-47FD-468D-B88D-D789CA0C663A</SubmissionID>
<UserID>1</UserID>
<Page>1</Page>
</Record>
</CheckingOutForUserReview>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(_data);
var _Svc = new SubmissionsService();
var _checkins = _Svc.CheckingOutForUserReview(doc.InnerXml);
}
UPDATE:
my CheckingOutForUserReview() method accepts a XmlDocument as i changed it to that in my stored procedure and with what i currently have it is giving an error that i have invalid arguments(System.Xml.XmlDocument) not sure if i messed up somewhere.
If this is a different way i am also open in trying new ways. Thanks for the help.
As I see there are two ways:
You should save your xml into an xml file by adding xml file in your
project then use it with XmlDocument using Load method like:
XmlDocument doc = new XmlDocument.Load(FileName);
...
...
var _checkins = _Svc.CheckingOutForUserReview(doc.innerXml);
Save your xml as a string literal and use it with XmlDocument using
LoadXml method like:
XmlDocument doc = new XmlDocument.LoadXml(stringThatContainsXml);
...
...
var _checkins = _Svc.CheckingOutForUserReview(doc.innerXml);
You can use XDocument and XElement classes as well but my focus on XmlDocument is that it will work for framework less than 3.5 too since XDocument and XElement is introduced in framework 3.5.
Also loading xml into a parser will help to filter out the invalid xml. (if mistakenly tried to use)
Another thing i have noticed in your snippet:
Assert.IsNotNull(_data);
It should come before the initialization of _Svc, because if there is no data in _data initialization doesn't make sense.
So your code looks like:
public void CheckingOutForUserReview()
{
string _data = "I want to pass in xml here";
Assert.IsNotNull(_data); <--------------- See the re-ordering
var _Svc = new SubmissionsService();
var _checkins = _Svc.CheckingOutForUserReview(_data);
}
Like I said in a comment, I think the best way to do this is to save the XML into a separate file.
If you don't want to do that, you can use verbatim string literal (note the double quotes):
string data = #"<CheckingOutForUserReview xmlns:i=""www.w3.org/2001/XMLSchema-instance"" xmlns=""schemas.name.com/2013/03/Malt.Models"">
<Record>
<QRCodeID>2FAC636E-F96C-4465-9272-760BAF73C0DF</QRCodeID>
<SubmissionID>10B5236C-47FD-468D-B88D-D789CA0C663A</SubmissionID>
<UserID>1</UserID>
<Page>1</Page>
</Record>
</CheckingOutForUserReview>";
I don't see what is the problem in passing any kind of strings as a parameter into a method
If your XML is generated from your code, you better have used a StringBuilder to build it to reduce creating new references while concatenating your string.
If your XML is originally from a file, pass the file path into your method, and open the document there. there are a lot of different ways to open and read XML documents, or loading a string to an XML document and deal with it as XML rather than a string.
Examples:
http://www.codeproject.com/Articles/24375/Working-with-XML
http://forum.codecall.net/topic/58239-c-tutorial-reading-and-writing-xml-files/
and finally from MSDN:
http://msdn.microsoft.com/en-us/library/aa288481%28v=vs.71%29.aspx
enjoy

Serilializing Linq.Table to XML

I have a very simple application which currently has a single Linq to Sql class based on a single table.
I need to serialize (to XML) all rows in the table using the DataContext for the Linq To Sql class.
How do I go about doing this?
This is my current code :
var db = new MyEntityDataContext();
Stream fs = new FileStream("Output.xml", FileMode.Create);
XmlWriter writer = new XmlTextWriter(fs, Encoding.Unicode);
serializer = new XmlSerializer(typeof(MyEntity));
foreach (var row in db.MyEntitys)
{
// Serialize object to XML
serializer.Serialize(writer,row);
}
writer.Close();
However it throws the following exception:
"Token StartElement in state Epilog would result in an invalid XML document."
I have also tried:
XmlSerializer serializer2 = new XmlSerializer(db.MyEntitys.GetType());
but this throws a
"To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy."
exception.
XmlSerializer may not be wonderful with associations. If you enable serialization on the data-context surface, it adds (WCF) data-contract attributes. Perhaps just use:
var data = db.MyEntitys.ToList();
var ser = new DataContractSerializer(data.GetType());
ser.WriteObject(dest, data);

How to use XmlReader class?

I want to save and load my xml data using XmlReader. But I don't know how to use this class. Can you give me a sample code for start?
MSDN has a simple example to get you started here.
If you're interested in reading and writing XML documents, and not just specifically using the XmlReader class, there's a nice article covering a few of your options here.
But if you just want to get started and play around, try this:
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create("file.xml", settings);
Personally I have switched away from XMLReader to System.XML.Linq.XDocument to manage my XML data files. This way I can easily pull data from xml into objects and manage them like any other object in my program. When I am done manipulating them I can just save the changes back out the the xml file at any time.
//Load my xml document
XDocument myData = XDocument.Load(PhysicalApplicationPath + "/Data.xml");
//Create my new object
HelpItem newitem = new HelpItem();
newitem.Answer = answer;
newitem.Question = question;
newitem.Category = category;
//Find the Parent Node and then add the new item to it.
XElement helpItems = myData.Descendants("HelpItems").First();
helpItems.Add(newitem.XmlHelpItem());
//then save it back out to the file system
myData.Save(PhysicalApplicationPath + "/Data.xml");
If I want to use this data in an easily managed data set I can bind it to a list of my objects.
List<HelpItem> helpitems = (from helpitem in myData.Descendants("HelpItem")
select new HelpItem
{
Category = helpitem.Element("Category").Value,
Question = helpitem.Element("Question").Value,
Answer = helpitem.Element("Answer").Value,
}).ToList<HelpItem>();
Now it can be passed around and manipulated with any inherent functions of my object class.
For convenience my class has a function to create itself as an xml node.
public XElement XmlHelpItem()
{
XElement helpitem = new XElement("HelpItem");
XElement category = new XElement("Category", Category);
XElement question = new XElement("Question", Question);
XElement answer = new XElement("Answer", Answer);
helpitem.Add(category);
helpitem.Add(question);
helpitem.Add(answer);
return helpitem;
}
You should use the Create method instead of using new, since XmlReader is an abstract class using the Factory pattern.
var xmlReader = XmlReader.Create("xmlfile.xml");
From the excellent C# 3.0 in a Nutshell, consider looking at the sample code from chapter 11.

Categories

Resources