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 (Common.ADP.IsEmpty(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(CultureInfo.InvariantCulture));
}
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 (Common.ADP.IsEmpty(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) );
// Bug 108292: Since we always write complex type as annonymous type, DO NOT WRITE ITS NAME
// DO NOT REVERT THIS CHANGE
}
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 (!Common.ADP.IsEmpty(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 (!Common.ADP.IsEmpty(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 (!Common.ADP.IsEmpty(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;
}