1 //------------------------------------------------------------------------------
2 // <copyright file="XMLSchema.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
9 namespace System.Data {
11 using System.Data.Common;
13 using System.Xml.Schema;
14 using System.Diagnostics;
15 using System.Collections;
16 using System.Collections.Generic;
17 using System.Globalization;
18 using System.ComponentModel;
19 using System.Security;
20 using System.Security.Permissions;
22 internal class XMLSchema {
24 internal static TypeConverter GetConverter(Type type) {
26 HostProtectionAttribute protAttrib = new HostProtectionAttribute();
27 protAttrib.SharedState = true;
28 CodeAccessPermission permission = (CodeAccessPermission)protAttrib.CreatePermission();
32 return TypeDescriptor.GetConverter(type);
36 CodeAccessPermission.RevertAssert();
41 internal static void SetProperties(Object instance, XmlAttributeCollection attrs) {
42 // This is called from both XSD and XDR schemas.
43 // Do we realy need it in XSD ???
44 for (int i = 0; i < attrs.Count; i++) {
45 if (attrs[i].NamespaceURI == Keywords.MSDNS) {
46 string name = attrs[i].LocalName;
47 string value = attrs[i].Value;
49 if (name == "DefaultValue" || name == "RemotingFormat")
51 // Webdata 97925, skipp expressions, we will handle them after SetProperties (in xdrschema)
52 if (name == "Expression" && instance is DataColumn)
55 PropertyDescriptor pd = TypeDescriptor.GetProperties(instance)[name];
58 Type type = pd.PropertyType;
60 TypeConverter converter = XMLSchema.GetConverter(type);
62 if (converter.CanConvertFrom(typeof(string))) {
63 propValue = converter.ConvertFromString(value);
64 }else if (type == typeof(Type)) {
65 propValue = DataStorage.GetType(value);
66 }else if (type == typeof(CultureInfo)) {
67 propValue = new CultureInfo(value);
69 throw ExceptionBuilder.CannotConvert(value,type.FullName);
71 pd.SetValue(instance, propValue);
77 internal static bool FEqualIdentity(XmlNode node, String name, String ns) {
78 if (node != null && node.LocalName == name && node.NamespaceURI == ns)
84 internal static bool GetBooleanAttribute(XmlElement element, String attrName, String attrNS, bool defVal) {
85 string value = element.GetAttribute(attrName, attrNS);
86 if (value == null || value.Length == 0) {
89 if ((value == Keywords.TRUE) || (value == Keywords.ONE_DIGIT)){
92 if ((value == Keywords.FALSE) || (value == Keywords.ZERO_DIGIT)){
96 throw ExceptionBuilder.InvalidAttributeValue(attrName, value);
99 internal static string GenUniqueColumnName(string proposedName, DataTable table) {
101 if (table.Columns.IndexOf(proposedName) >= 0) {
102 for (int i=0; i <= table.Columns.Count; i++) {
103 string tempName = proposedName + "_" + (i).ToString(CultureInfo.InvariantCulture);
104 if (table.Columns.IndexOf(tempName) >= 0) {
116 internal sealed class ConstraintTable {
117 public DataTable table;
118 public XmlSchemaIdentityConstraint constraint;
119 public ConstraintTable(DataTable t, XmlSchemaIdentityConstraint c) {
125 internal sealed class XSDSchema : XMLSchema
127 XmlSchemaSet _schemaSet = null;
128 XmlSchemaElement dsElement = null;
130 String _schemaName = null;
131 private ArrayList ColumnExpressions;
132 private Hashtable ConstraintNodes;
133 private ArrayList RefTables;
134 private ArrayList complexTypes;
135 XmlSchemaObjectCollection annotations;
136 XmlSchemaObjectCollection elements;
137 Hashtable attributes;
138 Hashtable elementsTable;
139 Hashtable attributeGroups;
140 Hashtable schemaTypes;
141 Hashtable expressions;
142 Dictionary <DataTable, List<DataTable>> tableDictionary;
144 Hashtable udSimpleTypes;
146 Hashtable existingSimpleTypeMap;
148 private bool fromInference = false;
150 internal bool FromInference {
152 return fromInference;
155 fromInference = value;
159 private void CollectElementsAnnotations(XmlSchema schema){
160 ArrayList schemaList = new ArrayList();
161 CollectElementsAnnotations(schema, schemaList);
165 private void CollectElementsAnnotations(XmlSchema schema, ArrayList schemaList){
166 if (schemaList.Contains(schema)) {
169 schemaList.Add(schema);
171 foreach(object item in schema.Items) {
172 if (item is XmlSchemaAnnotation) {
173 annotations.Add((XmlSchemaAnnotation)item);
175 if (item is XmlSchemaElement) {
176 XmlSchemaElement elem = (XmlSchemaElement)item;
178 elementsTable[elem.QualifiedName] = elem;
180 if (item is XmlSchemaAttribute) {
181 XmlSchemaAttribute attr = (XmlSchemaAttribute)item;
182 attributes[attr.QualifiedName] = attr;
184 if (item is XmlSchemaAttributeGroup) {
185 XmlSchemaAttributeGroup attr = (XmlSchemaAttributeGroup)item;
186 attributeGroups[attr.QualifiedName] = attr;
188 if (item is XmlSchemaType) {
189 string MSDATATargetNamespace = null;
190 if (item is XmlSchemaSimpleType) {
191 MSDATATargetNamespace = XSDSchema.GetMsdataAttribute((XmlSchemaType)item, Keywords.TARGETNAMESPACE);
194 XmlSchemaType type = (XmlSchemaType)item;
195 schemaTypes[type.QualifiedName] = type;
197 // Webdata 92054 if we have a User Defined simple type, cache it so later we may need for mapping
198 // meanwhile more convinient solution would be to directly use schemaTypes, but it would be more complex to handle
199 XmlSchemaSimpleType xmlSimpleType = (item as XmlSchemaSimpleType );
200 if (xmlSimpleType != null) {
201 if (udSimpleTypes == null) {
202 udSimpleTypes = new Hashtable();
205 udSimpleTypes[type.QualifiedName.ToString()] = xmlSimpleType;
206 DataColumn dc = (DataColumn)existingSimpleTypeMap[type.QualifiedName.ToString()];
207 // Assumption is that our simple type qualified name ihas the same output as XmlSchemaSimpleType type.QualifiedName.ToString()
208 SimpleType tmpSimpleType = (dc != null)? dc.SimpleType: null;
210 if (tmpSimpleType != null) {
211 SimpleType tmpDataSimpleType = new SimpleType(xmlSimpleType);
212 string errorStr = tmpSimpleType.HasConflictingDefinition(tmpDataSimpleType);
213 if (errorStr.Length != 0) {
214 throw ExceptionBuilder.InvalidDuplicateNamedSimpleTypeDelaration(tmpDataSimpleType.SimpleTypeQualifiedName, errorStr);
221 foreach(XmlSchemaExternal include in schema.Includes) {
222 if (include is XmlSchemaImport)
224 if (include.Schema != null) {
225 CollectElementsAnnotations(include.Schema, schemaList);
230 internal static string QualifiedName(string name) {
231 int iStart = name.IndexOf(':');
233 return Keywords.XSD_PREFIXCOLON + name;
238 internal static void SetProperties(Object instance, XmlAttribute[] attrs) {
239 // This is called from both XSD and XDR schemas.
240 // Do we realy need it in XSD ???
243 for (int i = 0; i < attrs.Length; i++) {
244 if (attrs[i].NamespaceURI == Keywords.MSDNS) {
245 string name = attrs[i].LocalName;
246 string value = attrs[i].Value;
248 if (name == "DefaultValue" || name == "Ordinal" || name == "Locale" || name == "RemotingFormat")
251 if (name == "Expression" && instance is DataColumn) // Webdata 97925: we will handle columnexpressions at HandleColumnExpression
254 if (name == "DataType") {
255 DataColumn col = instance as DataColumn;
257 col.DataType = DataStorage.GetType(value);
263 PropertyDescriptor pd = TypeDescriptor.GetProperties(instance)[name];
266 Type type = pd.PropertyType;
268 TypeConverter converter = XMLSchema.GetConverter(type);
270 if (converter.CanConvertFrom(typeof(string))) {
271 propValue = converter.ConvertFromString(value);
272 }else if (type == typeof(Type)) {
273 propValue = Type.GetType(value);
274 }else if (type == typeof(CultureInfo)) {
275 propValue = new CultureInfo(value);
277 throw ExceptionBuilder.CannotConvert(value,type.FullName);
279 pd.SetValue(instance, propValue);
285 private static void SetExtProperties(Object instance, XmlAttribute[] attrs) {
286 PropertyCollection props = null;
289 for (int i = 0; i < attrs.Length; i++) {
290 if (attrs[i].NamespaceURI == Keywords.MSPROPNS) {
292 object val = TypeDescriptor.GetProperties(instance)["ExtendedProperties"].GetValue(instance);
293 Debug.Assert(val is PropertyCollection, "We can set values only for classes that have ExtendedProperties");
294 props = (PropertyCollection) val;
296 string propName = XmlConvert.DecodeName(attrs[i].LocalName);
298 if (instance is ForeignKeyConstraint) {
299 if (propName.StartsWith(Keywords.MSD_FK_PREFIX, StringComparison.Ordinal))
300 propName = propName.Substring(3);
304 if ((instance is DataRelation) && (propName.StartsWith(Keywords.MSD_REL_PREFIX, StringComparison.Ordinal))) {
305 propName = propName.Substring(4);
307 else if ((instance is DataRelation) && (propName.StartsWith(Keywords.MSD_FK_PREFIX, StringComparison.Ordinal))) {
311 props.Add(propName, attrs[i].Value);
316 private void HandleColumnExpression(Object instance, XmlAttribute[] attrs) {
319 DataColumn dc = instance as DataColumn;
320 Debug.Assert(dc != null, "HandleColumnExpression is supposed to be called for DataColumn");
322 for (int i = 0; i < attrs.Length; i++) {
323 if (attrs[i].NamespaceURI == Keywords.MSDNS) {
324 if (attrs[i].LocalName == "Expression"){
325 if (this.expressions == null)
326 this.expressions = new Hashtable();
327 this.expressions[dc] = attrs[i].Value;
328 ColumnExpressions.Add(dc);
336 internal static String GetMsdataAttribute(XmlSchemaAnnotated node, String ln) {
337 XmlAttribute[] nodeAttributes = node.UnhandledAttributes;
338 if (nodeAttributes!=null)
339 for(int i=0; i<nodeAttributes.Length;i++)
340 if (nodeAttributes[i].LocalName == ln && nodeAttributes[i].NamespaceURI == Keywords.MSDNS)
341 return nodeAttributes[i].Value;
345 private static void SetExtProperties(Object instance, XmlAttributeCollection attrs) {
346 PropertyCollection props = null;
347 for (int i = 0; i < attrs.Count; i++) {
348 if (attrs[i].NamespaceURI == Keywords.MSPROPNS) {
350 object val = TypeDescriptor.GetProperties(instance)["ExtendedProperties"].GetValue(instance);
351 Debug.Assert(val is PropertyCollection, "We can set values only for classes that have ExtendedProperties");
352 props = (PropertyCollection) val;
354 string propName = XmlConvert.DecodeName(attrs[i].LocalName);
355 props.Add(propName, attrs[i].Value);
360 internal void HandleRefTableProperties(ArrayList RefTables, XmlSchemaElement element) {
361 string typeName = GetInstanceName(element);
362 DataTable table = _ds.Tables.GetTable(XmlConvert.DecodeName(typeName), element.QualifiedName.Namespace);
363 Debug.Assert(table != null, "ref table should have been already created");
365 SetProperties(table, element.UnhandledAttributes);
366 SetExtProperties(table, element.UnhandledAttributes);
369 internal void HandleRelation(XmlElement node, bool fNested) {
373 string [] parentNames;
374 string [] childNames;
376 bool fCreateConstraints = false; //if we have a relation,
377 //we do not have constraints
378 DataRelationCollection rels = _ds.Relations;
379 DataRelation relation;
380 DataColumn [] parentKey;
381 DataColumn [] childKey;
386 strName = XmlConvert.DecodeName(node.GetAttribute(Keywords.NAME));
387 for (int i = 0; i < rels.Count; ++i) {
388 if (0 == String.Compare(rels[i].RelationName, strName, StringComparison.Ordinal))
392 parentName = node.GetAttribute(Keywords.MSD_PARENT, Keywords.MSDNS);
393 if (parentName == null || parentName.Length==0)
394 throw ExceptionBuilder.RelationParentNameMissing(strName);
395 parentName = XmlConvert.DecodeName(parentName);
397 childName = node.GetAttribute(Keywords.MSD_CHILD, Keywords.MSDNS);
398 if (childName == null || childName.Length==0)
399 throw ExceptionBuilder.RelationChildNameMissing(strName);
400 childName = XmlConvert.DecodeName(childName);
402 value = node.GetAttribute(Keywords.MSD_PARENTKEY, Keywords.MSDNS);
403 if (value == null || value.Length==0)
404 throw ExceptionBuilder.RelationTableKeyMissing(strName);
406 parentNames = value.TrimEnd(null).Split(new char[] {Keywords.MSD_KEYFIELDSEP, Keywords.MSD_KEYFIELDOLDSEP});
407 value = node.GetAttribute(Keywords.MSD_CHILDKEY, Keywords.MSDNS);
408 if (value == null || value.Length==0)
409 throw ExceptionBuilder.RelationChildKeyMissing(strName);
411 childNames = value.TrimEnd(null).Split(new char[] {Keywords.MSD_KEYFIELDSEP, Keywords.MSD_KEYFIELDOLDSEP});
413 keyLength = parentNames.Length;
414 if (keyLength != childNames.Length)
415 throw ExceptionBuilder.MismatchKeyLength();
417 parentKey = new DataColumn[keyLength];
418 childKey = new DataColumn[keyLength];
420 string parentNs = node.GetAttribute(Keywords.MSD_PARENTTABLENS, Keywords.MSDNS);
421 string childNs = node.GetAttribute(Keywords.MSD_CHILDTABLENS, Keywords.MSDNS);
423 parent = _ds.Tables.GetTableSmart(parentName,parentNs);
426 throw ExceptionBuilder.ElementTypeNotFound(parentName);
428 child = _ds.Tables.GetTableSmart(childName,childNs);
431 throw ExceptionBuilder.ElementTypeNotFound(childName);
433 for (int i = 0; i < keyLength; i++) {
434 parentKey[i] = parent.Columns[XmlConvert.DecodeName(parentNames[i])];
435 if (parentKey[i] == null)
436 throw ExceptionBuilder.ElementTypeNotFound(parentNames[i]);
437 childKey[i] = child.Columns[XmlConvert.DecodeName(childNames[i])];
438 if (childKey[i] == null)
439 throw ExceptionBuilder.ElementTypeNotFound(childNames[i]);
441 relation = new DataRelation(strName, parentKey, childKey, fCreateConstraints);
442 relation.Nested = fNested;
443 SetExtProperties(relation, node.Attributes);
444 _ds.Relations.Add(relation);
445 if (FromInference && relation.Nested) {
446 tableDictionary[relation.ParentTable].Add(relation.ChildTable);
450 private bool HasAttributes(XmlSchemaObjectCollection attributes){
451 foreach (XmlSchemaObject so in attributes) {
452 if (so is XmlSchemaAttribute) {
455 if (so is XmlSchemaAttributeGroup) {
458 if (so is XmlSchemaAttributeGroupRef) {
465 private bool IsDatasetParticle(XmlSchemaParticle pt){
466 XmlSchemaObjectCollection items = GetParticleItems(pt);
469 return false; // empty element, threat it as table
471 bool isChoice = this.FromInference && (pt is XmlSchemaChoice);// currently we add this support for choice, just for inference
474 foreach (XmlSchemaAnnotated el in items){
475 if (el is XmlSchemaElement) {
477 // pushing max occur of choice element to its imidiate children of type xs:elements
478 if (isChoice && pt.MaxOccurs > Decimal.One && (((XmlSchemaElement)el).SchemaType is XmlSchemaComplexType)) // we know frominference condition
479 ((XmlSchemaElement)el).MaxOccurs = pt.MaxOccurs;
481 if (((XmlSchemaElement)el).RefName.Name.Length != 0) {
482 if (!FromInference || (((XmlSchemaElement)el).MaxOccurs != Decimal.One && !(((XmlSchemaElement)el).SchemaType is XmlSchemaComplexType)))
487 if (!IsTable ((XmlSchemaElement)el))
493 if (el is XmlSchemaParticle) {
494 if (!IsDatasetParticle((XmlSchemaParticle)el))
502 private int DatasetElementCount(XmlSchemaObjectCollection elements) {
504 foreach(XmlSchemaElement XmlElement in elements) {
505 if (GetBooleanAttribute(XmlElement, Keywords.MSD_ISDATASET, /*default:*/ false)) {
512 private XmlSchemaElement FindDatasetElement(XmlSchemaObjectCollection elements) {
513 foreach(XmlSchemaElement XmlElement in elements) {
514 if (GetBooleanAttribute(XmlElement, Keywords.MSD_ISDATASET, /*default:*/ false))
517 if ((elements.Count == 1) || (this.FromInference && elements.Count > 0)) { //let's see if this element looks like a DataSet
519 XmlSchemaElement node = (XmlSchemaElement)elements[0];
520 if (!GetBooleanAttribute(node, Keywords.MSD_ISDATASET, /*default:*/ true))
523 XmlSchemaComplexType ct = node.SchemaType as XmlSchemaComplexType;
528 if (HasAttributes(ct.Attributes))
531 if (ct.ContentModel is XmlSchemaSimpleContent){
532 XmlSchemaAnnotated cContent = ((XmlSchemaSimpleContent) (ct.ContentModel)).Content;
533 if (cContent is XmlSchemaSimpleContentExtension) {
534 XmlSchemaSimpleContentExtension ccExtension = ((XmlSchemaSimpleContentExtension) cContent );
535 if (HasAttributes(ccExtension.Attributes))
538 XmlSchemaSimpleContentRestriction ccRestriction = ((XmlSchemaSimpleContentRestriction) cContent );
539 if (HasAttributes(ccRestriction.Attributes))
545 XmlSchemaParticle particle = GetParticle(ct);
546 if (particle != null) {
547 if (!IsDatasetParticle(particle))
548 return null; // it's a table
551 if (ct.BaseXmlSchemaType is XmlSchemaComplexType)
552 ct = (XmlSchemaComplexType)ct.BaseXmlSchemaType;
558 //if we are here there all elements are tables
564 public void LoadSchema(XmlSchemaSet schemaSet , DataTable dt) {
565 if (dt.DataSet != null)
566 LoadSchema(schemaSet, dt.DataSet);
568 public void LoadSchema(XmlSchemaSet schemaSet , DataSet ds) { //Element schemaRoot, DataSet ds) {
569 ConstraintNodes = new Hashtable();
570 RefTables = new ArrayList();
571 ColumnExpressions = new ArrayList();
572 complexTypes = new ArrayList();
573 bool setRootNStoDataSet = false;
574 bool newDataSet = (ds.Tables.Count == 0);
576 if (schemaSet == null) //
578 _schemaSet = schemaSet;
580 ds.fIsSchemaLoading = true;
582 foreach (XmlSchema schemaRoot in schemaSet.Schemas()) {
583 _schemaName = schemaRoot.Id;
585 if (_schemaName == null ||_schemaName.Length == 0) {
586 _schemaName = "NewDataSet";
588 ds.DataSetName = XmlConvert.DecodeName(_schemaName);
589 string ns = schemaRoot.TargetNamespace;
590 if (ds.namespaceURI == null || ds.namespaceURI.Length == 0) {// set just one time, for backward compatibility
591 ds.namespaceURI = (ns== null)? string.Empty : ns; // see fx\Data\XDO\ReadXml\SchemaM2.xml for more info
593 break; // we just need to take Name and NS from first schema [V1.0 & v1.1 semantics]
596 annotations = new XmlSchemaObjectCollection();
597 elements = new XmlSchemaObjectCollection();
598 elementsTable = new Hashtable();
599 attributes = new Hashtable();
600 attributeGroups = new Hashtable();
601 schemaTypes = new Hashtable();
602 tableDictionary = new Dictionary <DataTable, List<DataTable>>() ;
604 existingSimpleTypeMap = new Hashtable();
605 foreach(DataTable dt in ds.Tables){
606 foreach(DataColumn dc in dt.Columns) {
607 if (dc.SimpleType!= null && dc.SimpleType.Name != null && dc.SimpleType.Name.Length != 0) {
608 existingSimpleTypeMap[dc.SimpleType.SimpleTypeQualifiedName] = dc;
609 // existingSimpleTypeMap[dc.SimpleType.SimpleTypeQualifiedName] = dc.SimpleType;
616 foreach (XmlSchema schemaRoot in schemaSet.Schemas())
617 CollectElementsAnnotations(schemaRoot);
621 dsElement = FindDatasetElement(elements);
622 if (dsElement != null) {
623 string mainName = GetStringAttribute (dsElement, Keywords.MSD_MAINDATATABLE, "");
624 if (null != mainName) {
625 ds.MainTableName = XmlConvert.DecodeName (mainName);
629 if (this.FromInference) {
630 ds.fTopLevelTable = true; // Backward compatability: for inference, if we do not read DataSet element
632 // we should not write it also
633 setRootNStoDataSet = true;
634 //incase of Root is not mapped to DataSet and is mapped to DataTable instead; to be backward compatable
635 // we need to set the Namespace of Root to DataSet's namespace also(it would be NS of First DataTable in collection)
638 List<XmlQualifiedName> qnames = new List<XmlQualifiedName>();
640 if (ds != null && ds.UseDataSetSchemaOnly) {
641 int dataSetElementCount = DatasetElementCount(elements);
642 if (dataSetElementCount == 0) {
643 throw ExceptionBuilder.IsDataSetAttributeMissingInSchema();
645 else if (dataSetElementCount > 1) {
646 throw ExceptionBuilder.TooManyIsDataSetAtributeInSchema();
649 XmlSchemaComplexType ct = (XmlSchemaComplexType) FindTypeNode(dsElement);
650 if (ct.Particle != null) {
651 XmlSchemaObjectCollection items = GetParticleItems(ct.Particle);
653 foreach (XmlSchemaAnnotated el in items){
654 XmlSchemaElement sel = el as XmlSchemaElement;
656 if(sel.RefName.Name.Length != 0 ) {
657 qnames.Add(sel.QualifiedName);
666 // Walk all the top level Element tags.
667 foreach (XmlSchemaElement element in elements) {
668 if (element == dsElement)
670 if (ds != null && ds.UseDataSetSchemaOnly && dsElement != null) {
671 if (dsElement.Parent != element.Parent) {
672 if (!qnames.Contains(element.QualifiedName)) {
678 String typeName = GetInstanceName(element);
679 if (RefTables.Contains(element.QualifiedName.Namespace +":"+ typeName)) {
680 HandleRefTableProperties(RefTables, element);
684 DataTable table = HandleTable(element);
688 HandleDataSet(dsElement, newDataSet);
690 foreach (XmlSchemaAnnotation annotation in annotations) {
691 HandleRelations(annotation, false);
694 //just add Expressions, at this point and if ColumnExpressions.Count > 0, this.expressions should not be null
695 for(int i=0; i<ColumnExpressions.Count; i++) {
696 DataColumn dc = ((DataColumn)(ColumnExpressions[i]));
697 dc.Expression = (string) this.expressions[dc];
700 foreach (DataTable dt in ds.Tables) {
701 if (dt.NestedParentRelations.Length == 0 && dt.Namespace == ds.Namespace) {
702 DataRelationCollection childRelations = dt.ChildRelations;// WebData 113251 if we nulling NS of parent table,
703 for (int j = 0; j < childRelations.Count; j++) { // we need to do the same thing for nested child tables as they
704 if (childRelations[j].Nested && dt.Namespace == childRelations[j].ChildTable.Namespace) { // take NS from Parent table
705 childRelations[j].ChildTable.tableNamespace = null;
708 dt.tableNamespace = null;
712 DataTable tmpTable = ds.Tables[ds.DataSetName, ds.Namespace];
713 if ( tmpTable != null) // this fix is done to support round-trip problem in case if there is one table with same name and NS
714 tmpTable.fNestedInDataset = true;
717 // this fix is for backward compatability with old inference engine
718 if (this.FromInference && ds.Tables.Count == 0 && String.Compare(ds.DataSetName, "NewDataSet", StringComparison.Ordinal) == 0)
719 ds.DataSetName = XmlConvert.DecodeName(((XmlSchemaElement)elements[0]).Name);
722 ds.fIsSchemaLoading = false; //reactivate column computations
725 //for backward compatability; we need to set NS of Root Element to DataSet, if root already does not mapped to dataSet
726 if (setRootNStoDataSet) {
727 if (ds.Tables.Count > 0) { // if there is table, take first one's NS
728 ds.Namespace = ds.Tables[0].Namespace;
729 ds.Prefix = ds.Tables[0].Prefix;
731 else {// otherwise, take TargetNS from first schema
732 Debug.Assert(schemaSet.Count == 1, "there should be one schema");
733 foreach (XmlSchema schemaRoot in schemaSet.Schemas()) { // we should have 1 schema
734 ds.Namespace = schemaRoot.TargetNamespace;
740 private void HandleRelations(XmlSchemaAnnotation ann, bool fNested) {
741 foreach (object __items in ann.Items)
742 if (__items is XmlSchemaAppInfo) {
743 XmlNode[] relations = ((XmlSchemaAppInfo) __items).Markup;
744 for (int i = 0; i<relations.Length; i++)
745 if (FEqualIdentity(relations[i], Keywords.MSD_RELATION, Keywords.MSDNS))
746 HandleRelation((XmlElement)relations[i], fNested);
750 internal XmlSchemaObjectCollection GetParticleItems(XmlSchemaParticle pt){
751 if (pt is XmlSchemaSequence)
752 return ((XmlSchemaSequence)pt).Items;
753 if (pt is XmlSchemaAll)
754 return ((XmlSchemaAll)pt).Items;
755 if (pt is XmlSchemaChoice)
756 return ((XmlSchemaChoice)pt).Items;
757 if (pt is XmlSchemaAny)
759 // the code below is a little hack for the SOM behavior
760 if (pt is XmlSchemaElement) {
761 XmlSchemaObjectCollection Items = new XmlSchemaObjectCollection();
765 if (pt is XmlSchemaGroupRef)
766 return GetParticleItems( ((XmlSchemaGroupRef)pt).Particle );
767 // should never get here.
772 internal void HandleParticle(XmlSchemaParticle pt, DataTable table, ArrayList tableChildren, bool isBase){
773 XmlSchemaObjectCollection items = GetParticleItems(pt);
778 foreach (XmlSchemaAnnotated item in items){
779 XmlSchemaElement el = item as XmlSchemaElement;
781 if (this.FromInference && pt is XmlSchemaChoice && pt.MaxOccurs > Decimal.One && (el.SchemaType is XmlSchemaComplexType))
782 ((XmlSchemaElement)el).MaxOccurs = pt.MaxOccurs;
785 DataTable child = null;
786 // to decide if element is our table, we need to match both name and ns
787 // 286043 - SQL BU Defect Tracking
788 if (((el.Name == null) && (el.RefName.Name == table.EncodedTableName && el.RefName.Namespace == table.Namespace)) ||
789 (IsTable(el) && el.Name == table.TableName)) {
790 if (this.FromInference) {
791 child = HandleTable ((XmlSchemaElement)el);
792 Debug.Assert(child == table, "table not the same");
799 child = HandleTable ((XmlSchemaElement)el);
800 if (child == null && this.FromInference && el.Name == table.TableName) {
806 if (!this.FromInference || el.Name != table.TableName) {// check is required to support 1.1 inference behavior
807 HandleElementColumn((XmlSchemaElement)el, table, isBase);
811 DataRelation relation = null;
812 if (el.Annotation != null)
813 HandleRelations(el.Annotation, true);
815 DataRelationCollection childRelations = table.ChildRelations;
816 for (int j = 0; j < childRelations.Count; j++) {
817 if (!childRelations[j].Nested)
820 if (child == childRelations[j].ChildTable)
821 relation = childRelations[j];
824 if (relation == null) {
825 tableChildren.Add(child);// how about prefix for this?
826 if(this.FromInference && table.UKColumnPositionForInference == -1) { // this is done for Inference
827 int ukColumnPosition = -1;
828 foreach(DataColumn dc in table.Columns) {
829 if (dc.ColumnMapping == MappingType.Element)
832 table.UKColumnPositionForInference = ukColumnPosition + 1; // since it starts from
838 HandleParticle((XmlSchemaParticle)item, table, tableChildren, isBase);
845 internal void HandleAttributes(XmlSchemaObjectCollection attributes, DataTable table, bool isBase) {
846 foreach (XmlSchemaObject so in attributes) {
847 if (so is XmlSchemaAttribute) {
848 HandleAttributeColumn((XmlSchemaAttribute) so, table, isBase);
850 else { // XmlSchemaAttributeGroupRef
851 XmlSchemaAttributeGroupRef groupRef = so as XmlSchemaAttributeGroupRef;
852 XmlSchemaAttributeGroup schemaGroup = attributeGroups[groupRef.RefName] as XmlSchemaAttributeGroup;
853 if (schemaGroup!=null) {
854 HandleAttributeGroup(schemaGroup, table, isBase);
860 private void HandleAttributeGroup(XmlSchemaAttributeGroup attributeGroup, DataTable table, bool isBase) {
861 foreach (XmlSchemaObject obj in attributeGroup.Attributes) {
862 if (obj is XmlSchemaAttribute) {
863 HandleAttributeColumn((XmlSchemaAttribute) obj, table, isBase);
865 else { // XmlSchemaAttributeGroupRef
866 XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)obj;
867 XmlSchemaAttributeGroup attributeGroupResolved;
868 if (attributeGroup.RedefinedAttributeGroup != null && attributeGroupRef.RefName == new XmlQualifiedName(attributeGroup.Name, attributeGroupRef.RefName.Namespace)) {
869 attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroup.RedefinedAttributeGroup;
872 attributeGroupResolved = (XmlSchemaAttributeGroup)attributeGroups[attributeGroupRef.RefName];
874 if (attributeGroupResolved != null) {
875 HandleAttributeGroup(attributeGroupResolved, table, isBase);
880 internal void HandleComplexType(XmlSchemaComplexType ct, DataTable table, ArrayList tableChildren, bool isNillable){
881 if (complexTypes.Contains(ct))
882 throw ExceptionBuilder.CircularComplexType(ct.Name);
884 complexTypes.Add(ct);
887 if (ct.ContentModel != null) {
889 HandleParticle(ct.CompiledParticle, table, tableChildren, isBase);
890 foreach (XmlSchemaAttribute s in ct.Attributes){
891 HandleAttributeColumn(s, table, isBase);
896 if (ct.ContentModel is XmlSchemaComplexContent) {
897 XmlSchemaAnnotated cContent = ((XmlSchemaComplexContent) (ct.ContentModel)).Content;
898 if (cContent is XmlSchemaComplexContentExtension) {
899 XmlSchemaComplexContentExtension ccExtension = ((XmlSchemaComplexContentExtension) cContent );
900 if (!(ct.BaseXmlSchemaType is XmlSchemaComplexType && this.FromInference))
901 HandleAttributes(ccExtension.Attributes, table, isBase);
903 if (ct.BaseXmlSchemaType is XmlSchemaComplexType) {
904 HandleComplexType((XmlSchemaComplexType)ct.BaseXmlSchemaType, table, tableChildren, isNillable);
907 Debug.Assert(ct.BaseXmlSchemaType is XmlSchemaSimpleType, "Expected SimpleType or ComplexType");
908 if (ccExtension.BaseTypeName.Namespace != Keywords.XSDNS){
909 // this is UDSimpleType, pass Qualified name of type
910 HandleSimpleContentColumn(ccExtension.BaseTypeName.ToString(), table, isBase, ct.ContentModel.UnhandledAttributes, isNillable);
912 else { // it is built in type
913 HandleSimpleContentColumn(ccExtension.BaseTypeName.Name, table, isBase, ct.ContentModel.UnhandledAttributes, isNillable);
916 if (ccExtension.Particle != null)
917 HandleParticle(ccExtension.Particle, table, tableChildren, isBase);
918 if (ct.BaseXmlSchemaType is XmlSchemaComplexType && this.FromInference)
919 HandleAttributes(ccExtension.Attributes, table, isBase);
921 Debug.Assert(cContent is XmlSchemaComplexContentRestriction, "Expected complexContent extension or restriction");
922 XmlSchemaComplexContentRestriction ccRestriction = ((XmlSchemaComplexContentRestriction) cContent );
923 if (!this.FromInference)
924 HandleAttributes(ccRestriction.Attributes, table, isBase);
925 if (ccRestriction.Particle != null)
926 HandleParticle(ccRestriction.Particle, table, tableChildren, isBase);
927 if (this.FromInference)
928 HandleAttributes(ccRestriction.Attributes, table, isBase);
931 Debug.Assert(ct.ContentModel is XmlSchemaSimpleContent, "expected simpleContent or complexContent");
932 XmlSchemaAnnotated cContent = ((XmlSchemaSimpleContent) (ct.ContentModel)).Content;
933 if (cContent is XmlSchemaSimpleContentExtension) {
934 XmlSchemaSimpleContentExtension ccExtension = ((XmlSchemaSimpleContentExtension) cContent );
935 HandleAttributes(ccExtension.Attributes, table, isBase);
936 if (ct.BaseXmlSchemaType is XmlSchemaComplexType) {
937 HandleComplexType((XmlSchemaComplexType)ct.BaseXmlSchemaType, table, tableChildren, isNillable);
940 Debug.Assert(ct.BaseXmlSchemaType is XmlSchemaSimpleType, "Expected SimpleType or ComplexType");
941 HandleSimpleTypeSimpleContentColumn((XmlSchemaSimpleType)ct.BaseXmlSchemaType, ccExtension.BaseTypeName.Name, table, isBase, ct.ContentModel.UnhandledAttributes, isNillable);
944 Debug.Assert(cContent is XmlSchemaSimpleContentRestriction, "Expected SimpleContent extension or restriction");
945 XmlSchemaSimpleContentRestriction ccRestriction = ((XmlSchemaSimpleContentRestriction) cContent );
946 HandleAttributes(ccRestriction.Attributes, table, isBase);
954 if (!this.FromInference)
955 HandleAttributes(ct.Attributes, table, isBase);
956 if (ct.Particle != null)
957 HandleParticle(ct.Particle, table, tableChildren, isBase);
958 if (this.FromInference) {
959 HandleAttributes(ct.Attributes, table, isBase);
960 if (isNillable) // this is for backward compatability to support xsi:Nill=true
961 HandleSimpleContentColumn("string", table, isBase, null, isNillable);
965 complexTypes.Remove(ct);
968 internal XmlSchemaParticle GetParticle(XmlSchemaComplexType ct){
969 if (ct.ContentModel != null) {
970 if (ct.ContentModel is XmlSchemaComplexContent) {
971 XmlSchemaAnnotated cContent = ((XmlSchemaComplexContent) (ct.ContentModel)).Content;
972 if (cContent is XmlSchemaComplexContentExtension) {
973 return ((XmlSchemaComplexContentExtension) cContent ).Particle;
975 Debug.Assert(cContent is XmlSchemaComplexContentRestriction, "Expected complexContent extension or restriction");
976 return ((XmlSchemaComplexContentRestriction) cContent ).Particle;
979 Debug.Assert(ct.ContentModel is XmlSchemaSimpleContent, "expected simpleContent or complexContent");
991 internal DataColumn FindField(DataTable table, string field) {
992 bool attribute = false;
993 String colName = field;
995 if (field.StartsWith("@", StringComparison.Ordinal)) {
997 colName = field.Substring(1);
1000 String [] split = colName.Split(':');
1001 colName = split [split.Length - 1];
1003 colName = XmlConvert.DecodeName(colName);
1004 DataColumn col = table.Columns[colName];
1006 throw ExceptionBuilder.InvalidField(field);
1008 bool _attribute = (col.ColumnMapping == MappingType.Attribute) || (col.ColumnMapping == MappingType.Hidden);
1010 if (_attribute != attribute)
1011 throw ExceptionBuilder.InvalidField(field);
1016 internal DataColumn[] BuildKey(XmlSchemaIdentityConstraint keyNode, DataTable table){
1017 ArrayList keyColumns = new ArrayList();
1019 foreach (XmlSchemaXPath node in keyNode.Fields) {
1020 keyColumns.Add(FindField(table, node.XPath));
1023 DataColumn [] key = new DataColumn[keyColumns.Count];
1024 keyColumns.CopyTo(key, 0);
1029 internal bool GetBooleanAttribute(XmlSchemaAnnotated element, String attrName, bool defVal) {
1030 string value = GetMsdataAttribute(element, attrName);
1031 if (value == null || value.Length == 0) {
1034 if ((value == Keywords.TRUE) || (value == Keywords.ONE_DIGIT)){
1037 if ((value == Keywords.FALSE) || (value == Keywords.ZERO_DIGIT)){
1040 // Error processing:
1041 throw ExceptionBuilder.InvalidAttributeValue(attrName, value);
1044 internal String GetStringAttribute(XmlSchemaAnnotated element, String attrName, String defVal) {
1045 string value = GetMsdataAttribute(element, attrName);
1046 if (value == null || value.Length == 0) {
1054 <selector>../Customers</selector>
1058 <selector>.</selector>
1059 <field>CustID</field>
1063 internal static AcceptRejectRule TranslateAcceptRejectRule( string strRule ) {
1064 if (strRule == "Cascade")
1065 return AcceptRejectRule.Cascade;
1066 else if (strRule == "None")
1067 return AcceptRejectRule.None;
1069 return ForeignKeyConstraint.AcceptRejectRule_Default;
1072 internal static Rule TranslateRule( string strRule ) {
1073 if (strRule == "Cascade")
1074 return Rule.Cascade;
1075 else if (strRule == "None")
1077 else if (strRule == "SetDefault")
1078 return Rule.SetDefault;
1079 else if (strRule == "SetNull")
1080 return Rule.SetNull;
1082 return ForeignKeyConstraint.Rule_Default;
1085 internal void HandleKeyref(XmlSchemaKeyref keyref) {
1086 string refer = XmlConvert.DecodeName(keyref.Refer.Name); // check here!!!
1087 string name = XmlConvert.DecodeName(keyref.Name);
1088 name = GetStringAttribute( keyref, "ConstraintName", /*default:*/ name);
1090 // we do not process key defined outside the current node
1092 String tableName = GetTableName(keyref);
1094 string tableNs = GetMsdataAttribute(keyref,Keywords.MSD_TABLENS);
1096 DataTable table = _ds.Tables.GetTableSmart(tableName,tableNs);
1101 if (refer == null || refer.Length == 0)
1102 throw ExceptionBuilder.MissingRefer(name);
1104 ConstraintTable key = (ConstraintTable) ConstraintNodes[refer];
1107 throw ExceptionBuilder.InvalidKey(name);
1110 DataColumn[] pKey = BuildKey(key.constraint, key.table);
1111 DataColumn[] fKey = BuildKey(keyref, table);
1113 ForeignKeyConstraint fkc = null;
1115 if (GetBooleanAttribute(keyref, Keywords.MSD_CONSTRAINTONLY, /*default:*/ false)) {
1116 int iExisting = fKey[0].Table.Constraints.InternalIndexOf(name);
1117 if (iExisting > -1) {
1118 if (fKey[0].Table.Constraints[iExisting].ConstraintName != name)
1122 if (iExisting < 0) {
1123 fkc = new ForeignKeyConstraint( name, pKey, fKey );
1124 fKey[0].Table.Constraints.Add(fkc);
1128 string relName = XmlConvert.DecodeName(GetStringAttribute( keyref, Keywords.MSD_RELATIONNAME, keyref.Name));
1130 if (relName == null || relName.Length == 0)
1133 int iExisting = fKey[0].Table.DataSet.Relations.InternalIndexOf(relName);
1134 if (iExisting > -1) {
1135 if (fKey[0].Table.DataSet.Relations[iExisting].RelationName != relName)
1138 DataRelation relation = null;
1139 if (iExisting < 0) {
1140 relation = new DataRelation(relName, pKey, fKey);
1141 SetExtProperties(relation, keyref.UnhandledAttributes);
1142 pKey[0].Table.DataSet.Relations.Add(relation);
1144 if (FromInference && relation.Nested) {
1145 if (tableDictionary.ContainsKey(relation.ParentTable)) {
1146 tableDictionary[relation.ParentTable].Add(relation.ChildTable);
1150 fkc = relation.ChildKeyConstraint;
1151 fkc.ConstraintName = name;
1154 relation = fKey[0].Table.DataSet.Relations[iExisting];
1156 if (GetBooleanAttribute(keyref, Keywords.MSD_ISNESTED, /*default:*/ false)) {
1157 relation.Nested = true;
1162 string acceptRejectRule = GetMsdataAttribute(keyref, Keywords.MSD_ACCEPTREJECTRULE);
1163 string updateRule = GetMsdataAttribute(keyref, Keywords.MSD_UPDATERULE);
1164 string deleteRule = GetMsdataAttribute(keyref, Keywords.MSD_DELETERULE);
1167 if (acceptRejectRule != null)
1168 fkc.AcceptRejectRule = TranslateAcceptRejectRule(acceptRejectRule);
1170 if (updateRule != null)
1171 fkc.UpdateRule = TranslateRule(updateRule);
1173 if (deleteRule != null)
1174 fkc.DeleteRule = TranslateRule(deleteRule);
1176 SetExtProperties(fkc, keyref.UnhandledAttributes);
1181 internal void HandleConstraint(XmlSchemaIdentityConstraint keyNode){
1184 name = XmlConvert.DecodeName(keyNode.Name);
1185 if (name==null || name.Length==0)
1186 throw ExceptionBuilder.MissingAttribute(Keywords.NAME);
1188 if (ConstraintNodes.ContainsKey(name))
1189 throw ExceptionBuilder.DuplicateConstraintRead(name);
1191 // we do not process key defined outside the current node
1192 String tableName = GetTableName(keyNode);
1193 string tableNs = GetMsdataAttribute(keyNode,Keywords.MSD_TABLENS);
1195 DataTable table = _ds.Tables.GetTableSmart(tableName,tableNs);
1200 ConstraintNodes.Add(name, new ConstraintTable(table, keyNode));
1202 bool fPrimaryKey = GetBooleanAttribute(keyNode, Keywords.MSD_PRIMARYKEY, /*default:*/ false);
1203 name = GetStringAttribute(keyNode, "ConstraintName", /*default:*/ name);
1207 DataColumn[] key = BuildKey(keyNode, table);
1209 if (0 < key.Length) {
1210 UniqueConstraint found = (UniqueConstraint) key[0].Table.Constraints.FindConstraint(new UniqueConstraint(name, key));
1212 if (found == null) {
1213 key[0].Table.Constraints.Add(name, key, fPrimaryKey);
1214 SetExtProperties(key[0].Table.Constraints[name], keyNode.UnhandledAttributes);
1217 key = found.ColumnsReference;
1218 SetExtProperties(found, keyNode.UnhandledAttributes);
1220 key[0].Table.PrimaryKey = key;
1222 if (keyNode is XmlSchemaKey) {
1223 for (int i=0; i<key.Length; i++)
1224 key[i].AllowDBNull = false;
1229 internal DataTable InstantiateSimpleTable(XmlSchemaElement node) {
1231 String typeName = XmlConvert.DecodeName(GetInstanceName(node));
1234 _TableUri = node.QualifiedName.Namespace;
1235 table = _ds.Tables.GetTable(typeName, _TableUri);
1241 /* if (table!=null) {
1242 throw ExceptionBuilder.DuplicateDeclaration(typeName);
1245 if (!FromInference && table!=null) {
1246 throw ExceptionBuilder.DuplicateDeclaration(typeName);
1250 if (table == null) {
1251 table = new DataTable( typeName);
1252 table.Namespace = _TableUri;
1253 // If msdata:targetNamespace node on element, then use it to override table.Namespace.
1254 table.Namespace = GetStringAttribute(node, "targetNamespace", _TableUri);
1256 if (!this.FromInference) {
1257 table.MinOccurs = node.MinOccurs;
1258 table.MaxOccurs = node.MaxOccurs;
1261 string prefix = GetPrefix(_TableUri);
1263 table.Prefix = prefix;
1266 SetProperties(table, node.UnhandledAttributes);
1267 SetExtProperties(table, node.UnhandledAttributes);
1271 XmlSchemaComplexType ct = node.SchemaType as XmlSchemaComplexType;
1272 // We assume node.ElementSchemaType.BaseSchemaType to be null for
1273 // <xs:element name="foo"/> and not null for <xs:element name="foo" type="xs:string"/>
1274 bool isSimpleContent = ((node.ElementSchemaType.BaseXmlSchemaType != null) ||(ct != null && ct.ContentModel is XmlSchemaSimpleContent));
1276 if (!FromInference ||(isSimpleContent && table.Columns.Count == 0 )) {// for inference backward compatability
1277 HandleElementColumn(node, table, false);
1280 if (this.FromInference) {
1282 colName = typeName + "_Text";
1283 while (table.Columns[colName] != null)
1284 colName = colName + i++;
1287 colName = typeName + "_Column";
1290 table.Columns[0].ColumnName = colName;
1291 table.Columns[0].ColumnMapping = MappingType.SimpleContent;
1294 if (!this.FromInference ||_ds.Tables.GetTable(typeName, _TableUri) == null) { // for inference; special case: add table if doesnot exists in collection
1295 _ds.Tables.Add(table);
1296 if (this.FromInference) {
1297 tableDictionary.Add(table, new List<DataTable>());
1301 // handle all the unique and key constraints related to this table
1303 if ((dsElement != null) && (dsElement.Constraints!=null)) {
1304 foreach (XmlSchemaIdentityConstraint key in dsElement.Constraints) {
1305 if (key is XmlSchemaKeyref)
1307 if (GetTableName(key) == table.TableName)
1308 HandleConstraint(key);
1311 table.fNestedInDataset = false;
1317 internal string GetInstanceName(XmlSchemaAnnotated node) {
1318 string instanceName = null;
1320 Debug.Assert( (node is XmlSchemaElement) || (node is XmlSchemaAttribute), "GetInstanceName should only be called on attribute or elements");
1322 if (node is XmlSchemaElement) {
1323 XmlSchemaElement el = (XmlSchemaElement) node;
1324 instanceName = el.Name != null ? el.Name : el.RefName.Name;
1326 else if (node is XmlSchemaAttribute) {
1327 XmlSchemaAttribute el = (XmlSchemaAttribute) node;
1328 instanceName = el.Name != null ? el.Name : el.RefName.Name;
1331 Debug.Assert((instanceName != null) && (instanceName.Length != 0), "instanceName cannot be null or empty. There's an error in the XSD compiler");
1333 return instanceName;
1336 // Sequences of handling Elements, Attributes and Text-only column should be the same as in InferXmlSchema
1337 internal DataTable InstantiateTable(XmlSchemaElement node, XmlSchemaComplexType typeNode, bool isRef) {
1339 String typeName = GetInstanceName(node);
1340 ArrayList tableChildren = new ArrayList();
1344 _TableUri = node.QualifiedName.Namespace;
1346 table = _ds.Tables.GetTable(XmlConvert.DecodeName(typeName), _TableUri);
1347 // TOD: Do not do this fix
1348 // if (table == null && node.RefName.IsEmpty && !IsTopLevelElement(node) && _TableUri != null && _TableUri.Length > 0) {
1349 // _TableUri = null; // it means form="qualified", so child element inherits namespace. [....]
1352 if (!FromInference || (FromInference && table == null))
1359 throw ExceptionBuilder.DuplicateDeclaration(typeName);
1363 RefTables.Add(_TableUri+":"+typeName);
1365 table = new DataTable(XmlConvert.DecodeName(typeName) );
1366 table.TypeName = node.SchemaTypeName;
1368 table.Namespace = _TableUri;
1369 table.Namespace = GetStringAttribute(node, "targetNamespace", _TableUri);
1371 //table.Prefix = node.Prefix;
1372 String value= GetStringAttribute(typeNode, Keywords.MSD_CASESENSITIVE, "") ;
1373 if (value.Length ==0)
1375 value= GetStringAttribute(node, Keywords.MSD_CASESENSITIVE, "") ;
1377 if (0 < value.Length) {
1378 if ((value == Keywords.TRUE) || (value == "True"))
1379 table.CaseSensitive = true;
1380 if ((value == Keywords.FALSE) || (value == "False"))
1381 table.CaseSensitive = false;
1384 value = GetMsdataAttribute(node, Keywords.MSD_LOCALE);
1385 if (null != value) { // set by user
1386 if (0 < value.Length) {
1387 // <... msdata:Locale="en-US"/>
1388 table.Locale = new CultureInfo(value);
1391 // everett bug behavior before <... msdata:Locale=""/> inherit from DataSet
1392 table.Locale = CultureInfo.InvariantCulture;
1396 // else inherit from DataSet, not set by user
1398 if (!this.FromInference)
1400 table.MinOccurs = node.MinOccurs;
1401 table.MaxOccurs = node.MaxOccurs;
1405 string prefix = GetPrefix(_TableUri);
1407 table.Prefix = prefix;
1410 _ds.Tables.Add(table);
1411 if (FromInference) {
1412 tableDictionary.Add(table, new List<DataTable>());
1416 HandleComplexType(typeNode, table, tableChildren, node.IsNillable);
1418 for (int i=0; i < table.Columns.Count ; i++)
1419 table.Columns[i].SetOrdinalInternal(i);
1422 if (xmlContent == XmlContent.Mixed) {
1423 string textColumn = GenUniqueColumnName(table.TableName+ "_Text", table);
1424 table.XmlText = new DataColumn(textColumn, typeof(string), null, MappingType.Text);
1427 SetProperties(table, node.UnhandledAttributes);
1428 SetExtProperties(table, node.UnhandledAttributes);
1430 // handle all the unique and key constraints related to this table
1431 if ((dsElement != null) && (dsElement.Constraints!=null)) {
1432 foreach (XmlSchemaIdentityConstraint key in dsElement.Constraints) {
1433 if (key is XmlSchemaKeyref)
1435 if (GetTableName(key) == table.TableName) {
1436 // respect the NS if it is specified for key, otherwise just go with table name check
1437 if( GetTableNamespace(key) == table.Namespace || GetTableNamespace(key) == null)
1438 HandleConstraint(key);
1439 /* if (GetTableNamespace(key) != null) {
1440 if (GetTableNamespace(key) == table.Namespace)
1441 HandleConstraint(key);
1444 HandleConstraint(key);
1451 foreach(DataTable _tableChild in tableChildren) {
1452 if (_tableChild != table && table.Namespace == _tableChild.Namespace)
1453 _tableChild.tableNamespace = null;
1455 if ((dsElement != null) && (dsElement.Constraints!=null)) {
1456 foreach (XmlSchemaIdentityConstraint key in dsElement.Constraints) {
1457 XmlSchemaKeyref keyref = key as XmlSchemaKeyref;
1461 bool isNested = GetBooleanAttribute(keyref, Keywords.MSD_ISNESTED, /*default:*/ false);
1464 if (GetTableName(keyref) == _tableChild.TableName) {
1465 if (_tableChild.DataSet.Tables.InternalIndexOf(_tableChild.TableName) < -1) { // if we have multiple tables with the same name
1466 if (GetTableNamespace(keyref) == _tableChild.Namespace) {
1467 HandleKeyref(keyref);
1471 HandleKeyref(keyref);
1477 DataRelation relation = null;
1479 DataRelationCollection childRelations = table.ChildRelations;
1480 for (int j = 0; j < childRelations.Count; j++) {
1481 if (!childRelations[j].Nested)
1484 if (_tableChild == childRelations[j].ChildTable)
1485 relation = childRelations[j];
1491 DataColumn parentKey;
1492 if (this.FromInference) {
1493 int position = table.UKColumnPositionForInference;// we keep posiotion of unique key column here, for inference
1495 foreach (DataColumn dc in table.Columns) {
1496 if (dc.ColumnMapping == MappingType.Attribute) {
1497 position = dc.Ordinal;
1501 parentKey = table.AddUniqueKey(position);
1505 parentKey = table.AddUniqueKey();
1508 // foreign key in the child table
1509 DataColumn childKey = _tableChild.AddForeignKey(parentKey);
1511 // when we add unique key, we do set prefix; but for Fk we do not do . So for backward compatability
1512 if (this.FromInference)
1513 childKey.Prefix = _tableChild.Prefix;
1514 // childKey.Prefix = GetPrefix(childKey.Namespace);
1516 // create relationship
1517 // setup relationship between parent and this table
1518 relation = new DataRelation(table.TableName + "_" + _tableChild.TableName, parentKey, childKey, true);
1519 relation.Nested = true;
1520 _tableChild.DataSet.Relations.Add(relation);
1521 if (FromInference && relation.Nested) {
1522 if (tableDictionary.ContainsKey(relation.ParentTable)) {
1523 tableDictionary[relation.ParentTable].Add(relation.ChildTable);
1531 private sealed class NameType : IComparable {
1532 public readonly String name;
1533 public readonly Type type;
1534 public NameType(String n, Type t) {
1538 public int CompareTo(object obj) { return String.Compare(name, (string)obj, StringComparison.Ordinal); }
1541 public static Type XsdtoClr(string xsdTypeName) {
1543 for(int i = 1; i < mapNameTypeXsd.Length; ++i) {
1544 Debug.Assert((mapNameTypeXsd[i-1].CompareTo(mapNameTypeXsd[i].name)) < 0, "incorrect sorting " + mapNameTypeXsd[i].name);
1547 int index = Array.BinarySearch(mapNameTypeXsd, xsdTypeName);
1549 throw ExceptionBuilder.UndefinedDatatype(xsdTypeName);
1551 return mapNameTypeXsd[index].type;
1554 // XSD spec: http://www.w3.org/TR/xmlschema-2/
1555 // April: http://www.w3.org/TR/2000/WD-xmlschema-2-20000407/datatypes.html
1556 // Fabr: http://www.w3.org/TR/2000/WD-xmlschema-2-20000225/
1557 private static readonly NameType[] mapNameTypeXsd = {
1558 new NameType("ENTITIES" , typeof(string) ), /* XSD Apr */
1559 new NameType("ENTITY" , typeof(string) ), /* XSD Apr */
1560 new NameType("ID" , typeof(string) ), /* XSD Apr */
1561 new NameType("IDREF" , typeof(string) ), /* XSD Apr */
1562 new NameType("IDREFS" , typeof(string) ), /* XSD Apr */
1563 new NameType("NCName" , typeof(string) ), /* XSD Apr */
1564 new NameType("NMTOKEN" , typeof(string) ), /* XSD Apr */
1565 new NameType("NMTOKENS" , typeof(string) ), /* XSD Apr */
1566 new NameType("NOTATION" , typeof(string) ), /* XSD Apr */
1567 new NameType("Name" , typeof(string) ), /* XSD Apr */
1568 new NameType("QName" , typeof(string) ), /* XSD Apr */
1570 new NameType("anyType" , typeof(System.Object) ), /* XSD Apr */
1571 new NameType("anyURI" , typeof(System.Uri) ), /* XSD Apr */
1572 new NameType("base64Binary" , typeof(Byte[]) ), /* XSD Apr : abstruct */
1573 new NameType("boolean" , typeof(bool) ), /* XSD Apr */
1574 new NameType("byte" , typeof(SByte) ), /* XSD Apr */
1575 new NameType("date" , typeof(DateTime)), /* XSD Apr */
1576 new NameType("dateTime" , typeof(DateTime)), /* XSD Apr */
1577 new NameType("decimal" , typeof(decimal) ), /* XSD 2001 [....] */
1578 new NameType("double" , typeof(double) ), /* XSD Apr */
1579 new NameType("duration" , typeof(TimeSpan)), /* XSD Apr */
1580 new NameType("float" , typeof(Single) ), /* XSD Apr */
1581 new NameType("gDay" , typeof(DateTime)), /* XSD Apr */
1582 new NameType("gMonth" , typeof(DateTime)), /* XSD Apr */
1583 new NameType("gMonthDay" , typeof(DateTime)), /* XSD Apr */
1584 new NameType("gYear" , typeof(DateTime)), /* XSD Apr */
1585 new NameType("gYearMonth" , typeof(DateTime)), /* XSD Apr */
1586 new NameType("hexBinary" , typeof(Byte[]) ), /* XSD Apr : abstruct */
1587 new NameType("int" , typeof(Int32) ), /* XSD Apr */
1588 new NameType("integer" , typeof(Int64) ), /* XSD Apr */ // <xs:element name="" msdata:DataType="System.Numerics.BigInteger" type="xs:integer" minOccurs="0" />
1589 new NameType("language" , typeof(string) ), /* XSD Apr */
1590 new NameType("long" , typeof(Int64) ), /* XSD Apr */
1591 new NameType("negativeInteger" , typeof(Int64) ), /* XSD Apr */
1592 new NameType("nonNegativeInteger" , typeof(UInt64) ), /* XSD Apr */
1593 new NameType("nonPositiveInteger" , typeof(Int64) ), /* XSD Apr */
1594 new NameType("normalizedString" , typeof(string) ), /* XSD Apr */
1595 new NameType("positiveInteger" , typeof(UInt64) ), /* XSD Apr */
1596 new NameType("short" , typeof(Int16) ), /* XSD Apr */
1597 new NameType("string" , typeof(string) ), /* XSD Apr */
1598 new NameType("time" , typeof(DateTime)), /* XSD Apr */
1599 new NameType("unsignedByte" , typeof(Byte) ), /* XSD Apr */
1600 new NameType("unsignedInt" , typeof(UInt32) ), /* XSD Apr */
1601 new NameType("unsignedLong" , typeof(UInt64) ), /* XSD Apr */
1602 new NameType("unsignedShort" , typeof(UInt16) ), /* XSD Apr */
1605 private static NameType FindNameType(string name) {
1607 for(int i = 1; i < mapNameTypeXsd.Length; ++i) {
1608 Debug.Assert((mapNameTypeXsd[i-1].CompareTo(mapNameTypeXsd[i].name)) < 0, "incorrect sorting " + mapNameTypeXsd[i].name);
1611 int index = Array.BinarySearch(mapNameTypeXsd, name);
1613 throw ExceptionBuilder.UndefinedDatatype(name);
1615 return mapNameTypeXsd[index];
1618 // input param dt is a "qName" for UDSimpleType else it assumes it's a XSD builtin simpleType
1619 private Type ParseDataType(string dt) {
1620 if (!IsXsdType(dt)) {
1621 if (udSimpleTypes != null) {
1622 XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) udSimpleTypes[dt];
1623 if (simpleType == null) { // it is not named simple type, it is not XSD type, it should be unsupported type like xs:token
1624 throw ExceptionBuilder.UndefinedDatatype(dt);
1626 SimpleType rootType = new SimpleType(simpleType);
1627 while (rootType.BaseSimpleType != null) {
1628 rootType = rootType.BaseSimpleType;
1631 return ParseDataType(rootType.BaseType);
1634 NameType nt = FindNameType(dt);
1637 /* later we may need such a function
1638 private Boolean IsUDSimpleType(string qname) {
1639 if (udSimpleTypes == null)
1641 return (udSimpleTypes.Contains(qname));
1644 internal static Boolean IsXsdType(string name) {
1646 for(int i = 1; i < mapNameTypeXsd.Length; ++i) {
1647 Debug.Assert((mapNameTypeXsd[i-1].CompareTo(mapNameTypeXsd[i].name)) < 0, "incorrect sorting " + mapNameTypeXsd[i].name);
1650 int index = Array.BinarySearch(mapNameTypeXsd, name);
1653 // Let's check that we realy don't have this name:
1654 foreach (NameType nt in mapNameTypeXsd) {
1655 Debug.Assert(nt.name != name, "FindNameType('" + name + "') -- failed. Existed name not found");
1660 Debug.Assert(mapNameTypeXsd[index].name == name, "FindNameType('" + name + "') -- failed. Wrong name found");
1665 internal XmlSchemaAnnotated FindTypeNode(XmlSchemaAnnotated node) {
1666 // this function is returning null
1667 // if the typeNode for node is in the XSD namespace.
1669 XmlSchemaAttribute attr = node as XmlSchemaAttribute;
1670 XmlSchemaElement el = node as XmlSchemaElement;
1671 bool isAttr = false;
1676 String _type = isAttr ? attr.SchemaTypeName.Name : el.SchemaTypeName.Name;
1677 String _typeNs = isAttr ? attr.SchemaTypeName.Namespace : el.SchemaTypeName.Namespace;
1678 if (_typeNs == Keywords.XSDNS)
1680 XmlSchemaAnnotated typeNode;
1681 if (_type == null || _type.Length == 0) {
1682 _type = isAttr ? attr.RefName.Name : el.RefName.Name;
1683 if (_type == null || _type.Length == 0)
1684 typeNode = (XmlSchemaAnnotated) (isAttr ? attr.SchemaType : el.SchemaType);
1686 typeNode = isAttr ? FindTypeNode((XmlSchemaAnnotated)attributes[attr.RefName]) :FindTypeNode((XmlSchemaAnnotated)elementsTable[el.RefName]);
1689 typeNode = (XmlSchemaAnnotated)schemaTypes[isAttr ? ((XmlSchemaAttribute)node).SchemaTypeName : ((XmlSchemaElement)node).SchemaTypeName];
1694 internal void HandleSimpleTypeSimpleContentColumn(XmlSchemaSimpleType typeNode, string strType, DataTable table, bool isBase, XmlAttribute[] attrs, bool isNillable){
1695 // disallow multiple simple content columns for the table
1696 if(FromInference && table.XmlText != null) { // backward compatability for inference
1701 SimpleType xsdType = null;
1703 // if (typeNode.QualifiedName.Namespace != Keywords.XSDNS) { // this means UDSimpleType
1704 if (typeNode.QualifiedName.Name != null && typeNode.QualifiedName.Name.Length != 0 && typeNode.QualifiedName.Namespace != Keywords.XSDNS) { // this means UDSimpleType
1705 xsdType = new SimpleType(typeNode);
1706 strType = typeNode.QualifiedName.ToString(); // use qualifed name
1707 type = ParseDataType(typeNode.QualifiedName.ToString());
1709 else {// previous code V 1.1
1710 XmlSchemaSimpleType ancestor = typeNode.BaseXmlSchemaType as XmlSchemaSimpleType;
1711 if ((ancestor != null) && (ancestor.QualifiedName.Namespace != Keywords.XSDNS)) {
1712 xsdType = new SimpleType(typeNode);
1713 SimpleType rootType = xsdType;
1715 while (rootType.BaseSimpleType != null) {
1716 rootType = rootType.BaseSimpleType;
1718 type = ParseDataType(rootType.BaseType);
1719 strType = xsdType.Name;
1722 type = ParseDataType(strType);
1730 if (this.FromInference) {
1732 colName = table.TableName + "_Text";
1733 while (table.Columns[colName] != null) {
1734 colName = colName + i++;
1738 colName = table.TableName + "_text";
1740 string columnName = colName;
1741 bool isToAdd = true;
1742 if ((!isBase) && (table.Columns.Contains(columnName, true))){
1743 column = table.Columns[columnName];
1747 column = new DataColumn(columnName, type, null, MappingType.SimpleContent);
1750 SetProperties(column, attrs);
1751 HandleColumnExpression(column, attrs);
1752 SetExtProperties(column, attrs);
1754 String tmp = (-1).ToString(CultureInfo.CurrentCulture);
1755 string defValue = null;
1756 //try to see if attributes contain allownull
1757 column.AllowDBNull = isNillable;
1760 for(int i=0; i< attrs.Length;i++) {
1761 if ( attrs[i].LocalName == Keywords.MSD_ALLOWDBNULL && attrs[i].NamespaceURI == Keywords.MSDNS)
1762 if ( attrs[i].Value == Keywords.FALSE)
1763 column.AllowDBNull = false;
1764 if ( attrs[i].LocalName == Keywords.MSD_ORDINAL && attrs[i].NamespaceURI == Keywords.MSDNS)
1765 tmp = attrs[i].Value;
1766 if ( attrs[i].LocalName == Keywords.MSD_DEFAULTVALUE && attrs[i].NamespaceURI == Keywords.MSDNS)
1767 defValue = attrs[i].Value;
1769 int ordinal = (int)Convert.ChangeType(tmp, typeof(int), null);
1772 //SetExtProperties(column, attr.UnhandledAttributes);
1774 if ((column.Expression!=null)&&(column.Expression.Length!=0)) {
1775 ColumnExpressions.Add(column);
1778 // Update XSD type to point to simple types actual namespace instead of normalized default namespace in case of remoting
1779 if (xsdType != null && xsdType.Name != null && xsdType.Name.Length > 0) {
1780 if (XSDSchema.GetMsdataAttribute(typeNode, Keywords.TARGETNAMESPACE)!= null) {
1781 column.XmlDataType = xsdType.SimpleTypeQualifiedName;
1785 column.XmlDataType = strType;
1787 column.SimpleType = xsdType;
1789 //column.Namespace = typeNode.SourceUri;
1791 if (this.FromInference) {
1792 column.Prefix = GetPrefix(table.Namespace);
1793 column.AllowDBNull = true;
1795 if(ordinal>-1 && ordinal<table.Columns.Count)
1796 table.Columns.AddAt(ordinal, column);
1798 table.Columns.Add(column);
1801 if (defValue != null)
1803 column.DefaultValue = column.ConvertXmlToObject(defValue);
1805 catch (System.FormatException) {
1806 throw ExceptionBuilder.CannotConvert(defValue, type.FullName);
1812 internal void HandleSimpleContentColumn(String strType, DataTable table, bool isBase, XmlAttribute[] attrs, bool isNillable){
1813 // for Named Simple type support : We should not recieved anything here other than string.
1814 // there can not be typed simple content
1815 // disallow multiple simple content columns for the table
1816 if(this.FromInference && table.XmlText != null) // backward compatability for inference
1820 if (strType == null) {
1823 type = ParseDataType(strType); // we pass it correctly when we call the method, no need to special check.
1828 if (this.FromInference) {
1830 colName = table.TableName + "_Text";
1831 while (table.Columns[colName] != null) {
1832 colName = colName + i++;
1836 colName = table.TableName + "_text";
1838 string columnName = colName;
1839 bool isToAdd = true;
1841 if ((!isBase) && (table.Columns.Contains(columnName, true))){
1842 column = table.Columns[columnName];
1846 column = new DataColumn(columnName, type, null, MappingType.SimpleContent);
1849 SetProperties(column, attrs);
1850 HandleColumnExpression(column, attrs);
1851 SetExtProperties(column, attrs);
1853 String tmp = (-1).ToString(CultureInfo.CurrentCulture);
1854 string defValue = null;
1855 //try to see if attributes contain allownull
1856 column.AllowDBNull = isNillable;
1859 for(int i=0; i< attrs.Length;i++) {
1860 if ( attrs[i].LocalName == Keywords.MSD_ALLOWDBNULL && attrs[i].NamespaceURI == Keywords.MSDNS)
1861 if ( attrs[i].Value == Keywords.FALSE)
1862 column.AllowDBNull = false;
1863 if ( attrs[i].LocalName == Keywords.MSD_ORDINAL && attrs[i].NamespaceURI == Keywords.MSDNS)
1864 tmp = attrs[i].Value;
1865 if ( attrs[i].LocalName == Keywords.MSD_DEFAULTVALUE && attrs[i].NamespaceURI == Keywords.MSDNS)
1866 defValue = attrs[i].Value;
1868 int ordinal = (int)Convert.ChangeType(tmp, typeof(int), null);
1871 //SetExtProperties(column, attr.UnhandledAttributes);
1873 if ((column.Expression!=null)&&(column.Expression.Length!=0)) {
1874 ColumnExpressions.Add(column);
1877 column.XmlDataType = strType;
1878 column.SimpleType = null;
1880 //column.Namespace = typeNode.SourceUri;
1881 if(this.FromInference)
1882 column.Prefix = GetPrefix(column.Namespace);
1884 if (this.FromInference) // move this setting to SetProperties
1885 column.AllowDBNull = true;
1886 if(ordinal>-1 && ordinal<table.Columns.Count)
1887 table.Columns.AddAt(ordinal, column);
1889 table.Columns.Add(column);
1892 if (defValue != null)
1894 column.DefaultValue = column.ConvertXmlToObject(defValue);
1896 catch (System.FormatException) {
1897 throw ExceptionBuilder.CannotConvert(defValue, type.FullName);
1903 internal void HandleAttributeColumn(XmlSchemaAttribute attrib, DataTable table, bool isBase){
1905 XmlSchemaAttribute attr = attrib.Name != null ? attrib : (XmlSchemaAttribute) attributes[attrib.RefName];
1908 XmlSchemaAnnotated typeNode = FindTypeNode(attr);
1909 String strType = null;
1910 SimpleType xsdType = null;
1912 if (typeNode == null) {
1913 strType = attr.SchemaTypeName.Name;
1914 if (Common.ADP.IsEmpty(strType)) {
1916 type = typeof(string);
1919 if (attr.SchemaTypeName.Namespace != Keywords.XSDNS) // it is UD Simple Type, can it be?
1921 type = ParseDataType(attr.SchemaTypeName.ToString());
1923 type = ParseDataType(attr.SchemaTypeName.Name);
1926 else if (typeNode is XmlSchemaSimpleType) {
1928 XmlSchemaSimpleType node = typeNode as XmlSchemaSimpleType;
1929 xsdType = new SimpleType(node);
1930 if (node.QualifiedName.Name != null && node.QualifiedName.Name.Length != 0 && node.QualifiedName.Namespace != Keywords.XSDNS) { // this means UDSimpleType
1931 strType = node.QualifiedName.ToString(); // use qualifed name
1932 type = ParseDataType(node.QualifiedName.ToString());// search with QName
1935 type = ParseDataType(xsdType.BaseType);
1936 strType = xsdType.Name;
1937 if(xsdType.Length == 1 && type == typeof(string)) {
1938 type = typeof(Char);
1942 else if (typeNode is XmlSchemaElement) {
1943 strType = ((XmlSchemaElement)typeNode).SchemaTypeName.Name;
1944 type = ParseDataType(strType);
1947 if (typeNode.Id == null)
1948 throw ExceptionBuilder.DatatypeNotDefined();
1950 throw ExceptionBuilder.UndefinedDatatype(typeNode.Id);
1954 string columnName = XmlConvert.DecodeName(GetInstanceName(attr));
1955 bool isToAdd = true;
1957 if ((!isBase || FromInference) && (table.Columns.Contains(columnName, true))) {
1958 column = table.Columns[columnName];
1961 if (FromInference) { // for backward compatability with old inference
1962 // throw eception if same column is being aded with different mapping
1963 if (column.ColumnMapping != MappingType.Attribute)
1964 throw ExceptionBuilder.ColumnTypeConflict(column.ColumnName);
1965 // in previous inference , if we have incoming column with different NS, we think as different column and
1966 //while adding , since there is no NS concept for datacolumn, we used to throw exception
1967 // simulate the same behavior.
1968 if ((Common.ADP.IsEmpty(attrib.QualifiedName.Namespace) && Common.ADP.IsEmpty(column._columnUri)) || // backward compatability :SQL BU DT 310912
1969 (string.Compare(attrib.QualifiedName.Namespace, column.Namespace, StringComparison.Ordinal) == 0))
1971 return; // backward compatability
1973 column = new DataColumn(columnName, type, null, MappingType.Attribute); // this is to fix issue with Exception we used to throw for old inference engine if column
1974 //exists with different namespace; while adding it to columncollection
1980 column = new DataColumn(columnName, type, null, MappingType.Attribute);
1983 SetProperties(column, attr.UnhandledAttributes);
1984 HandleColumnExpression(column, attr.UnhandledAttributes);
1985 SetExtProperties(column, attr.UnhandledAttributes);
1987 if ((column.Expression!=null)&&(column.Expression.Length!=0)) {
1988 ColumnExpressions.Add(column);
1991 if (xsdType != null && xsdType.Name != null && xsdType.Name.Length > 0) {
1992 if (XSDSchema.GetMsdataAttribute(typeNode, Keywords.TARGETNAMESPACE)!= null) {
1993 column.XmlDataType = xsdType.SimpleTypeQualifiedName;
1997 column.XmlDataType = strType;
2000 column.SimpleType = xsdType;
2002 column.AllowDBNull = !(attrib.Use == XmlSchemaUse.Required);
2003 column.Namespace = attrib.QualifiedName.Namespace;
2004 column.Namespace = GetStringAttribute(attrib, "targetNamespace", column.Namespace);
2007 if (this.FromInference) { // move this setting to SetProperties
2008 column.AllowDBNull = true;
2009 column.Prefix = GetPrefix(column.Namespace);
2011 table.Columns.Add(column);
2014 if (attrib.Use == XmlSchemaUse.Prohibited) {
2015 column.ColumnMapping = MappingType.Hidden;
2017 column.AllowDBNull = GetBooleanAttribute(attr, Keywords.MSD_ALLOWDBNULL, true) ;
2018 String defValue = GetMsdataAttribute(attr, Keywords.MSD_DEFAULTVALUE);
2019 if (defValue != null)
2021 column.DefaultValue = column.ConvertXmlToObject(defValue);
2023 catch (System.FormatException) {
2024 throw ExceptionBuilder.CannotConvert(defValue, type.FullName);
2029 // XDR [....] change
2030 string strDefault = (attrib.Use == XmlSchemaUse.Required) ? GetMsdataAttribute(attr, Keywords.MSD_DEFAULTVALUE) : attr.DefaultValue;
2031 if ((attr.Use == XmlSchemaUse.Optional) && (strDefault == null ))
2032 strDefault = attr.FixedValue;
2034 if (strDefault != null)
2036 column.DefaultValue = column.ConvertXmlToObject(strDefault);
2038 catch (System.FormatException) {
2039 throw ExceptionBuilder.CannotConvert(strDefault, type.FullName);
2043 internal void HandleElementColumn(XmlSchemaElement elem, DataTable table, bool isBase){
2045 XmlSchemaElement el = elem.Name != null ? elem : (XmlSchemaElement) elementsTable[elem.RefName];
2047 if (el == null) // it's possible due to some XSD compiler optimizations
2048 return; // do nothing
2050 XmlSchemaAnnotated typeNode = FindTypeNode(el);
2051 String strType = null;
2052 SimpleType xsdType = null;
2054 if (typeNode == null) {
2055 strType = el.SchemaTypeName.Name;
2056 if (Common.ADP.IsEmpty(strType)) {
2058 type = typeof(string);
2061 type = ParseDataType(el.SchemaTypeName.Name);
2064 else if (typeNode is XmlSchemaSimpleType) {
2066 XmlSchemaSimpleType simpleTypeNode = typeNode as XmlSchemaSimpleType;
2067 xsdType = new SimpleType(simpleTypeNode);
2068 // ((XmlSchemaSimpleType)typeNode).Name != null && ((XmlSchemaSimpleType)typeNode).Name.Length != 0 check is for annonymos simple type,
2069 // it should be user defined Named simple type
2070 if (((XmlSchemaSimpleType)typeNode).Name != null && ((XmlSchemaSimpleType)typeNode).Name.Length != 0 && ((XmlSchemaSimpleType)typeNode).QualifiedName.Namespace != Keywords.XSDNS) {
2072 string targetNamespace = XSDSchema.GetMsdataAttribute(typeNode, Keywords.TARGETNAMESPACE);
2073 strType = ((XmlSchemaSimpleType)typeNode).QualifiedName.ToString(); // use qualifed name
2074 type = ParseDataType(strType);
2077 simpleTypeNode = (xsdType.XmlBaseType!= null && xsdType.XmlBaseType.Namespace != Keywords.XSDNS) ?
2078 schemaTypes[xsdType.XmlBaseType] as XmlSchemaSimpleType :
2080 while (simpleTypeNode != null) {
2081 xsdType.LoadTypeValues(simpleTypeNode);
2082 simpleTypeNode = (xsdType.XmlBaseType!= null && xsdType.XmlBaseType.Namespace != Keywords.XSDNS) ?
2083 schemaTypes[xsdType.XmlBaseType] as XmlSchemaSimpleType :
2087 type = ParseDataType(xsdType.BaseType);
2088 strType = xsdType.Name;
2090 if(xsdType.Length == 1 && type == typeof(string)) {
2091 type = typeof(Char);
2095 else if (typeNode is XmlSchemaElement) { // theoratically no named simpletype should come here
2096 strType = ((XmlSchemaElement)typeNode).SchemaTypeName.Name;
2097 type = ParseDataType(strType);
2099 else if (typeNode is XmlSchemaComplexType) {
2100 if (ADP.IsEmpty(XSDSchema.GetMsdataAttribute(elem, Keywords.MSD_DATATYPE))) {
2101 throw ExceptionBuilder.DatatypeNotDefined();
2104 type = typeof(object);
2108 if (typeNode.Id == null)
2109 throw ExceptionBuilder.DatatypeNotDefined();
2111 throw ExceptionBuilder.UndefinedDatatype(typeNode.Id);
2115 string columnName = XmlConvert.DecodeName(GetInstanceName(el));
2116 bool isToAdd = true;
2118 if (((!isBase) || FromInference) && (table.Columns.Contains(columnName, true))) {
2119 column = table.Columns[columnName];
2122 if (FromInference) { // for backward compatability with old inference
2123 if (column.ColumnMapping != MappingType.Element)
2124 throw ExceptionBuilder.ColumnTypeConflict(column.ColumnName);
2125 // in previous inference , if we have incoming column with different NS, we think as different column and
2126 //while adding , since there is no NS concept for datacolumn, we used to throw exception
2127 // simulate the same behavior.
2128 if ((Common.ADP.IsEmpty(elem.QualifiedName.Namespace) && Common.ADP.IsEmpty(column._columnUri)) || // backward compatability :SQL BU DT 310912
2129 (string.Compare(elem.QualifiedName.Namespace, column.Namespace, StringComparison.Ordinal) == 0))
2131 return; // backward compatability
2133 column = new DataColumn(columnName, type, null, MappingType.Element);// this is to fix issue with Exception we used to throw for old inference engine if column
2134 //exists with different namespace; while adding it to columncollection
2139 column = new DataColumn(columnName, type, null, MappingType.Element);
2142 SetProperties(column, el.UnhandledAttributes);
2143 HandleColumnExpression(column, el.UnhandledAttributes);
2144 SetExtProperties(column, el.UnhandledAttributes);
2146 if (!Common.ADP.IsEmpty(column.Expression)) {
2147 ColumnExpressions.Add(column);
2150 // Update XSD type to point to simple types actual namespace instead of normalized default namespace in case of remoting
2151 if (xsdType != null && xsdType.Name != null && xsdType.Name.Length > 0) {
2152 if (XSDSchema.GetMsdataAttribute(typeNode, Keywords.TARGETNAMESPACE)!= null) {
2153 column.XmlDataType = xsdType.SimpleTypeQualifiedName;
2157 column.XmlDataType = strType;
2159 column.SimpleType = xsdType;
2161 column.AllowDBNull = this.FromInference ||(elem.MinOccurs == 0 ) || elem.IsNillable;
2164 if (!elem.RefName.IsEmpty || elem.QualifiedName.Namespace != table.Namespace)
2165 { // if ref element (or in diferent NS) it is global element, so form MUST BE Qualified
2166 column.Namespace = elem.QualifiedName.Namespace;
2167 column.Namespace = GetStringAttribute(el, "targetNamespace", column.Namespace);
2169 else { // it is local, hence check for 'form' on local element, if not specified, check for 'elemenfformdefault' on schema element
2170 if (elem.Form == XmlSchemaForm.Unqualified) {
2171 column.Namespace = String.Empty;
2173 else if (elem.Form == XmlSchemaForm.None) {
2174 XmlSchemaObject e = (XmlSchemaObject)elem.Parent;
2175 while (e.Parent != null) {
2178 if (((XmlSchema)e).ElementFormDefault == XmlSchemaForm.Unqualified) {
2179 column.Namespace = String.Empty;
2183 column.Namespace = elem.QualifiedName.Namespace;
2184 column.Namespace = GetStringAttribute(el, "targetNamespace", column.Namespace);
2188 String tmp = GetStringAttribute(elem, Keywords.MSD_ORDINAL, (-1).ToString(CultureInfo.CurrentCulture));
2189 int ordinal = (int)Convert.ChangeType(tmp, typeof(int), null);
2192 if(ordinal>-1 && ordinal<table.Columns.Count)
2193 table.Columns.AddAt(ordinal, column);
2195 table.Columns.Add(column);
2198 if (column.Namespace == table.Namespace)
2199 column._columnUri = null; // to not raise a column change namespace again
2201 if(this.FromInference) {// search for prefix after adding to table, so NS has its final value, and
2202 column.Prefix = GetPrefix(column.Namespace); // it can inherit its NS from DataTable, if it is null
2205 string strDefault = el.DefaultValue;
2206 if (strDefault != null )
2208 column.DefaultValue = column.ConvertXmlToObject(strDefault);
2210 catch (System.FormatException) {
2212 throw ExceptionBuilder.CannotConvert(strDefault, type.FullName);
2216 internal void HandleDataSet(XmlSchemaElement node, bool isNewDataSet) {
2217 string dsName = node.Name;
2218 string dsNamespace = node.QualifiedName.Namespace;
2219 int initialTableCount = _ds.Tables.Count; // just use for inference backward compatablity
2221 List<DataTable> tableSequenceList = new List<DataTable>();
2223 String value = GetMsdataAttribute(node, Keywords.MSD_LOCALE);
2224 if (null != value) { // set by user
2225 if (0 != value.Length) {
2226 // <... msdata:Locale="en-US"/>
2227 _ds.Locale = new CultureInfo(value);
2230 // everett bug behavior before <... msdata:Locale=""/> becoming CultureInfo(0x409)
2231 _ds.Locale = CultureInfo.InvariantCulture;
2234 else { // not set by user
2235 // MSD_LOCALE overrides MSD_USECURRENTLOCALE
2236 if (GetBooleanAttribute(node, Keywords.MSD_USECURRENTLOCALE, false)) {
2237 _ds.SetLocaleValue(CultureInfo.CurrentCulture, false);
2240 // everett behavior before <... msdata:UseCurrentLocale="true"/>
2241 _ds.SetLocaleValue(new CultureInfo(0x409), false);
2246 value = GetMsdataAttribute(node, Keywords.MSD_DATASETNAME);
2247 if (value!=null && value.Length != 0) {
2251 value = GetMsdataAttribute(node, Keywords.MSD_DATASETNAMESPACE);
2252 if (value!=null && value.Length != 0) {
2253 dsNamespace = value;
2256 SetProperties(_ds, node.UnhandledAttributes);
2257 SetExtProperties(_ds, node.UnhandledAttributes);
2260 if (dsName != null && dsName.Length != 0)
2261 _ds.DataSetName = XmlConvert.DecodeName(dsName);
2263 // _ds.Namespace = node.QualifiedName.Namespace;
2264 _ds.Namespace = dsNamespace;
2266 if (this.FromInference)
2267 _ds.Prefix = GetPrefix(_ds.Namespace);
2269 XmlSchemaComplexType ct = (XmlSchemaComplexType) FindTypeNode(node);
2270 if (ct.Particle != null) {
2271 XmlSchemaObjectCollection items = GetParticleItems(ct.Particle);
2273 if (items == null) {
2277 foreach (XmlSchemaAnnotated el in items){
2278 if (el is XmlSchemaElement) {
2279 if(((XmlSchemaElement)el).RefName.Name.Length != 0) {
2280 if (!FromInference) {
2284 DataTable tempTable = _ds.Tables.GetTable(XmlConvert.DecodeName(GetInstanceName((XmlSchemaElement)el)), node.QualifiedName.Namespace);
2285 if (tempTable != null) {
2286 tableSequenceList.Add(tempTable); // if ref table is created, add it
2288 bool isComplexTypeOrValidElementType = false;
2289 if (node.ElementSchemaType != null || !(((XmlSchemaElement)el).SchemaType is XmlSchemaComplexType)) {
2290 isComplexTypeOrValidElementType = true;
2292 // bool isComplexTypeOrValidElementType = (node.ElementType != null || !(((XmlSchemaElement)el).SchemaType is XmlSchemaComplexType));
2293 if ((((XmlSchemaElement)el).MaxOccurs != Decimal.One ) && (!isComplexTypeOrValidElementType)) {
2299 DataTable child = HandleTable ((XmlSchemaElement)el);
2301 child.fNestedInDataset = true;
2303 if (FromInference) {
2304 tableSequenceList.Add(child);
2307 else if (el is XmlSchemaChoice){ // should we check for inference?
2308 XmlSchemaObjectCollection choiceItems = ((XmlSchemaChoice)el).Items;
2309 if (choiceItems == null)
2311 foreach (XmlSchemaAnnotated choiceEl in choiceItems) {
2312 if (choiceEl is XmlSchemaElement) {
2313 if (((XmlSchemaParticle)el).MaxOccurs > Decimal.One && (((XmlSchemaElement)choiceEl).SchemaType is XmlSchemaComplexType)) // amir
2314 ((XmlSchemaElement)choiceEl).MaxOccurs = ((XmlSchemaParticle)el).MaxOccurs;
2315 if ((((XmlSchemaElement)choiceEl).RefName.Name.Length != 0) && (!FromInference && ((XmlSchemaElement)choiceEl).MaxOccurs != Decimal.One && !(((XmlSchemaElement)choiceEl).SchemaType is XmlSchemaComplexType)))
2318 DataTable child = HandleTable ((XmlSchemaElement)choiceEl);
2319 if (FromInference) {
2320 tableSequenceList.Add(child);
2324 child.fNestedInDataset = true;
2332 // Handle the non-nested keyref constraints
2333 if (node.Constraints != null) {
2334 foreach (XmlSchemaIdentityConstraint key in node.Constraints) {
2335 XmlSchemaKeyref keyref = key as XmlSchemaKeyref;
2339 bool isNested = GetBooleanAttribute(keyref, Keywords.MSD_ISNESTED, /*default:*/ false);
2343 HandleKeyref(keyref);
2346 if (FromInference && isNewDataSet) {
2347 List<DataTable> _tableList = new List<DataTable>(_ds.Tables.Count);
2348 foreach(DataTable dt in tableSequenceList) {
2349 AddTablesToList(_tableList, dt);
2351 _ds.Tables.ReplaceFromInference(_tableList); // replace the list with the one in correct order: BackWard compatability for inference
2355 private void AddTablesToList(List<DataTable> tableList, DataTable dt) { // kind of depth _first travarsal
2356 if (!tableList.Contains(dt)) {
2358 foreach(DataTable childTable in tableDictionary[dt]) {
2359 AddTablesToList(tableList, childTable);
2364 private string GetPrefix(string ns) {
2367 foreach (XmlSchema schemaRoot in _schemaSet.Schemas()) {
2368 XmlQualifiedName[] qualifiedNames = schemaRoot.Namespaces.ToArray();
2369 for(int i = 0; i < qualifiedNames.Length; i++) {
2370 if (qualifiedNames[i].Namespace == ns)
2371 return qualifiedNames[i].Name;
2377 private string GetNamespaceFromPrefix(string prefix) {
2378 if ((prefix == null) ||(prefix.Length == 0))
2380 foreach (XmlSchema schemaRoot in _schemaSet.Schemas()) {
2381 XmlQualifiedName[] qualifiedNames = schemaRoot.Namespaces.ToArray();
2382 for(int i = 0; i < qualifiedNames.Length; i++) {
2383 if (qualifiedNames[i].Name == prefix)
2384 return qualifiedNames[i].Namespace;
2391 private String GetTableNamespace(XmlSchemaIdentityConstraint key) {
2392 string xpath = key.Selector.XPath;
2393 string [] split = xpath.Split('/');
2394 string prefix =string.Empty;
2396 string QualifiedTableName = split[split.Length - 1]; //get the last string after '/' and ':'
2398 if ((QualifiedTableName == null) || (QualifiedTableName.Length == 0))
2399 throw ExceptionBuilder.InvalidSelector(xpath);
2401 if (QualifiedTableName.IndexOf(':') != -1)
2402 prefix = QualifiedTableName.Substring(0, QualifiedTableName.IndexOf(':'));
2404 return GetMsdataAttribute(key, Keywords.MSD_TABLENS);
2406 prefix = XmlConvert.DecodeName(prefix );
2408 return GetNamespaceFromPrefix(prefix);
2411 private String GetTableName(XmlSchemaIdentityConstraint key) {
2412 string xpath = key.Selector.XPath;
2413 string [] split = xpath.Split('/',':');
2414 String tableName = split[split.Length - 1]; //get the last string after '/' and ':'
2416 if ((tableName == null) || (tableName.Length == 0))
2417 throw ExceptionBuilder.InvalidSelector(xpath);
2419 tableName = XmlConvert.DecodeName(tableName);
2423 internal bool IsTable(XmlSchemaElement node) {
2424 if (node.MaxOccurs == decimal.Zero)
2427 XmlAttribute[] attribs = node.UnhandledAttributes;
2428 if (attribs != null) {
2429 for(int i = 0; i < attribs.Length; i++) {
2430 XmlAttribute attrib = attribs[i];
2431 if (attrib.LocalName == Keywords.MSD_DATATYPE &&
2432 attrib.Prefix == Keywords.MSD &&
2433 attrib.NamespaceURI == Keywords.MSDNS)
2438 Object typeNode = FindTypeNode(node);
2440 if ( (node.MaxOccurs > decimal.One) && typeNode == null ){
2445 if ((typeNode==null) || !(typeNode is XmlSchemaComplexType)) {
2449 XmlSchemaComplexType ctNode = (XmlSchemaComplexType) typeNode;
2451 if (ctNode.IsAbstract)
2452 throw ExceptionBuilder.CannotInstantiateAbstract(node.Name);
2457 // internal bool IsTopLevelElement (XmlSchemaElement node) {
2458 // return (elements.IndexOf(node) != -1);
2460 internal DataTable HandleTable(XmlSchemaElement node) {
2465 Object typeNode = FindTypeNode(node);
2467 if ( (node.MaxOccurs > decimal.One) && typeNode == null ){
2468 return InstantiateSimpleTable(node);
2471 DataTable table = InstantiateTable(node,(XmlSchemaComplexType)typeNode, (node.RefName != null)); // this is wrong , correct check should be node.RefName.IsEmpty
2473 table.fNestedInDataset = false;
2480 internal sealed class XmlIgnoreNamespaceReader : XmlNodeReader {
2481 private List<string> namespacesToIgnore;
2485 internal XmlIgnoreNamespaceReader(XmlDocument xdoc, string[] namespacesToIgnore) : base(xdoc) {
2486 this.namespacesToIgnore = new List<string>(namespacesToIgnore);
2490 // XmlReader implementation
2493 public override bool MoveToFirstAttribute() {
2494 if (base.MoveToFirstAttribute()) {
2495 if ( namespacesToIgnore.Contains(this.NamespaceURI) ||
2496 (this.NamespaceURI == Keywords.XML_XMLNS && this.LocalName != "lang")) { //try next one
2497 return MoveToNextAttribute();
2506 public override bool MoveToNextAttribute() {
2511 if (base.MoveToNextAttribute()) {
2514 if ( namespacesToIgnore.Contains(this.NamespaceURI) ||
2515 (this.NamespaceURI == Keywords.XML_XMLNS && this.LocalName != "lang")) {