internal void XmlDataRowWriter(DataRow row, string encodedTableName)
{
object value;
string prefix = (row.Table.Namespace.Length == 0) ? "" : row.Table.Prefix;
_xmlw.WriteStartElement(prefix, encodedTableName, row.Table.Namespace);
if (_isDiffgram)
{
_xmlw.WriteAttributeString(Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, row.Table.TableName + row.rowID.ToString(CultureInfo.InvariantCulture));
_xmlw.WriteAttributeString(Keywords.MSD, Keywords.ROWORDER, Keywords.MSDNS, _rowsOrder[row].ToString());
if (row.RowState == DataRowState.Added)
{
_xmlw.WriteAttributeString(Keywords.DFF, Keywords.HASCHANGES, Keywords.DFFNS, Keywords.INSERTED);
}
if (row.RowState == DataRowState.Modified)
{
_xmlw.WriteAttributeString(Keywords.DFF, Keywords.HASCHANGES, Keywords.DFFNS, Keywords.MODIFIED);
}
if (RowHasErrors(row))
{
_xmlw.WriteAttributeString(Keywords.DFF, Keywords.HASERRORS, Keywords.DFFNS, Keywords.TRUE);
}
}
//write the attribute columns first, if any
foreach (DataColumn col in row.Table.Columns)
{
if (col._columnMapping == MappingType.Attribute)
{
value = row[col];
string colPrefix = (col.Namespace.Length == 0) ? "" : col.Prefix;
if ((value != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(value)))
{
XmlTreeGen.ValidateColumnMapping(col.DataType);
_xmlw.WriteAttributeString(colPrefix, col.EncodedColumnName, col.Namespace, col.ConvertObjectToXml(value));
}
}
if (!_isDiffgram)
continue;
if (col._columnMapping == MappingType.Hidden)
{
value = row[col];
if ((value != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(value)))
{
XmlTreeGen.ValidateColumnMapping(col.DataType);
_xmlw.WriteAttributeString(Keywords.MSD, "hidden" + col.EncodedColumnName, Keywords.MSDNS, col.ConvertObjectToXml(value));
}
}
} //end foreach
foreach (DataColumn col in row.Table.Columns)
{
if (col._columnMapping != MappingType.Hidden)
{
value = row[col];
string colPrefix = (col.Namespace.Length == 0) ? "" : col.Prefix;
bool startElementSkipped = true;
if (((value == DBNull.Value) || (col.ImplementsINullable && DataStorage.IsObjectSqlNull(value))) && (col.ColumnMapping == MappingType.SimpleContent))
_xmlw.WriteAttributeString(Keywords.XSI, Keywords.XSI_NIL, Keywords.XSINS, Keywords.TRUE);
// basically this is a continue; if it is null we write xsi:nil='true'
// below, the check is if it is not null
if (((value != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(value))) && (col._columnMapping != MappingType.Attribute))
{
if (col._columnMapping != MappingType.SimpleContent)
{
// again, if we need to use XmlSerializer, do not write start Element (see above for more info)
if (!col.IsCustomType || !col.IsValueCustomTypeInstance(value) || (typeof(IXmlSerializable).IsAssignableFrom(value.GetType())))
{
_xmlw.WriteStartElement(colPrefix, col.EncodedColumnName, col.Namespace);
startElementSkipped = false;
}
}
Type valuesType = value.GetType();
if (!col.IsCustomType)
{ // if column's type is built in type: CLR and SQLTypes : ie storage supported types
if (valuesType == typeof(char) || valuesType == typeof(string))
{
if (PreserveSpace(value))
{
_xmlw.WriteAttributeString(Keywords.XML, Keywords.SPACE, Keywords.XML_XMLNS, Keywords.PRESERVE);
}
}
_xmlw.WriteString(col.ConvertObjectToXml(value));
}
else
{ // Columns type is CDT
if (col.IsValueCustomTypeInstance(value) /*&& !(value is Type) && valuesType != typeof(Type)*/)
{// value is also CDT
// if SkippedElement, ie does not implement IXMLSerializable: so No Polymorphism Support.
if (!startElementSkipped && valuesType != col.DataType)
{ // for polymorphism.
_xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, DataStorage.GetQualifiedName(valuesType));
}
if (!startElementSkipped)
{ // make sure XmlRootAttribute is passed null as this type implement IXmlSerializable
col.ConvertObjectToXml(value, _xmlw, null); // pass XmlRootAttribute as null, it also means: No XmlSerializer
}
else
{ // startElement is skipped: this guy does not implement IXmlSerializable, need to go via XmlSerializer
if (value.GetType() != col.DataType)
{ // throw if polymorphism; not supported
throw ExceptionBuilder.PolymorphismNotSupported(valuesType.AssemblyQualifiedName);
}
// therefore we are skipping the start element, but by passing XmlRootAttribute with the same name as
// we open the start element (column's name), XmlSerializer will open and close it for us
XmlRootAttribute xmlAttrib = new XmlRootAttribute(col.EncodedColumnName);
xmlAttrib.Namespace = col.Namespace;
col.ConvertObjectToXml(value, _xmlw, xmlAttrib);
}
}
else
{ // this is case that column type is object and value is CLR or SQLTypes
if (valuesType == typeof(Type) || valuesType == typeof(Guid) || valuesType == typeof(char) ||
DataStorage.IsSqlType(valuesType))
{ // if unmapped type or SQL type write msdata:Datatype=typeofinstance
_xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, valuesType.FullName);
}
else if (value is Type)
{
_xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, Keywords.TYPEINSTANCE);
}
else
{
string xsdTypeName = Keywords.XSD_PREFIXCOLON + XmlTreeGen.XmlDataTypeName(valuesType);
_xmlw.WriteAttributeString(Keywords.XSI, Keywords.TYPE, Keywords.XSINS, xsdTypeName);
_xmlw.WriteAttributeString(Keywords.XMLNS_XSD, Keywords.XSDNS);
}
if (!DataStorage.IsSqlType(valuesType))
{
_xmlw.WriteString(col.ConvertObjectToXml(value));
}
else
{
col.ConvertObjectToXml(value, _xmlw, null);
}
}
}
if (col._columnMapping != MappingType.SimpleContent && !startElementSkipped)
_xmlw.WriteEndElement();
}
}
} //end foreach
if (_ds != null)
foreach (DataRelation dr in GetNestedChildRelations(row))
{
foreach (DataRow r in row.GetChildRows(dr))
{
XmlDataRowWriter(r, dr.ChildTable.EncodedTableName);
}
}
_xmlw.WriteEndElement();
}
internal static bool PreserveSpace(object value)