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;
78 dataSetLocale = dataset.LocaleSpecified ? dataset.Locale : null;
79 dataSetProperties = dataset.ExtendedProperties;
82 this.tables = new DataTable[tables.Count];
83 for(int i=0;i<tables.Count;i++) this.tables[i] = tables[i];
85 if (relations != null) {
86 this.relations = new DataRelation[relations.Count];
87 for(int i=0;i<relations.Count;i++) this.relations[i] = relations[i];
91 public XmlSchemaWriter (XmlWriter writer,
93 DataRelation[] relations,
100 this.relations = relations;
101 this.mainDataTable = mainDataTable;
102 this.dataSetName = dataSetName;
103 this.dataSetLocale = locale;
104 this.dataSetProperties = new PropertyCollection();
105 if (tables[0].DataSet != null) {
106 dataSetNamespace = tables[0].DataSet.Namespace;
108 dataSetNamespace = tables[0].Namespace;
114 DataRelation[] relations;
115 string mainDataTable;
117 string dataSetNamespace;
118 PropertyCollection dataSetProperties;
119 CultureInfo dataSetLocale;
121 ArrayList globalTypeTables = new ArrayList ();
122 Hashtable additionalNamespaces = new Hashtable ();
124 ArrayList annotation = new ArrayList ();
126 public string ConstraintPrefix {
127 get { return dataSetNamespace != String.Empty ? XmlConstants.TnsPrefix + ':' : String.Empty; }
132 public void WriteSchema ()
134 ListDictionary names = new ListDictionary ();
135 ListDictionary includes = new ListDictionary ();
137 // Add namespaces used in DataSet components (tables, columns, ...)
138 foreach (DataTable dt in tables) {
139 foreach (DataColumn col in dt.Columns)
140 CheckNamespace (col.Prefix, col.Namespace, names, includes);
141 CheckNamespace (dt.Prefix, dt.Namespace, names, includes);
144 w.WriteStartElement ("xs", "schema", xmlnsxs);
145 w.WriteAttributeString ("id", XmlHelper.Encode (dataSetName));
147 if (dataSetNamespace != String.Empty) {
148 w.WriteAttributeString ("targetNamespace",
150 w.WriteAttributeString (
152 XmlConstants.TnsPrefix,
153 XmlConstants.XmlnsNS,
156 w.WriteAttributeString ("xmlns", dataSetNamespace);
158 w.WriteAttributeString ("xmlns", "xs",
159 XmlConstants.XmlnsNS, xmlnsxs);
160 w.WriteAttributeString ("xmlns",
161 XmlConstants.MsdataPrefix,
162 XmlConstants.XmlnsNS,
163 XmlConstants.MsdataNamespace);
165 if (CheckExtendedPropertyExists (tables, relations))
166 w.WriteAttributeString ("xmlns",
167 XmlConstants.MspropPrefix,
168 XmlConstants.XmlnsNS,
169 XmlConstants.MspropNamespace);
171 if (dataSetNamespace != String.Empty) {
172 w.WriteAttributeString ("attributeFormDefault", "qualified");
173 w.WriteAttributeString ("elementFormDefault", "qualified");
176 foreach (string prefix in names.Keys)
177 w.WriteAttributeString ("xmlns", prefix,
178 XmlConstants.XmlnsNS,
179 names [prefix] as string);
181 if (includes.Count > 0)
182 w.WriteComment ("ATTENTION: This schema contains references to other imported schemas");
183 foreach (string ns in includes.Keys) {
184 w.WriteStartElement ("xs", "import", xmlnsxs);
185 w.WriteAttributeString ("namespace", ns);
186 w.WriteAttributeString ("schemaLocation", includes [ns] as string);
187 w.WriteEndElement ();
190 foreach (DataTable table in tables) {
191 bool isTopLevel = true;
192 foreach (DataRelation rel in table.ParentRelations) {
198 // LAMESPEC: You have a nested relationship but only one table,
199 // write table element first
200 if (!isTopLevel && tables.Length < 2)
201 WriteTableElement (table);
204 WriteDataSetElement ();
206 w.WriteEndElement (); // xs:schema
211 // FIXME: actually there are some cases that this method(ology)
213 private void WriteDataSetElement ()
215 w.WriteStartElement ("xs", "element", xmlnsxs);
216 w.WriteAttributeString ("name", XmlHelper.Encode (dataSetName));
217 w.WriteAttributeString (XmlConstants.MsdataPrefix,
218 "IsDataSet", XmlConstants.MsdataNamespace,
221 bool useCurrentLocale = (dataSetLocale == null);
223 if (!useCurrentLocale)
225 w.WriteAttributeString (
226 XmlConstants.MsdataPrefix,
228 XmlConstants.MsdataNamespace,
232 if(mainDataTable != null && mainDataTable != "")
233 w.WriteAttributeString (
234 XmlConstants.MsdataPrefix,
236 XmlConstants.MsdataNamespace,
239 if (useCurrentLocale) {
240 w.WriteAttributeString (
241 XmlConstants.MsdataPrefix,
243 XmlConstants.MsdataNamespace,
247 AddExtendedPropertyAttributes (dataSetProperties);
249 w.WriteStartElement ("xs", "complexType", xmlnsxs);
250 w.WriteStartElement ("xs", "choice", xmlnsxs);
251 w.WriteAttributeString ("minOccurs", "0");
252 w.WriteAttributeString ("maxOccurs", "unbounded");
254 foreach (DataTable table in tables) {
255 bool isTopLevel = true;
256 foreach (DataRelation rel in table.ParentRelations) {
263 // If there is a relation but only one table, could be that
264 // we have to add a ref attribute
266 if (!isTopLevel && tables.Length < 2) {
272 if (dataSetNamespace != table.Namespace ||
274 // <xs:element ref="X:y" />
275 w.WriteStartElement ("xs",
278 w.WriteStartAttribute ("ref", String.Empty);
279 w.WriteQualifiedName (XmlHelper.Encode (table.TableName), table.Namespace);
280 w.WriteEndAttribute ();
281 w.WriteEndElement ();
284 WriteTableElement (table);
288 w.WriteEndElement (); // choice
289 w.WriteEndElement (); // complexType
291 WriteConstraints (); // DataSet constraints
293 w.WriteEndElement (); // element
295 if (annotation.Count > 0) {
296 w.WriteStartElement ("xs", "annotation", xmlnsxs);
297 w.WriteStartElement ("xs", "appinfo", xmlnsxs);
299 foreach (object o in annotation) {
300 if (!(o is DataRelation))
302 WriteDataRelationAnnotation ((DataRelation)o);
304 w.WriteEndElement ();
305 w.WriteEndElement ();
309 private void WriteDataRelationAnnotation (DataRelation rel)
311 String colnames = String.Empty;
312 w.WriteStartElement (XmlConstants.MsdataPrefix, "Relationship",
313 XmlConstants.MsdataNamespace);
315 w.WriteAttributeString ("name", XmlHelper.Encode (rel.RelationName));
317 w.WriteAttributeString (
318 XmlConstants.MsdataPrefix,
320 XmlConstants.MsdataNamespace,
321 XmlHelper.Encode (rel.ParentTable.TableName));
323 w.WriteAttributeString (
324 XmlConstants.MsdataPrefix,
326 XmlConstants.MsdataNamespace,
327 XmlHelper.Encode (rel.ChildTable.TableName));
329 colnames = String.Empty;
330 foreach (DataColumn col in rel.ParentColumns)
331 colnames += XmlHelper.Encode (col.ColumnName) + " ";
332 w.WriteAttributeString (
333 XmlConstants.MsdataPrefix,
335 XmlConstants.MsdataNamespace,
336 colnames.TrimEnd ());
338 colnames = String.Empty;
339 foreach (DataColumn col in rel.ChildColumns)
340 colnames += XmlHelper.Encode (col.ColumnName) + " ";
341 w.WriteAttributeString (
342 XmlConstants.MsdataPrefix,
344 XmlConstants.MsdataNamespace,
345 colnames.TrimEnd ());
347 w.WriteEndElement ();
350 private void WriteConstraints ()
352 ArrayList names = new ArrayList ();
354 // add all unique constraints.
355 foreach (DataTable table in tables) {
356 foreach (Constraint c in table.Constraints) {
358 c as UniqueConstraint;
360 AddUniqueConstraints (u, names);
364 ForeignKeyConstraint fk = c as ForeignKeyConstraint;
365 bool haveConstraint = false;
366 if (relations != null) {
367 foreach (DataRelation r in relations)
368 if (r.RelationName == fk.ConstraintName)
369 haveConstraint = true;
371 if (tables.Length > 1 && fk != null && !haveConstraint) {
372 DataRelation rel = new DataRelation (fk.ConstraintName,
373 fk.RelatedColumns, fk.Columns);
374 AddForeignKeys (rel, names, true);
380 // Add all foriegn key constraints.
381 if (relations != null)
382 foreach (DataRelation rel in relations) {
383 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null) {
384 annotation.Add (rel);
387 AddForeignKeys (rel, names,false);
391 // Add unique constaraints to the schema.
392 // return hashtable with the names of all XmlSchemaUnique elements we created.
393 private void AddUniqueConstraints (UniqueConstraint uniq,
396 // if column of the constraint is hidden do not write the constraint.
397 foreach (DataColumn column in uniq.Columns)
398 if (column.ColumnMapping == MappingType.Hidden)
399 return; // do nothing
401 w.WriteStartElement ("xs", "unique", xmlnsxs);
402 // if constaraint name do not exist in the hashtable we can use it.
404 if (!names.Contains (uniq.ConstraintName)) {
405 name = XmlHelper.Encode (uniq.ConstraintName);
406 w.WriteAttributeString ("name", name);
408 // otherwise generate new constraint name for the
409 // XmlSchemaUnique element.
411 name = XmlHelper.Encode (uniq.Table.TableName) + "_" + XmlHelper.Encode (uniq.ConstraintName);
412 w.WriteAttributeString ("name", name);
413 w.WriteAttributeString (
414 XmlConstants.MsdataPrefix,
415 XmlConstants.ConstraintName,
416 XmlConstants.MsdataNamespace,
417 XmlHelper.Encode (uniq.ConstraintName));
421 if (uniq.IsPrimaryKey) {
422 w.WriteAttributeString (
423 XmlConstants.MsdataPrefix,
424 XmlConstants.PrimaryKey,
425 XmlConstants.MsdataNamespace,
429 AddExtendedPropertyAttributes (uniq.ExtendedProperties);
431 w.WriteStartElement ("xs", "selector",
433 w.WriteAttributeString ("xpath", ".//" +
434 ConstraintPrefix + XmlHelper.Encode (uniq.Table.TableName));
435 w.WriteEndElement (); // selector
436 foreach (DataColumn c in uniq.Columns) {
437 w.WriteStartElement ("xs", "field",
439 w.WriteStartAttribute ("xpath", String.Empty);
440 if (c.ColumnMapping == MappingType.Attribute)
442 w.WriteString (ConstraintPrefix);
443 w.WriteString (XmlHelper.Encode (c.ColumnName));
444 w.WriteEndAttribute (); // xpath
445 w.WriteEndElement (); // field
448 w.WriteEndElement (); // unique
451 // Add the foriegn keys to the schema.
452 private void AddForeignKeys (DataRelation rel, ArrayList names, bool isConstraintOnly)
454 // Do nothing if it contains hidden relation
455 foreach (DataColumn col in rel.ParentColumns)
456 if (col.ColumnMapping == MappingType.Hidden)
458 foreach (DataColumn col in rel.ChildColumns)
459 if (col.ColumnMapping == MappingType.Hidden)
462 w.WriteStartElement ("xs", "keyref", xmlnsxs);
463 w.WriteAttributeString ("name", XmlHelper.Encode (rel.RelationName));
465 //ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
466 UniqueConstraint uqConst = null;
468 if (isConstraintOnly) {
469 foreach (Constraint c in rel.ParentTable.Constraints) {
470 uqConst = c as UniqueConstraint;
473 if (uqConst.Columns == rel.ParentColumns)
478 uqConst = rel.ParentKeyConstraint;
480 string concatName = XmlHelper.Encode (rel.ParentTable.TableName) + "_" + XmlHelper.Encode (uqConst.ConstraintName);
481 // first try to find the concatenated name. If we didn't find it - use constraint name.
482 if (names.Contains (concatName)) {
483 w.WriteStartAttribute ("refer", String.Empty);
484 w.WriteQualifiedName (concatName, dataSetNamespace);
485 w.WriteEndAttribute ();
488 w.WriteStartAttribute ("refer", String.Empty);
489 w.WriteQualifiedName (XmlHelper.Encode (uqConst.ConstraintName), dataSetNamespace);
490 w.WriteEndAttribute ();
493 if (isConstraintOnly)
494 w.WriteAttributeString ( XmlConstants.MsdataPrefix,
495 XmlConstants.ConstraintOnly,
496 XmlConstants.MsdataNamespace,
499 w.WriteAttributeString (
500 XmlConstants.MsdataPrefix,
501 XmlConstants.IsNested,
502 XmlConstants.MsdataNamespace,
505 AddExtendedPropertyAttributes (uqConst.ExtendedProperties);
507 w.WriteStartElement ("xs", "selector", xmlnsxs);
508 w.WriteAttributeString ("xpath", ".//" +
509 ConstraintPrefix + XmlHelper.Encode (rel.ChildTable.TableName));
510 w.WriteEndElement ();
512 foreach (DataColumn c in rel.ChildColumns) {
513 w.WriteStartElement ("xs", "field",
515 w.WriteStartAttribute ("xpath", String.Empty);
516 if (c.ColumnMapping == MappingType.Attribute)
518 w.WriteString (ConstraintPrefix);
519 w.WriteString (XmlHelper.Encode (c.ColumnName));
520 w.WriteEndAttribute ();
521 w.WriteEndElement (); // field
524 w.WriteEndElement (); // keyref
527 // ExtendedProperties
529 private bool CheckExtendedPropertyExists (
531 DataRelation[] relations)
533 if (dataSetProperties.Count > 0)
535 foreach (DataTable dt in tables) {
536 if (dt.ExtendedProperties.Count > 0)
538 foreach (DataColumn col in dt.Columns)
539 if (col.ExtendedProperties.Count > 0)
541 foreach (Constraint c in dt.Constraints)
542 if (c.ExtendedProperties.Count > 0)
545 if (relations == null)
547 foreach (DataRelation rel in relations)
548 if (rel.ExtendedProperties.Count > 0)
553 private void AddExtendedPropertyAttributes (PropertyCollection props)
555 // add extended properties to xs:element
556 foreach (DictionaryEntry de in props) {
557 w.WriteStartAttribute (
558 XmlConstants.MspropPrefix,
559 XmlConvert.EncodeName (de.Key.ToString ()),
560 XmlConstants.MspropNamespace);
561 if (de.Value != null)
563 DataSet.WriteObjectXml (de.Value));
564 w.WriteEndAttribute ();
570 private void WriteTableElement (DataTable table)
572 w.WriteStartElement ("xs", "element", xmlnsxs);
573 w.WriteAttributeString ("name", XmlHelper.Encode (table.TableName));
575 AddExtendedPropertyAttributes (table.ExtendedProperties);
577 WriteTableType (table);
579 w.WriteEndElement ();
582 private void WriteTableType (DataTable table)
588 DataSet.SplitColumns (table, out atts, out elements, out simple);
590 w.WriteStartElement ("xs", "complexType", xmlnsxs);
592 if (simple != null) {
593 w.WriteStartElement ("xs", "simpleContent", xmlnsxs);
594 // add column name attribute
595 w.WriteAttributeString (
596 XmlConstants.MsdataPrefix,
597 XmlConstants.ColumnName,
598 XmlConstants.MsdataNamespace,
599 XmlHelper.Encode (simple.ColumnName));
601 // add ordinal attribute
602 w.WriteAttributeString (
603 XmlConstants.MsdataPrefix,
604 XmlConstants.Ordinal,
605 XmlConstants.MsdataNamespace,
606 XmlConvert.ToString (simple.Ordinal));
609 w.WriteStartElement ("xs", "extension",
611 w.WriteStartAttribute ("base", String.Empty);
612 WriteQName (MapType (simple.DataType));
613 w.WriteEndAttribute ();
615 WriteTableAttributes (atts);
617 w.WriteEndElement ();
619 WriteTableAttributes (atts);
620 bool isNested = false;
621 foreach (DataRelation rel in table.ParentRelations) {
628 // When we have a nested relationship and only one table,
629 // could be that we have a reference attribute
630 if (elements.Count > 0 || (isNested && tables.Length < 2)) {
631 w.WriteStartElement ("xs", "sequence",
634 foreach (DataColumn col in elements)
635 WriteTableTypeParticles (col);
637 foreach (DataRelation rel in table.ChildRelations)
639 WriteChildRelations (rel);
640 w.WriteEndElement ();
644 w.WriteFullEndElement (); // complexType
647 private void WriteTableTypeParticles (DataColumn col)
649 w.WriteStartElement ("xs", "element", xmlnsxs);
650 w.WriteAttributeString ("name", XmlHelper.Encode (col.ColumnName));
652 if (col.ColumnName != col.Caption && col.Caption != String.Empty)
653 w.WriteAttributeString (
654 XmlConstants.MsdataPrefix,
655 XmlConstants.Caption,
656 XmlConstants.MsdataNamespace,
659 if (col.AutoIncrement == true)
660 w.WriteAttributeString (
661 XmlConstants.MsdataPrefix,
662 XmlConstants.AutoIncrement,
663 XmlConstants.MsdataNamespace,
666 if (col.AutoIncrementSeed != 0) {
667 w.WriteAttributeString (
669 XmlConstants.MsdataPrefix,
670 XmlConstants.AutoIncrementSeed,
671 XmlConstants.MsdataNamespace,
672 XmlConvert.ToString (col.AutoIncrementSeed));
675 if (col.AutoIncrementStep != 1) {
676 w.WriteAttributeString (
678 XmlConstants.MsdataPrefix,
679 XmlConstants.AutoIncrementStep,
680 XmlConstants.MsdataNamespace,
681 XmlConvert.ToString (col.AutoIncrementStep));
684 if (!DataColumn.GetDefaultValueForType (col.DataType).Equals (col.DefaultValue))
685 w.WriteAttributeString ("default",
686 DataSet.WriteObjectXml (col.DefaultValue));
689 w.WriteAttributeString (
690 XmlConstants.MsdataPrefix,
691 XmlConstants.ReadOnly,
692 XmlConstants.MsdataNamespace,
695 XmlQualifiedName typeQName = null;
696 if (col.MaxLength < 0) {
697 w.WriteStartAttribute ("type", String.Empty);
698 typeQName = MapType (col.DataType);
699 WriteQName (typeQName);
700 w.WriteEndAttribute ();
703 if (typeQName == XmlConstants.QnString
704 && col.DataType != typeof (string)
705 && col.DataType != typeof (char)) {
706 w.WriteStartAttribute (
707 XmlConstants.MsdataPrefix,
708 XmlConstants.DataType,
709 XmlConstants.MsdataNamespace);
710 string runtimeName = col.DataType.AssemblyQualifiedName;
711 w.WriteString (runtimeName);
712 w.WriteEndAttribute ();
716 w.WriteAttributeString ("minOccurs", "0");
718 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
719 // XmlConstants.Ordinal,
720 // XmlConstants.MsdataNamespace,
721 // col.Ordinal.ToString ());
723 AddExtendedPropertyAttributes (col.ExtendedProperties);
725 // Write SimpleType if column have MaxLength
726 if (col.MaxLength > -1)
727 WriteSimpleType (col);
729 w.WriteEndElement (); // sequence
732 private void WriteChildRelations (DataRelation rel)
734 // If there is a parent/child relation and only one table,
735 // it would just be a ref element.
736 if (rel.ChildTable.Namespace != dataSetNamespace ||
738 w.WriteStartElement ("xs", "element", xmlnsxs);
739 w.WriteStartAttribute ("ref", String.Empty);
740 w.WriteQualifiedName (
741 XmlHelper.Encode (rel.ChildTable.TableName),
742 rel.ChildTable.Namespace);
743 w.WriteEndAttribute ();
745 w.WriteStartElement ("xs", "element", xmlnsxs);
746 w.WriteStartAttribute ("name", String.Empty);
747 w.WriteQualifiedName (
748 XmlHelper.Encode (rel.ChildTable.TableName),
749 rel.ChildTable.Namespace);
750 w.WriteEndAttribute ();
751 w.WriteAttributeString ("minOccurs", "0");
752 w.WriteAttributeString ("maxOccurs", "unbounded");
754 globalTypeTables.Add (rel.ChildTable);
757 // Iff there is a genuine ChildTable and not just a ref, call WriteTableType
758 if (tables.Length > 1)
759 WriteTableType (rel.ChildTable);
760 w.WriteEndElement ();
763 private void WriteTableAttributes (ArrayList atts)
765 //Then a list of attributes
766 foreach (DataColumn col in atts) {
767 w.WriteStartElement ("xs", "attribute", xmlnsxs);
769 string name = XmlHelper.Encode (col.ColumnName);
770 if (col.Namespace != String.Empty) {
771 w.WriteAttributeString ("form", "qualified");
772 string prefix = col.Prefix == String.Empty ? "app" + additionalNamespaces.Count : col.Prefix;
773 name = prefix + ":" + name;
774 // FIXME: Handle prefix mapping correctly.
775 additionalNamespaces [prefix] = col.Namespace;
777 w.WriteAttributeString ("name", name);
779 AddExtendedPropertyAttributes (
780 col.ExtendedProperties);
783 w.WriteAttributeString (
784 XmlConstants.MsdataPrefix,
785 XmlConstants.ReadOnly,
786 XmlConstants.MsdataNamespace,
789 if (col.MaxLength < 0) {
790 // otherwise simpleType is written later
791 w.WriteStartAttribute ("type", String.Empty);
792 WriteQName (MapType (col.DataType));
793 w.WriteEndAttribute ();
796 if (!col.AllowDBNull)
797 w.WriteAttributeString ("use", "required");
798 if (col.DefaultValue != DataColumn.GetDefaultValueForType (col.DataType))
799 w.WriteAttributeString ("default",
800 DataSet.WriteObjectXml (col.DefaultValue));
802 if (col.MaxLength > -1)
803 WriteSimpleType (col);
805 w.WriteEndElement (); // attribute
809 private void WriteSimpleType (DataColumn col)
811 w.WriteStartElement ("xs", "simpleType", xmlnsxs);
812 w.WriteStartElement ("xs", "restriction", xmlnsxs);
813 w.WriteStartAttribute ("base", String.Empty);
814 WriteQName (MapType (col.DataType));
815 w.WriteEndAttribute ();
817 w.WriteStartElement ("xs", "maxLength", xmlnsxs);
818 w.WriteAttributeString ("value",
819 XmlConvert.ToString (col.MaxLength));
820 w.WriteEndElement (); // maxLength
821 w.WriteEndElement (); // restriction
822 w.WriteEndElement (); // simpleType
825 private void WriteQName (XmlQualifiedName name)
827 w.WriteQualifiedName (name.Name, name.Namespace);
830 private void CheckNamespace (string prefix, string ns, ListDictionary names, ListDictionary includes)
832 if (ns == String.Empty)
834 if (dataSetNamespace != ns) {
835 if ((string)names [prefix] != ns) {
836 for (int i = 1; i < int.MaxValue; i++) {
837 string p = "app" + i;
838 if (names [p] == null) {
840 HandleExternalNamespace (p, ns, includes);
848 private void HandleExternalNamespace (string prefix, string ns, ListDictionary includes)
850 if (includes.Contains (ns))
851 return; // nothing to do
852 includes.Add (ns, "_" + prefix + ".xsd");
855 private /*static*/ XmlQualifiedName MapType (Type type)
857 switch (Type.GetTypeCode (type)) {
858 case TypeCode.String: return XmlConstants.QnString;
859 case TypeCode.Int16: return XmlConstants.QnShort;
860 case TypeCode.Int32: return XmlConstants.QnInt;
861 case TypeCode.Int64: return XmlConstants.QnLong;
862 case TypeCode.Boolean: return XmlConstants.QnBoolean;
863 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
864 //case TypeCode.Char: return XmlConstants.QnChar;
865 case TypeCode.DateTime: return XmlConstants.QnDateTime;
866 case TypeCode.Decimal: return XmlConstants.QnDecimal;
867 case TypeCode.Double: return XmlConstants.QnDouble;
868 case TypeCode.SByte: return XmlConstants.QnSbyte;
869 case TypeCode.Single: return XmlConstants.QnFloat;
870 case TypeCode.UInt16: return XmlConstants.QnUnsignedShort;
871 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
872 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
875 if (typeof (TimeSpan) == type)
876 return XmlConstants.QnDuration;
877 else if (typeof (System.Uri) == type)
878 return XmlConstants.QnUri;
879 else if (typeof (byte[]) == type)
880 return XmlConstants.QnBase64Binary;
881 else if (typeof (XmlQualifiedName) == type)
882 return XmlConstants.QnXmlQualifiedName;
884 return XmlConstants.QnString;