xmlsaver.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Data / System / Data / xmlsaver.cs / 2 / xmlsaver.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

namespace System.Data { 
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data.SqlTypes; 
    using System.Data.Common;
    using System.Diagnostics; 
    using System.Globalization; 
    using System.IO;
    using System.Text; 
    using System.Xml;
    using System.Xml.Serialization;

    internal enum SchemaFormat { 
        Public = 1,
        Remoting = 2, 
        WebService = 3, 
        RemotingSkipSchema = 4,
        WebServiceSkipSchema = 5 
    }

    /// 
    ///  
    internal sealed class XmlTreeGen {
        ArrayList ConstraintNames; 
        Hashtable namespaces; 
        Hashtable autogenerated;
        Hashtable prefixes; 

        DataSet _ds;
        ArrayList _tables = new ArrayList();
        ArrayList _relations = new ArrayList(); 

        XmlDocument _dc; 
        XmlElement _sRoot; 
        int prefixCount = 0;
        private SchemaFormat schFormat = SchemaFormat.Public; 
        private string filePath = null;
        private string fileName = null;
        private string fileExt = null;
        XmlElement dsElement = null; 
        XmlElement constraintSeparator = null;
 
 

        internal XmlTreeGen(SchemaFormat format) { 
            this.schFormat = format;
        }

        internal static void AddXdoProperties(Object instance, XmlElement root, XmlDocument xd) { 
            if (instance == null) {
                return; 
            } 

            PropertyDescriptorCollection pds = TypeDescriptor.GetProperties(instance) ; 

            if (!((instance is DataSet) || (instance is DataTable) || (instance is DataColumn) || (instance is DataRelation))) {
                return;
            } 

            for (int i = 0 ; i < pds.Count ; i++) { 
                AddXdoProperty(pds[i], instance, root, xd); 
            }
            return; 
        }

        internal static void AddExtendedProperties(PropertyCollection props, XmlElement node) {
            AddExtendedProperties(props, node, null); 
        }
 
        internal static void AddExtendedProperties(PropertyCollection props, XmlElement node, Type type) { 
            if(props != null) {
                foreach(DictionaryEntry entry in props) { 
                    String s, v;

                    if (entry.Key is INullable) {
                        s = (String) SqlConvert.ChangeTypeForXML(entry.Key, typeof(string)); 

                    } 
                    else { 
                        s = (String) Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
                    } 

                    if (entry.Value is INullable) {
                        v = (String) SqlConvert.ChangeTypeForXML(entry.Value, typeof(string));
                    } 
                    else {
                        v = (String) Convert.ToString(entry.Value, CultureInfo.InvariantCulture); 
                    } 

                    if (type == typeof(DataRelation)) { 
                        s = Keywords.MSD_REL_PREFIX + s;
                    }
                    else if (type == typeof(ForeignKeyConstraint)) {
                        s = Keywords.MSD_FK_PREFIX + s; 
                    }
                    node.SetAttribute(XmlConvert.EncodeLocalName(s), Keywords.MSPROPNS, v); 
                } 
            }
        } 
        internal static void AddXdoProperty(PropertyDescriptor pd, Object instance, XmlElement root, XmlDocument xd) {
            Type type = pd.PropertyType;
            bool  bisDataColumn = false;
            DataColumn col = null;  // it may cause problem to assign null here, I will need to change this. 
            bool bIsSqlType = false;
            bool bImplementsInullable = false; 
 
            if (instance is DataColumn) {
                col = (DataColumn)instance; 
                bisDataColumn = true;
                bIsSqlType =  col.IsSqlType;
                bImplementsInullable = col.ImplementsINullable;
            } 

            if (bImplementsInullable == false && 
                 type != typeof(string) &&     // DO NOT REMOVE THIS 
                 type != typeof(bool) &&
                 type != typeof(Type) && 
                 type != typeof(object) &&
                 type != typeof(CultureInfo) &&
                 type != typeof(Int64) &&
                 type != typeof(Int32) ) { 
                return;
            } 
 
            if ((!pd.ShouldSerializeValue(instance) || !pd.Attributes.Contains(DesignerSerializationVisibilityAttribute.Visible))&&( bIsSqlType == false)) {
                return; 
            }

            Object propInst = pd.GetValue(instance) ;
 
            if (propInst is InternalDataCollectionBase)
                return; 
 
            if (propInst is PropertyCollection) {
                return; 
            }
            // [....]: perf: Why not have this as a table?
            // there are several xdo properties that equal to some xml attributes, we should not explicitly ouput them.
            if ( 
                0 == String.Compare(pd.Name, "Namespace"    , StringComparison.Ordinal) ||
                0 == String.Compare(pd.Name, "PrimaryKey"   , StringComparison.Ordinal) || 
                0 == String.Compare(pd.Name, "ColumnName"   , StringComparison.Ordinal) || 
                0 == String.Compare(pd.Name, "DefaultValue" , StringComparison.Ordinal) ||
                0 == String.Compare(pd.Name, "TableName"    , StringComparison.Ordinal) || 
                0 == String.Compare(pd.Name, "DataSetName"  , StringComparison.Ordinal) ||
                0 == String.Compare(pd.Name, "AllowDBNull"  , StringComparison.Ordinal) ||
                0 == String.Compare(pd.Name, "Unique"       , StringComparison.Ordinal) ||
                0 == String.Compare(pd.Name, "NestedInDataSet" , StringComparison.Ordinal) || 
                0 == String.Compare(pd.Name, "Locale"       , StringComparison.Ordinal) ||
                0 == String.Compare(pd.Name, "CaseSensitive", StringComparison.Ordinal) || 
                0 == String.Compare(pd.Name, "RemotingFormat"       , StringComparison.Ordinal) 
            ) {
                return; 
            }

            if (bisDataColumn){    //(instance is DataColumn) {
                if (0 == String.Compare(pd.Name, "DataType", StringComparison.Ordinal)) { 
                    string dt = XmlDataTypeName(col.DataType);
                    if(bIsSqlType) { 
                        root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, col.DataType.FullName); 
                    }
                    else if ((dt.Length == 0) || bImplementsInullable || ((dt == Keywords.XSD_ANYTYPE) && (col.XmlDataType != Keywords.XSD_ANYTYPE))) { 
                        // in Whidbey, XmlDataTypeName function changed to return "anyType" for typeof(Object)
                        // should still always hit this code path for all non-built in types
                        // to handle version qualified typeof(Object) and other CDT objects correctly
 
                        // we must write the output exactly the same way as we read it
                       root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, col.DataType.AssemblyQualifiedName); 
                    } 
                    return;
                } 
                if (0 == String.Compare(pd.Name, "Attribute", StringComparison.Ordinal)) {
                    return;
                }
            } 

            string textValue = pd.Converter.ConvertToString(propInst) ; 
            root.SetAttribute(pd.Name, Keywords.MSDNS, textValue); 
            return;
 
        }

