internal void HandleElementColumn(XmlSchemaElement elem, DataTable table, bool isBase)
{
Type type = null;
XmlSchemaElement el = elem.Name != null ? elem : (XmlSchemaElement)_elementsTable[elem.RefName];
if (el == null) // it's possible due to some XSD compiler optimizations
return; // do nothing
XmlSchemaAnnotated typeNode = FindTypeNode(el);
string strType = null;
SimpleType xsdType = null;
if (typeNode == null)
{
strType = el.SchemaTypeName.Name;
if (string.IsNullOrEmpty(strType))
{
strType = string.Empty;
type = typeof(string);
}
else
{
type = ParseDataType(el.SchemaTypeName.Name);
}
}
else if (typeNode is XmlSchemaSimpleType)
{
XmlSchemaSimpleType simpleTypeNode = typeNode as XmlSchemaSimpleType;
xsdType = new SimpleType(simpleTypeNode);
// ((XmlSchemaSimpleType)typeNode).Name != null && ((XmlSchemaSimpleType)typeNode).Name.Length != 0 check is for annonymos simple type,
// it should be user defined Named simple type
if (((XmlSchemaSimpleType)typeNode).Name != null && ((XmlSchemaSimpleType)typeNode).Name.Length != 0 && ((XmlSchemaSimpleType)typeNode).QualifiedName.Namespace != Keywords.XSDNS)
{
string targetNamespace = XSDSchema.GetMsdataAttribute(typeNode, Keywords.TARGETNAMESPACE);
strType = ((XmlSchemaSimpleType)typeNode).QualifiedName.ToString(); // use qualifed name
type = ParseDataType(strType);
}
else
{
simpleTypeNode = (xsdType.XmlBaseType != null && xsdType.XmlBaseType.Namespace != Keywords.XSDNS) ?
_schemaTypes[xsdType.XmlBaseType] as XmlSchemaSimpleType :
null;
while (simpleTypeNode != null)
{
xsdType.LoadTypeValues(simpleTypeNode);
simpleTypeNode = (xsdType.XmlBaseType != null && xsdType.XmlBaseType.Namespace != Keywords.XSDNS) ?
_schemaTypes[xsdType.XmlBaseType] as XmlSchemaSimpleType :
null;
}
type = ParseDataType(xsdType.BaseType);
strType = xsdType.Name;
if (xsdType.Length == 1 && type == typeof(string))
{
type = typeof(char);
}
}
}
else if (typeNode is XmlSchemaElement)
{ // theoratically no named simpletype should come here
strType = ((XmlSchemaElement)typeNode).SchemaTypeName.Name;
type = ParseDataType(strType);
}
else if (typeNode is XmlSchemaComplexType)
{
if (string.IsNullOrEmpty(XSDSchema.GetMsdataAttribute(elem, Keywords.MSD_DATATYPE)))
{
throw ExceptionBuilder.DatatypeNotDefined();
}
else
{
type = typeof(object);
}
}
else
{
if (typeNode.Id == null)
throw ExceptionBuilder.DatatypeNotDefined();
else
throw ExceptionBuilder.UndefinedDatatype(typeNode.Id);
}
DataColumn column;
string columnName = XmlConvert.DecodeName(GetInstanceName(el));
bool isToAdd = true;
if (((!isBase) || FromInference) && (table.Columns.Contains(columnName, true)))
{
column = table.Columns[columnName];
isToAdd = false;
if (FromInference)
{ // for backward compatability with old inference
if (column.ColumnMapping != MappingType.Element)
throw ExceptionBuilder.ColumnTypeConflict(column.ColumnName);
// in previous inference , if we have incoming column with different NS, we think as different column and
//while adding , since there is no NS concept for datacolumn, we used to throw exception
// simulate the same behavior.
if ((string.IsNullOrEmpty(elem.QualifiedName.Namespace) && string.IsNullOrEmpty(column._columnUri)) || // backward compatability :SQL BU DT 310912
(string.Equals(elem.QualifiedName.Namespace, column.Namespace, StringComparison.Ordinal)))
{
return; // backward compatability
}
column = new DataColumn(columnName, type, null, MappingType.Element);// this is to fix issue with Exception we used to throw for old inference engine if column
//exists with different namespace; while adding it to columncollection
isToAdd = true;
}
}
else
{
column = new DataColumn(columnName, type, null, MappingType.Element);
}
SetProperties(column, el.UnhandledAttributes);
HandleColumnExpression(column, el.UnhandledAttributes);
SetExtProperties(column, el.UnhandledAttributes);
if (!string.IsNullOrEmpty(column.Expression))
{
_columnExpressions.Add(column);
}
// Update XSD type to point to simple types actual namespace instead of normalized default namespace in case of remoting
if (xsdType != null && xsdType.Name != null && xsdType.Name.Length > 0)
{
if (XSDSchema.GetMsdataAttribute(typeNode, Keywords.TARGETNAMESPACE) != null)
{
column.XmlDataType = xsdType.SimpleTypeQualifiedName;
}
}
else
{
column.XmlDataType = strType;
}
column.SimpleType = xsdType;
column.AllowDBNull = FromInference || (elem.MinOccurs == 0) || elem.IsNillable;
if (!elem.RefName.IsEmpty || elem.QualifiedName.Namespace != table.Namespace)
{ // if ref element (or in diferent NS) it is global element, so form MUST BE Qualified
column.Namespace = elem.QualifiedName.Namespace;
column.Namespace = GetStringAttribute(el, "targetNamespace", column.Namespace);
}
else
{ // it is local, hence check for 'form' on local element, if not specified, check for 'elemenfformdefault' on schema element
if (elem.Form == XmlSchemaForm.Unqualified)
{
column.Namespace = string.Empty;
}
else if (elem.Form == XmlSchemaForm.None)
{
XmlSchemaObject e = elem.Parent;
while (e.Parent != null)
{
e = e.Parent;
}
if (((XmlSchema)e).ElementFormDefault == XmlSchemaForm.Unqualified)
{
column.Namespace = string.Empty;
}
}
else
{
column.Namespace = elem.QualifiedName.Namespace;
column.Namespace = GetStringAttribute(el, "targetNamespace", column.Namespace);
}
}
string tmp = GetStringAttribute(elem, Keywords.MSD_ORDINAL, (-1).ToString(CultureInfo.CurrentCulture));
int ordinal = (int)Convert.ChangeType(tmp, typeof(int), null);
if (isToAdd)
{
if (ordinal > -1 && ordinal < table.Columns.Count)
table.Columns.AddAt(ordinal, column);
else
table.Columns.Add(column);
}
if (column.Namespace == table.Namespace)
column._columnUri = null; // to not raise a column change namespace again
if (FromInference)
{// search for prefix after adding to table, so NS has its final value, and
column.Prefix = GetPrefix(column.Namespace); // it can inherit its NS from DataTable, if it is null
}
string strDefault = el.DefaultValue;
if (strDefault != null)
try
{
column.DefaultValue = column.ConvertXmlToObject(strDefault);
}
catch (System.FormatException)
{
throw ExceptionBuilder.CannotConvert(strDefault, type.FullName);
}
}