XMLTextWriter v/s XElement
I have to move some data from Database to a XML file. A very simple task, write a SQL query, get the result and put it into a XML File. So here is my data query
DownloadDataContext db = new DownloadDataContext();
IQueryable downloads =
from f in db.Files
join fr in db.FamilyReleases
on f.ReleaseID equals fr.ReleaseID
join fdl in db.FamilyDetailsByLocales
on fr.FamilyID equals fdl.FamilyID
select new DownloadDetails{
FamilyID = fdl.FamilyID,
FileName = f.FileName,
FileSize = f.FileSize, URL = f.URL
)
Once I got the data in IQueryable downloads, Out of old habit, I proceeded to make the XML as follows:
MemoryStream ms = new MemoryStream();
using (XmlTextWriter w = new XmlTextWriter( ms, Encoding.UTF8 )) {
w.Formatting = Formatting.Indented;
w.WriteStartElement("Products");
foreach (DownloadDetails d in downloads) {
w.WriteStartElement("FamilyID"); w.WriteValue(d.FamilyID.ToString());
w.WriteEndElement(); w.WriteStartElement("FileName"); w.WriteValue(d.FileName ); w.WriteEndElement(); w.WriteStartElement("FileSize"); w.WriteValue(d.FileSize); w.WriteEndElement(); w.WriteStartElement("URL"); w.WriteValue(d.URL); w.WriteEndElement(); }
w.WriteEndElement(); //products
}
StreamReader r = new StreamReader(ms,Encoding.UTF8);
ms.Seek(0, SeekOrigin.Begin);
return r.ReadToEnd();
Very simple, However when I check the returned XML string, it is always cut in between and a proper XML is not formed. As the data is localized there may be a possibility that there is some funny character came in between and stream reader ReadToEnd function got confused. Debugging with 40+ languages in data was a nightmare, and I had no clue why streamreader is not working as it is suppose to work. There were other problems too, If any of the values are null, TextWriter.WriteValue complain very loudly. So every where I have to put a check to see if the value is null or not. However, the XElement came to my rescue. XElement does take all the possible data types, and does not complain if any of the data type is null.
XElement x = new XElement("Products");
foreach (DownloadDetails d in downloads) {
x.Add(new XElement("Product",
new XElement("FamilyID", d.FamilyID.ToString()),
new XElement("FileName", d.FileName),
new XElement("FileSize", d.FileSize),
new XElement("URL", d.URL + ""))); }
XElement not only handles NULL gracefully but does not complain about any of the unknown characters which threw StreamReader off. Clearly XElement is a better choice to make XML out of data, here is another example of XElement use.