//
        internal static string XmlDataTypeName(Type type) { 
            if (type == typeof(Char))
                return "_";         // has to have SimpleType in this column. 
            if (type == typeof(Byte[]) || type == typeof(SqlBytes)) 
                return "base64Binary";       // has to have SimpleType in this column.
            if (type == typeof(DateTime) || type == typeof(SqlDateTime) ) 
                return "dateTime";
            if (type == typeof(TimeSpan))
                return "duration";
            if (type == typeof(Decimal)|| type == typeof(SqlDecimal) || type == typeof(SqlMoney)) 
                return "decimal";
            if (type == typeof(int)) 
                return "int"; 
            if (type == typeof(Boolean)|| type == typeof(SqlBoolean))
                return "boolean"; 
            if (type == typeof(Single)|| type == typeof(SqlSingle))
                return "float";
            if (type == typeof(double)  || type == typeof(SqlDouble))
                return "double"; 
            if (type == typeof(SByte)|| type == typeof(SqlByte))
                return "byte"; 
            if (type == typeof(Byte)) 
                return "unsignedByte";
            if (type == typeof(Int16)  || type == typeof(SqlInt16)) 
                return "short";
            if (type == typeof(Int32)  || type == typeof(SqlInt32))
                return "int";
            if (type == typeof(Int64)  || type == typeof(SqlInt64)) 
                return "long";
            if (type == typeof(UInt16)) 
                return "unsignedShort"; 
            if (type == typeof(UInt32))
                return "unsignedInt"; 
            if (type == typeof(UInt64))
                return "unsignedLong";
            if (type == typeof(Uri))
                return "anyURI"; 
            if (type == typeof(SqlBinary))
                return "hexBinary"; 
            if (type == typeof(string) ||type == typeof(SqlGuid)  ||type == typeof(SqlString) || type == typeof(SqlChars)) 
                return "string";
            if (type == typeof(object) || type == typeof(SqlXml)) 
                return Keywords.XSD_ANYTYPE;

            return String.Empty;
            // by default, if we dont map anything, we will map to String 
            // but I can not make Sql Types that will map to string be unmapped, because in schema , I will miss the second part and wont
            // be able to differenciate between string snd SqlString and others that map to String 
        } 

        private void GenerateConstraintNames(DataTable table, bool fromTable) { 
// if constraint created obased on relation and it is self related rel. then add constraint
            StringBuilder builder = null;
            foreach(Constraint constr in table.Constraints) {
                if (fromTable) { 
                    if (constr is ForeignKeyConstraint) { // if parent table does not exist , no need to create FKConst
                        if (!_tables.Contains((DataTable)(((ForeignKeyConstraint)constr).RelatedTable))) { 
                            continue; 
                        }
                    } 
                }

                int nameInt = 0;
                string name = constr.ConstraintName; 
                while (ConstraintNames.Contains(name)) {
                    if (null == builder) { 
                        builder = new StringBuilder(); 
                    }
                    builder.Append(table.TableName).Append('_').Append(constr.ConstraintName); 

                    if (0 < nameInt) {
                        builder.Append('_').Append(nameInt);
                    } 
                    nameInt++;
                    name = builder.ToString(); 
                    builder.Length = 0; 
                }
                ConstraintNames.Add(name); 
                constr.SchemaName = name;
            }
        }
 
        private void GenerateConstraintNames(ArrayList tables) {
            for (int i = 0; i < tables.Count; i++) { 
                GenerateConstraintNames((DataTable)tables[i], true); 
            }
        } 

        private void GenerateConstraintNames(DataSet ds) {
            foreach(DataTable dt in ds.Tables) {
                GenerateConstraintNames(dt, false); 
            }
        } 
 
        //Does the DS or ANY object in it have ExtendedProperties?
        private static bool _PropsNotEmpty(PropertyCollection props) { 
            return props != null && props.Count != 0;
        }

        private bool HaveExtendedProperties(DataSet ds) { 
            if(_PropsNotEmpty(ds.extendedProperties)) {
                return true; 
            } 
            for(int t = 0; t < ds.Tables.Count; t ++) {
                DataTable table = ds.Tables[t]; 
                if(_PropsNotEmpty(table.extendedProperties)) {
                    return true;
                }
                for(int c = 0; c < table.Columns.Count; c ++) { 
                    if(_PropsNotEmpty(table.Columns[c].extendedProperties)) {
                        return true; 
                    } 
                }
            } 
            // What is the best way to enumerate relations? from DataSet of from DataTable?
            for(int r = 0; r < ds.Relations.Count; r ++) {
                if(_PropsNotEmpty(ds.Relations[r].extendedProperties)) {
                    return true; 
                }
            } 
            // What about constraints? 
            return false;
        }// HaveExtendedProperties 

        internal void WriteSchemaRoot(XmlDocument xd, XmlElement rootSchema, string targetNamespace) {
/*
            if (_ds != null) 
                rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName(_ds.DataSetName));
            else 
                rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName("NewDataSet")); 
*/
 

                if (!Common.ADP.IsEmpty(targetNamespace)) {
                    rootSchema.SetAttribute(Keywords.TARGETNAMESPACE, targetNamespace );
                    rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, targetNamespace ); 
                }
                // Add the namespaces 
                // rootSchema.SetAttribute(Keywords.XMLNS, Keywords.XSD_ATOM.String)); 
                rootSchema.SetAttribute(Keywords.XMLNS, targetNamespace);
                rootSchema.SetAttribute(Keywords.XMLNS_XSD, Keywords.XSDNS); 
                rootSchema.SetAttribute(Keywords.XMLNS_MSDATA, Keywords.MSDNS);
                if((_ds != null) && (HaveExtendedProperties(_ds))) {
                    rootSchema.SetAttribute(Keywords.XMLNS_MSPROP, Keywords.MSPROPNS);
                } 

                if (!Common.ADP.IsEmpty(targetNamespace)) { 
                    rootSchema.SetAttribute(Keywords.XSD_ATTRIBUTEFORMDEFAULT, Keywords.QUALIFIED); 
                    rootSchema.SetAttribute(Keywords.XSD_ELEMENTFORMDEFAULT, Keywords.QUALIFIED);
                } 
        }

        internal static void ValidateColumnMapping(Type columnType) {
            if (DataStorage.IsTypeCustomType(columnType)) { 
                throw ExceptionBuilder.InvalidDataColumnMapping(columnType);
            } 
        } 

        internal void SetupAutoGenerated(DataSet ds){ 
            foreach (DataTable dt in ds.Tables)
                SetupAutoGenerated(dt);
        }
 
        internal void SetupAutoGenerated(ArrayList dt){
            for(int i = 0; i < dt.Count; i++) { 
                SetupAutoGenerated((DataTable)dt[i]); 
            }
        } 

        internal void SetupAutoGenerated(DataTable dt){
            foreach (DataColumn col in dt.Columns) {
                if (AutoGenerated(col)) 
                    autogenerated[col] = col;
            } 
 
            foreach (Constraint cs in dt.Constraints) {
                ForeignKeyConstraint fk = (cs as ForeignKeyConstraint); 
                if (null != fk) {
                    if (AutoGenerated(fk))
                        autogenerated[fk] = fk;
                    else { 
                        if (autogenerated[fk.Columns[0]] != null)
                            autogenerated[fk.Columns[0]] = null; 
                        if (autogenerated[fk.RelatedColumnsReference[0]] != null) 
                            autogenerated[fk.RelatedColumnsReference[0]] = null;
                        // special case of the ghosted constraints: 
                        UniqueConstraint _constraint = (UniqueConstraint) fk.RelatedTable.Constraints.FindConstraint( new UniqueConstraint( "TEMP", fk.RelatedColumnsReference));

                        if (_constraint == null)
                            continue; 

                        if(autogenerated[_constraint] != null) 
                            autogenerated[_constraint] = null; 
                        if(autogenerated[_constraint.Key.ColumnsReference[0]] != null)
                            autogenerated[_constraint.Key.ColumnsReference[0]] = null; 
                    }
                }
                else {
                    UniqueConstraint unique = (UniqueConstraint) cs; 
                    if (AutoGenerated(unique))
                        autogenerated[unique] = unique; 
                    else { 
                        if (autogenerated[unique.Key.ColumnsReference[0]] != null)
                            autogenerated[unique.Key.ColumnsReference[0]] = null; 
                    }
                }
            }
        } 
        private void CreateTablesHierarchy(DataTable dt) {
//            if (!dt.SerializeHierarchy) 
//                return; 
            foreach( DataRelation r in dt.ChildRelations ) {
                if (! _tables.Contains((DataTable)r.ChildTable)) { 
                    _tables.Add((DataTable)r.ChildTable);
                    CreateTablesHierarchy(r.ChildTable);
                }
            } 
        }
 
        private void CreateRelations(DataTable dt) { 
            foreach( DataRelation r in dt.ChildRelations ) {
                if (! _relations.Contains((DataRelation)r)) { 
                    _relations.Add((DataRelation)r);
//                  if (dt.SerializeHierarchy)
                        CreateRelations(r.ChildTable);
                } 
            }
        } 
 
        private DataTable[] CreateToplevelTables() {
            ArrayList topTables = new ArrayList(); 
            for (int i = 0; i < _tables.Count; i++) {
                DataTable table =(DataTable) _tables[i];
                if (table.ParentRelations.Count == 0)
                    topTables.Add(table); 
                else {
                    bool fNestedButNotSelfNested = false; 
                    for (int j = 0; j < table.ParentRelations.Count; j++) { 
                        if (table.ParentRelations[j].Nested) {
                            if (table.ParentRelations[j].ParentTable == table) { 
                                fNestedButNotSelfNested = false;
                                break;
                            }
                            fNestedButNotSelfNested = true; 
                        }
                    } 
                    if (!fNestedButNotSelfNested) 
                        topTables.Add(table);
                } 
            }
            if (topTables.Count == 0)
                return (new DataTable[0]);
            DataTable[] temp = new DataTable[topTables.Count]; 
            topTables.CopyTo(temp, 0);
            return temp; 
        } 

        internal void SchemaTree(XmlDocument xd, XmlWriter xmlWriter, DataSet ds, DataTable dt, bool writeHierarchy) { 
            ConstraintNames = new ArrayList();
            autogenerated = new Hashtable();
            bool genSecondary = filePath != null; //null non-file based streams.
 
            dsElement = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
 
            DataTable   []  top; 
            bool            fFlat = false;
 
            DataTable _dt = dt;

            if (ds != null) {
                _ds = ds; 
                foreach(DataTable table in ds.Tables) {
                    _tables.Add(table); 
                } 
            }
            else { 
                if (dt.DataSet != null) {
                        // preserve datatable's dataset to use for xml
                        // if null it would write out document element instead of dt.DataSet.DataSetName
                    _ds = dt.DataSet; 
                }
                _tables.Add(dt); 
                if (writeHierarchy) { 
                    CreateTablesHierarchy(dt);
                } 
            }

            _dc = xd;
 
            namespaces = new Hashtable();
            prefixes = new Hashtable(); 
 
            XmlElement rootSchema = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SCHEMA, Keywords.XSDNS);
            _sRoot = rootSchema; 

            // Need to writeid attribute on schema, as webservice relys on it for typeddataset deserialization
            // to get  class name
            if (_ds != null) { 
                rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName(_ds.DataSetName));
            } 
            else { 
                rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName("NewDataSet"));
            } 
            if (_ds != null) {
                WriteSchemaRoot(xd, rootSchema, _ds.Namespace);
            }
            else { 
                WriteSchemaRoot(xd, rootSchema, _dt.Namespace);
            } 
 
// register the root element and associated NS
            if (schFormat == SchemaFormat.Remoting) { 
                if (_ds != null) {
                    namespaces[_ds.Namespace] = rootSchema;
                }
                else { 
                    namespaces[_dt.Namespace] = rootSchema;
                } 
            } 

            if (schFormat != SchemaFormat.Remoting) { 
                if (_ds != null) {
                    namespaces[_ds.Namespace] = rootSchema;
                    if (_ds.Namespace.Length == 0)
                        prefixes[_ds.Namespace] = null; 
                    else {
                        // generate a prefix for the dataset schema itself. 
                        rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, _ds.Namespace ); 
                        prefixes[_ds.Namespace] = "mstns";
                    } 
                }
            }

            // Generate all the constraint names 
            if (ds != null)
                GenerateConstraintNames(ds); 
            else 
                GenerateConstraintNames(_tables);
 
            // Setup AutoGenerated table
            if (schFormat != SchemaFormat.Remoting) {
                if (ds != null) {
                    SetupAutoGenerated(ds); 
                }
                else { 
                    SetupAutoGenerated(_tables); 
                }
            } 


            //
            // Output all top level elements, which will recursively invoke to other tables. 
            //
 
            top = ((ds != null) ? ds.TopLevelTables(true) : CreateToplevelTables()); 

             if (top.Length == 0 || schFormat == SchemaFormat.WebServiceSkipSchema || schFormat == SchemaFormat.RemotingSkipSchema) { 
                // return an empty schema for now.
                // probably we need to throw an exception
                FillDataSetElement(xd, ds, dt);
                rootSchema.AppendChild(dsElement); 
                AddXdoProperties(_ds, dsElement, xd );
                AddExtendedProperties(ds.extendedProperties, dsElement); 
 

                xd.AppendChild(rootSchema); 
                xd.Save(xmlWriter);
                xmlWriter.Flush();
                return ; // rootSchema content has already been pushed to xmlWriter
            } 

