Preface
Dataset class has GetXml method. The method takes data and creates XML.The problem is that you cannot change XML that created by function For example if you created SQL statement
Select PersonId,PersonName from Employee.
You will get following XML
<newdataset>
<table1>
<personId >354</personId >
<personName >Jhon</personName >
</table1>
</newdataset>
But if you want to change it to
<newdataset>
<Persons>
<Person personId = 354 personName="Jhon" >
</Persons>
</newdataset>
You cannot do it.
The other problem that can happen, that if SQL statement includes Left Outer Join, and one of the field
will be Null, the field will not be included in XML.
In order to solve these issus I created my "GetXml" function . You can customize your code any way you like.
Implementation
Basically I needed to implemented this function when I created statefull mechanism between client and server. So I needed to add in each row field "StateId" that will show the status of the row.
So here is the code
private string GetXmlFromDataset(DataSet dataSet, bool isStatefull) {
XmlTextWriter xwriter = null;
try
{
xwriter = new XmlTextWriter(new MemoryStream(), Encoding.UTF8);
xwriter.WriteStartElement("NewDataSet");
//start enumerate in table collection
foreach (DataTable dt in dataSet .Tables )
{
int rowNum = 0;
DateTime tmp = DateTime.MinValue;
if (isStatefull)
dt.Columns.Add(new DataColumn("IsDummy", typeof(bool)));
if (isStatefull && dt.Rows.Count == 0)
{
dt.Rows.Add(dt.NewRow());
dt.Rows[0]["IsDummy"] = true;
}
//start enumerate in rows collection
foreach (DataRow dr in dt.Rows)
{
//start <Table> element
xwriter.WriteStartElement(dt.TableName);
if (isStatefull)
{
xwriter.WriteAttributeString("stat", "0");
xwriter.WriteAttributeString("rowNum", rowNum.ToString());
}
DateTime tmpDate = DateTime.MinValue ;
//start enumerate in columns collection
foreach (DataColumn dc in dr.Table.Columns)
{
string colValue = String.Empty;
switch (dc.DataType.Name)
{
case "DateTime":
if (DateTime.TryParse(dr[dc, DataRowVersion.Current].ToString(), out tmpDate))
colValue = tmpDate.ToString("yyyy-MM-ddTHH:mm:ss");
else
colValue = dr[dc, DataRowVersion.Current].ToString();
break;
default:
colValue = dr[dc, DataRowVersion.Current].ToString();
break;
}
xwriter.WriteStartElement(dc.ColumnName.Replace(" ","_x0020_"));
if ( isStatefull || String.Compare(dc.DataType.Name, "string", true) != 0)
{
xwriter.WriteAttributeString("datatype", dc.DataType.Name);
}
if (isStatefull)
{
xwriter.WriteAttributeString("stat", "0");
}
xwriter.WriteString(colValue);
xwriter.WriteEndElement();
}
//end <Table> element
xwriter.WriteEndElement();
rowNum++;
}
}
//end <NewDataSet> element
xwriter.WriteEndElement();
xwriter.Flush();
xwriter.BaseStream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(xwriter.BaseStream);
return reader.ReadToEnd();
}
finally
{
if (xwriter != null)
{
xwriter.Close();
xwriter = null;
}
}
}
The code iterates over the tables and build XML accrodingly.
Summary
We learned in this post how to write custom "GetXml" function.