* DataSet.cs :
[mono.git] / mcs / class / System.Data / System.Data / XmlSchemaMapper.cs
1 //
2 // mcs/class/System.Data/System.Data/XmlSchemaMapper.cs
3 //
4 // Purpose: Maps XmlSchema to DataSet 
5 //
6 // class: XmlSchemaMapper
7 // assembly: System.Data.dll
8 // namespace: System.Data
9 //
10 // Author:
11 //     Ville Palo <vi64pa@koti.soon.fi>
12 //
13 // (C) 2002 Ville Palo
14 //
15 //
16
17 using System;
18 using System.Data;
19 using System.Xml;
20 using System.Xml.Schema;
21 using System.Collections;
22 using System.Globalization;
23
24 namespace System.Data {
25
26         internal class XmlSchemaMapper
27         {       
28                 #region Fields
29
30                 private DataSet DSet;
31                 private DataTable table;
32                 enum ElementType {ELEMENT_UNDEFINED, ELEMENT_TABLE, ELEMENT_COLUMN};
33                 private Hashtable TypeCollection = new Hashtable ();
34                 private Hashtable ElementCollection = new Hashtable ();
35
36                 #endregion // Fields
37
38                 #region Constructors
39
40                 public XmlSchemaMapper (DataSet dataset)
41                 {
42                         DSet = dataset;
43                 }
44
45                 public XmlSchemaMapper (DataTable datatable)
46                 {
47                         table = datatable;
48                 }
49                 
50                 #endregion // Constructors
51
52                 #region Public methods
53
54                 public void Read (XmlReader Reader)
55                 {
56                         XmlSchema Schema = XmlSchema.Read (Reader, new ValidationEventHandler (OnXmlSchemaValidation));
57                         if (Reader.NodeType == XmlNodeType.Element)
58                                 Reader.ReadEndElement ();
59                         if (DSet != null) DSet.Namespace = Schema.TargetNamespace;
60
61                         // read items
62                         foreach (XmlSchemaObject Item in Schema.Items)
63                                 ReadXmlSchemaItem (Item);
64                 }
65
66                 #endregion // Public methods
67
68                 #region Private methods
69
70                 private void ReadXmlSchemaItem (XmlSchemaObject Item)
71                 {
72                         XmlSchemaObject SchemaObject;
73                         
74                         if (Item is XmlSchemaType)
75                                 ReadXmlSchemaType ((XmlSchemaType)Item);
76                         else if (Item is XmlSchemaElement)
77                                 ReadXmlSchemaElement (Item as XmlSchemaElement, ElementType.ELEMENT_UNDEFINED);
78                 }
79
80                 private void ReadXmlSchemaSequence (XmlSchemaSequence Sequence)
81                 {
82                         ReadXmlSchemaSequence (Sequence, null);
83                 }
84
85                 private void ReadXmlSchemaSequence (XmlSchemaSequence Sequence, DataTable Table)
86                 {
87                         foreach (XmlSchemaObject TempObj in Sequence.Items) {
88                                 if (TempObj is XmlSchemaElement){
89                                         XmlSchemaElement schemaElement = (XmlSchemaElement)TempObj;
90                                         // the element can be a Column or a Table
91                                         // tables do not have a type.
92                                         if (schemaElement.SchemaTypeName.Name.Length > 0 || (schemaElement.SchemaType is XmlSchemaSimpleType))
93                                                 ReadXmlSchemaElement (schemaElement, ElementType.ELEMENT_COLUMN, Table);
94                                         else
95                                                 ReadXmlSchemaElement (schemaElement, ElementType.ELEMENT_TABLE, Table);
96                                 }
97                         }
98                 }
99
100                 private void ReadXmlSchemaChoice (XmlSchemaChoice Choice)
101                 {
102                         XmlSchemaObject SchemaObject;
103                         foreach (XmlSchemaObject TempObject in Choice.Items) {
104                                 if ((SchemaObject = TempObject as XmlSchemaElement) != null)
105                                         ReadXmlSchemaElement ((XmlSchemaElement)SchemaObject, ElementType.ELEMENT_TABLE);
106                         }
107                 }
108
109                 private void ReadXmlSchemaElement (XmlSchemaElement Element)
110                 {
111                         ReadXmlSchemaElement (Element, ElementType.ELEMENT_UNDEFINED);
112                 }
113
114                 private void ReadXmlSchemaElement (XmlSchemaElement Element, ElementType ElType)
115                 {
116                         ReadXmlSchemaElement (Element, ElType, null);
117                 }
118
119                 private void ReadXmlSchemaElement (XmlSchemaElement Element, ElementType ElType, DataTable Table)
120                 {
121                         Hashtable Attributes = ReadUnhandledAttributes (Element.UnhandledAttributes);
122                         DataTable Table2 = null;
123
124                         if (Attributes.Contains (XmlConstants.IsDataSet)) { // DataSet -elemt
125                         
126                                 if (String.Compare (Attributes [XmlConstants.IsDataSet].ToString (), "true", true) == 0 && DSet != null)
127                                         DSet.DataSetName = Element.Name;
128
129                                 if (Attributes.Contains (XmlConstants.Locale)) {
130                                         CultureInfo cinfo = new CultureInfo((String)Attributes [XmlConstants.Locale]);
131                                         if (DSet != null) DSet.Locale = cinfo;
132                                         else table.Locale = cinfo;
133                                 }
134                         }
135                         else if (Element.SchemaTypeName != null && Element.SchemaTypeName.Namespace != XmlConstants.SchemaNamespace 
136                                  && Element.SchemaTypeName.Name != String.Empty) {
137
138                                 //
139                                 // If type is not standard type
140                                 //
141
142                                 if (DSet == null) throw new InvalidOperationException ("Schema not valid for a DataTable");
143                                 
144                                 DataTable TempTable = new DataTable (Element.Name);
145                                 DSet.Tables.Add (TempTable);
146                                 
147                                 // If type is already defined in schema read it...                              
148                                 if (TypeCollection.Contains (Element.SchemaTypeName.ToString ()))
149                                         ReadXmlSchemaType ((XmlSchemaType)TypeCollection [Element.SchemaTypeName.ToString ()], TempTable);
150                                 else // but if it's not yet defined put it safe to wait if we need it later. 
151                                         ElementCollection.Add (Element.SchemaTypeName.Name, TempTable);
152
153                         }
154                         else if (Element.RefName != null && Element.RefName.Name != string.Empty) { // if there is a ref=
155
156                                 if (ElementCollection.Contains (Element.RefName.Name))
157                                         ReadXmlSchemaElement ((XmlSchemaElement)ElementCollection [Element.RefName.Name], ElementType.ELEMENT_TABLE);
158                         }
159                         else if (ElementType.ELEMENT_UNDEFINED != ElType) {
160                                 
161                                 if (ElType == ElementType.ELEMENT_TABLE){
162                                         ReadTable (Element);
163                                         // we have to return else all child element of the table will be computed again.
164                                         return;
165                                 }
166                                 else if (ElType == ElementType.ELEMENT_COLUMN && Table != null)
167                                         ReadColumn (Element, Table);
168                         }
169                         else {
170                                 // this element is undefined, for now
171                                 ElementCollection.Add (Element.Name, Element);
172                         }
173
174                         // Read Element type
175                         if (Element.SchemaType != null)
176                                 ReadXmlSchemaType (Element.SchemaType);
177
178                         // Read possible constraints
179                         if (Element.Constraints != null && Element.Constraints.Count > 0){
180                                 ReadXmlSchemaConstraints (Element.Constraints);
181                         }
182                 }
183
184                 private void ReadTable (XmlSchemaElement Element)
185                 {
186                         DataTable TempTable = null;
187                         
188                         // Add the table to the DataSet only if it is not already in there.
189                         if (DSet != null) {
190                                 if (DSet.Tables.Contains (Element.Name)) return;
191                                 TempTable = new DataTable (Element.Name);
192                                 DSet.Tables.Add (TempTable);
193                         }
194                         else {
195                                 if (table.TableName.Length != 0) 
196                                         throw new InvalidOperationException ("More than one table is defined in this schema");
197                                 table.TableName = Element.Name;
198                                 TempTable = table;
199                         }
200                         ReadXmlSchemaType (Element.SchemaType, TempTable);
201                 }
202
203                 private void ReadColumn (XmlSchemaElement Element, DataTable Table)
204                 {
205                         DataColumn Column = new DataColumn (Element.Name);
206                         Column.DataType = GetColumnType(Element.SchemaTypeName.Name);
207                         Table.Columns.Add (Column);
208
209                         if (Element.UnhandledAttributes != null) {
210                                 
211                                 foreach (XmlAttribute Attr in Element.UnhandledAttributes) {
212                                         switch (Attr.LocalName) {
213                                                 
214                                         case XmlConstants.Caption:
215                                                 Column.Caption = Attr.Value;
216                                                 break;
217                                         case XmlConstants.DataType:
218                                                 Column.DataType = Type.GetType (Attr.Value);
219                                                 break;
220                                         case XmlConstants.AutoIncrement:
221                                                 Column.AutoIncrement = bool.Parse(Attr.Value);
222                                                 break;
223                                         case XmlConstants.AutoIncrementSeed:
224                                                 Column.AutoIncrementSeed = int.Parse(Attr.Value);
225                                                 break;
226                                         default:
227                                                 break;
228                                         }
229                                 }
230                         }
231
232                         //
233                         // Handel rest of the parameters
234                         //
235
236                         if (Column.DataType == null)
237                                 Column.DataType = Type.GetType ("System.String");
238                         
239                         if (Element.DefaultValue != null)
240                                 Column.DefaultValue = Element.DefaultValue;
241
242                         // If Element have type
243                         if (Element.SchemaType != null)
244                                 ReadXmlSchemaType (Element.SchemaType, Column);
245
246                 }
247
248                 private Type GetColumnType (String typeName)
249                 {
250                         if (typeName == null || typeName.Length == 0)
251                                 return typeof (string);
252                         Type t;
253                         switch (typeName) {
254                         case "char":
255                                 t = typeof (char);
256                                 break;
257                         case "int" :
258                                 t = typeof (int);
259                                 break;
260                         case "unsignedInt" :
261                                 t = typeof (uint);
262                                 break;
263                         case "unsignedByte" :
264                                 t = typeof (byte);
265                                 break;
266                         case "byte" :
267                                 t = typeof (sbyte);
268                                 break;
269                         case "short" :
270                                 t = typeof (short);
271                                 break;
272                         case "usignedShort" :
273                                 t = typeof (ushort);
274                                 break;
275                         case "long" :
276                                 t = typeof (long);
277                                 break;
278                         case "unsignedLong" :
279                                 t = typeof (ulong);
280                                 break;
281                         case "boolean" :
282                                 t = typeof (bool);
283                                 break;
284                         case "float" :
285                                 t = typeof (float);
286                                 break;
287                         case "double" :
288                                 t = typeof (double);
289                                 break;
290                         case "decimal" :
291                                 t = typeof (decimal);
292                                 break;
293                         case "dateTime" :
294                                 t = typeof (DateTime);
295                                 break;
296                         case "duration" :
297                                 t = typeof (TimeSpan);
298                                 break;
299                         case "base64Binary" :
300                                 t = typeof (byte[]);
301                                 break;
302                         default :
303                                 t = typeof (string);
304                                 break;
305                         }
306                         
307                         return t;
308                 }
309
310                 // Makes new Hashtable of the attributes.
311                 private Hashtable ReadUnhandledAttributes (XmlAttribute [] Attributes)
312                 {
313                         Hashtable Result = new Hashtable ();
314
315                         if (Attributes == null)
316                                 return Result;
317
318                         foreach (XmlAttribute attribute in Attributes) {
319                                 Result.Add (attribute.LocalName, attribute.Value);
320                         }
321                         
322                         return Result;
323                 }
324
325                 private void ReadXmlSchemaConstraints (XmlSchemaObjectCollection Constraints)
326                 {
327                         foreach (XmlSchemaObject Constraint in Constraints) {
328                                 if (Constraint is XmlSchemaUnique)
329                                         ReadXmlSchemaUnique ((XmlSchemaUnique)Constraint);
330                                 if (Constraint is XmlSchemaKeyref)
331                                         ReadXmlSchemaKeyref ((XmlSchemaKeyref)Constraint, Constraints);
332                         }
333                 }
334
335                 [MonoTODO()]
336                 private void ReadXmlSchemaUnique (XmlSchemaUnique Unique)
337                 {
338                         // FIXME: Parsing XPath
339                         string TableName = Unique.Selector.XPath;
340                         int index = TableName.IndexOf(':');
341                         if (index != -1)
342                                 TableName = TableName.Substring (index + 1);
343                         else if(TableName.StartsWith (".//"))
344                                 TableName = TableName.Substring (3);
345                         
346                         DataColumn [] Columns;
347                         DataTable Table = GetTable (TableName);
348                         if (Table != null) {
349                                 Columns = new DataColumn [Unique.Fields.Count];
350                                 int i = 0;
351                                 foreach (XmlSchemaXPath Field in Unique.Fields) {
352                                         string columnName = Field.XPath;
353                                         index = columnName.IndexOf (':');
354                                         if (index != -1)
355                                                 columnName = columnName.Substring (index + 1);
356                                         if (Table.Columns.Contains (columnName)) {
357                                                 Columns [i] = Table.Columns [columnName];
358                                                 i++;
359                                         }
360                                 }
361                                 
362                                 bool isPK = false;
363                                 // find if there is an attribute with the constraint name
364                                 // if not use the XmlSchemaUnique name.
365                                 string constraintName = Unique.Name;
366                                 if (Unique.UnhandledAttributes != null){
367                                         foreach (XmlAttribute attr in Unique.UnhandledAttributes){
368                                                 if (attr.LocalName == "ConstraintName"){
369                                                         constraintName = attr.Value;
370                                                 }
371                                                 else if (attr.LocalName == XmlConstants.PrimaryKey){
372                                                         isPK = bool.Parse(attr.Value);
373                                                 }
374
375                                         }
376                                 }
377                                 UniqueConstraint Constraint = new UniqueConstraint (constraintName, Columns, isPK);
378                                 Table.Constraints.Add (Constraint);
379                         }
380                 }
381
382                 [MonoTODO()]
383                 private void ReadXmlSchemaKeyref (XmlSchemaKeyref KeyRef, XmlSchemaObjectCollection collection) {
384                         
385                         if (DSet == null) return;       // Ignore relations for table-only schemas
386                         
387                         string TableName = KeyRef.Selector.XPath;
388                         int index = TableName.IndexOf(':');
389                         if (index != -1)
390                                 TableName = TableName.Substring (index + 1);
391                         else if (TableName.StartsWith (".//"))
392                                 TableName = TableName.Substring (3);
393                         DataColumn [] Columns;
394                         DataTable Table = GetTable (TableName);
395                         if (Table != null) {
396                                 Columns = new DataColumn [KeyRef.Fields.Count];
397                                 int i = 0;
398                                 foreach (XmlSchemaXPath Field in KeyRef.Fields) {
399                                         string columnName = Field.XPath;
400                                         index = columnName.IndexOf (':');
401                                         if (index != -1)
402                                                 columnName = columnName.Substring (index + 1);
403                                         if (Table.Columns.Contains (columnName)) {
404                                                 Columns [i] = Table.Columns [columnName];
405                                                 i++;
406                                         }
407                                 }
408                                 string name = KeyRef.Refer.Name;
409                                 // get the unique constraint for the releation
410                                 UniqueConstraint constraint = GetDSConstraint(name, collection);
411                                 // generate the FK.
412                                 ForeignKeyConstraint fkConstraint = new ForeignKeyConstraint(KeyRef.Name, constraint.Columns, Columns);
413                                 Table.Constraints.Add (fkConstraint);
414                                 // generate the relation.
415                                 DataRelation relation = new DataRelation(KeyRef.Name, constraint.Columns, Columns, false);
416                                 if (KeyRef.UnhandledAttributes != null){
417                                         foreach (XmlAttribute attr in KeyRef.UnhandledAttributes){
418                                                 if (attr.LocalName == "IsNested"){
419                                                         if (attr.Value == "true")
420                                                                 relation.Nested = true;
421                                                 }
422                                         }
423                                 }
424                                 relation.SetParentKeyConstraint (constraint);
425                                 relation.SetChildKeyConstraint (fkConstraint);
426
427                                 DSet.Relations.Add(relation);
428                         }
429                 }
430                 
431                 // get the unique constraint for the relation.
432                 // name - the name of the XmlSchemaUnique element
433                 private UniqueConstraint GetDSConstraint(string name, XmlSchemaObjectCollection collection)
434                 {
435                         // find the element in the constraint collection.
436                         foreach (XmlSchemaObject shemaObj in collection){
437                                 if (shemaObj is XmlSchemaUnique){
438                                         XmlSchemaUnique unique = (XmlSchemaUnique) shemaObj;
439                                         if (unique.Name == name){
440                                                 string tableName = unique.Selector.XPath;
441                                                 int index = tableName.IndexOf (':');
442                                                 if (index != -1)
443                                                         tableName = tableName.Substring (index + 1);
444                                                 else if (tableName.StartsWith (".//"))
445                                                         tableName = tableName.Substring (3);
446                                                 
447                                                 // find the table in the dataset.
448                                                 DataTable table = GetTable (tableName);
449                                                 if (table != null){
450                                                         
451                                                         string constraintName = unique.Name;
452                                                         // find if there is an attribute with the constraint name
453                                                         // if not use the XmlSchemaUnique name.
454                                                         if (unique.UnhandledAttributes != null){
455                                                                 foreach (XmlAttribute attr in unique.UnhandledAttributes){
456                                                                         if (attr.LocalName == "ConstraintName"){
457                                                                                 constraintName = attr.Value;
458                                                                                 break;
459                                                                         }
460                                                                 }
461                                                         }
462                                                         if (table.Constraints.Contains(constraintName))
463                                                                 return (UniqueConstraint)table.Constraints[constraintName];
464                                                 }
465
466                                         }
467                                 }
468                         }
469                         return null;
470                 }
471
472
473                 #endregion // Private methods
474
475                 #region Private listeners
476
477                 private void OnXmlSchemaValidation (object sender, ValidationEventArgs args)
478                 {
479                         ;
480                 }
481
482                 #endregion // Private listeners
483
484                 #region Private TypeReaders
485
486                 // Reads XmlSchemaType
487                 private void ReadXmlSchemaType (XmlSchemaType SchemaType)
488                 {
489                         ReadXmlSchemaType (SchemaType, (DataTable)null);
490                 }
491
492                 // Reads XmlSchemaType and decides is it Complex or Simple and continue reading those types
493                 private void ReadXmlSchemaType (XmlSchemaType SchemaType, DataTable Table)
494                 {
495                         if (SchemaType is XmlSchemaComplexType)
496                                 ReadXmlSchemaComplexType ((XmlSchemaComplexType)SchemaType, Table);
497                         else if (SchemaType is XmlSchemaSimpleType)
498                                 ReadXmlSchemaSimpleType ((XmlSchemaSimpleType)SchemaType, Table);
499                 }
500
501                 // Same as above but with DataColumn
502                 private void ReadXmlSchemaType (XmlSchemaType SchemaType, DataColumn Column)
503                 {
504                         if (SchemaType is XmlSchemaComplexType)
505                                 ReadXmlSchemaComplexType ((XmlSchemaComplexType)SchemaType, Column);
506                         else if (SchemaType is XmlSchemaSimpleType)
507                                 ReadXmlSchemaSimpleType ((XmlSchemaSimpleType)SchemaType, Column);
508                 }
509
510                 #endregion // PrivateTypeReader
511
512                 #region TypeReaderHelppers
513
514                 private void ReadXmlSchemaSimpleType (XmlSchemaSimpleType SimpleType, DataColumn Column)
515                 {
516                         // Read Contents
517                         if (SimpleType.Content is XmlSchemaSimpleTypeRestriction)
518                                 ReadXmlSchemaSimpleTypeRestriction ((XmlSchemaSimpleTypeRestriction)SimpleType.Content, Column);
519                 }
520
521                 [MonoTODO]
522                 private void ReadXmlSchemaSimpleType (XmlSchemaSimpleType SimpleType, DataTable Table)
523                 {
524                         // TODO: Is it possible that Table-element have simpletype???
525                 }
526
527                 [MonoTODO]
528                 private void ReadXmlSchemaSimpleTypeRestriction (XmlSchemaSimpleTypeRestriction Restriction, DataColumn Column)
529                 {
530                         foreach (XmlSchemaObject Facet in Restriction.Facets) {
531                                 
532                                 // FIXME: I dont know are everyone of these needed but, let them be here for now
533                                 if (Facet is XmlSchemaMaxLengthFacet) 
534                                         Column.MaxLength = Int32.Parse(((XmlSchemaFacet)Facet).Value);
535                                 //else if (Facet is XmlSchemaMinLengthFacet) 
536                                 //      ;
537                                 //else if (Facet is XmlSchemaLengthFacet)
538                                 //      ;
539                                 //else if (Facet is XmlSchemaPatternFacet)
540                                 //      ;
541                                 //else if (Facet is XmlSchemaEnumerationFacet)
542                                 //      ;
543                                 //else if (Facet is XmlSchemaMaxInclusiveFacet)
544                                 //      ;
545                                 //else if (Facet is XmlSchemaMaxExclusiveFacet)
546                                 //      ;
547                                 //else if (Facet is XmlSchemaMinInclusiveFacet)
548                                 //      ;
549                                 //else if (Facet is XmlSchemaMinExclusiveFacet)
550                                 //      ;
551                                 //else if (Facet is XmlSchemaFractionDigitsFacet)
552                                 //      ;
553                                 //else if (Facet is XmlSchemaTotalDigitsFacet)
554                                 //      ;
555                                 //else if (Facet is XmlSchemaWhiteSpaceFacet)
556                                 //      ;
557                         }
558                 }
559
560                 [MonoTODO]
561                 private void ReadXmlSchemaComplexType (XmlSchemaComplexType Type, DataColumn Column)
562                 {
563                         // TODO: is it possible that column-element have complextype
564                 }
565
566                 // Reads XmlSchemaComplexType with DataTable
567                 private void ReadXmlSchemaComplexType (XmlSchemaComplexType Type, DataTable Table)
568                 {
569                         XmlSchemaComplexType ComplexType = Type as XmlSchemaComplexType;
570                         
571                         if (ComplexType.Name != null && ComplexType.Name != string.Empty) {
572
573                                 if (ElementCollection.Contains (ComplexType.Name)) {
574
575                                         if (ComplexType.Particle is XmlSchemaChoice) {
576                                                 ReadXmlSchemaChoice (ComplexType.Particle as XmlSchemaChoice);
577                                         }
578                                         else if (ComplexType.Particle is XmlSchemaSequence) {
579
580                                                 DataTable TempTable = ElementCollection [ComplexType.Name] as DataTable;
581                                                 ElementCollection.Remove (ComplexType.Name);
582                                                 ReadXmlSchemaSequence (ComplexType.Particle as XmlSchemaSequence, TempTable);
583                                         }
584                                 }
585                                 else if (ComplexType.Name != null && !TypeCollection.Contains (ComplexType.Name)) {
586                                         TypeCollection.Add (ComplexType.Name, ComplexType);
587                                 } 
588                                 else {
589
590                                         // If we are here it means that types of elements are Tables :-P
591                                         if (ComplexType.Particle is XmlSchemaSequence)
592                                                 ReadXmlSchemaSequence (ComplexType.Particle as XmlSchemaSequence, Table);
593                                 }
594
595                         }
596                         else {
597                                 XmlSchemaParticle Particle;
598                                 if ((Particle = ComplexType.Particle as XmlSchemaChoice) != null) {
599                                         ReadXmlSchemaChoice (Particle as XmlSchemaChoice);
600                                 }
601                                 else if ((Particle = ComplexType.Particle as XmlSchemaSequence) != null) {
602                                         ReadXmlSchemaSequence (Particle as XmlSchemaSequence, Table);
603                                 }
604                                 
605                                 // read columns if they were written as simplecontent.
606                                 XmlSchemaSimpleContent simpleContent;
607                                 if ((simpleContent = ComplexType.ContentModel as XmlSchemaSimpleContent) != null){
608                                         ReadColumn (simpleContent, Table);
609                                 }
610                                 
611                                 // read columns if they were written as attributes
612                                 if (ComplexType.Attributes != null) {
613                                 
614                                         foreach (XmlSchemaObject sobj in ComplexType.Attributes) {
615                                                 if (sobj is XmlSchemaAttribute)
616                                                         ReadColumn ((XmlSchemaAttribute)sobj, Table);
617                                         }
618                                 }
619                         }
620                 }
621
622                 private void ReadColumn (XmlSchemaSimpleContent simpleContent, DataTable Table)
623                 {
624                         DataColumn Column = new DataColumn ();
625                         
626
627                         if (simpleContent.UnhandledAttributes != null) {
628                                 
629                                 foreach (XmlAttribute Attr in simpleContent.UnhandledAttributes) {
630                                         switch (Attr.LocalName) {
631                                                 
632                                         case XmlConstants.ColumnName:
633                                                 Column.ColumnName = Attr.Value;
634                                                 break;
635                                         default:
636                                                 break;
637                                         }
638                                 }
639                         }\r
640                         \r
641                         \r
642                         XmlSchemaSimpleContentExtension extension;\r
643                         if ((extension = simpleContent.Content as XmlSchemaSimpleContentExtension) != null) {\r
644                                 Column.DataType = GetColumnType (extension.BaseTypeName.Name);  \r
645                         }\r
646 \r
647                         Table.Columns.Add (Column);
648                 }
649
650                 private void ReadColumn (XmlSchemaAttribute schemaAttribute, DataTable table)
651                 {
652                         DataColumn column = new DataColumn (schemaAttribute.Name);
653                         column.DataType = GetColumnType (schemaAttribute.SchemaTypeName.Name);
654                         table.Columns.Add (column);
655                 }
656                 
657                 DataTable GetTable (string name)
658                 {
659                         if (DSet != null)
660                                 return DSet.Tables [name];
661                         else if (name == table.TableName) 
662                                 return table;
663                         else
664                                 throw new InvalidOperationException ("Schema not valid for table '" + table.TableName + "'");
665                 }
666                 
667                 #endregion // TypeReaderHelppers
668         }
669 }
670