//            if (schFormat != SchemaFormat.WebService && namespaces.Count > 1 && !genSecondary) { 
//               rootSchema.SetAttribute(Keywords.MSD_FRAGMENTCOUNT, Keywords.MSDNS, namespaces.Count.ToString()); 
//            }
 
            // Fill out dataset element
            XmlElement dsCompositor = FillDataSetElement(xd, ds, dt);

            constraintSeparator =  xd.CreateElement(Keywords.XSD_PREFIX, "SHOULDNOTBEHERE", Keywords.XSDNS); 
            dsElement.AppendChild(constraintSeparator);
            // DataSet properties 
            if (_ds != null) { 
                AddXdoProperties(_ds, dsElement, xd );
                AddExtendedProperties(_ds.extendedProperties, dsElement); 
            }


            for (int i = 0; i < top.Length; i++) { 
                XmlElement el = HandleTable(top[i], xd, rootSchema);
                if (((_ds != null )&& (_ds.Namespace == top[i].Namespace)) || Common.ADP.IsEmpty(top[i].Namespace) || (schFormat == SchemaFormat.Remoting)) { 
                    bool fNestedInDataset = top[i].fNestedInDataset; 

                    if (((_ds != null )&& (_ds.Namespace.Length != 0)) && Common.ADP.IsEmpty(top[i].Namespace)) { 
                        fNestedInDataset = true;
                    }

                    // what if dt has two nested relation , one self nested , the other with dtParent 
                    if (top[i].SelfNested) { // regarding above check : is it selfnested!
                        fNestedInDataset = false; 
                    } 

                    if (top[i].NestedParentsCount > 1) { // if it has multiple parents, it should be global 
                        fNestedInDataset = false;
                    }

                    if(fNestedInDataset) { //deal with maxOccurs properly 
                    if (top[i].MinOccurs != 1) {
                        el.SetAttribute(Keywords.MINOCCURS, top[i].MinOccurs.ToString(CultureInfo.InvariantCulture)); 
                      } 
                    if (top[i].MaxOccurs == -1){
                        el.SetAttribute(Keywords.MAXOCCURS, Keywords.ZERO_OR_MORE); 
                      }
                    else if (top[i].MaxOccurs != 1){
                        el.SetAttribute(Keywords.MAXOCCURS, top[i].MaxOccurs.ToString(CultureInfo.InvariantCulture));
                      } 
                    }
 
                    if (!fNestedInDataset) { 
                            rootSchema.AppendChild(el);
                            XmlElement node = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS); 
                            if ((_ds != null && _ds.Namespace == top[i].Namespace) || Common.ADP.IsEmpty(top[i].Namespace) || (schFormat == SchemaFormat.Remoting))
                                node.SetAttribute(Keywords.REF, top[i].EncodedTableName);
                            else
                                node.SetAttribute(Keywords.REF, ((string)prefixes[top[i].Namespace])+':'+top[i].EncodedTableName); 

                            dsCompositor.AppendChild(node); 
                        } 
                    else
                        dsCompositor.AppendChild(el); 
                    }
                else {
                    AppendChildWithoutRef(rootSchema, top[i].Namespace, el, Keywords.XSD_ELEMENT);
                    XmlElement node = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS); 
                    node.SetAttribute(Keywords.REF, ((string)prefixes[top[i].Namespace])+':'+top[i].EncodedTableName);
                    dsCompositor.AppendChild(node); 
                } 
            }
 

            dsElement.RemoveChild(constraintSeparator);
            rootSchema.AppendChild(dsElement);
 
            // Output all non-heirarchical relations without constraints
 
            DataRelation [] rels = new DataRelation[0]; 
            if (ds != null && _tables.Count> 0) { // we need to make sure we want to write relation just for tables in list
                rels = new DataRelation[ds.Relations.Count]; 
                for (int i = 0 ; i < ds.Relations.Count ; i++) {
                    rels[i] = ds.Relations[i];
                }
            } 
            else if (writeHierarchy && _tables.Count > 0 ) {
                  CreateRelations((DataTable)_tables[0]); 
                  rels = new DataRelation[_relations.Count]; 
                  _relations.CopyTo(rels, 0);
            } 

            XmlElement nodeAnn = null;
            XmlElement nodeApp = null;
 
            for (int i = 0; i < rels.Length; ++i) {
                DataRelation rel = rels[i]; 
 
                if (!rel.Nested || fFlat) {
                    if (rel.ChildKeyConstraint == null) { 
                        if (nodeAnn == null) {
                            nodeAnn = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ANNOTATION, Keywords.XSDNS);
                            rootSchema.AppendChild(nodeAnn);
 
                            nodeApp = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_APPINFO, Keywords.XSDNS);
                            nodeAnn.AppendChild(nodeApp); 
                        } 
                        Debug.Assert(nodeApp != null, "Need to create  node first.");
                        nodeApp.AppendChild(HandleRelation(rel, xd)); 
                    }
                }
            }
 

            XmlComment comment = null; 
            bool isMultipleNamespaceAndStreamingWriter = (namespaces.Count > 1 && !genSecondary); 

            if (schFormat != SchemaFormat.Remoting && schFormat != SchemaFormat.RemotingSkipSchema) { 
                // complete processing of rootSchema
                foreach (string ns in namespaces.Keys) {
                    if (ns == ((_ds != null) ? _ds.Namespace : _dt.Namespace) || Common.ADP.IsEmpty(ns)) {
                        continue; 
                    }
                    XmlElement _import = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_IMPORT, Keywords.XSDNS); 
                    _import.SetAttribute(Keywords.XSD_NAMESPACE, ns); 
                    if ( schFormat != SchemaFormat.WebService && !isMultipleNamespaceAndStreamingWriter) {
                        _import.SetAttribute(Keywords.XSD_SCHEMALOCATION, fileName + "_" + prefixes[ns] + ".xsd"); 
                    }
                    ((XmlNode)rootSchema).PrependChild((XmlNode)_import);
                }
                if (schFormat != SchemaFormat.WebService && isMultipleNamespaceAndStreamingWriter) { 
                    rootSchema.SetAttribute(Keywords.MSD_FRAGMENTCOUNT, Keywords.MSDNS, namespaces.Count.ToString(CultureInfo.InvariantCulture));
                } 
                // Post rootSchema content to xmlWriter. 
                xd.AppendChild(rootSchema);  // KB
                if (schFormat != SchemaFormat.WebService && isMultipleNamespaceAndStreamingWriter) { 
                    xd.WriteTo(xmlWriter);
                }
                else {
                    xd.Save(xmlWriter); 
                }
 
                xd.RemoveChild(rootSchema); //KB 

                foreach(string ns in namespaces.Keys) 
                {
                    if (ns == ((_ds != null)?_ds.Namespace:_dt.Namespace) || Common.ADP.IsEmpty(ns)) {
                        continue;
                    } 

                    XmlWriter xw = null; 
 
                    if (!genSecondary) {
                        xw = xmlWriter; 
                    }
                    else {
                        xw = new XmlTextWriter(filePath + fileName + "_" + prefixes[ns] + ".xsd", null);
                    } 

                    try { 
                        if (genSecondary) { 
                           if (xw is XmlTextWriter) {
                               ((XmlTextWriter)xw).Formatting = Formatting.Indented; 
                           }
                           xw.WriteStartDocument(true);
                        }
 
                        XmlElement tNode = (XmlElement) namespaces[ns] ;
                        _dc.AppendChild( tNode ); 
 
                        foreach(string imp_ns in namespaces.Keys)
                        { 
                            if (ns == imp_ns) {
                                continue; // don't write out yourself
                            }
                            string prefix = (string) prefixes[imp_ns]; 
                            if (prefix == null) { // only for dataset.Namespace == empty
                                continue; // do nothing 
                            } 
                            tNode.SetAttribute("xmlns:"+prefix, imp_ns);
                            XmlElement _import2 =  _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_IMPORT, Keywords.XSDNS); 
                            _import2.SetAttribute(Keywords.XSD_NAMESPACE, imp_ns);

                            if ( schFormat != SchemaFormat.WebService && !isMultipleNamespaceAndStreamingWriter)
                            { 
                                if (imp_ns == ((_ds != null)?_ds.Namespace:_dt.Namespace))
                                   _import2.SetAttribute(Keywords.XSD_SCHEMALOCATION, fileName + fileExt); // for the dataset namespace don't append anything 
                                else 
                                   _import2.SetAttribute(Keywords.XSD_SCHEMALOCATION, fileName + "_" + prefix +".xsd");
                            } 

                            ((XmlNode)tNode).PrependChild((XmlNode)_import2);
                        }
 
                        if (schFormat != SchemaFormat.WebService && isMultipleNamespaceAndStreamingWriter) {
                            _dc.WriteTo(xw); 
                        } 
                        else {
                            _dc.Save(xw); 
                        }
                        _dc.RemoveChild( tNode );
                        if (genSecondary) {
                            xw.WriteEndDocument(); 
                        }
                    } 
                    finally { 
                        if (genSecondary) {
                           xw.Close(); 
                        }
                    }
                }
            } 
            else {
                xd.AppendChild(rootSchema); 
                xd.Save(xmlWriter); 
            }
            if (comment != null) { 
                ((XmlNode)rootSchema).PrependChild((XmlNode)comment);
            }

            if (!genSecondary) { 
                xmlWriter.Flush();
            } 
            return;// rootSchema; 
        }
 
        internal XmlElement SchemaTree(XmlDocument xd, DataTable dt) {
            dsElement = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
            ConstraintNames = new ArrayList();
            _ds = dt.DataSet; 
            _dc = xd;
 
            namespaces = new Hashtable(); 
            prefixes = new Hashtable();
 
            if (schFormat != SchemaFormat.Remoting) {
                autogenerated = new Hashtable();
            }
 
            XmlElement rootSchema = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SCHEMA, Keywords.XSDNS);
            _sRoot = rootSchema; 
            WriteSchemaRoot(xd, rootSchema, dt.Namespace); 

            XmlElement dsCompositor = FillDataSetElement(xd, null, dt); 

            constraintSeparator =  xd.CreateElement(Keywords.XSD_PREFIX, "SHOULDNOTBEHERE", Keywords.XSDNS);
            dsElement.AppendChild(constraintSeparator);
 

            if (schFormat != SchemaFormat.Remoting) { 
                if (_ds != null) { 
                    namespaces[_ds.Namespace] = rootSchema;
                    if (_ds.Namespace.Length == 0) { 
                        prefixes[_ds.Namespace] = null;
                    }
                    else {
                        // generate a prefix for the dataset schema itself. 
                        rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, _ds.Namespace );
                        prefixes[_ds.Namespace] = "mstns"; 
                    } 
                }
                else { 
                    namespaces[dt.Namespace] = rootSchema;
                    if (dt.Namespace.Length == 0) {
                        prefixes[dt.Namespace] = null;
                    } 
                    else {
                        // generate a prefix for the dataset schema itself. 
                        rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, dt.Namespace ); 
                        prefixes[dt.Namespace] = "mstns";
                    } 
                }
            }

            // Generate all the constraint names 
            GenerateConstraintNames(dt, true);
 
            // 
            // Output all top level elements, which will recursively invoke to other tables.
            // 

            XmlElement el = HandleTable(dt, xd, rootSchema, false);
            rootSchema.AppendChild(el);
 
            dsElement.RemoveChild(constraintSeparator);
            rootSchema.AppendChild(dsElement); 
 
            return rootSchema;
        } 

        internal XmlElement FillDataSetElement(XmlDocument xd, DataSet ds, DataTable dt) {
            DataSet dataSet = (ds != null) ? ds : dt.DataSet;
            if (dataSet != null) { 
                    dsElement.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName(dataSet.DataSetName));
                    dsElement.SetAttribute(Keywords.MSD_ISDATASET, Keywords.MSDNS, Keywords.TRUE); 
                    if (ds == null) 
                        dsElement.SetAttribute(Keywords.MSD_MAINDATATABLE, Keywords.MSDNS, XmlConvert.EncodeLocalName(((dt.Namespace.Length == 0)?dt.TableName : (dt.Namespace + ":" + dt.TableName))));
 
                    // Add CaseSensitive and locale properties
                    if (dataSet.CaseSensitive) {
                        dsElement.SetAttribute(Keywords.MSD_CASESENSITIVE, Keywords.MSDNS, Keywords.TRUE);
                    } 
                    if (dataSet.ShouldSerializeLocale() || !dataSet.Locale.Equals(CultureInfo.CurrentCulture)) {
                        dsElement.SetAttribute(Keywords.MSD_LOCALE, Keywords.MSDNS, dataSet.Locale.ToString()); 
                    } 
                    else {
                        dsElement.SetAttribute(Keywords.MSD_USECURRENTLOCALE, Keywords.MSDNS, Keywords.TRUE); 
                    }
            }
            else { // No DataSet
                if (dt != null) { 
                    dsElement.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName("NewDataSet"));
                    dsElement.SetAttribute(Keywords.MSD_ISDATASET, Keywords.MSDNS, Keywords.TRUE); 
                    dsElement.SetAttribute(Keywords.MSD_MAINDATATABLE, Keywords.MSDNS, XmlConvert.EncodeLocalName(((dt.Namespace.Length == 0)?dt.TableName : (dt.Namespace + ":" + dt.TableName)))); 

                    if (dt.CaseSensitive) { // WebData 111631 :it is a bug to go and write casesensitive attrib as 'true', by default 
                        dsElement.SetAttribute(Keywords.MSD_CASESENSITIVE, Keywords.MSDNS, Keywords.TRUE);
                    }
                    if (dt.ShouldSerializeLocale() || !dt.Locale.Equals(CultureInfo.CurrentCulture)) {
                        dsElement.SetAttribute(Keywords.MSD_LOCALE, Keywords.MSDNS, dt.Locale.ToString()); 
                    }
                    else { 
                        dsElement.SetAttribute(Keywords.MSD_USECURRENTLOCALE, Keywords.MSDNS, Keywords.TRUE); 
                    }
                } 
            }

            XmlElement type = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_COMPLEXTYPE, Keywords.XSDNS);
            dsElement.AppendChild(type); 
            XmlElement compositor = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_CHOICE, Keywords.XSDNS);
            compositor.SetAttribute(Keywords.MINOCCURS, Keywords.ZERO_DIGIT); 
            compositor.SetAttribute(Keywords.MAXOCCURS, Keywords.ZERO_OR_MORE); 
            type.AppendChild(compositor);
 
            return compositor;
        }

        internal void SetPath(XmlWriter xw){ 
            FileStream fs = null;
 
            DataTextWriter sw = xw as DataTextWriter; 
            fs = (sw != null) ? sw.BaseStream as FileStream : null ;
 
            if (fs == null) {
                XmlTextWriter textw = xw as XmlTextWriter;
                if (textw == null)
                    return; 
                fs = textw.BaseStream as FileStream;
                if (fs == null) 
                    return; 
            }
 
            this.filePath = Path.GetDirectoryName(fs.Name);
            this.fileName = Path.GetFileNameWithoutExtension(fs.Name);
            this.fileExt = Path.GetExtension(fs.Name);
            if (!Common.ADP.IsEmpty(this.filePath)) 
                this.filePath  = filePath + "\\";
        } 
 
        internal void Save(DataSet ds, XmlWriter xw) {
            Save(ds, (DataTable)null, xw); 
        }

        internal void Save(DataTable dt, XmlWriter xw) {
            XmlDocument doc = new XmlDocument(); 
            if (schFormat == SchemaFormat.Public) {
                SetPath(xw); 
            } 
            XmlElement rootSchema = SchemaTree(doc, dt);
            doc.AppendChild( rootSchema ); 
            doc.Save(xw);
        }

        internal void Save(DataSet ds, DataTable dt, XmlWriter xw) { 
            Save(ds, dt, xw, false);
        } 
 
        internal void Save(DataSet ds, DataTable dt, XmlWriter xw, bool writeHierarchy) {
 
            XmlDocument doc = new XmlDocument();
            if (schFormat == SchemaFormat.Public) {
                SetPath(xw);
            } 
            if (schFormat == SchemaFormat.WebServiceSkipSchema && xw.WriteState==WriteState.Element) {
                xw.WriteAttributeString(Keywords.MSD, Keywords.MSD_SCHEMASERIALIZATIONMODE, Keywords.MSDNS, Keywords.MSD_EXCLUDESCHEMA); 
            } 
            SchemaTree(doc, xw, ds, dt, writeHierarchy);
        } 


        internal XmlElement HandleRelation(DataRelation rel, XmlDocument dc) {
            XmlElement root = dc.CreateElement(Keywords.MSD, Keywords.MSD_RELATION, Keywords.MSDNS); 

            // convert relation name to valid xml name 
            root.SetAttribute( Keywords.NAME,  XmlConvert.EncodeLocalName( rel.RelationName )); 

            root.SetAttribute(Keywords.MSD_PARENT, Keywords.MSDNS, rel.ParentKey.Table.EncodedTableName); 
            root.SetAttribute(Keywords.MSD_CHILD, Keywords.MSDNS, rel.ChildKey.Table.EncodedTableName);

            if ((_ds == null) || (_ds.Tables.InternalIndexOf(rel.ParentKey.Table.TableName) ==-3))
                root.SetAttribute( Keywords.MSD_PARENTTABLENS, Keywords.MSDNS, rel.ParentKey.Table.Namespace); 

            if ((_ds == null) || (_ds.Tables.InternalIndexOf(rel.ChildKey.Table.TableName) ==-3)) 
                root.SetAttribute( Keywords.MSD_CHILDTABLENS, Keywords.MSDNS, rel.ChildKey.Table.Namespace); 

            DataColumn[] key = rel.ParentKey.ColumnsReference; 

            string text = key[0].EncodedColumnName;
            StringBuilder builder = null;
            if (1 < key.Length) { 
                builder = new StringBuilder();
                builder.Append(text); 
                for (int i = 1; i < key.Length; i++) { 
                    builder.Append(Keywords.MSD_KEYFIELDSEP).Append(key[i].EncodedColumnName);
                } 
                text = builder.ToString();
            }
            root.SetAttribute( Keywords.MSD_PARENTKEY, Keywords.MSDNS, text);
 
            key = rel.ChildKey.ColumnsReference;
            text = key[0].EncodedColumnName; 
            if (1 < key.Length) { 
                if (null != builder) {
                    builder.Length = 0; 
                }
                else {
                    builder = new StringBuilder();
                } 
                builder.Append(text);
                for (int i = 1; i < key.Length; i++) { 
                    builder.Append(Keywords.MSD_KEYFIELDSEP).Append(key[i].EncodedColumnName); 
                }
                text = builder.ToString(); 
            }
            root.SetAttribute( Keywords.MSD_CHILDKEY, Keywords.MSDNS, text);
            AddExtendedProperties(rel.extendedProperties, root);
            return root; 
        }
 
        private static XmlElement FindSimpleType(XmlElement schema, string name) { 
            for (XmlNode n = schema.FirstChild; n != null; n = n.NextSibling) {
                if (n is XmlElement) { 
                    XmlElement e = (XmlElement) n;
                    if(e.GetAttribute(Keywords.NAME) == name) {
                        return e;
                    } 
                }
            } 
            return null; 
        }// FindSimpleType
 
        internal XmlElement GetSchema(string NamespaceURI) {
            XmlElement schemaEl = (XmlElement) namespaces[NamespaceURI];
            if (schemaEl == null) {
                schemaEl = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SCHEMA, Keywords.XSDNS); 
                WriteSchemaRoot(_dc, schemaEl, NamespaceURI);
                if (!Common.ADP.IsEmpty(NamespaceURI)) { 
                    string prefix = Keywords.APP+Convert.ToString(++prefixCount, CultureInfo.InvariantCulture); 
                    _sRoot.SetAttribute("xmlns:"+prefix, NamespaceURI);
                    schemaEl.SetAttribute("xmlns:"+prefix, NamespaceURI); 
                    prefixes[NamespaceURI] = prefix;
                }
                namespaces[NamespaceURI] = schemaEl;
            } 
            return schemaEl;
        } 
 
        internal void HandleColumnType(DataColumn col, XmlDocument dc, XmlElement root, XmlElement schema) {
            string keyword = Keywords.TYPE; 
            if (col.ColumnMapping == MappingType.SimpleContent)
                keyword = Keywords.BASE;

            if (col.SimpleType != null) { 
                // generate simpleType node
                SimpleType stNode = col.SimpleType; 
 
                while (stNode != null) {
                    // for remoting, set the msdata:targetNamespace for the simpleType. 
                    XmlNode type;
                    string name = stNode.Name;

                    if (name != null && name.Length != 0) { 
                        // For remoting, always need to work with root schema's namespace
                        string nSpace = (schFormat != SchemaFormat.Remoting) ? stNode.Namespace : 
                                                   (col.Table.DataSet != null ? col.Table.DataSet.Namespace : col.Table.Namespace); 

                        // for remoting we need to use columns NS, for other cases it is wrong to get Columns NS, we need to take type's namespace 
                        XmlElement schNode= GetSchema(nSpace);

                        //SchNode To Ensure BaseSimpleType Prefix is Generated
                        if (stNode.BaseSimpleType != null && stNode.BaseSimpleType.Namespace != null &&  stNode.BaseSimpleType.Namespace.Length>0) 
                            GetSchema(stNode.BaseSimpleType.Namespace); //it will ensure a prefix has been created for this namespace
 
                        type = stNode.ToNode(dc, prefixes, (schFormat == SchemaFormat.Remoting)); 

                        if (stNode == col.SimpleType) { 
                            string prefix = (string) prefixes[nSpace];
                            // set the columns's type
                            if (prefix != null && prefix.Length > 0) {
                                if (schFormat != SchemaFormat.Remoting) 
                                    root.SetAttribute(keyword,(prefix + ":" + name)); // look at below,this loop assumes we would be here just oen time: Its Wrong
                                else // As all types (in remoting) belong to the same namespace, just write type name 
                                    root.SetAttribute(keyword, name); 
                            }
                            else 
                                root.SetAttribute(keyword, name);
                        // set the root to the actual type, do not overwrite it in the iteration.
                        }
 
                        XmlElement elmSimpeType = FindSimpleType(schNode, name);
                        if(elmSimpeType == null) { 
                            // if we don't have the defenition for this simpleType yet. Add it 
                            schNode.AppendChild(type);
                        }else { 
    #if DEBUG
    // [....]: TO DO: replace the constructor with IsEqual(XmlElement)
    //                        Debug.Assert(col.SimpleType.IsEqual(new SimpleType(elmSimpeType)), "simpleTypes with the same name have to be the same: "+name);
    #endif 
                        }
                    } 
                    else { 
                        //SchNode To Ensure BaseSimpleType Prefix is Generated
                        if (stNode.BaseSimpleType != null && stNode.BaseSimpleType.Namespace != null &&  stNode.BaseSimpleType.Namespace.Length>0) 
                            GetSchema(stNode.BaseSimpleType.Namespace); //it will ensure a prefix has been created for this namespace
                        type = stNode.ToNode(dc, prefixes, schFormat == SchemaFormat.Remoting);
                        root.AppendChild(type);
                    } 

                    stNode = stNode.BaseSimpleType; 
                } 
            }
            else if (col.XmlDataType != null && col.XmlDataType.Length != 0 && XSDSchema.IsXsdType(col.XmlDataType)) { 
                root.SetAttribute(keyword, XSDSchema.QualifiedName(col.XmlDataType));
            }
            else {
                string typeName = XmlDataTypeName(col.DataType); // do not update the hashtable, as it will not write msdata:DataType 
                if (typeName == null || typeName.Length == 0) {
                    if (col.DataType == typeof(Guid) || col.DataType == typeof(Type) ) { 
                        typeName = "string"; 
                    }
                    else { 
                        if (col.ColumnMapping == MappingType.Attribute) {
                            XmlTreeGen.ValidateColumnMapping(col.DataType);
                        }
                        typeName = Keywords.XSD_ANYTYPE; 
                    }
                } 
                root.SetAttribute(keyword, XSDSchema.QualifiedName(typeName)); 
            }
 
        }

        internal void AddColumnProperties(DataColumn col, XmlElement root){
 
            if (col.DataType != typeof(String)) {
                string dt = XmlDataTypeName(col.DataType); 
                if ((col.IsSqlType && ((dt.Length == 0) || col.ImplementsINullable)) || (typeof(SqlXml) == col.DataType)) { // no need to check if it is Sql typee if it already implements INullable, 
                    root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, col.DataType.FullName);
                } 
                else if ((dt.Length == 0) || col.ImplementsINullable || ((dt == Keywords.XSD_ANYTYPE) && (col.XmlDataType != Keywords.XSD_ANYTYPE))) {
                    // in Whidbey, XmlDataTypeName function changed to return "anyType" for typeof(Object)
                    // should still always hit this code path for all non-built in types
                    // to handle version qualified typeof(Object) and other CDT objects correctly 

                    // we must write the output exactly the same way as we read it 
                    root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, col.DataType.AssemblyQualifiedName); 
                }
            } 

            if (col.ReadOnly)
                root.SetAttribute("ReadOnly", Keywords.MSDNS, Keywords.TRUE);
 
            if (col.Expression.Length != 0)
                root.SetAttribute("Expression", Keywords.MSDNS, col.Expression); 
 
            if (col.AutoIncrement) {
                root.SetAttribute("AutoIncrement", Keywords.MSDNS, Keywords.TRUE); 
            }

            if (col.AutoIncrementSeed !=0 )
                root.SetAttribute("AutoIncrementSeed", Keywords.MSDNS, col.AutoIncrementSeed.ToString(CultureInfo.InvariantCulture)); 

            if (col.AutoIncrementStep !=1 ) 
                root.SetAttribute("AutoIncrementStep", Keywords.MSDNS, col.AutoIncrementStep.ToString(CultureInfo.InvariantCulture)); 

            if (col.Caption != col.ColumnName) 
                root.SetAttribute("Caption", Keywords.MSDNS, col.Caption);

            if (col.Prefix.Length != 0)
                root.SetAttribute("Prefix", Keywords.MSDNS, col.Prefix); 

            if (col.DataType == typeof(DateTime) && col.DateTimeMode != DataSetDateTime.UnspecifiedLocal) { 
                root.SetAttribute("DateTimeMode", Keywords.MSDNS, col.DateTimeMode.ToString()); 
            }
 
        }

        private string FindTargetNamespace(DataTable table) {
            string tgNamespace = table.TypeName.IsEmpty ? table.Namespace : table.TypeName.Namespace; 
            if (Common.ADP.IsEmpty(tgNamespace)) {
                DataRelation [] nestedParentRelations = table.NestedParentRelations; 
                if (nestedParentRelations.Length != 0) { 
                    for(int i = 0; i < nestedParentRelations.Length; i++) {
                        DataTable parentTable = nestedParentRelations[i].ParentTable; 
                        if (table != parentTable) {// table can be self nested so it may go to infinite loop!
                            tgNamespace = FindTargetNamespace(parentTable);
                            if (!Common.ADP.IsEmpty(tgNamespace)) {
                                break; 
                            }
                        } 
                    } 
                }
                else { // if it does not have any parent table , then it should inherit NS from DataSet 
                    tgNamespace = _ds.Namespace;
                }
            }
            return tgNamespace; 
        }
 
        internal XmlElement HandleColumn(DataColumn col, XmlDocument dc, XmlElement schema, bool fWriteOrdinal) { 
            XmlElement  root;
            int         minOccurs; 

            Debug.Assert(col.ColumnMapping != MappingType.SimpleContent , "Illegal state");

            String refString = (col.ColumnMapping != MappingType.Element) ? Keywords.XSD_ATTRIBUTE : Keywords.XSD_ELEMENT; 
            root = dc.CreateElement(Keywords.XSD_PREFIX, refString, Keywords.XSDNS);
 
            // First add any attributes. 
            root.SetAttribute( Keywords.NAME, col.EncodedColumnName);
 
            if (col.Namespace.Length == 0) {
                DataTable _table = col.Table;
                // We need to travese the hirerarchy to find the targetnamepace
                string tgNamespace = FindTargetNamespace(_table); 
                if (col.Namespace != tgNamespace) {
                    root.SetAttribute( Keywords.FORM, Keywords.UNQUALIFIED); 
                } 
            }
 
            if (col.GetType() != typeof(DataColumn))
                AddXdoProperties(col, root, dc);
            else
                AddColumnProperties(col, root); 

 
            AddExtendedProperties(col.extendedProperties, root); 
            HandleColumnType(col, dc, root, schema);
            if (col.ColumnMapping == MappingType.Hidden) { // CDT / UDT can not be mapped to Hidden column 
                if (!col.AllowDBNull)
                    root.SetAttribute(Keywords.MSD_ALLOWDBNULL, Keywords.MSDNS, Keywords.FALSE);

                if (!col.DefaultValueIsNull) 
                    if (col.DataType == typeof(bool))
                        root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, (bool)(col.DefaultValue)? Keywords.TRUE : Keywords.FALSE); 
                    else 
                    {
                    XmlTreeGen.ValidateColumnMapping(col.DataType); 
                    root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, col.ConvertObjectToXml(col.DefaultValue));
                    }
            }
 

            if ((!col.DefaultValueIsNull)&& (col.ColumnMapping != MappingType.Hidden)){ 
                XmlTreeGen.ValidateColumnMapping(col.DataType); 
                if (col.ColumnMapping == MappingType.Attribute && !col.AllowDBNull ) {
                    if (col.DataType == typeof(bool)) { 
                        root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, (bool)(col.DefaultValue)? Keywords.TRUE : Keywords.FALSE);
                    }
                    else { // CDT / UDT columns cn not be mapped to Attribute also
                        root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, col.ConvertObjectToXml(col.DefaultValue)); 
                    }
                } 
                else { // Element Column : need to handle CDT 
                    if (col.DataType == typeof(bool)) {
                        root.SetAttribute(Keywords.DEFAULT, (bool)(col.DefaultValue)? Keywords.TRUE : Keywords.FALSE); 
                    }
                    else {
                        if (!col.IsCustomType) { // built in type
                            root.SetAttribute(Keywords.DEFAULT, col.ConvertObjectToXml(col.DefaultValue)); 
                        }
                        else { // UDT column 
                        } 
                    }
                } 
            }

            if (schFormat == SchemaFormat.Remoting)
                root.SetAttribute( Keywords.TARGETNAMESPACE, Keywords.MSDNS, col.Namespace); 

            else { 
 
                if ((col.Namespace != (col.Table.TypeName.IsEmpty ? col.Table.Namespace : col.Table.TypeName.Namespace)) && (col.Namespace.Length != 0))
             { 
                        XmlElement schNode = GetSchema(col.Namespace);
                        if (FindTypeNode(schNode, col.EncodedColumnName) == null)
                            schNode.AppendChild(root);
                        root = _dc.CreateElement(Keywords.XSD_PREFIX, refString, Keywords.XSDNS); 
                        root.SetAttribute( Keywords.REF, prefixes[ col.Namespace]+":"+ col.EncodedColumnName);
                        if (col.Table.Namespace!=_ds.Namespace) { 
                            string prefix = (string)prefixes[col.Namespace]; 
                            XmlElement tNode = GetSchema(col.Table.Namespace);
                    } 
                    }
                }

 
            minOccurs = (col.AllowDBNull) ? 0 : 1;
 
 
            // March 2001 change
            if (col.ColumnMapping == MappingType.Attribute && minOccurs != 0) 
                root.SetAttribute(Keywords.USE, Keywords.REQUIRED);


            if (col.ColumnMapping == MappingType.Hidden) { 
                root.SetAttribute(Keywords.USE, Keywords.PROHIBITED);
            } 
            else 
                if (col.ColumnMapping != MappingType.Attribute && minOccurs != 1)
                    root.SetAttribute(Keywords.MINOCCURS, minOccurs.ToString(CultureInfo.InvariantCulture)); 

            if ((col.ColumnMapping == MappingType.Element) && fWriteOrdinal)
                root.SetAttribute(Keywords.MSD_ORDINAL,Keywords.MSDNS, col.Ordinal.ToString(CultureInfo.InvariantCulture));
 
            return root;
        } 
 

        internal static string TranslateAcceptRejectRule( AcceptRejectRule rule ) { 
            switch (rule) {
                case AcceptRejectRule.Cascade:  return "Cascade";
                case AcceptRejectRule.None:     return "None";
                default:                        return null; 
            }
        } 
 
        internal static string TranslateRule( Rule rule ) {
            switch (rule) { 
                case Rule.Cascade:  return "Cascade";
                case Rule.None:     return "None";
                case Rule.SetNull:  return "SetNull";
                case Rule.SetDefault: return "SetDefault"; 
                default: return null;
            } 
        } 

        internal void AppendChildWithoutRef(XmlElement node, string Namespace, XmlElement el, string refString) { 
            XmlElement schNode = GetSchema(Namespace);
            if (FindTypeNode(schNode, el.GetAttribute(Keywords.NAME)) == null)
                schNode.AppendChild(el);
        } 

        internal XmlElement FindTypeNode(XmlElement node, string strType) { 
            if (node == null) 
                return null;
 
            for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) {
                if (!(n is XmlElement))
                    continue;
 
                XmlElement child = (XmlElement) n;
 
                if (XSDSchema.FEqualIdentity(child, Keywords.XSD_ELEMENT, Keywords.XSDNS) || 
                    XSDSchema.FEqualIdentity(child, Keywords.XSD_ATTRIBUTE, Keywords.XSDNS) ||
                    XSDSchema.FEqualIdentity(child, Keywords.XSD_COMPLEXTYPE, Keywords.XSDNS) || 
                    XSDSchema.FEqualIdentity(child, Keywords.XSD_SIMPLETYPE, Keywords.XSDNS)) {
                    if (child.GetAttribute(Keywords.NAME) == strType)
                        return child;
                } 
            }
            return null; 
        } 

        internal XmlElement HandleTable(DataTable table, XmlDocument dc, XmlElement schema) { 
            return HandleTable(table, dc, schema, true);
        }

        // we write out column Ordinals only if the table contains columns 
        // that map both to Attributes and Elements
 
        private bool HasMixedColumns(DataTable table) { 
            bool hasAttributes = false;
            bool hasElements = false; 
            foreach(DataColumn col in table.Columns) {
                if (!hasElements && col.ColumnMapping == MappingType.Element)
                    hasElements = true;
                if (!hasAttributes && (col.ColumnMapping == MappingType.Attribute || col.ColumnMapping == MappingType.Hidden)) 
                    hasAttributes = !AutoGenerated(col);
                if (hasAttributes && hasElements) 
                    return true; 
            }
            return false; 
        }

        internal static  bool AutoGenerated(DataColumn col) {
            // for now we use just this simple logic for the columns. 

            if (col.ColumnMapping != MappingType.Hidden) 
                return false; 

            if (col.DataType != typeof(int)) 
                return false;

            string generatedname = col.Table.TableName+"_Id";
 
            if ((col.ColumnName == generatedname) || (col.ColumnName == generatedname+"_0"))
                return true; 
 
            generatedname = "";
 
            foreach (DataRelation rel in col.Table.ParentRelations) {
                if (!rel.Nested)
                    continue;
                if (rel.ChildColumnsReference.Length != 1) 
                    continue;
 
                if (rel.ChildColumnsReference[0] != col) 
                    continue;
 
                if (rel.ParentColumnsReference.Length != 1)
                    continue;

                //ok if we are here it means that we have a 1column-1column relation 
                generatedname = rel.ParentColumnsReference[0].Table.TableName+"_Id";
            } 
 
            if ((col.ColumnName == generatedname) || (col.ColumnName == generatedname+"_0"))
                return true; 

            return false;
        }
        internal static  bool AutoGenerated(DataRelation rel) { 
            string rName = rel.ParentTable.TableName + "_" + rel.ChildTable.TableName;
            if (!rel.RelationName.StartsWith(rName, StringComparison.Ordinal)) 
                return false; 
            if (rel.ExtendedProperties.Count > 0)
                return false; 
            return true;
        }
        internal static  bool AutoGenerated(UniqueConstraint unique) {
            // for now we use just this simple logic for the columns. 
            if (!unique.ConstraintName.StartsWith("Constraint", StringComparison.Ordinal))
                return false; 
            if (unique.Key.ColumnsReference.Length !=1) 
                return false;
            if (unique.ExtendedProperties.Count > 0) 
                return false;
            return AutoGenerated(unique.Key.ColumnsReference[0]);
        }
 
        private bool AutoGenerated(ForeignKeyConstraint fk) {
            return AutoGenerated(fk, true); 
        } 

        internal static  bool AutoGenerated(ForeignKeyConstraint fk, bool checkRelation) { 
            // for now we use just this simple logic for the columns.
            DataRelation rel = fk.FindParentRelation();
            if (checkRelation) {
                if (rel == null) 
                     return false; // otherwise roundtrip will create column
 
 		if (!AutoGenerated(rel)) 
                    return false;
 
                if (rel.RelationName != fk.ConstraintName)
                    return false;
            }
 
            if (fk.ExtendedProperties.Count > 0)
                return false; 
 

            if (fk.AcceptRejectRule != AcceptRejectRule.None) 
                return false;
            if (fk.DeleteRule != Rule.Cascade)
                return false;
            if (fk.DeleteRule != Rule.Cascade) 
                return false;
 
 
            if (fk.RelatedColumnsReference.Length !=1)
                return false; 
            return AutoGenerated(fk.RelatedColumnsReference[0]);
        }

        private bool IsAutoGenerated(object o) { 
            if (schFormat != SchemaFormat.Remoting)
                return autogenerated[o]!=null; 
            return false; 
        }
 
        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) { // o-ho 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;
        }
    }
 

 
 internal sealed class NewDiffgramGen { 
        internal XmlDocument    _doc;
        internal DataSet        _ds; 
        internal DataTable      _dt;
        internal XmlWriter     _xmlw;
        private bool fBefore = false;
        private bool fErrors = false; 
        internal Hashtable rowsOrder = null;
        ArrayList _tables = new ArrayList(); 
        bool _writeHierarchy = false; 

 
        internal NewDiffgramGen(DataSet ds) {
            _ds = ds;
            _dt = null;
            _doc = new XmlDocument(); 

            for (int i = 0; i < ds.Tables.Count; i++) { 
                _tables.Add(ds.Tables[i]); 
            }
            DoAssignments(_tables); 
        }

        internal NewDiffgramGen(DataTable dt, bool writeHierarchy) {
            _ds = null; 
            _dt = dt;
            _doc = new XmlDocument(); 
            _tables.Add(dt); 
            if (writeHierarchy) {
                this._writeHierarchy = true; 
                CreateTableHierarchy(dt);
            }

            DoAssignments(_tables); 
        }
 
        private void CreateTableHierarchy(DataTable dt) { 
//            if (!dt.SerializeHierarchy)
//                return; 
            foreach( DataRelation r in dt.ChildRelations ) {
                if (! _tables.Contains((DataTable)r.ChildTable)) {
                    _tables.Add((DataTable)r.ChildTable);
                    CreateTableHierarchy(r.ChildTable); 
                }
            } 
        } 

 
        private void DoAssignments(ArrayList tables) {

            int rows = 0;
            for (int i = 0; i < tables.Count; i++) { 
                rows += ((DataTable)tables[i]).Rows.Count ;
            } 
            rowsOrder = new Hashtable(rows); 
            for (int i = 0; i < tables.Count; i++) {
                DataTable dt = (DataTable)tables[i]; 
                DataRowCollection rc = dt.Rows;
                rows = rc.Count ;
                for (int j=0; j 0)
                    return false;
            }
            return true; 
        }
 
        internal void Save(XmlWriter xmlw) { 
            Save (xmlw, null);
    } 

        internal void Save(XmlWriter xmlw, DataTable table) {
            _xmlw = DataTextWriter.CreateWriter(xmlw);
 
            _xmlw.WriteStartElement(Keywords.DFF, Keywords.DIFFGRAM,  Keywords.DFFNS);
            _xmlw.WriteAttributeString(Keywords.XMLNS, Keywords.MSD, null, Keywords.MSDNS); 
//            _xmlw.WriteAttributeString(Keywords.XMLNS, Keywords.UPDG, null, Keywords.UPDGNS); 

            if (! EmptyData()) { 
                // write the datapart
                if (table != null)
                    new XmlDataTreeWriter(table, this._writeHierarchy).SaveDiffgramData(_xmlw, rowsOrder);
                else 
                    new XmlDataTreeWriter(_ds).SaveDiffgramData(_xmlw, rowsOrder);
 
                // Walk the xd using relational apis and create nodes in nodeRoot appropriately. 

                if (table==null) { 
                    for (int i = 0; i < _ds.Tables.Count; ++i) {
                        GenerateTable(_ds.Tables[i]);
                    }
                } 
                else {
                    for(int i = 0; i < _tables.Count; i++) { 
                        GenerateTable((DataTable)_tables[i]); 
                    }
                } 

                if (fBefore)
                    _xmlw.WriteEndElement();  //SQL_BEFORE
 
                if (table==null) {
                    for (int i = 0; i < _ds.Tables.Count; ++i) { 
                        GenerateTableErrors(_ds.Tables[i]); 
                    }
                } 
                else {
                    for(int i = 0; i < _tables.Count; i++) {
                        GenerateTableErrors((DataTable)_tables[i]);
                    } 
                }
 
                if (fErrors) 
                    _xmlw.WriteEndElement();  //ERRORS
            } 

            _xmlw.WriteEndElement();
            _xmlw.Flush();
        } 

        private void GenerateTable(DataTable table) { 
            int rowCount = table.Rows.Count; 

            if (rowCount <= 0) 
                return;

            for (int rowNum = 0; rowNum < rowCount; ++rowNum)
                GenerateRow(table.Rows[rowNum]); 
        }
 
 
        private void GenerateTableErrors(DataTable table) {
            int rowCount = table.Rows.Count; 
            int colCount = table.Columns.Count;

            if (rowCount <= 0)
                return; 

            for (int rowNum = 0; rowNum < rowCount; ++rowNum) { 
                bool tableName = false; 

                DataRow row = table.Rows[rowNum]; 
                string prefix = (table.Namespace.Length != 0) ? table.Prefix : String.Empty;
                if ((row.HasErrors) && (row.RowError.Length > 0)) {
                    if (!fErrors) {
                        _xmlw.WriteStartElement( Keywords.DFF, Keywords.MSD_ERRORS, Keywords.DFFNS ); 
                        fErrors = true;
                    } 
                    _xmlw.WriteStartElement( prefix, row.Table.EncodedTableName, row.Table.Namespace); 
                    _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, row.Table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture));
                    _xmlw.WriteAttributeString( Keywords.DFF, Keywords.MSD_ERROR, Keywords.DFFNS, row.RowError); 
                    tableName = true;
                }
                if (colCount <=0)
                    continue; 
                for (int colNum = 0; colNum < colCount; ++colNum) {
                    DataColumn column = table.Columns[colNum]; 
                    string error = row.GetColumnError(column); 
                    string columnPrefix = (column.Namespace.Length != 0) ? column.Prefix : String.Empty;
                    if (error == null || error.Length == 0) { 
                        continue;
                    }

                    if (!tableName) { 
                        if (!fErrors) {
                            _xmlw.WriteStartElement( Keywords.DFF, Keywords.MSD_ERRORS, Keywords.DFFNS ); 
                            fErrors = true; 
                        }
 
                        _xmlw.WriteStartElement( prefix, row.Table.EncodedTableName, row.Table.Namespace);
                        _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, row.Table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture));
                        tableName = true;
 
                    }
 
 
                    _xmlw.WriteStartElement( columnPrefix, column.EncodedColumnName, column.Namespace);
                    _xmlw.WriteAttributeString( Keywords.DFF, Keywords.MSD_ERROR, Keywords.DFFNS, error); 

                    _xmlw.WriteEndElement();

 
                }
 
                if(tableName) 
                    _xmlw.WriteEndElement();
            } 
        }

        private void GenerateRow(DataRow row) {
            DataRowState state = row.RowState; 
            if ((state == DataRowState.Unchanged ) || (state  == DataRowState.Added)) {
                return; 
            } 
            if (!fBefore) {
                _xmlw.WriteStartElement( Keywords.DFF, Keywords.SQL_BEFORE, Keywords.DFFNS); 
                fBefore = true;
            }

            DataTable table = row.Table; 
            int colCount = table.Columns.Count;
            string rowIDString = table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture); 
            string parentId = null; 
            if ( (state == DataRowState.Deleted )  && (row.Table.NestedParentRelations.Length != 0)){
                DataRow parentRow = row.GetNestedParentRow(DataRowVersion.Original); 
                if (parentRow != null) {
                    parentId = parentRow.Table.TableName+parentRow.rowID.ToString(CultureInfo.InvariantCulture);
                }
            } 

 
            string tablePrefix = (table.Namespace.Length != 0) ? table.Prefix : String.Empty; 

            // read value if the TextOnly column (if any) 
            object val = (table.XmlText == null ? DBNull.Value : row[table.XmlText, DataRowVersion.Original]);

                    //old row
            _xmlw.WriteStartElement( tablePrefix, row.Table.EncodedTableName, row.Table.Namespace); 

            _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, rowIDString); 
 
            if ( (state == DataRowState.Deleted ) && XmlDataTreeWriter.RowHasErrors(row))
                _xmlw.WriteAttributeString( Keywords.DFF, Keywords.HASERRORS, Keywords.DFFNS, Keywords.TRUE); 

            if (parentId != null)
                _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFPID, Keywords.DFFNS, parentId);
 
            _xmlw.WriteAttributeString( Keywords.MSD, Keywords.ROWORDER, Keywords.MSDNS, rowsOrder[row].ToString());
            for (int colNum = 0; colNum < colCount; ++colNum) { 
                if ((row.Table.Columns[colNum].ColumnMapping == MappingType.Attribute) || 
                    (row.Table.Columns[colNum].ColumnMapping == MappingType.Hidden))
                GenerateColumn(row,  row.Table.Columns[colNum], DataRowVersion.Original); 
            }
            for (int colNum = 0; colNum < colCount; ++colNum) {
                if ((row.Table.Columns[colNum].ColumnMapping == MappingType.Element) ||
                    (row.Table.Columns[colNum].ColumnMapping == MappingType.SimpleContent)) 
                GenerateColumn(row,  row.Table.Columns[colNum], DataRowVersion.Original);
            } 
            _xmlw.WriteEndElement();  //old row 
        }
 
        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, valuesType.AssemblyQualifiedName); 
                                }
                                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;
                } 
        }
 
        internal static string QualifiedName(string prefix, string name) { 
            if (prefix != null)
                return prefix + ":" + name; 

            return name;
        }
    } 

    // DataTreeWriter 
    internal sealed class XmlDataTreeWriter { 
        XmlWriter _xmlw;
 
        DataSet _ds = null;
        DataTable _dt=null;

        ArrayList _dTables = new ArrayList(); 
        DataTable [] topLevelTables;
 
        bool    fFromTable = false; // also means no hierarchy 
        bool    isDiffgram = false;
        Hashtable rowsOrder = null; 
        bool _writeHierarchy = false;


 
        internal XmlDataTreeWriter(DataSet ds) {
            _ds = ds; 
            topLevelTables = ds.TopLevelTables(); 
            foreach(DataTable table in ds.Tables) {
                _dTables.Add(table); 
            }
        }

        internal XmlDataTreeWriter(DataSet ds, DataTable dt) { // need to modify this also 
            _ds = ds;
            _dt = dt; 
 
            _dTables.Add(dt);
            topLevelTables = ds.TopLevelTables(); 
        }

        internal XmlDataTreeWriter(DataTable dt, bool writeHierarchy) {
          _dt = dt; 
          fFromTable = true;
          if (dt.DataSet == null) { 
            _dTables.Add(dt); 
            topLevelTables = new DataTable[] {dt};
          } 
          else {
            _ds = dt.DataSet;
            _dTables.Add(dt);
            if (writeHierarchy) { 
                this._writeHierarchy = true;
                CreateTablesHierarchy(dt); 
                topLevelTables = CreateToplevelTables(); 
            }
            else // if no hierarchy , top level table should be dt 
                topLevelTables = new DataTable[] {dt};
          }
        }
 
        private DataTable[] CreateToplevelTables() {
            ArrayList topTables = new ArrayList(); 
            for (int i = 0; i < _dTables.Count; i++) { 
                DataTable table =(DataTable) _dTables[i];
                if (table.ParentRelations.Count == 0) 
                    topTables.Add(table);
                else {
                    bool fNestedButNotSelfNested = false;
                    for (int j = 0; j < table.ParentRelations.Count; j++) { 
                        if (table.ParentRelations[j].Nested) {
                            if (table.ParentRelations[j].ParentTable == table) { 
                                fNestedButNotSelfNested = false; 
                                break;
                            } 
                            fNestedButNotSelfNested = true;
                        }
                    }
                    if (!fNestedButNotSelfNested) 
                        topTables.Add(table);
                } 
            } 
            if (topTables.Count == 0)
                return (new DataTable[0]); 
            DataTable[] temp = new DataTable[topTables.Count];
            topTables.CopyTo(temp, 0);
            return temp;
        } 

        private void CreateTablesHierarchy(DataTable dt) { 
//            if (!dt.SerializeHierarchy) 
//                return;
            foreach( DataRelation r in dt.ChildRelations ) { 
                if (! _dTables.Contains((DataTable)r.ChildTable)) {
                    _dTables.Add((DataTable)r.ChildTable);
                    CreateTablesHierarchy(r.ChildTable)     ;
                } 
            }
        } 
 
        internal static bool RowHasErrors(DataRow row) {
          int colCount = row.Table.Columns.Count; 

                if ((row.HasErrors) && (row.RowError.Length > 0))
            return true;
 
            for (int colNum = 0; colNum < colCount; ++colNum) {
                      DataColumn column = row.Table.Columns[colNum]; 
                      string error = row.GetColumnError(column); 
                      if (error == null || error.Length == 0) {
                          continue; 
                      }
              return true;
            }
 
          return false;
        } 
 
        // the following line writes the data part
        // for the new diffgram format 

        internal void SaveDiffgramData(XmlWriter xw, Hashtable rowsOrder) {
            _xmlw = DataTextWriter.CreateWriter(xw);
            isDiffgram = true; 
            this.rowsOrder = rowsOrder;
 
            int countTopTable = topLevelTables.Length; 

            string prefix = (_ds!= null)?(( _ds.Namespace.Length == 0 )? "" : _ds.Prefix):(( _dt.Namespace.Length == 0 )? "" : _dt.Prefix); 

            if (_ds == null || _ds.DataSetName == null || _ds.DataSetName.Length == 0)
                _xmlw.WriteStartElement(prefix, Keywords.DOCUMENTELEMENT, ( _dt.Namespace == null) ? "":_dt.Namespace);
            else 
                _xmlw.WriteStartElement(prefix, XmlConvert.EncodeLocalName(_ds.DataSetName), _ds.Namespace);
 
            // new XmlTreeGen(true).Save(_ds,_xmlw, false /* we don't care since we specified it's serialized */); 

                for(int i = 0; i < _dTables.Count ; i++) { 
                    DataTable tempTable = ((DataTable)_dTables[i]);
                    foreach (DataRow row in tempTable.Rows) {
                        if (row.RowState == DataRowState.Deleted)
                            continue; 
                        int nestedParentRowCount = row.GetNestedParentCount();
                        if (nestedParentRowCount == 0) { 
                            DataTable tempDT = ((DataTable)_dTables[i]); 
                            XmlDataRowWriter(row,tempDT.EncodedTableName);
                        } 
                        else if (nestedParentRowCount > 1){
                            throw ExceptionBuilder.MultipleParentRows(tempTable.Namespace.Length == 0 ? tempTable.TableName:tempTable.Namespace + tempTable.TableName);
                            // At all times a nested row can only have 0 or 1 parents, never more than 1
                        } 
                    }
                } 
 
            _xmlw.WriteEndElement();
            _xmlw.Flush(); 

        }

 
        internal void Save(XmlWriter xw, bool writeSchema) {
            _xmlw = DataTextWriter.CreateWriter(xw); 
 
            int countTopTable = topLevelTables.Length;
            bool fWriteDSElement = true; 

            string prefix = (_ds!= null)?(( _ds.Namespace.Length == 0 )? "" : _ds.Prefix):(( _dt.Namespace.Length == 0 )? "" : _dt.Prefix);

            if (!writeSchema && _ds != null && _ds.fTopLevelTable && countTopTable == 1) { 
                if (_ds.TopLevelTables()[0].Rows.Count == 1)
                    fWriteDSElement = false; 
            } 

            if (fWriteDSElement) { 

                  if (_ds == null) {
                      _xmlw.WriteStartElement(prefix, Keywords.DOCUMENTELEMENT, _dt.Namespace);
                  } 
                  else {
                    if (_ds.DataSetName == null || _ds.DataSetName.Length == 0) 
                        _xmlw.WriteStartElement(prefix, Keywords.DOCUMENTELEMENT, _ds.Namespace); 
                    else
                        _xmlw.WriteStartElement(prefix, XmlConvert.EncodeLocalName(_ds.DataSetName), _ds.Namespace); 
                  }

                for(int i = 0; i < _dTables.Count ; i++) {
                    if (((DataTable)_dTables[i]).xmlText != null) { 
                        _xmlw.WriteAttributeString(Keywords.XMLNS, Keywords.XSI, Keywords.XSD_XMLNS_NS, Keywords.XSINS);
                        break; 
                    } 
                }
 
                if (writeSchema) {
                    if (!fFromTable) {
                        new XmlTreeGen(SchemaFormat.Public).Save(_ds,_xmlw);
                    } 
                    else {
                        new XmlTreeGen(SchemaFormat.Public).Save( null, _dt, _xmlw, this._writeHierarchy); 
                    } 
                }
            } 

            for(int i = 0; i < _dTables.Count ; i++) {
                foreach (DataRow row in ((DataTable)_dTables[i]).Rows) {
                    if (row.RowState == DataRowState.Deleted) 
                        continue;
                    int parentRowCount = row.GetNestedParentCount(); 
                    if (parentRowCount == 0) { 
                        XmlDataRowWriter(row, ((DataTable)_dTables[i]).EncodedTableName);
                    } 
                    else if (parentRowCount > 1) {
                        DataTable dt = (DataTable)_dTables[i];
                        throw ExceptionBuilder.MultipleParentRows(dt.Namespace.Length == 0 ? dt.TableName : (dt.Namespace + dt.TableName));
                        // At all times a nested row can only have 0 or 1 parents, never more than 1 
                    }
                } 
            } 

            if (fWriteDSElement) 
                _xmlw.WriteEndElement();
            _xmlw.Flush();
        }
 
        private ArrayList GetNestedChildRelations(DataRow row) {
            ArrayList list = new ArrayList(); 
 
            foreach( DataRelation r in row.Table.ChildRelations ) {
                if (r.Nested) 
                    list.Add(r);
            }

            return list; 
        }
 
 
        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, valuesType.AssemblyQualifiedName);
                                } 
                                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) { 
            Debug.Assert(value != null, "Value can not be null"); 
            string tempValue = value.ToString();
            if (tempValue.Length == 0) { 
                return false;
            }
            for(int i =0; i < tempValue.Length; i++) {
                if (!Char.IsWhiteSpace(tempValue, i)) { 
                    return false;
                } 
            } 
            return true;
        } 
    }

    internal sealed class DataTextWriter : XmlWriter {
        private XmlWriter _xmltextWriter; 

        internal static XmlWriter CreateWriter(XmlWriter xw) { 
            return new DataTextWriter(xw); 
        }
 
        private DataTextWriter(XmlWriter w) {
            _xmltextWriter = w;
        }
 
        internal Stream BaseStream  {
            get { 
                XmlTextWriter textWriter = _xmltextWriter as XmlTextWriter; 
                if (null != textWriter) {
                    return textWriter.BaseStream; 
                }
                return null;
            }
        } 

        public override void WriteStartDocument() { 
            _xmltextWriter.WriteStartDocument(); 
        }
 
        public override void WriteStartDocument(bool standalone) {
            _xmltextWriter.WriteStartDocument(standalone);
        }
 
        public override void WriteEndDocument() {
            _xmltextWriter.WriteEndDocument(); 
        } 

        public override void WriteDocType(string name, string pubid, string sysid, string subset) { 
            _xmltextWriter.WriteDocType(name, pubid, sysid, subset);
        }

        public override void WriteStartElement(string prefix, string localName, string ns) { 
            _xmltextWriter.WriteStartElement(prefix, localName, ns);
        } 
 
        public override void WriteEndElement() {
            _xmltextWriter.WriteEndElement(); 
        }

        public override  void WriteFullEndElement() {
            _xmltextWriter.WriteFullEndElement(); 
        }
 
        public override  void WriteStartAttribute(string prefix, string localName, string ns) { 
            _xmltextWriter.WriteStartAttribute(prefix, localName, ns);
        } 

        public override void WriteEndAttribute() {
            _xmltextWriter.WriteEndAttribute();
        } 

        public override void WriteCData(string text) { 
            _xmltextWriter.WriteCData(text); 
        }
 
        public override void WriteComment(string text) {
            _xmltextWriter.WriteComment(text);
        }
 
        public override void WriteProcessingInstruction(string name, string text) {
            _xmltextWriter.WriteProcessingInstruction(name, text); 
        } 

        public override void WriteEntityRef(string name) { 
            _xmltextWriter.WriteEntityRef(name);
        }

        public override void WriteCharEntity(char ch) { 
            _xmltextWriter.WriteCharEntity(ch);
        } 
 
        public override void WriteWhitespace(string ws) {
            _xmltextWriter.WriteWhitespace(ws); 
        }

        public override void WriteString(string text) {
            _xmltextWriter.WriteString(text); 
        }
 
        public override void WriteSurrogateCharEntity(char lowChar, char highChar){ 
            _xmltextWriter.WriteSurrogateCharEntity(lowChar, highChar);
        } 

        public override void WriteChars(Char[] buffer, int index, int count) {
            _xmltextWriter.WriteChars(buffer, index, count);
        } 

        public override void WriteRaw(Char[] buffer, int index, int count) { 
            _xmltextWriter.WriteRaw(buffer, index, count); 
        }
 
        public override void WriteRaw(String data) {
            _xmltextWriter.WriteRaw(data);
        }
 
        public override void WriteBase64(byte[] buffer, int index, int count) {
            _xmltextWriter.WriteBase64(buffer, index, count); 
        } 

        public override void WriteBinHex( byte[] buffer, int index, int count ) { 
            _xmltextWriter.WriteBinHex(buffer, index, count);
        }

        public override WriteState WriteState { 
            get {
                return _xmltextWriter.WriteState; 
            } 
        }
 
        public override void Close() {
            _xmltextWriter.Close();
        }
 
        public override void Flush() {
            _xmltextWriter.Flush(); 
        } 

        public override void WriteName(string name) { 
            _xmltextWriter.WriteName(name);
        }

        public override void WriteQualifiedName(string localName, string ns) { 
            _xmltextWriter.WriteQualifiedName(localName, ns);
        } 
 
        public override string LookupPrefix(string ns) {
            return _xmltextWriter.LookupPrefix(ns); 
        }

        public override XmlSpace XmlSpace {
            get { 
                return _xmltextWriter.XmlSpace;
            } 
        } 

        public override string XmlLang { 
            get {
                return _xmltextWriter.XmlLang;
            }
        } 

        public override void WriteNmToken(string name) { 
            _xmltextWriter.WriteNmToken(name); 
        }
   } 


    internal sealed class DataTextReader : XmlReader {
 
        private XmlReader _xmlreader;
 
        internal static XmlReader CreateReader(XmlReader xr) { 
            Debug.Assert(!(xr is DataTextReader), "XmlReader is DataTextReader");
            return new DataTextReader(xr); 
        }

        private DataTextReader( XmlReader input ) {
            _xmlreader = input; 
        }
 
        public override XmlReaderSettings Settings { 
            get {
                return _xmlreader.Settings; 
            }
        }

        public override XmlNodeType NodeType { 
            get {
                return _xmlreader.NodeType; 
            } 
        }
 
        public override string Name {
            get {
                return _xmlreader.Name;
            } 
        }
 
        public override string LocalName { 
            get {
                return _xmlreader.LocalName; 
            }
        }

        public override string NamespaceURI { 
            get {
                return _xmlreader.NamespaceURI; 
            } 
        }
 
        public override string Prefix {
            get { return _xmlreader.Prefix; }
        }
 
        public override bool HasValue {
            get { return _xmlreader.HasValue; } 
        } 

        public override string Value { 
            get { return _xmlreader.Value; }
        }

        public override int Depth { 
            get { return _xmlreader.Depth; }
        } 
 
        public override string BaseURI {
            get { return _xmlreader.BaseURI; } 
        }

        public override bool IsEmptyElement {
            get { return _xmlreader.IsEmptyElement; } 
        }
 
        public override bool IsDefault { 
            get { return _xmlreader.IsDefault; }
        } 

        public override char QuoteChar {
            get { return _xmlreader.QuoteChar; }
        } 

        public override XmlSpace XmlSpace { 
            get { return _xmlreader.XmlSpace; } 
        }
 
        public override string XmlLang {
            get { return _xmlreader.XmlLang; }
        }
 
        public override int AttributeCount { get { return _xmlreader.AttributeCount; } }
 
        public override string GetAttribute( string name ) { 
            return _xmlreader.GetAttribute( name );
        } 

        public override string GetAttribute( string localName, string namespaceURI ) {
            return _xmlreader.GetAttribute( localName, namespaceURI );
        } 

        public override string GetAttribute( int i ) { 
            return _xmlreader.GetAttribute( i ); 
        }
 
        public override bool MoveToAttribute( string name ) {
            return _xmlreader.MoveToAttribute( name );
        }
 
        public override bool MoveToAttribute( string localName, string namespaceURI ) {
            return _xmlreader.MoveToAttribute( localName, namespaceURI ); 
        } 

        public override void MoveToAttribute( int i ) { 
            _xmlreader.MoveToAttribute( i );
        }

        public override bool MoveToFirstAttribute() { 
            return _xmlreader.MoveToFirstAttribute();
        } 
 
        public override bool MoveToNextAttribute() {
            return _xmlreader.MoveToNextAttribute(); 
        }

        public override bool MoveToElement() {
            return _xmlreader.MoveToElement(); 
        }
 
        public override bool ReadAttributeValue() { 
            return _xmlreader.ReadAttributeValue();
        } 

        public override bool Read() {
            return _xmlreader.Read();
        } 

        public override bool EOF { 
            get { return _xmlreader.EOF; } 
        }
 
        public override void Close() {
            _xmlreader.Close();
        }
 
        public override ReadState ReadState {
            get { return _xmlreader.ReadState; } 
        } 

        public override void Skip() { 
            _xmlreader.Skip();
        }

        public override XmlNameTable NameTable { 
            get { return _xmlreader.NameTable; }
        } 
 
        public override String LookupNamespace( String prefix ) {
            return _xmlreader.LookupNamespace(prefix); 
        }

        public override bool CanResolveEntity  {
            get { return _xmlreader.CanResolveEntity;} 
        }
 
        public override void ResolveEntity() { 
            _xmlreader.ResolveEntity();
        } 

        public override bool CanReadBinaryContent {
            get { return _xmlreader.CanReadBinaryContent ; }
        } 

        public override int ReadContentAsBase64( byte[] buffer, int index, int count ) { 
            return _xmlreader.ReadContentAsBase64( buffer, index, count ); 
        }
 
        public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) {
            return _xmlreader.ReadElementContentAsBase64( buffer, index, count );
        }
 
        public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) {
            return _xmlreader.ReadContentAsBinHex( buffer, index, count ); 
        } 

        public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) { 
            return _xmlreader.ReadElementContentAsBinHex( buffer, index, count );
        }

        public override bool CanReadValueChunk { 
            get { return _xmlreader.CanReadValueChunk ; }
        } 
 
        public override string ReadString() {
            return _xmlreader.ReadString(); 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK