private void GenerateColumn(DataRow row, DataColumn col, DataRowVersion version) {
string value = null;
value = col.GetColumnValueAsString(row, version); // this is useless for CTD
if (value == null) {
if (col.ColumnMapping == MappingType.SimpleContent)
_xmlw.WriteAttributeString(Keywords.XSI, Keywords.XSI_NIL, Keywords.XSINS, Keywords.TRUE);
return;
}
string colPrefix = (col.Namespace.Length != 0) ? col.Prefix : String.Empty;
switch (col.ColumnMapping) {
case MappingType.Attribute:
_xmlw.WriteAttributeString(colPrefix, col.EncodedColumnName, col.Namespace, value);
break;
case MappingType.Hidden:
_xmlw.WriteAttributeString(Keywords.MSD, "hidden"+col.EncodedColumnName, Keywords.MSDNS, value);
break;
case MappingType.SimpleContent:
_xmlw.WriteString(value);
break;
case MappingType.Element:
bool startElementSkipped = true;
object columnValue = row[col, version];
// if the object is built in type or if it implements IXMLSerializable, write the start Element, otherwise
//(if CDT and does not implement IXmlSerializable) skip it
if (!col.IsCustomType || !col.IsValueCustomTypeInstance(columnValue) ||(typeof(IXmlSerializable).IsAssignableFrom(columnValue.GetType()))) {
_xmlw.WriteStartElement( colPrefix, col.EncodedColumnName, col.Namespace);
startElementSkipped = false;
}
Type valuesType = columnValue.GetType();
if (!col.IsCustomType ) { // if column's type is built in type CLR or SQLType
if(valuesType == typeof(char) || valuesType == typeof(string)) {
if (XmlDataTreeWriter.PreserveSpace(value)) {
_xmlw.WriteAttributeString(Keywords.XML, Keywords.SPACE, Keywords.XML_XMLNS, Keywords.PRESERVE);
}
}
_xmlw.WriteString(value);
}
else { // Columns type is CDT
if ((columnValue != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(columnValue))){
if (col.IsValueCustomTypeInstance(columnValue)/* && valuesType != typeof(Type)*/) {// value is also CDT
// if SkippedElement, ie does not implement IXMLSerializable: so No Polymorphysm Support.
if (!startElementSkipped && columnValue.GetType() != col.DataType) {
_xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, DataStorage.GetQualifiedName(valuesType));
}
if (!startElementSkipped) {
col.ConvertObjectToXml(columnValue, _xmlw, null); // XmlRootAttribute MUST be passed null
}
else{
// this guy does not implement IXmlSerializable, so we need to handle serialization via XmlSerializer
if (columnValue.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(columnValue, _xmlw, xmlAttrib);
}
}
else { // value is built in CLR type (eg: string, int etc.)
// these basic clr types do not have direct xsd type mappings
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 (columnValue 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(columnValue));
}
else {
col.ConvertObjectToXml(columnValue, _xmlw, null);
}
}
}
}
if (!startElementSkipped) {
_xmlw.WriteEndElement();
}
break;
}
}