当我调用 dataSet.GetXml() 时,我没有为具有空值或空值的列返回任何 xml。有没有一种简单有效的方法来解决这个问题?以下问题的示例。注意第二个结果部分是如何缺少 a2 的。
<results>
<a1>test1</a1>
<a2>test2</a2>
<a3>test3</a3>
</results>
<results>
<a1>Atest1</a1>
<a3>Atest3</a3>
</results>
Microsoft 知识库文章中详细介绍了该问题:http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q317961。有关详细信息,请参阅之前的 SO 问题:DataSet.GetXml not returning null results.
我认为你的直接问题没有很好的解决方案。鉴于上下文,可能还有另一种方法来解决这个问题。
一个对我有用的解决方案。
首先克隆 DataTable,将所有列设为字符串类型,用
string.empty
替换所有空值,然后在新的 DataSet 上调用 GetXml
。
DataTable dtCloned = dt.Clone();
foreach (DataColumn dc in dtCloned.Columns)
dc.DataType = typeof(string);
foreach (DataRow row in dt.Rows)
{
dtCloned.ImportRow(row);
}
foreach (DataRow row in dtCloned.Rows)
{
for (int i = 0; i < dtCloned.Columns.Count; i++)
{
dtCloned.Columns[i].ReadOnly = false;
if (string.IsNullOrEmpty(row[i].ToString()))
row[i] = string.Empty;
}
}
DataSet ds = new DataSet();
ds.Tables.Add(dtCloned);
string xml = ds.GetXml();
我一直在全世界寻找使用 DataSet.WriteXML() 将空字段写入 XML 的解决方案。我发现以下以性能优化的方式工作。为了您的方便,我创建了一个函数。通过调用以下函数并替换表,一个接一个地更改数据集表。
private DataTable GetNullFilledDataTableForXML(DataTable dtSource)
{
// Create a target table with same structure as source and fields as strings
// We can change the column datatype as long as there is no data loaded
DataTable dtTarget = dtSource.Clone();
foreach (DataColumn col in dtTarget.Columns)
col.DataType = typeof(string);
// Start importing the source into target by ItemArray copying which
// is found to be reasonably fast for nulk operations. VS 2015 is reporting
// 500-525 milliseconds for loading 100,000 records x 10 columns
// after null conversion in every cell which may be usable in many
// circumstances.
// Machine config: i5 2nd Gen, 8 GB RAM, Windows 7 64bit, VS 2015 Update 1
int colCountInTarget = dtTarget.Columns.Count;
foreach (DataRow sourceRow in dtSource.Rows)
{
// Get a new row loaded with data from source row
DataRow targetRow = dtTarget.NewRow();
targetRow.ItemArray = sourceRow.ItemArray;
// Update DBNull.Values to empty string in the new (target) row
// We can safely assign empty string since the target table columns
// are all of string type
for (int ctr = 0; ctr < colCountInTarget; ctr++)
if (targetRow[ctr] == DBNull.Value)
targetRow[ctr] = String.Empty;
// Now add the null filled row to target datatable
dtTarget.Rows.Add(targetRow);
}
// Return the target datatable
return dtTarget;
}
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count == 0)
{
foreach (DataTable dt in ds.Tables)
{
foreach (DataColumn dc in dt.Columns)
{
dc.DataType = typeof(String);
}
}
DataRow dr = ds.Tables[0].NewRow();
for (int i = 0; i < dr.ItemArray.Count(); i++)
{
dr[i] = string.Empty;
}
ds.Tables[0].Rows.Add(dr);
}
private static string GetNonNullXMLDataFromDataSet(DataSet dsData, string sNullValueReplacementString)
{
string xml = "";
////xml = dsData.GetXml();
DataRow drClonned = null;
DataTable dtCloned = null;
//////// Make a clone and set all columns as string
DataSet dsCloned = dsData.Clone();
foreach (DataTable dt in dsCloned.Tables)
{
foreach (DataColumn dc in dt.Columns)
{
dc.DataType = typeof(string);
////dc.ColumnMapping = MappingType.Attribute;
}
}
//////// Get data from orignal datatable and create new row in cloned table
//////// replace DBNull.Value with the provided string marker
foreach (DataTable dt in dsData.Tables)
{
dtCloned = dsCloned.Tables[dt.TableName];
if (dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
drClonned = dtCloned.NewRow();
foreach (DataColumn dcc in dt.Columns)
{
if (row[dcc.ColumnName] == DBNull.Value)
{
drClonned[dcc.ColumnName] = sNullValueReplacementString;
}
else
{
drClonned[dcc.ColumnName] = row[dcc.ColumnName].ToString();
}
}
dtCloned.Rows.Add(drClonned);
}
}
else
{
drClonned = dtCloned.NewRow();
foreach (DataColumn dcc in dtCloned.Columns)
{
drClonned[dcc.ColumnName] = sNullValueReplacementString;
}
dtCloned.Rows.Add(drClonned);
}
}
xml = dsCloned.GetXml();
////StringReader sr = new StringReader(xml);
////dsCloned.ReadXml(sr);
////xml = dsCloned.GetXml();
return xml;
}