internal XmlElement HandleTable(DataTable table, XmlDocument dc, XmlElement schema, bool genNested)
{
XmlElement root = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
bool fWriteOrdinals = false;
bool fUnqualified = false;
if (((table.DataSet == null) || (_ds != null && table.Namespace != _ds.Namespace)) && (_schFormat == SchemaFormat.Remoting))
root.SetAttribute(Keywords.TARGETNAMESPACE, Keywords.MSDNS, table.Namespace);
// First add any attributes.
root.SetAttribute(Keywords.NAME, table.EncodedTableName);
if (table.Namespace.Length == 0)
{
DataTable _table = table;
string tgNamespace = _table.Namespace;
while (string.IsNullOrEmpty(tgNamespace))
{
DataRelation[] nestedParentRelations = _table.NestedParentRelations;
if (nestedParentRelations.Length == 0)
{
tgNamespace = (_ds != null) ? _ds.Namespace : "";
break;
}
int nestedparentPosition = -1; // it is find non-self-nested-parent
for (int i = 0; i < nestedParentRelations.Length; i++)
{
if (nestedParentRelations[i].ParentTable != _table)
{
nestedparentPosition = i;
break;
}
}
if (nestedparentPosition == -1)
{
break;
}
else
{
_table = nestedParentRelations[nestedparentPosition].ParentTable;
}
tgNamespace = _table.Namespace;
}
if (table.Namespace != tgNamespace)
{
root.SetAttribute(Keywords.FORM, Keywords.UNQUALIFIED);
fUnqualified = true;
}
}
if (table.ShouldSerializeCaseSensitive())
{
root.SetAttribute(Keywords.MSD_CASESENSITIVE, Keywords.MSDNS, table.CaseSensitive.ToString());
}
if (table.ShouldSerializeLocale())
{
root.SetAttribute(Keywords.MSD_LOCALE, Keywords.MSDNS, table.Locale.ToString());
}
AddXdoProperties(table, root, dc);
DataColumnCollection columns = table.Columns;
int cCount = columns.Count;
int realCount = 0;
if (cCount == 1 || cCount == 2)
for (int i = 0; i < cCount; i++)
{
DataColumn col = columns[i];
if (col.ColumnMapping == MappingType.Hidden)
{
DataRelationCollection childRelations = table.ChildRelations;
for (int j = 0; j < childRelations.Count; j++)
{
if (childRelations[j].Nested && childRelations[j].ParentKey.ColumnsReference.Length == 1 && childRelations[j].ParentKey.ColumnsReference[0] == col)
realCount++;
}
}
if (col.ColumnMapping == MappingType.Element)
realCount++;
}
if ((table._repeatableElement) && (realCount == 1))
{
// I only have 1 column and that gives me
// the type for this element
DataColumn col = table.Columns[0];
string _typeName = XmlDataTypeName(col.DataType);
if (_typeName == null || _typeName.Length == 0)
{
_typeName = Keywords.XSD_ANYTYPE;
}
root.SetAttribute(Keywords.TYPE, XSDSchema.QualifiedName(_typeName));
return root;
}
// Now add the type information nested inside the element or global.
XmlElement type = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_COMPLEXTYPE, Keywords.XSDNS);
if (!table.TypeName.IsEmpty && _schFormat != SchemaFormat.Remoting)
{
XmlElement typeSchema = GetSchema(table.TypeName.Namespace);
if (string.IsNullOrEmpty(table.TypeName.Namespace))
{
if (_ds == null)
typeSchema = GetSchema(table.Namespace);
else
typeSchema = fUnqualified ? GetSchema(_ds.Namespace) : GetSchema(table.Namespace);
}
if (FindTypeNode(typeSchema, table.TypeName.Name) == null)
typeSchema.AppendChild(type);
type.SetAttribute(Keywords.NAME, table.TypeName.Name);
}
else
{
root.AppendChild(type);
}
if (!table.TypeName.IsEmpty)
{
if (_schFormat != SchemaFormat.Remoting)
root.SetAttribute(Keywords.TYPE, NewDiffgramGen.QualifiedName((string)_prefixes[table.TypeName.Namespace], table.TypeName.Name));
}
XmlElement compositor = null;
DataColumn colTxt = table.XmlText;
if (colTxt != null)
{
XmlElement sc = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SIMPLECONTENT, Keywords.XSDNS);
if (colTxt.GetType() != typeof(DataColumn))
AddXdoProperties(colTxt, sc, dc);
else
AddColumnProperties(colTxt, sc);
AddExtendedProperties(colTxt._extendedProperties, sc);
if (colTxt.AllowDBNull)
root.SetAttribute(Keywords.XSD_NILLABLE, string.Empty, Keywords.TRUE);
if (!colTxt.DefaultValueIsNull)
{
XmlTreeGen.ValidateColumnMapping(colTxt.DataType);
sc.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, colTxt.ConvertObjectToXml(colTxt.DefaultValue));
}
sc.SetAttribute(Keywords.MSD_COLUMNNAME, Keywords.MSDNS, colTxt.ColumnName);
sc.SetAttribute(Keywords.MSD_ORDINAL, Keywords.MSDNS, colTxt.Ordinal.ToString(CultureInfo.InvariantCulture));
type.AppendChild(sc);
XmlElement ext = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_EXTENSION, Keywords.XSDNS);
sc.AppendChild(ext);
HandleColumnType(colTxt, dc, ext, schema);
type = ext;
}
compositor = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SEQUENCE, Keywords.XSDNS);
type.AppendChild(compositor);
fWriteOrdinals = HasMixedColumns(table);
for (int i = 0; i < cCount; i++)
{
DataColumn col = columns[i];
if (col.ColumnMapping == MappingType.SimpleContent)
continue;
if (col.ColumnMapping == MappingType.Attribute || col.ColumnMapping == MappingType.Element || col.ColumnMapping == MappingType.Hidden)
{
if (IsAutoGenerated(col)) // skip automanifactured columns
continue;
bool isAttribute = col.ColumnMapping != MappingType.Element;
XmlElement el = HandleColumn(col, dc, schema, fWriteOrdinals);
XmlElement node = isAttribute ? type : compositor;
//bool flag = isAttribute ? col.Namespace == "" : col.Namespace == table.Namespace;
node.AppendChild(el);
}
}
if ((table.XmlText == null) && (genNested))
{
DataRelationCollection childRelations = table.ChildRelations;
for (int j = 0; j < childRelations.Count; j++)
{
XmlElement NestedTable;
if (!childRelations[j].Nested)
continue;
DataTable childTable = childRelations[j].ChildTable;
if (childTable == table)
{ // self join
NestedTable = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
NestedTable.SetAttribute(Keywords.REF, table.EncodedTableName);
}
else if (childTable.NestedParentsCount > 1)
{ // skip relations with multiple parents
NestedTable = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
NestedTable.SetAttribute(Keywords.REF, childTable.EncodedTableName);
}
else
NestedTable = HandleTable(childTable, dc, schema);
if (childTable.Namespace == table.Namespace)
{
NestedTable.SetAttribute(Keywords.MINOCCURS, "0");
NestedTable.SetAttribute(Keywords.MAXOCCURS, Keywords.ZERO_OR_MORE);
}
if ((childTable.Namespace == table.Namespace) || (childTable.Namespace.Length == 0) || _schFormat == SchemaFormat.Remoting)
{
compositor.AppendChild(NestedTable);
}
else
{
if (childTable.NestedParentsCount <= 1)
GetSchema(childTable.Namespace).AppendChild(NestedTable);
NestedTable = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
NestedTable.SetAttribute(Keywords.REF, ((string)_prefixes[childTable.Namespace]) + ':' + childTable.EncodedTableName);
compositor.AppendChild(NestedTable);
}
if (childRelations[j].ChildKeyConstraint != null)
continue; // we write the relation using the constraint
XmlElement nodeAnn = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ANNOTATION, Keywords.XSDNS);
NestedTable.PrependChild(nodeAnn);
XmlElement nodeApp = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_APPINFO, Keywords.XSDNS);
nodeAnn.AppendChild(nodeApp);
nodeApp.AppendChild(HandleRelation(childRelations[j], dc));
}
}
if (compositor != null)
if (!compositor.HasChildNodes)
type.RemoveChild(compositor);
// Output all constraints.
ConstraintCollection constraints = table.Constraints;
XmlElement selector, field;
string xpathprefix = (_ds != null) ? (_ds.Namespace.Length != 0 ? Keywords.MSTNS_PREFIX : string.Empty) : string.Empty;
if (_schFormat != SchemaFormat.Remoting)
{
GetSchema(table.Namespace); // to ensure prefix handling
xpathprefix = table.Namespace.Length != 0 ? (string)_prefixes[table.Namespace] + ':' : string.Empty;
}
for (int i = 0; i < constraints.Count; i++)
{
XmlElement constraint = null;
DataColumn[] fields;
if (constraints[i] is UniqueConstraint)
{
UniqueConstraint unique = (UniqueConstraint)constraints[i];
if (IsAutoGenerated(unique))
continue;
// special case of the ghosted constraints:
fields = unique.Key.ColumnsReference;
constraint = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_UNIQUE, Keywords.XSDNS);
if ((_ds == null) || (_ds.Tables.InternalIndexOf(table.TableName) == -3))
constraint.SetAttribute(Keywords.MSD_TABLENS, Keywords.MSDNS, table.Namespace);
// convert constraint name to valid xml name
constraint.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName(unique.SchemaName));
if (unique.ConstraintName != unique.SchemaName)
constraint.SetAttribute(Keywords.MSD_CONSTRAINTNAME, Keywords.MSDNS, unique.ConstraintName);
AddExtendedProperties(unique._extendedProperties, constraint);
selector = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SELECTOR, Keywords.XSDNS);
selector.SetAttribute(Keywords.XSD_XPATH, ".//" + xpathprefix + table.EncodedTableName);
constraint.AppendChild(selector);
if (unique.IsPrimaryKey)
{
constraint.SetAttribute(Keywords.MSD_PRIMARYKEY, Keywords.MSDNS, Keywords.TRUE);
}
if (0 < fields.Length)
{
StringBuilder encodedName = new StringBuilder();
for (int k = 0; k < fields.Length; k++)
{
encodedName.Length = 0;
if (_schFormat != SchemaFormat.Remoting)
{
GetSchema(fields[k].Namespace);
if (!string.IsNullOrEmpty(fields[k].Namespace))
{
encodedName.Append(_prefixes[fields[k].Namespace]).Append(':');
}
encodedName.Append(fields[k].EncodedColumnName);
}
else
{
encodedName.Append(xpathprefix).Append(fields[k].EncodedColumnName);
}
if ((fields[k].ColumnMapping == MappingType.Attribute) || (fields[k].ColumnMapping == MappingType.Hidden))
{
encodedName.Insert(0, '@');
}
field = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_FIELD, Keywords.XSDNS);
field.SetAttribute(Keywords.XSD_XPATH, encodedName.ToString());
constraint.AppendChild(field);
}
}
_dsElement.InsertBefore(constraint, _constraintSeparator);
}
else if (constraints[i] is ForeignKeyConstraint && genNested)
{
ForeignKeyConstraint foreign = (ForeignKeyConstraint)constraints[i];
if (_tables.Count > 0)
{
if (!_tables.Contains(foreign.RelatedTable) || !_tables.Contains(foreign.Table))
continue;
}
if (IsAutoGenerated(foreign))
continue;
DataRelation rel = foreign.FindParentRelation();
// special case of the ghosted constraints:
fields = foreign.RelatedColumnsReference;
UniqueConstraint _constraint = (UniqueConstraint)foreign.RelatedTable.Constraints.FindConstraint(new UniqueConstraint("TEMP", fields));
if (_constraint == null)
{
constraint = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_KEY, Keywords.XSDNS);
constraint.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName(foreign.SchemaName));
if ((_ds == null) || (_ds.Tables.InternalIndexOf(table.TableName) == -3))
constraint.SetAttribute(Keywords.MSD_TABLENS, Keywords.MSDNS, table.Namespace);
selector = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SELECTOR, Keywords.XSDNS);
selector.SetAttribute(Keywords.XSD_XPATH, ".//" + xpathprefix + foreign.RelatedTable.EncodedTableName);
constraint.AppendChild(selector);
if (0 < fields.Length)
{
StringBuilder encodedName = new StringBuilder();
for (int k = 0; k < fields.Length; k++)
{
encodedName.Length = 0;
if (_schFormat != SchemaFormat.Remoting)
{
GetSchema(fields[k].Namespace);
if (!string.IsNullOrEmpty(fields[k].Namespace))
{
encodedName.Append(_prefixes[fields[k].Namespace]).Append(':');
}
encodedName.Append(fields[k].EncodedColumnName);
}
else
{
encodedName.Append(xpathprefix).Append(fields[k].EncodedColumnName);
}
if ((fields[k].ColumnMapping == MappingType.Attribute) || (fields[k].ColumnMapping == MappingType.Hidden))
{
encodedName.Insert(0, '@');
}
field = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_FIELD, Keywords.XSDNS);
field.SetAttribute(Keywords.XSD_XPATH, encodedName.ToString());
constraint.AppendChild(field);
}
}
_dsElement.InsertBefore(constraint, _constraintSeparator);
}
constraint = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_KEYREF, Keywords.XSDNS);
// convert constraint name to valid xml name
constraint.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName(foreign.SchemaName));
if ((_ds == null) || (_ds.Tables.InternalIndexOf(foreign.RelatedTable.TableName) == -3)) // if there is a conflicting name/namespace only
constraint.SetAttribute(Keywords.MSD_TABLENS, Keywords.MSDNS, foreign.Table.Namespace);
if (_constraint == null)
constraint.SetAttribute(Keywords.REFER, XmlConvert.EncodeLocalName(foreign.SchemaName));
else
constraint.SetAttribute(Keywords.REFER, XmlConvert.EncodeLocalName(_constraint.SchemaName));
AddExtendedProperties(foreign._extendedProperties, constraint, typeof(ForeignKeyConstraint));
if (foreign.ConstraintName != foreign.SchemaName)
constraint.SetAttribute(Keywords.MSD_CONSTRAINTNAME, Keywords.MSDNS, foreign.ConstraintName);
if (null == rel)
{
constraint.SetAttribute(Keywords.MSD_CONSTRAINTONLY, Keywords.MSDNS, Keywords.TRUE);
}
else
{
if (rel.Nested)
constraint.SetAttribute(Keywords.MSD_ISNESTED, Keywords.MSDNS, Keywords.TRUE);
AddExtendedProperties(rel._extendedProperties, constraint, typeof(DataRelation));
if (foreign.ConstraintName != rel.RelationName)
{
constraint.SetAttribute(Keywords.MSD_RELATIONNAME, Keywords.MSDNS, XmlConvert.EncodeLocalName(rel.RelationName));
}
}
selector = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SELECTOR, Keywords.XSDNS);
selector.SetAttribute(Keywords.XSD_XPATH, ".//" + xpathprefix + table.EncodedTableName);
constraint.AppendChild(selector);
if (foreign.AcceptRejectRule != ForeignKeyConstraint.AcceptRejectRule_Default)
constraint.SetAttribute(Keywords.MSD_ACCEPTREJECTRULE, Keywords.MSDNS,
TranslateAcceptRejectRule(foreign.AcceptRejectRule));
if (foreign.UpdateRule != ForeignKeyConstraint.Rule_Default)
constraint.SetAttribute(Keywords.MSD_UPDATERULE, Keywords.MSDNS, TranslateRule(foreign.UpdateRule));
if (foreign.DeleteRule != ForeignKeyConstraint.Rule_Default)
constraint.SetAttribute(Keywords.MSD_DELETERULE, Keywords.MSDNS, TranslateRule(foreign.DeleteRule));
fields = foreign.Columns;
if (0 < fields.Length)
{
StringBuilder encodedName = new StringBuilder();
for (int k = 0; k < fields.Length; k++)
{
encodedName.Length = 0;
if (_schFormat != SchemaFormat.Remoting)
{
GetSchema(fields[k].Namespace);
if (!string.IsNullOrEmpty(fields[k].Namespace))
{
encodedName.Append(_prefixes[fields[k].Namespace]).Append(':');
}
encodedName.Append(fields[k].EncodedColumnName);
}
else
{
encodedName.Append(xpathprefix).Append(fields[k].EncodedColumnName);
}
if ((fields[k].ColumnMapping == MappingType.Attribute) || (fields[k].ColumnMapping == MappingType.Hidden))
{
encodedName.Insert(0, '@');
}
field = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_FIELD, Keywords.XSDNS);
field.SetAttribute(Keywords.XSD_XPATH, encodedName.ToString());
constraint.AppendChild(field);
}
}
_dsElement.InsertAfter(constraint, _constraintSeparator);
}
}
AddExtendedProperties(table._extendedProperties, root);
return root;
}