2 // XmlSchemaWriter.cs - DataSet.WriteXmlSchema() support
6 // Atsushi Enomoto <atsushi@ximian.com>
8 // Original WriteXml/WriteXmlSchema authors are:
9 // Ville Palo, Alan Tam, Lluis Sanchez and Eran Domb.
13 // Copyright (C) 2004-05 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Collections.Specialized;
38 using System.Globalization;
44 internal class XmlSchemaWriter
46 const string xmlnsxs = System.Xml.Schema.XmlSchema.Namespace;
48 public static void WriteXmlSchema (DataSet dataset,
51 WriteXmlSchema (dataset, writer, dataset.Tables,
55 public static void WriteXmlSchema (DataSet dataset,
56 XmlWriter writer, DataTableCollection tables,
57 DataRelationCollection relations)
59 new XmlSchemaWriter (dataset, writer,
60 tables, relations).WriteSchema ();
63 internal static void WriteXmlSchema (XmlWriter writer, DataTable[] tables,
64 DataRelation[] relations,
69 new XmlSchemaWriter (writer, tables, relations, mainDataTable, dataSetName, locale).WriteSchema ();
72 public XmlSchemaWriter (DataSet dataset,
73 XmlWriter writer, DataTableCollection tables,
74 DataRelationCollection relations)
76 dataSetName = dataset.DataSetName;
77 dataSetNamespace = dataset.Namespace;
79 dataSetLocale = dataset.LocaleSpecified ? dataset.Locale : null;
81 dataSetLocale = dataset.Locale;
83 dataSetProperties = dataset.ExtendedProperties;
86 this.tables = new DataTable[tables.Count];
87 for(int i=0;i<tables.Count;i++) this.tables[i] = tables[i];
89 if (relations != null) {
90 this.relations = new DataRelation[relations.Count];
91 for(int i=0;i<relations.Count;i++) this.relations[i] = relations[i];
95 public XmlSchemaWriter (XmlWriter writer,
97 DataRelation[] relations,
103 this.tables = tables;
104 this.relations = relations;
105 this.mainDataTable = mainDataTable;
106 this.dataSetName = dataSetName;
107 this.dataSetLocale = locale;
108 this.dataSetProperties = new PropertyCollection();
109 if (tables[0].DataSet != null) {
110 dataSetNamespace = tables[0].DataSet.Namespace;
112 dataSetLocale = tables[0].DataSet.Locale;
115 dataSetNamespace = tables[0].Namespace;
117 dataSetLocale = tables[0].Locale;
124 DataRelation[] relations;
125 string mainDataTable;
127 string dataSetNamespace;
128 PropertyCollection dataSetProperties;
129 CultureInfo dataSetLocale;
131 ArrayList globalTypeTables = new ArrayList ();
132 Hashtable additionalNamespaces = new Hashtable ();
134 ArrayList annotation = new ArrayList ();
136 public string ConstraintPrefix {
137 get { return dataSetNamespace != String.Empty ? XmlConstants.TnsPrefix + ':' : String.Empty; }
142 public void WriteSchema ()
144 ListDictionary names = new ListDictionary ();
145 ListDictionary includes = new ListDictionary ();
147 // Add namespaces used in DataSet components (tables, columns, ...)
148 foreach (DataTable dt in tables) {
149 foreach (DataColumn col in dt.Columns)
150 CheckNamespace (col.Prefix, col.Namespace, names, includes);
151 CheckNamespace (dt.Prefix, dt.Namespace, names, includes);
154 w.WriteStartElement ("xs", "schema", xmlnsxs);
155 w.WriteAttributeString ("id", XmlHelper.Encode (dataSetName));
157 if (dataSetNamespace != String.Empty) {
158 w.WriteAttributeString ("targetNamespace",
160 w.WriteAttributeString (
162 XmlConstants.TnsPrefix,
163 XmlConstants.XmlnsNS,
166 w.WriteAttributeString ("xmlns", dataSetNamespace);
168 w.WriteAttributeString ("xmlns", "xs",
169 XmlConstants.XmlnsNS, xmlnsxs);
170 w.WriteAttributeString ("xmlns",
171 XmlConstants.MsdataPrefix,
172 XmlConstants.XmlnsNS,
173 XmlConstants.MsdataNamespace);
175 if (CheckExtendedPropertyExists (tables, relations))
176 w.WriteAttributeString ("xmlns",
177 XmlConstants.MspropPrefix,
178 XmlConstants.XmlnsNS,
179 XmlConstants.MspropNamespace);
181 if (dataSetNamespace != String.Empty) {
182 w.WriteAttributeString ("attributeFormDefault", "qualified");
183 w.WriteAttributeString ("elementFormDefault", "qualified");
186 foreach (string prefix in names.Keys)
187 w.WriteAttributeString ("xmlns", prefix,
188 XmlConstants.XmlnsNS,
189 names [prefix] as string);
191 if (includes.Count > 0)
192 w.WriteComment ("ATTENTION: This schema contains references to other imported schemas");
193 foreach (string ns in includes.Keys) {
194 w.WriteStartElement ("xs", "import", xmlnsxs);
195 w.WriteAttributeString ("namespace", ns);
196 w.WriteAttributeString ("schemaLocation", includes [ns] as string);
197 w.WriteEndElement ();
200 foreach (DataTable table in tables) {
201 bool isTopLevel = true;
202 foreach (DataRelation rel in table.ParentRelations) {
208 // LAMESPEC: You have a nested relationship but only one table,
209 // write table element first
210 if (!isTopLevel && tables.Length < 2)
211 WriteTableElement (table);
214 WriteDataSetElement ();
216 w.WriteEndElement (); // xs:schema
221 // FIXME: actually there are some cases that this method(ology)
223 private void WriteDataSetElement ()
225 w.WriteStartElement ("xs", "element", xmlnsxs);
226 w.WriteAttributeString ("name", XmlHelper.Encode (dataSetName));
227 w.WriteAttributeString (XmlConstants.MsdataPrefix,
228 "IsDataSet", XmlConstants.MsdataNamespace,
232 bool useCurrentLocale = (dataSetLocale == null);
234 if (!useCurrentLocale)
237 w.WriteAttributeString (
238 XmlConstants.MsdataPrefix,
240 XmlConstants.MsdataNamespace,
245 if(mainDataTable != null && mainDataTable != "")
246 w.WriteAttributeString (
247 XmlConstants.MsdataPrefix,
249 XmlConstants.MsdataNamespace,
252 if (useCurrentLocale) {
253 w.WriteAttributeString (
254 XmlConstants.MsdataPrefix,
256 XmlConstants.MsdataNamespace,
261 AddExtendedPropertyAttributes (dataSetProperties);
263 w.WriteStartElement ("xs", "complexType", xmlnsxs);
264 w.WriteStartElement ("xs", "choice", xmlnsxs);
265 w.WriteAttributeString ("minOccurs", "0");
266 w.WriteAttributeString ("maxOccurs", "unbounded");
268 foreach (DataTable table in tables) {
269 bool isTopLevel = true;
270 foreach (DataRelation rel in table.ParentRelations) {
277 // If there is a relation but only one table, could be that
278 // we have to add a ref attribute
280 if (!isTopLevel && tables.Length < 2) {
286 if (dataSetNamespace != table.Namespace ||
288 // <xs:element ref="X:y" />
289 w.WriteStartElement ("xs",
292 w.WriteStartAttribute ("ref", String.Empty);
293 w.WriteQualifiedName (XmlHelper.Encode (table.TableName), table.Namespace);
294 w.WriteEndAttribute ();
295 w.WriteEndElement ();
298 WriteTableElement (table);
302 w.WriteEndElement (); // choice
303 w.WriteEndElement (); // complexType
305 WriteConstraints (); // DataSet constraints
307 w.WriteEndElement (); // element
309 if (annotation.Count > 0) {
310 w.WriteStartElement ("xs", "annotation", xmlnsxs);
311 w.WriteStartElement ("xs", "appinfo", xmlnsxs);
313 foreach (object o in annotation) {
314 if (!(o is DataRelation))
316 WriteDataRelationAnnotation ((DataRelation)o);
318 w.WriteEndElement ();
319 w.WriteEndElement ();
323 private void WriteDataRelationAnnotation (DataRelation rel)
325 String colnames = String.Empty;
326 w.WriteStartElement (XmlConstants.MsdataPrefix, "Relationship",
327 XmlConstants.MsdataNamespace);
329 w.WriteAttributeString ("name", XmlHelper.Encode (rel.RelationName));
331 w.WriteAttributeString (
332 XmlConstants.MsdataPrefix,
334 XmlConstants.MsdataNamespace,
335 XmlHelper.Encode (rel.ParentTable.TableName));
337 w.WriteAttributeString (
338 XmlConstants.MsdataPrefix,
340 XmlConstants.MsdataNamespace,
341 XmlHelper.Encode (rel.ChildTable.TableName));
343 colnames = String.Empty;
344 foreach (DataColumn col in rel.ParentColumns)
345 colnames += XmlHelper.Encode (col.ColumnName) + " ";
346 w.WriteAttributeString (
347 XmlConstants.MsdataPrefix,
349 XmlConstants.MsdataNamespace,
350 colnames.TrimEnd ());
352 colnames = String.Empty;
353 foreach (DataColumn col in rel.ChildColumns)
354 colnames += XmlHelper.Encode (col.ColumnName) + " ";
355 w.WriteAttributeString (
356 XmlConstants.MsdataPrefix,
358 XmlConstants.MsdataNamespace,
359 colnames.TrimEnd ());
361 w.WriteEndElement ();
364 private void WriteConstraints ()
366 ArrayList names = new ArrayList ();
368 // add all unique constraints.
369 foreach (DataTable table in tables) {
370 foreach (Constraint c in table.Constraints) {
372 c as UniqueConstraint;
374 AddUniqueConstraints (u, names);
378 ForeignKeyConstraint fk = c as ForeignKeyConstraint;
379 bool haveConstraint = false;
380 if (relations != null) {
381 foreach (DataRelation r in relations)
382 if (r.RelationName == fk.ConstraintName)
383 haveConstraint = true;
385 if (tables.Length > 1 && fk != null && !haveConstraint) {
386 DataRelation rel = new DataRelation (fk.ConstraintName,
387 fk.RelatedColumns, fk.Columns);
388 AddForeignKeys (rel, names, true);
394 // Add all foriegn key constraints.
395 if (relations != null)
396 foreach (DataRelation rel in relations) {
397 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null) {
398 annotation.Add (rel);
401 AddForeignKeys (rel, names,false);
405 // Add unique constaraints to the schema.
406 // return hashtable with the names of all XmlSchemaUnique elements we created.
407 private void AddUniqueConstraints (UniqueConstraint uniq,
410 // if column of the constraint is hidden do not write the constraint.
411 foreach (DataColumn column in uniq.Columns)
412 if (column.ColumnMapping == MappingType.Hidden)
413 return; // do nothing
415 w.WriteStartElement ("xs", "unique", xmlnsxs);
416 // if constaraint name do not exist in the hashtable we can use it.
418 if (!names.Contains (uniq.ConstraintName)) {
419 name = XmlHelper.Encode (uniq.ConstraintName);
420 w.WriteAttributeString ("name", name);
422 // otherwise generate new constraint name for the
423 // XmlSchemaUnique element.
425 name = XmlHelper.Encode (uniq.Table.TableName) + "_" + XmlHelper.Encode (uniq.ConstraintName);
426 w.WriteAttributeString ("name", name);
427 w.WriteAttributeString (
428 XmlConstants.MsdataPrefix,
429 XmlConstants.ConstraintName,
430 XmlConstants.MsdataNamespace,
431 XmlHelper.Encode (uniq.ConstraintName));
435 if (uniq.IsPrimaryKey) {
436 w.WriteAttributeString (
437 XmlConstants.MsdataPrefix,
438 XmlConstants.PrimaryKey,
439 XmlConstants.MsdataNamespace,
443 AddExtendedPropertyAttributes (uniq.ExtendedProperties);
445 w.WriteStartElement ("xs", "selector",
447 w.WriteAttributeString ("xpath", ".//" +
448 ConstraintPrefix + XmlHelper.Encode (uniq.Table.TableName));
449 w.WriteEndElement (); // selector
450 foreach (DataColumn c in uniq.Columns) {
451 w.WriteStartElement ("xs", "field",
453 w.WriteStartAttribute ("xpath", String.Empty);
454 if (c.ColumnMapping == MappingType.Attribute)
456 w.WriteString (ConstraintPrefix);
457 w.WriteString (XmlHelper.Encode (c.ColumnName));
458 w.WriteEndAttribute (); // xpath
459 w.WriteEndElement (); // field
462 w.WriteEndElement (); // unique
465 // Add the foriegn keys to the schema.
466 private void AddForeignKeys (DataRelation rel, ArrayList names, bool isConstraintOnly)
468 // Do nothing if it contains hidden relation
469 foreach (DataColumn col in rel.ParentColumns)
470 if (col.ColumnMapping == MappingType.Hidden)
472 foreach (DataColumn col in rel.ChildColumns)
473 if (col.ColumnMapping == MappingType.Hidden)
476 w.WriteStartElement ("xs", "keyref", xmlnsxs);
477 w.WriteAttributeString ("name", XmlHelper.Encode (rel.RelationName));
479 //ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
480 UniqueConstraint uqConst = null;
482 if (isConstraintOnly) {
483 foreach (Constraint c in rel.ParentTable.Constraints) {
484 uqConst = c as UniqueConstraint;
487 if (uqConst.Columns == rel.ParentColumns)
492 uqConst = rel.ParentKeyConstraint;
494 string concatName = XmlHelper.Encode (rel.ParentTable.TableName) + "_" + XmlHelper.Encode (uqConst.ConstraintName);
495 // first try to find the concatenated name. If we didn't find it - use constraint name.
496 if (names.Contains (concatName)) {
497 w.WriteStartAttribute ("refer", String.Empty);
498 w.WriteQualifiedName (concatName, dataSetNamespace);
499 w.WriteEndAttribute ();
502 w.WriteStartAttribute ("refer", String.Empty);
503 w.WriteQualifiedName (XmlHelper.Encode (uqConst.ConstraintName), dataSetNamespace);
504 w.WriteEndAttribute ();
507 if (isConstraintOnly)
508 w.WriteAttributeString ( XmlConstants.MsdataPrefix,
509 XmlConstants.ConstraintOnly,
510 XmlConstants.MsdataNamespace,
513 w.WriteAttributeString (
514 XmlConstants.MsdataPrefix,
515 XmlConstants.IsNested,
516 XmlConstants.MsdataNamespace,
519 AddExtendedPropertyAttributes (uqConst.ExtendedProperties);
521 w.WriteStartElement ("xs", "selector", xmlnsxs);
522 w.WriteAttributeString ("xpath", ".//" +
523 ConstraintPrefix + XmlHelper.Encode (rel.ChildTable.TableName));
524 w.WriteEndElement ();
526 foreach (DataColumn c in rel.ChildColumns) {
527 w.WriteStartElement ("xs", "field",
529 w.WriteStartAttribute ("xpath", String.Empty);
530 if (c.ColumnMapping == MappingType.Attribute)
532 w.WriteString (ConstraintPrefix);
533 w.WriteString (XmlHelper.Encode (c.ColumnName));
534 w.WriteEndAttribute ();
535 w.WriteEndElement (); // field
538 w.WriteEndElement (); // keyref
541 // ExtendedProperties
543 private bool CheckExtendedPropertyExists (
545 DataRelation[] relations)
547 if (dataSetProperties.Count > 0)
549 foreach (DataTable dt in tables) {
550 if (dt.ExtendedProperties.Count > 0)
552 foreach (DataColumn col in dt.Columns)
553 if (col.ExtendedProperties.Count > 0)
555 foreach (Constraint c in dt.Constraints)
556 if (c.ExtendedProperties.Count > 0)
559 if (relations == null)
561 foreach (DataRelation rel in relations)
562 if (rel.ExtendedProperties.Count > 0)
567 private void AddExtendedPropertyAttributes (PropertyCollection props)
569 // add extended properties to xs:element
570 foreach (DictionaryEntry de in props) {
571 w.WriteStartAttribute (
572 XmlConstants.MspropPrefix,
573 XmlConvert.EncodeName (de.Key.ToString ()),
574 XmlConstants.MspropNamespace);
575 if (de.Value != null)
577 DataSet.WriteObjectXml (de.Value));
578 w.WriteEndAttribute ();
584 private void WriteTableElement (DataTable table)
586 w.WriteStartElement ("xs", "element", xmlnsxs);
587 w.WriteAttributeString ("name", XmlHelper.Encode (table.TableName));
589 AddExtendedPropertyAttributes (table.ExtendedProperties);
591 WriteTableType (table);
593 w.WriteEndElement ();
596 private void WriteTableType (DataTable table)
602 DataSet.SplitColumns (table, out atts, out elements, out simple);
604 w.WriteStartElement ("xs", "complexType", xmlnsxs);
606 if (simple != null) {
607 w.WriteStartElement ("xs", "simpleContent", xmlnsxs);
608 // add column name attribute
609 w.WriteAttributeString (
610 XmlConstants.MsdataPrefix,
611 XmlConstants.ColumnName,
612 XmlConstants.MsdataNamespace,
613 XmlHelper.Encode (simple.ColumnName));
615 // add ordinal attribute
616 w.WriteAttributeString (
617 XmlConstants.MsdataPrefix,
618 XmlConstants.Ordinal,
619 XmlConstants.MsdataNamespace,
620 XmlConvert.ToString (simple.Ordinal));
623 w.WriteStartElement ("xs", "extension",
625 w.WriteStartAttribute ("base", String.Empty);
626 WriteQName (MapType (simple.DataType));
627 w.WriteEndAttribute ();
629 WriteTableAttributes (atts);
631 w.WriteEndElement ();
633 WriteTableAttributes (atts);
634 bool isNested = false;
635 foreach (DataRelation rel in table.ParentRelations) {
642 // When we have a nested relationship and only one table,
643 // could be that we have a reference attribute
644 if (elements.Count > 0 || (isNested && tables.Length < 2)) {
645 w.WriteStartElement ("xs", "sequence",
648 foreach (DataColumn col in elements)
649 WriteTableTypeParticles (col);
651 foreach (DataRelation rel in table.ChildRelations)
653 WriteChildRelations (rel);
654 w.WriteEndElement ();
658 w.WriteFullEndElement (); // complexType
661 private void WriteTableTypeParticles (DataColumn col)
663 w.WriteStartElement ("xs", "element", xmlnsxs);
664 w.WriteAttributeString ("name", XmlHelper.Encode (col.ColumnName));
666 if (col.ColumnName != col.Caption && col.Caption != String.Empty)
667 w.WriteAttributeString (
668 XmlConstants.MsdataPrefix,
669 XmlConstants.Caption,
670 XmlConstants.MsdataNamespace,
673 if (col.AutoIncrement == true)
674 w.WriteAttributeString (
675 XmlConstants.MsdataPrefix,
676 XmlConstants.AutoIncrement,
677 XmlConstants.MsdataNamespace,
680 if (col.AutoIncrementSeed != 0) {
681 w.WriteAttributeString (
683 XmlConstants.MsdataPrefix,
684 XmlConstants.AutoIncrementSeed,
685 XmlConstants.MsdataNamespace,
686 XmlConvert.ToString (col.AutoIncrementSeed));
689 if (col.AutoIncrementStep != 1) {
690 w.WriteAttributeString (
692 XmlConstants.MsdataPrefix,
693 XmlConstants.AutoIncrementStep,
694 XmlConstants.MsdataNamespace,
695 XmlConvert.ToString (col.AutoIncrementStep));
698 if (!DataColumn.GetDefaultValueForType (col.DataType).Equals (col.DefaultValue))
699 w.WriteAttributeString ("default",
700 DataSet.WriteObjectXml (col.DefaultValue));
703 w.WriteAttributeString (
704 XmlConstants.MsdataPrefix,
705 XmlConstants.ReadOnly,
706 XmlConstants.MsdataNamespace,
709 XmlQualifiedName typeQName = null;
710 if (col.MaxLength < 0) {
711 w.WriteStartAttribute ("type", String.Empty);
712 typeQName = MapType (col.DataType);
713 WriteQName (typeQName);
714 w.WriteEndAttribute ();
717 if (typeQName == XmlConstants.QnString
718 && col.DataType != typeof (string)
719 && col.DataType != typeof (char)) {
720 w.WriteStartAttribute (
721 XmlConstants.MsdataPrefix,
722 XmlConstants.DataType,
723 XmlConstants.MsdataNamespace);
724 string runtimeName = col.DataType.AssemblyQualifiedName;
725 w.WriteString (runtimeName);
726 w.WriteEndAttribute ();
730 w.WriteAttributeString ("minOccurs", "0");
732 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
733 // XmlConstants.Ordinal,
734 // XmlConstants.MsdataNamespace,
735 // col.Ordinal.ToString ());
737 // Write SimpleType if column have MaxLength
738 if (col.MaxLength > -1)
739 WriteSimpleType (col);
741 AddExtendedPropertyAttributes (col.ExtendedProperties);
743 w.WriteEndElement (); // sequence
746 private void WriteChildRelations (DataRelation rel)
748 // If there is a parent/child relation and only one table,
749 // it would just be a ref element.
750 if (rel.ChildTable.Namespace != dataSetNamespace ||
752 w.WriteStartElement ("xs", "element", xmlnsxs);
753 w.WriteStartAttribute ("ref", String.Empty);
754 w.WriteQualifiedName (
755 XmlHelper.Encode (rel.ChildTable.TableName),
756 rel.ChildTable.Namespace);
757 w.WriteEndAttribute ();
759 w.WriteStartElement ("xs", "element", xmlnsxs);
760 w.WriteStartAttribute ("name", String.Empty);
761 w.WriteQualifiedName (
762 XmlHelper.Encode (rel.ChildTable.TableName),
763 rel.ChildTable.Namespace);
764 w.WriteEndAttribute ();
765 w.WriteAttributeString ("minOccurs", "0");
766 w.WriteAttributeString ("maxOccurs", "unbounded");
768 globalTypeTables.Add (rel.ChildTable);
771 // Iff there is a genuine ChildTable and not just a ref, call WriteTableType
772 if (tables.Length > 1)
773 WriteTableType (rel.ChildTable);
774 w.WriteEndElement ();
777 private void WriteTableAttributes (ArrayList atts)
779 //Then a list of attributes
780 foreach (DataColumn col in atts) {
781 w.WriteStartElement ("xs", "attribute", xmlnsxs);
783 string name = XmlHelper.Encode (col.ColumnName);
784 if (col.Namespace != String.Empty) {
785 w.WriteAttributeString ("form", "qualified");
786 string prefix = col.Prefix == String.Empty ? "app" + additionalNamespaces.Count : col.Prefix;
787 name = prefix + ":" + name;
788 // FIXME: Handle prefix mapping correctly.
789 additionalNamespaces [prefix] = col.Namespace;
791 w.WriteAttributeString ("name", name);
793 AddExtendedPropertyAttributes (
794 col.ExtendedProperties);
797 w.WriteAttributeString (
798 XmlConstants.MsdataPrefix,
799 XmlConstants.ReadOnly,
800 XmlConstants.MsdataNamespace,
803 if (col.MaxLength < 0) {
804 // otherwise simpleType is written later
805 w.WriteStartAttribute ("type", String.Empty);
806 WriteQName (MapType (col.DataType));
807 w.WriteEndAttribute ();
810 if (!col.AllowDBNull)
811 w.WriteAttributeString ("use", "required");
812 if (col.DefaultValue != DataColumn.GetDefaultValueForType (col.DataType))
813 w.WriteAttributeString ("default",
814 DataSet.WriteObjectXml (col.DefaultValue));
816 if (col.MaxLength > -1)
817 WriteSimpleType (col);
819 w.WriteEndElement (); // attribute
823 private void WriteSimpleType (DataColumn col)
825 w.WriteStartElement ("xs", "simpleType", xmlnsxs);
826 w.WriteStartElement ("xs", "restriction", xmlnsxs);
827 w.WriteStartAttribute ("base", String.Empty);
828 WriteQName (MapType (col.DataType));
829 w.WriteEndAttribute ();
831 w.WriteStartElement ("xs", "maxLength", xmlnsxs);
832 w.WriteAttributeString ("value",
833 XmlConvert.ToString (col.MaxLength));
834 w.WriteEndElement (); // maxLength
835 w.WriteEndElement (); // restriction
836 w.WriteEndElement (); // simpleType
839 private void WriteQName (XmlQualifiedName name)
841 w.WriteQualifiedName (name.Name, name.Namespace);
844 private void CheckNamespace (string prefix, string ns, ListDictionary names, ListDictionary includes)
846 if (ns == String.Empty)
848 if (dataSetNamespace != ns) {
849 if ((string)names [prefix] != ns) {
850 for (int i = 1; i < int.MaxValue; i++) {
851 string p = "app" + i;
852 if (names [p] == null) {
854 HandleExternalNamespace (p, ns, includes);
862 private void HandleExternalNamespace (string prefix, string ns, ListDictionary includes)
864 if (includes.Contains (ns))
865 return; // nothing to do
866 includes.Add (ns, "_" + prefix + ".xsd");
869 private /*static*/ XmlQualifiedName MapType (Type type)
871 switch (Type.GetTypeCode (type)) {
872 case TypeCode.String: return XmlConstants.QnString;
873 case TypeCode.Int16: return XmlConstants.QnShort;
874 case TypeCode.Int32: return XmlConstants.QnInt;
875 case TypeCode.Int64: return XmlConstants.QnLong;
876 case TypeCode.Boolean: return XmlConstants.QnBoolean;
877 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
878 //case TypeCode.Char: return XmlConstants.QnChar;
879 case TypeCode.DateTime: return XmlConstants.QnDateTime;
880 case TypeCode.Decimal: return XmlConstants.QnDecimal;
881 case TypeCode.Double: return XmlConstants.QnDouble;
882 case TypeCode.SByte: return XmlConstants.QnSbyte;
883 case TypeCode.Single: return XmlConstants.QnFloat;
884 case TypeCode.UInt16: return XmlConstants.QnUnsignedShort;
885 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
886 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
889 if (typeof (TimeSpan) == type)
890 return XmlConstants.QnDuration;
891 else if (typeof (System.Uri) == type)
892 return XmlConstants.QnUri;
893 else if (typeof (byte[]) == type)
894 return XmlConstants.QnBase64Binary;
895 else if (typeof (XmlQualifiedName) == type)
896 return XmlConstants.QnXmlQualifiedName;
898 return XmlConstants.QnString;