Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Xml / System / Xml / Schema / Inference / Infer.cs
blob49254264120862ddd30279364fc3096abe0e4ae4
1 //------------------------------------------------------------------------------
2 // <copyright file="Infer.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="false" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
9 using System;
10 using System.IO;
11 using System.Xml;
12 using System.Collections;
13 using System.Diagnostics;
14 using System.Globalization;
15 using System.Security.Permissions;
20 namespace System.Xml.Schema
23 /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer"]/*' />
24 /// <summary>
25 /// Infer class serves for infering XML Schema from given XML instance document.
26 /// </summary>
27 public sealed class XmlSchemaInference
29 internal static XmlQualifiedName ST_boolean = new XmlQualifiedName("boolean", XmlSchema.Namespace);
30 internal static XmlQualifiedName ST_byte = new XmlQualifiedName("byte", XmlSchema.Namespace);
31 internal static XmlQualifiedName ST_unsignedByte = new XmlQualifiedName("unsignedByte", XmlSchema.Namespace);
32 internal static XmlQualifiedName ST_short = new XmlQualifiedName("short", XmlSchema.Namespace);
33 internal static XmlQualifiedName ST_unsignedShort = new XmlQualifiedName("unsignedShort", XmlSchema.Namespace);
34 internal static XmlQualifiedName ST_int = new XmlQualifiedName("int", XmlSchema.Namespace);
35 internal static XmlQualifiedName ST_unsignedInt = new XmlQualifiedName("unsignedInt", XmlSchema.Namespace);
36 internal static XmlQualifiedName ST_long = new XmlQualifiedName("long", XmlSchema.Namespace);
37 internal static XmlQualifiedName ST_unsignedLong = new XmlQualifiedName("unsignedLong", XmlSchema.Namespace);
38 internal static XmlQualifiedName ST_integer = new XmlQualifiedName("integer", XmlSchema.Namespace);
39 internal static XmlQualifiedName ST_decimal = new XmlQualifiedName("decimal", XmlSchema.Namespace);
40 internal static XmlQualifiedName ST_float = new XmlQualifiedName("float", XmlSchema.Namespace);
41 internal static XmlQualifiedName ST_double = new XmlQualifiedName("double", XmlSchema.Namespace);
42 internal static XmlQualifiedName ST_duration = new XmlQualifiedName("duration", XmlSchema.Namespace);
43 internal static XmlQualifiedName ST_dateTime = new XmlQualifiedName("dateTime", XmlSchema.Namespace);
44 internal static XmlQualifiedName ST_time = new XmlQualifiedName("time", XmlSchema.Namespace);
45 internal static XmlQualifiedName ST_date = new XmlQualifiedName("date", XmlSchema.Namespace);
46 internal static XmlQualifiedName ST_gYearMonth = new XmlQualifiedName("gYearMonth", XmlSchema.Namespace);
47 internal static XmlQualifiedName ST_string = new XmlQualifiedName("string", XmlSchema.Namespace);
48 internal static XmlQualifiedName ST_anySimpleType = new XmlQualifiedName("anySimpleType", XmlSchema.Namespace);
50 internal static XmlQualifiedName[] SimpleTypes =
52 ST_boolean,
53 ST_byte,
54 ST_unsignedByte,
55 ST_short,
56 ST_unsignedShort,
57 ST_int,
58 ST_unsignedInt,
59 ST_long,
60 ST_unsignedLong,
61 ST_integer,
62 ST_decimal,
63 ST_float,
64 ST_double,
65 ST_duration,
66 ST_dateTime,
67 ST_time,
68 ST_date,
69 ST_gYearMonth,
70 ST_string
73 internal const short HC_ST_boolean = 0;
74 internal const short HC_ST_byte = 1;
75 internal const short HC_ST_unsignedByte = 2;
76 internal const short HC_ST_short = 3;
77 internal const short HC_ST_unsignedShort = 4;
78 internal const short HC_ST_int = 5;
79 internal const short HC_ST_unsignedInt = 6;
80 internal const short HC_ST_long = 7;
81 internal const short HC_ST_unsignedLong = 8;
82 internal const short HC_ST_integer = 9;
83 internal const short HC_ST_decimal = 10;
84 internal const short HC_ST_float = 11;
85 internal const short HC_ST_double = 12;
86 internal const short HC_ST_duration = 13;
87 internal const short HC_ST_dateTime = 14;
88 internal const short HC_ST_time = 15;
89 internal const short HC_ST_date = 16;
90 internal const short HC_ST_gYearMonth = 17;
91 internal const short HC_ST_string = 18;
92 internal const short HC_ST_Count = HC_ST_string +1;
95 internal const int TF_boolean = 1<<HC_ST_boolean;
96 internal const int TF_byte = 1<<HC_ST_byte;
97 internal const int TF_unsignedByte = 1<<HC_ST_unsignedByte;
98 internal const int TF_short = 1<<HC_ST_short;
99 internal const int TF_unsignedShort = 1<<HC_ST_unsignedShort;
100 internal const int TF_int = 1<<HC_ST_int;
101 internal const int TF_unsignedInt = 1<<HC_ST_unsignedInt;
102 internal const int TF_long = 1<<HC_ST_long;
103 internal const int TF_unsignedLong = 1<<HC_ST_unsignedLong;
104 internal const int TF_integer = 1<<HC_ST_integer;
105 internal const int TF_decimal = 1<<HC_ST_decimal;
106 internal const int TF_float = 1<<HC_ST_float;
107 internal const int TF_double = 1<<HC_ST_double;
108 internal const int TF_duration = 1<<HC_ST_duration;
109 internal const int TF_dateTime = 1<<HC_ST_dateTime;
110 internal const int TF_time = 1<<HC_ST_time;
111 internal const int TF_date = 1<<HC_ST_date;
112 internal const int TF_gYearMonth = 1<<HC_ST_gYearMonth;
113 internal const int TF_string = 1<<HC_ST_string;
115 XmlSchema rootSchema = null; //(XmlSchema) xsc[TargetNamespace];
116 private XmlSchemaSet schemaSet;
117 private XmlReader xtr;
118 private NameTable nametable;
119 private string TargetNamespace;
120 private XmlNamespaceManager NamespaceManager;
121 //private Hashtable schemas; //contains collection of schemas before they get added to the XmlSchemaSet xsc
122 //private bool bRefine = false; //indicates if we are going to infer or refine schema when InferSchema is called
123 ArrayList schemaList;
124 InferenceOption occurrence = InferenceOption.Restricted;
125 InferenceOption typeInference = InferenceOption.Restricted;
127 /* internal struct ReplaceList
129 internal XmlSchemaObjectCollection col;
130 internal int position;
132 internal ReplaceList(XmlSchemaObjectCollection col, int position)
134 this.col = col;
135 this.position = position;
139 /// <include file='doc\Infer.uex' path='docs/doc[@for="InferenceOption"]/*' />
140 public enum InferenceOption
142 /// <include file='doc\Infer.uex' path='docs/doc[@for="InferenceOption.Restricted"]/*' />
143 Restricted,
144 /// <include file='doc\Infer.uex' path='docs/doc[@for="InferenceOption.Relaxed"]/*' />
145 Relaxed
148 /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.Occurrence"]/*' />
149 public InferenceOption Occurrence
151 set
153 this.occurrence = value;
155 get
157 return this.occurrence;
161 /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.TypeInference"]/*' />
162 public InferenceOption TypeInference
164 set
166 this.typeInference = value;
168 get
170 return this.typeInference;
174 /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.Infer"]/*' />
175 public XmlSchemaInference()
177 this.nametable = new NameTable();
178 this.NamespaceManager = new XmlNamespaceManager(nametable);
179 this.NamespaceManager.AddNamespace("xs", XmlSchema.Namespace);
180 this.schemaList = new ArrayList();
183 /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.InferSchema"]/*' />
184 public XmlSchemaSet InferSchema(XmlReader instanceDocument)
186 return InferSchema1(instanceDocument, new XmlSchemaSet(nametable));
189 /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.InferSchema1"]/*' />
190 public XmlSchemaSet InferSchema(XmlReader instanceDocument, XmlSchemaSet schemas)
192 if (schemas == null)
194 schemas = new XmlSchemaSet(nametable);
196 return InferSchema1(instanceDocument, schemas);
198 internal XmlSchemaSet InferSchema1(XmlReader instanceDocument, XmlSchemaSet schemas)
200 if (instanceDocument == null)
202 throw new ArgumentNullException("instanceDocument");
204 this.rootSchema = null;
205 xtr = instanceDocument;
206 schemas.Compile();
207 this.schemaSet = schemas;
208 //schemas = new Hashtable();
209 //while(xtr.Read())
211 while (xtr.NodeType != XmlNodeType.Element && xtr.Read()) ;
214 if (xtr.NodeType == XmlNodeType.Element)
216 //Create and process the root element
217 TargetNamespace = xtr.NamespaceURI;
218 if ( xtr.NamespaceURI == XmlSchema.Namespace)
220 throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
222 XmlSchemaElement xse = null;
223 foreach (XmlSchemaElement elem in schemas.GlobalElements.Values)
225 if (elem.Name == xtr.LocalName && elem.QualifiedName.Namespace == xtr.NamespaceURI)
227 rootSchema = elem.Parent as XmlSchema;
228 xse = elem;
229 break;
233 if (rootSchema == null)
235 //rootSchema = CreateXmlSchema(xtr.NamespaceURI);
236 xse = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, null, null, -1);
238 else
240 //bRefine = true;
241 InferElement(xse, false, rootSchema);
244 /* foreach (ReplaceList listItem in schemaList)
246 if (listItem.position < listItem.col.Count)
248 XmlSchemaElement particle = listItem.col[listItem.position] as XmlSchemaElement;
249 if (particle != null && (particle.RefName.Namespace == XmlSchema.Namespace))
251 XmlSchemaAny any = new XmlSchemaAny();
252 if (particle.MaxOccurs != 1)
254 any.MaxOccurs = particle.MaxOccurs;
256 if (particle.MinOccurs != 1)
258 any.MinOccurs = particle.MinOccurs;
260 any.ProcessContents = XmlSchemaContentProcessing.Skip;
261 any.MinOccurs = decimal.Zero;
262 any.Namespace = particle.RefName.Namespace;
263 listItem.col[listItem.position] = any;
267 foreach(String prefix in this.NamespaceManager)
269 if (!prefix.Equals("xml") && !prefix.Equals("xmlns"))
271 String ns = this.NamespaceManager.LookupNamespace(this.nametable.Get(prefix));
272 if (ns.Length != 0) { //Do not add xmlns=""
273 rootSchema.Namespaces.Add(prefix, ns);
277 Debug.Assert(this.rootSchema != null, "rootSchema is null");
278 schemas.Reprocess(rootSchema);
279 schemas.Compile();
280 //break;
282 else
284 throw new XmlSchemaInferenceException(Res.SchInf_NoElement, 0, 0);
286 return schemas;
289 private XmlSchemaAttribute AddAttribute(string localName, string prefix, string childURI, string attrValue, bool bCreatingNewType, XmlSchema parentSchema, XmlSchemaObjectCollection addLocation, XmlSchemaObjectTable compiledAttributes)
291 if (childURI == XmlSchema.Namespace)
293 throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
296 XmlSchemaAttribute xsa = null;
297 int AttributeType = -1;
298 XmlSchemaAttribute returnedAttribute = null; //this value will change to attributeReference if childURI!= parentURI
299 XmlSchema xs = null;
300 bool add = true;
302 Debug.Assert(compiledAttributes != null); //AttributeUses is never null
303 // First we need to look into the already compiled attributes
304 // (they come from the schemaset which we got on input)
305 // If there are none or we don't find it there, then we must search the list of attributes
306 // where we are going to add a new one (if it doesn't exist).
307 // This is necessary to avoid adding duplicate attribute declarations.
308 ICollection searchCollectionPrimary, searchCollectionSecondary;
309 if (compiledAttributes.Count > 0) {
310 searchCollectionPrimary = compiledAttributes.Values;
311 searchCollectionSecondary = addLocation;
313 else {
314 searchCollectionPrimary = addLocation;
315 searchCollectionSecondary = null;
317 if (childURI == XmlReservedNs.NsXml)
319 XmlSchemaAttribute attributeReference = null;
320 //see if the reference exists
321 attributeReference = FindAttributeRef(searchCollectionPrimary, localName, childURI);
322 if (attributeReference == null && searchCollectionSecondary != null) {
323 attributeReference = FindAttributeRef(searchCollectionSecondary, localName, childURI);
325 if (attributeReference == null)
327 attributeReference = new XmlSchemaAttribute();
328 attributeReference.RefName = new XmlQualifiedName(localName, childURI);
329 if (bCreatingNewType && this.Occurrence == InferenceOption.Restricted)
331 attributeReference.Use = XmlSchemaUse.Required;
333 else
335 attributeReference.Use = XmlSchemaUse.Optional;
338 addLocation.Add(attributeReference);
340 returnedAttribute = attributeReference;
342 else
344 if (childURI.Length == 0)
346 xs = parentSchema;
347 add = false;
349 else if (childURI != null && !schemaSet.Contains(childURI))
351 /*if (parentSchema.AttributeFormDefault = XmlSchemaForm.Unqualified && childURI.Length == 0)
353 xs = parentSchema;
354 add = false;
355 break;
357 xs = new XmlSchema();
358 xs.AttributeFormDefault = XmlSchemaForm.Unqualified;
359 xs.ElementFormDefault = XmlSchemaForm.Qualified;
360 if (childURI.Length != 0)
361 xs.TargetNamespace = childURI;
362 //schemas.Add(childURI, xs);
363 this.schemaSet.Add(xs);
364 if (prefix.Length != 0 && String.Compare(prefix, "xml", StringComparison.OrdinalIgnoreCase) != 0)
365 NamespaceManager.AddNamespace(prefix, childURI);
367 else
369 ArrayList col = this.schemaSet.Schemas(childURI) as ArrayList;
370 if (col != null && col.Count > 0)
372 xs = col[0] as XmlSchema;
376 if (childURI.Length != 0) //
378 XmlSchemaAttribute attributeReference = null;
379 //see if the reference exists
380 attributeReference = FindAttributeRef(searchCollectionPrimary, localName, childURI);
381 if (attributeReference == null & searchCollectionSecondary != null) {
382 attributeReference = FindAttributeRef(searchCollectionSecondary, localName, childURI);
384 if (attributeReference == null)
386 attributeReference = new XmlSchemaAttribute();
387 attributeReference.RefName = new XmlQualifiedName(localName, childURI);
388 if (bCreatingNewType && this.Occurrence == InferenceOption.Restricted)
390 attributeReference.Use = XmlSchemaUse.Required;
392 else
394 attributeReference.Use = XmlSchemaUse.Optional;
397 addLocation.Add(attributeReference);
399 returnedAttribute = attributeReference;
401 //see if the attribute exists on the global level
402 xsa = FindAttribute(xs.Items, localName);
403 if (xsa == null)
405 xsa = new XmlSchemaAttribute();
406 xsa.Name = localName;
407 xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
408 xsa.LineNumber = AttributeType; //we use LineNumber to store flags of valid types
409 xs.Items.Add(xsa);
412 else
414 if (xsa.Parent == null)
416 AttributeType = xsa.LineNumber; // we use LineNumber to store flags of valid types
418 else
420 AttributeType = GetSchemaType(xsa.SchemaTypeName);
421 xsa.Parent = null;
423 xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
424 xsa.LineNumber = AttributeType; // we use LineNumber to store flags of valid types
427 else
429 xsa = FindAttribute(searchCollectionPrimary, localName);
430 if (xsa == null && searchCollectionSecondary != null) {
431 xsa = FindAttribute(searchCollectionSecondary, localName);
433 if (xsa == null)
435 xsa = new XmlSchemaAttribute();
436 xsa.Name = localName;
437 xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
438 xsa.LineNumber = AttributeType; // we use LineNumber to store flags of valid types
439 if (bCreatingNewType && this.Occurrence == InferenceOption.Restricted)
440 xsa.Use = XmlSchemaUse.Required;
441 else
442 xsa.Use = XmlSchemaUse.Optional;
443 addLocation.Add(xsa);
444 if (xs.AttributeFormDefault != XmlSchemaForm.Unqualified)
446 xsa.Form = XmlSchemaForm.Unqualified;
449 else
451 if (xsa.Parent == null)
453 AttributeType = xsa.LineNumber; // we use LineNumber to store flags of valid types
455 else
457 AttributeType = GetSchemaType(xsa.SchemaTypeName);
458 xsa.Parent = null;
460 xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
461 xsa.LineNumber = AttributeType; // we use LineNumber to store flags of valid types
463 returnedAttribute = xsa;
466 string nullString = null;
467 if (add && childURI != parentSchema.TargetNamespace)
469 for (int i = 0; i < parentSchema.Includes.Count; ++i)
471 XmlSchemaImport import = parentSchema.Includes[i] as XmlSchemaImport;
472 if (import == null)
474 continue;
476 if (import.Namespace == childURI)
478 add = false;
481 if (add)
483 XmlSchemaImport import = new XmlSchemaImport();
484 import.Schema = xs;
485 if (childURI.Length != 0)
487 nullString = childURI;
489 import.Namespace = nullString;
490 parentSchema.Includes.Add(import);
495 return returnedAttribute;
498 private XmlSchema CreateXmlSchema(string targetNS)
500 Debug.Assert(targetNS == null || targetNS.Length > 0 , "targetns for schema is empty");
501 XmlSchema xs = new XmlSchema();
502 xs.AttributeFormDefault = XmlSchemaForm.Unqualified;
503 xs.ElementFormDefault = XmlSchemaForm.Qualified;
504 xs.TargetNamespace = targetNS;
505 this.schemaSet.Add(xs);
506 return xs;
509 private XmlSchemaElement AddElement(string localName, string prefix, string childURI, XmlSchema parentSchema, XmlSchemaObjectCollection addLocation, int positionWithinCollection)
511 if (childURI == XmlSchema.Namespace)
513 throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
516 XmlSchemaElement xse = null;
517 XmlSchemaElement returnedElement = xse; //this value will change to elementReference if childURI!= parentURI
518 XmlSchema xs = null;
519 bool bCreatingNewType = true;
520 if (childURI == String.Empty)
522 childURI = null;
524 // The new element belongs to the same ns as parent and addlocation is not null
525 if (parentSchema != null && childURI == parentSchema.TargetNamespace)
527 xse = new XmlSchemaElement();
528 xse.Name = localName;
529 xs = parentSchema;
530 if (xs.ElementFormDefault != XmlSchemaForm.Qualified && addLocation != null)
532 xse.Form = XmlSchemaForm.Qualified;
535 else if (schemaSet.Contains(childURI))
537 xse = this.FindGlobalElement(childURI, localName, out xs);
538 if (xse == null)
540 ArrayList col = this.schemaSet.Schemas(childURI)as ArrayList;
541 if (col != null && col.Count > 0 )
543 xs = col[0] as XmlSchema;
545 xse = new XmlSchemaElement();
546 xse.Name = localName;
547 xs.Items.Add(xse);
549 else
550 bCreatingNewType = false;
553 else
555 xs = CreateXmlSchema(childURI);
556 if (prefix.Length!=0)
557 NamespaceManager.AddNamespace(prefix, childURI);
558 xse=new XmlSchemaElement();
559 xse.Name = localName;
560 xs.Items.Add(xse); //add global element declaration only when creating new schema
562 if (parentSchema == null)
564 parentSchema = xs;
565 this.rootSchema = parentSchema;
568 if (childURI != parentSchema.TargetNamespace )
570 bool add = true;
572 for (int i = 0; i < parentSchema.Includes.Count; ++i)
574 XmlSchemaImport import = parentSchema.Includes[i] as XmlSchemaImport;
575 if (import == null)
577 continue;
579 //Debug.WriteLine(import.Schema.TargetNamespace);
581 if (import.Namespace == childURI)
583 add = false;
586 if (add)
588 XmlSchemaImport import = new XmlSchemaImport();
589 import.Schema = xs;
590 import.Namespace = childURI;
591 parentSchema.Includes.Add(import);
594 returnedElement = xse;
595 if (addLocation != null)
597 if (childURI == parentSchema.TargetNamespace )
599 if (this.Occurrence == InferenceOption.Relaxed /*&& parentSchema.Items != addLocation*/)
601 xse.MinOccurs = 0;
603 if (positionWithinCollection == -1)
605 positionWithinCollection = addLocation.Add(xse);
607 else
609 addLocation.Insert(positionWithinCollection, xse);
612 else
614 XmlSchemaElement elementReference = new XmlSchemaElement();
615 elementReference.RefName = new XmlQualifiedName(localName, childURI);
616 if (this.Occurrence == InferenceOption.Relaxed)
618 elementReference.MinOccurs = 0;
620 if (positionWithinCollection == -1)
622 positionWithinCollection = addLocation.Add(elementReference);
624 else
626 addLocation.Insert(positionWithinCollection, elementReference);
628 returnedElement = elementReference;
629 /* if (childURI == XmlSchema.Namespace)
631 schemaList.Add(new ReplaceList(addLocation, positionWithinCollection));
637 InferElement(xse, bCreatingNewType, xs);
639 return returnedElement;
642 /// <summary>
643 /// Sets type of the xse based on the currently read element.
644 /// If the type is already set, verifies that it matches the instance and if not, updates the type to validate the instance.
645 /// </summary>
646 /// <param name="xse">XmlSchemaElement corresponding to the element just read by the xtr XmlTextReader</param>
647 /// <param name="bCreatingNewType">true if the type is newly created, false if the type already existed and matches the current element name</param>
648 /// <param name="nsContext">namespaceURI of the parent element. Used to distinguish if ref= should be used when parent is in different ns than child.</param>
649 internal void InferElement(XmlSchemaElement xse, bool bCreatingNewType, XmlSchema parentSchema)
652 bool bEmptyElement = xtr.IsEmptyElement;
653 int lastUsedSeqItem = -1;
655 Hashtable table = new Hashtable();
656 XmlSchemaType schemaType = GetEffectiveSchemaType(xse, bCreatingNewType);
657 XmlSchemaComplexType ct = schemaType as XmlSchemaComplexType;
659 //infer type based on content of the current element
660 if (xtr.MoveToFirstAttribute())
662 ProcessAttributes(ref xse, schemaType, bCreatingNewType, parentSchema);
664 else
666 if (!bCreatingNewType && ct != null)
667 { //if type already exists and can potentially have attributes
668 MakeExistingAttributesOptional(ct, null);
671 if (ct == null || ct == XmlSchemaComplexType.AnyType) { //It was null or simple type, after processing attributes, this might have been set
672 ct = xse.SchemaType as XmlSchemaComplexType;
674 //xse's type is set either to complex type if attributes exist or null
675 if (bEmptyElement) //<element attr="3232" />
677 if (!bCreatingNewType)
679 if (null != ct)
681 if (null!= ct.Particle )
684 ct.Particle.MinOccurs = 0;
686 else if (null != ct.ContentModel)
688 XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
689 sce.BaseTypeName = ST_string;
690 sce.LineNumber = TF_string;
693 else if (!xse.SchemaTypeName.IsEmpty)
695 xse.LineNumber = TF_string;
696 xse.SchemaTypeName = ST_string;
699 else
701 xse.LineNumber = TF_string;
702 //xse.SchemaTypeName = ST_string; //My change
704 return; //We are done processing this element - all attributes are already added
706 bool bWhiteSpace = false;
709 xtr.Read();
710 if (xtr.NodeType == XmlNodeType.Whitespace)
712 bWhiteSpace = true;
714 if (xtr.NodeType == XmlNodeType.EntityReference)
716 throw new XmlSchemaInferenceException(Res.SchInf_entity, 0, 0);
718 } while( (!xtr.EOF) && (xtr.NodeType != XmlNodeType.EndElement) && (xtr.NodeType != XmlNodeType.CDATA)&&(xtr.NodeType != XmlNodeType.Element)&&(xtr.NodeType != XmlNodeType.Text) );
720 if (xtr.NodeType == XmlNodeType.EndElement)
722 if (bWhiteSpace) {
723 if (ct != null)
725 if (null != ct.ContentModel)
727 XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
728 sce.BaseTypeName = ST_string;
729 sce.LineNumber = TF_string;
731 else if (bCreatingNewType)
733 //attributes exist, but both Particle and ContentModel == null - this must be complex type with simpleContent extension
734 XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
735 ct.ContentModel = sc;
736 XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
737 sc.Content = sce;
739 MoveAttributes(ct, sce, bCreatingNewType);
741 sce.BaseTypeName = ST_string;
742 sce.LineNumber = TF_string;
744 else
745 ct.IsMixed = true;
747 else
749 xse.SchemaTypeName = ST_string;
750 xse.LineNumber = TF_string;
753 if (bCreatingNewType)
755 xse.LineNumber = TF_string;
756 //xse.SchemaTypeName = ST_string; //my change
758 else
760 if (null != ct)
762 if (null!= ct.Particle)
764 ct.Particle.MinOccurs = 0;
766 else if (null != ct.ContentModel)
768 XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
769 sce.BaseTypeName = ST_string;
770 sce.LineNumber = TF_string;
773 else if (!xse.SchemaTypeName.IsEmpty)
775 xse.LineNumber = TF_string;
776 xse.SchemaTypeName = ST_string;
780 return; //<element attr="232"></element>
782 int iChildNumber = 0;
783 bool bCreatingNewSequence = false;
784 while (!xtr.EOF && (xtr.NodeType != XmlNodeType.EndElement))
786 bool bNextNodeAlreadyRead = false; //In some cases we have to look ahead one node. If true means that we did look ahead.
787 iChildNumber++;
788 if ((xtr.NodeType == XmlNodeType.Text) || (xtr.NodeType == XmlNodeType.CDATA) ) //node can be simple type, complex with simple content or complex with mixed content
790 if (null != ct)
792 if (null != ct.Particle)
794 ct.IsMixed = true;
795 if (iChildNumber==1)
797 //if this is the only child and other elements do not follow, we must set particle minOccurs="0"
798 do{ xtr.Read();} while( (!xtr.EOF) && ((xtr.NodeType == XmlNodeType.CDATA)||(xtr.NodeType == XmlNodeType.Text) || (xtr.NodeType == XmlNodeType.Comment) || (xtr.NodeType == XmlNodeType.ProcessingInstruction) || (xtr.NodeType == XmlNodeType.Whitespace) || (xtr.NodeType == XmlNodeType.SignificantWhitespace) || (xtr.NodeType == XmlNodeType.XmlDeclaration)));
799 bNextNodeAlreadyRead = true;
800 if (xtr.NodeType == XmlNodeType.EndElement)
801 ct.Particle.MinOccurs=decimal.Zero;
804 else if (null!=ct.ContentModel)
805 { //complexType with simpleContent
806 XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
807 if ((xtr.NodeType == XmlNodeType.Text) && (iChildNumber==1))
809 int SimpleType = -1;
810 if (xse.Parent == null)
812 SimpleType = sce.LineNumber; // we use LineNumber to represent valid type flags
814 else
816 SimpleType = GetSchemaType(sce.BaseTypeName);
817 xse.Parent = null;
819 sce.BaseTypeName = RefineSimpleType(xtr.Value, ref SimpleType);
820 sce.LineNumber = SimpleType; // we use LineNumber to represent valid type flags
822 else
824 sce.BaseTypeName = ST_string;
825 sce.LineNumber = TF_string;
828 else
830 //attributes exist, but both Particle and ContentModel == null - this must be complex type with simpleContent extension
831 XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
832 ct.ContentModel = sc;
833 XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
834 sc.Content = sce;
836 MoveAttributes(ct, sce, bCreatingNewType);
838 if (xtr.NodeType == XmlNodeType.Text)
840 int TypeFlags;
841 if(!bCreatingNewType)
842 //previously this was empty element
843 TypeFlags=TF_string;
844 else
845 TypeFlags = -1;
846 sce.BaseTypeName = RefineSimpleType(xtr.Value, ref TypeFlags);
847 sce.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
849 else
851 sce.BaseTypeName = ST_string;
852 sce.LineNumber = TF_string;
857 else
858 { //node is currently empty or with SimpleType
859 //node will become simple type
860 if (iChildNumber>1)
862 //more than one consecutive text nodes probably with PI in between
863 xse.SchemaTypeName = ST_string;
864 xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
866 else
868 int TypeFlags = -1;
869 if (bCreatingNewType)
870 if (xtr.NodeType == XmlNodeType.Text)
872 xse.SchemaTypeName = RefineSimpleType(xtr.Value, ref TypeFlags);
873 xse.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
875 else
877 xse.SchemaTypeName = ST_string;
878 xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
880 else if (xtr.NodeType == XmlNodeType.Text)
882 if (xse.Parent == null)
884 TypeFlags = xse.LineNumber;
886 else
888 TypeFlags = GetSchemaType(xse.SchemaTypeName);
889 if (TypeFlags == -1 && xse.LineNumber == TF_string) { //Since schemaTypeName is not set for empty elements (<e></e>)
890 TypeFlags = TF_string;
892 xse.Parent = null;
894 xse.SchemaTypeName = RefineSimpleType(xtr.Value, ref TypeFlags); //simple type
895 xse.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
897 else
899 xse.SchemaTypeName = ST_string;
900 xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
905 else if (xtr.NodeType == XmlNodeType.Element)
907 XmlQualifiedName qname = new XmlQualifiedName(xtr.LocalName, xtr.NamespaceURI);
908 bool Maxoccursflag = false;
909 if (table.Contains(qname))
911 Maxoccursflag = true;
913 else
915 table.Add(qname, null);
917 if (ct==null)
918 { //untill now the element was empty or SimpleType - it now becomes complex type
919 ct = new XmlSchemaComplexType();
920 xse.SchemaType = ct;
921 if (!xse.SchemaTypeName.IsEmpty) //
923 ct.IsMixed=true;
924 xse.SchemaTypeName = XmlQualifiedName.Empty;
927 if (ct.ContentModel !=null)
928 { //type was previously identified as simple content extension - we need to convert it to sequence
929 XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
930 MoveAttributes(sce, ct);
931 ct.ContentModel = null;
932 ct.IsMixed = true;
933 if (ct.Particle != null)
934 throw new XmlSchemaInferenceException(Res.SchInf_particle, 0, 0);
935 ct.Particle = new XmlSchemaSequence();
936 bCreatingNewSequence = true;
937 XmlSchemaElement subelement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema,((XmlSchemaSequence)ct.Particle).Items, -1);
938 lastUsedSeqItem = 0;
939 if (!bCreatingNewType)
940 ct.Particle.MinOccurs=0; //previously this was simple type so subelements did not exist
942 else if (ct.Particle == null)
944 ct.Particle = new XmlSchemaSequence();
945 bCreatingNewSequence = true;
946 XmlSchemaElement subelement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema,((XmlSchemaSequence)ct.Particle).Items, -1);
947 if (!bCreatingNewType)
949 ((XmlSchemaSequence)ct.Particle).MinOccurs = decimal.Zero;
950 // subelement.MinOccurs = decimal.Zero;
953 lastUsedSeqItem = 0;
955 else
957 bool bParticleChanged = false;
958 XmlSchemaElement subelement = FindMatchingElement(bCreatingNewType || bCreatingNewSequence, xtr, ct, ref lastUsedSeqItem, ref bParticleChanged, parentSchema, Maxoccursflag);
961 else if (xtr.NodeType == XmlNodeType.Text)
963 if (ct==null)
964 throw new XmlSchemaInferenceException(Res.SchInf_ct, 0, 0);
965 ct.IsMixed = true;
969 if (xtr.NodeType == XmlNodeType.EntityReference)
971 throw new XmlSchemaInferenceException(Res.SchInf_entity, 0, 0);
974 if (!bNextNodeAlreadyRead)
976 xtr.Read();
978 else
980 bNextNodeAlreadyRead = false;
982 } while( (!xtr.EOF) && (xtr.NodeType != XmlNodeType.EndElement) && (xtr.NodeType != XmlNodeType.CDATA)&&(xtr.NodeType != XmlNodeType.Element)&&(xtr.NodeType != XmlNodeType.Text));
984 if (lastUsedSeqItem != -1)
986 //Verify if all elements in a sequence exist, if not set MinOccurs=0
987 while (++lastUsedSeqItem < ((XmlSchemaSequence)ct.Particle).Items.Count)
989 if (((XmlSchemaSequence)ct.Particle).Items[lastUsedSeqItem].GetType() != typeof (XmlSchemaElement))
990 throw new XmlSchemaInferenceException(Res.SchInf_seq, 0 , 0);
991 XmlSchemaElement subElement = (XmlSchemaElement) ((XmlSchemaSequence)ct.Particle).Items[lastUsedSeqItem];
992 subElement.MinOccurs = 0;
998 private XmlSchemaSimpleContentExtension CheckSimpleContentExtension(XmlSchemaComplexType ct) {
999 XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
1000 if (sc == null) {
1001 throw new XmlSchemaInferenceException(Res.SchInf_simplecontent, 0, 0);
1003 XmlSchemaSimpleContentExtension sce = sc.Content as XmlSchemaSimpleContentExtension;
1004 if (sce == null) {
1005 throw new XmlSchemaInferenceException(Res.SchInf_extension, 0, 0);
1007 return sce;
1010 private XmlSchemaType GetEffectiveSchemaType(XmlSchemaElement elem, bool bCreatingNewType) {
1011 XmlSchemaType effectiveSchemaType = null;
1012 if (!bCreatingNewType && elem.ElementSchemaType != null) {
1013 effectiveSchemaType = elem.ElementSchemaType;
1015 else { //creating new type, hence look up pre-compiled info
1016 Debug.Assert(elem.ElementDecl == null);
1017 if (elem.SchemaType != null) {
1018 effectiveSchemaType = elem.SchemaType;
1020 else if (elem.SchemaTypeName != XmlQualifiedName.Empty) {
1021 effectiveSchemaType = schemaSet.GlobalTypes[elem.SchemaTypeName] as XmlSchemaType;
1022 if (effectiveSchemaType == null) {
1023 effectiveSchemaType = XmlSchemaType.GetBuiltInSimpleType(elem.SchemaTypeName);
1025 if (effectiveSchemaType == null) {
1026 effectiveSchemaType = XmlSchemaType.GetBuiltInComplexType(elem.SchemaTypeName);
1030 return effectiveSchemaType;
1032 /// <summary>
1033 /// Verifies that the current element has its corresponding element in the sequence and order is the same.
1034 /// If the order is not the same, it changes the particle from Sequence to Sequence with Choice.
1035 /// If there is more elements of the same kind in the sequence, sets maxOccurs to unbounded
1036 /// </summary>
1037 /// <param name="bCreatingNewType">True if this is a new type. This is important for setting minOccurs=0 for elements that did not exist in a particle.</param>
1038 /// <param name="xtr">text reader positioned to the current element</param>
1039 /// <param name="ct">complex type with Sequence or Choice Particle</param>
1040 /// <param name="lastUsedSeqItem">ordinal number in the sequence to indicate current sequence position</param>
1041 /// <param name="itemsMadeOptional">hashtable of elements with minOccurs changed to 0 in order to satisfy sequence requirements. These elements will be rolled back if Sequence becomes Sequence of Choice.</param>
1042 /// <param name="bParticleChanged">This indicates to the caller if Sequence was changed to Choice</param>
1043 internal XmlSchemaElement FindMatchingElement(bool bCreatingNewType, XmlReader xtr,XmlSchemaComplexType ct, ref int lastUsedSeqItem, ref bool bParticleChanged, XmlSchema parentSchema, bool setMaxoccurs)
1045 if (xtr.NamespaceURI == XmlSchema.Namespace)
1047 throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
1050 bool bItemNotUsedYet = ((lastUsedSeqItem == -1)? true: false);
1051 XmlSchemaObjectCollection minOccursCandidates = new XmlSchemaObjectCollection(); //elements that are skipped in the sequence and need minOccurs modified.
1052 if (ct.Particle.GetType() == typeof (XmlSchemaSequence))
1054 string childURI = xtr.NamespaceURI;
1055 if (childURI.Length == 0)
1057 childURI = null;
1059 XmlSchemaSequence xss = (XmlSchemaSequence) ct.Particle;
1060 if (xss.Items.Count < 1 && !bCreatingNewType)
1062 lastUsedSeqItem = 0;
1063 XmlSchemaElement e = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema, xss.Items,-1);
1064 e.MinOccurs = 0;
1065 return e;
1067 if (xss.Items[0].GetType() == typeof (XmlSchemaChoice))
1068 { // <sequence minOccurs="0" maxOccurs="unbounded"><choice><element>...</choice></sequence>
1069 XmlSchemaChoice xsch = (XmlSchemaChoice) xss.Items[0];
1070 for (int i = 0; i < xsch.Items.Count; ++i)
1072 XmlSchemaElement el = xsch.Items[i] as XmlSchemaElement;
1073 if (el == null)
1075 throw new XmlSchemaInferenceException(Res.SchInf_UnknownParticle, 0, 0);
1077 if ((el.Name == xtr.LocalName) &&( parentSchema.TargetNamespace == childURI))
1078 { // element is in the same namespace
1079 InferElement(el, false, parentSchema);
1080 SetMinMaxOccurs(el, setMaxoccurs);
1081 return el;
1083 else if ((el.RefName.Name == xtr.LocalName) && (el.RefName.Namespace == xtr.NamespaceURI))
1085 XmlSchemaElement referencedElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
1086 InferElement(referencedElement, false, parentSchema);
1087 SetMinMaxOccurs(el, setMaxoccurs);
1088 return referencedElement;
1091 XmlSchemaElement subElement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema, xsch.Items,-1);
1092 return subElement;
1094 else
1095 { //this should be sequence of elements
1096 int iSeqItem = 0; //iterator through schema sequence items
1097 if (lastUsedSeqItem >= 0)
1098 iSeqItem = lastUsedSeqItem;
1099 XmlSchemaParticle particle = xss.Items[iSeqItem] as XmlSchemaParticle;
1100 XmlSchemaElement el = particle as XmlSchemaElement;
1101 if (el == null)
1103 throw new XmlSchemaInferenceException(Res.SchInf_UnknownParticle, 0, 0);
1105 if (el.Name == xtr.LocalName && parentSchema.TargetNamespace == childURI)
1107 if (!bItemNotUsedYet) //read: if item was already used one or more times
1108 el.MaxOccurs = decimal.MaxValue; //set it to unbounded
1109 lastUsedSeqItem = iSeqItem;
1110 InferElement(el, false, parentSchema);
1111 SetMinMaxOccurs(el, false);
1112 return el;
1114 else if (el.RefName.Name == xtr.LocalName && el.RefName.Namespace == xtr.NamespaceURI)
1116 if (!bItemNotUsedYet) //read: if item was already used one or more times
1117 el.MaxOccurs = decimal.MaxValue; //set it to unbounded
1118 lastUsedSeqItem = iSeqItem;
1119 XmlSchemaElement referencedElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
1120 InferElement(referencedElement, false, parentSchema);
1121 SetMinMaxOccurs(el, false);
1122 return el;
1124 if (bItemNotUsedYet && el.MinOccurs!=decimal.Zero)
1125 minOccursCandidates.Add(el);
1126 iSeqItem++;
1127 while (iSeqItem < xss.Items.Count)
1129 particle = xss.Items[iSeqItem] as XmlSchemaParticle;
1130 el = particle as XmlSchemaElement;
1131 if (el == null)
1133 throw new XmlSchemaInferenceException(Res.SchInf_UnknownParticle, 0, 0);
1135 if (el.Name == xtr.LocalName && parentSchema.TargetNamespace == childURI)
1137 lastUsedSeqItem = iSeqItem;
1138 for (int i = 0; i < minOccursCandidates.Count; ++i)
1140 ((XmlSchemaElement) minOccursCandidates[i]).MinOccurs = decimal.Zero;
1142 InferElement(el, false, parentSchema);
1143 SetMinMaxOccurs(el, setMaxoccurs);
1144 return el;
1146 else if (el.RefName.Name == xtr.LocalName && el.RefName.Namespace == xtr.NamespaceURI)
1148 lastUsedSeqItem = iSeqItem;
1149 for (int i = 0; i < minOccursCandidates.Count; ++i)
1151 ((XmlSchemaElement) minOccursCandidates[i]).MinOccurs = decimal.Zero;
1153 XmlSchemaElement referencedElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
1154 InferElement(referencedElement, false, parentSchema);
1155 SetMinMaxOccurs(el, setMaxoccurs);
1156 return referencedElement;
1160 minOccursCandidates.Add(el);
1161 iSeqItem++;
1164 //element not found in the sequence order, if it is found out of order change Sequence of elements to Sequence of Choices otherwise insert into sequence as optional
1165 XmlSchemaElement subElement = null;
1166 XmlSchemaElement actualElement = null;
1169 if (parentSchema.TargetNamespace == childURI)
1171 subElement = FindElement(xss.Items, xtr.LocalName);
1172 actualElement = subElement;
1174 else
1176 subElement = FindElementRef(xss.Items, xtr.LocalName, xtr.NamespaceURI);
1177 if (subElement != null)
1179 actualElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
1182 if (null != subElement)
1184 XmlSchemaChoice xsc = new XmlSchemaChoice();
1185 xsc.MaxOccurs = decimal.MaxValue;
1186 SetMinMaxOccurs(subElement, setMaxoccurs);
1187 InferElement(actualElement, false, parentSchema);
1188 for (int i = 0; i < xss.Items.Count; ++i)
1190 xsc.Items.Add(CreateNewElementforChoice((XmlSchemaElement) xss.Items[i]));
1192 xss.Items.Clear();
1193 xss.Items.Add(xsc);
1194 return subElement;
1196 else
1198 subElement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema, xss.Items, ++lastUsedSeqItem);
1199 if (!bCreatingNewType)
1200 subElement.MinOccurs = decimal.Zero;
1201 return subElement;
1205 else
1207 throw new XmlSchemaInferenceException(Res.SchInf_noseq, 0, 0);
1211 internal void ProcessAttributes(ref XmlSchemaElement xse, XmlSchemaType effectiveSchemaType, bool bCreatingNewType, XmlSchema parentSchema)
1213 XmlSchemaObjectCollection attributesSeen = new XmlSchemaObjectCollection();
1214 XmlSchemaComplexType ct = effectiveSchemaType as XmlSchemaComplexType;
1216 Debug.Assert(xtr.NodeType == XmlNodeType.Attribute);
1219 if (xtr.NamespaceURI == XmlSchema.Namespace)
1221 throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
1224 if (xtr.NamespaceURI == XmlReservedNs.NsXmlNs)
1226 if (xtr.Prefix=="xmlns")
1227 NamespaceManager.AddNamespace(xtr.LocalName, xtr.Value);
1229 else if (xtr.NamespaceURI == XmlReservedNs.NsXsi)
1231 string localName = xtr.LocalName;
1232 if (localName == "nil")
1234 xse.IsNillable = true;
1236 else if (localName != "type" && localName != "schemaLocation" && localName != "noNamespaceSchemaLocation")
1238 throw new XmlSchemaInferenceException(Res.Sch_NotXsiAttribute,localName);
1241 else
1243 if (ct == null || ct == XmlSchemaComplexType.AnyType)
1245 ct = new XmlSchemaComplexType();
1246 xse.SchemaType = ct;
1249 XmlSchemaAttribute xsa=null;
1250 //The earlier assumption of checking just schemaTypeName !Empty is not correct for schemas that are not generated by us, schemaTypeName can point to any complex type as well
1251 //Check that it is a simple type by checking typeCode
1252 //Switch to complex type simple content extension
1253 if (effectiveSchemaType != null && effectiveSchemaType.Datatype != null && !xse.SchemaTypeName.IsEmpty)
1255 //type was previously simple type, now it will become complex with simple type extension
1256 Debug.Assert(ct != null);
1257 XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
1258 ct.ContentModel = sc;
1259 XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
1260 sc.Content = sce;
1261 sce.BaseTypeName = xse.SchemaTypeName;
1262 sce.LineNumber = xse.LineNumber;
1263 xse.LineNumber = 0;
1264 xse.SchemaTypeName = XmlQualifiedName.Empty; //re-set the name
1267 Debug.Assert(ct != null); //either the user-defined type itself is a complex type or we switched from a simple type to a complex type
1268 if (ct.ContentModel != null)
1270 XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
1271 Debug.Assert(sce != null);
1272 xsa = AddAttribute(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, xtr.Value, bCreatingNewType, parentSchema, sce.Attributes, ct.AttributeUses);
1274 else //add atributes directly to complex type
1276 xsa = AddAttribute(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, xtr.Value, bCreatingNewType, parentSchema, ct.Attributes, ct.AttributeUses);
1278 if (xsa != null) {
1279 attributesSeen.Add(xsa);
1283 } while (xtr.MoveToNextAttribute());
1284 if (!bCreatingNewType)
1286 //make attributes that did not appear this time optional
1287 if (ct!=null) {
1288 MakeExistingAttributesOptional(ct, attributesSeen);
1293 private void MoveAttributes(XmlSchemaSimpleContentExtension scExtension, XmlSchemaComplexType ct) {
1294 //copy all attributes from the simple content to the complex type
1295 //This is ok since when we move from complex type to simple content extension we copy from AttributeUses property
1296 for (int i = 0; i < scExtension.Attributes.Count; ++i) //since simpleContent is being cleared
1298 ct.Attributes.Add(scExtension.Attributes[i]);
1302 private void MoveAttributes(XmlSchemaComplexType ct, XmlSchemaSimpleContentExtension simpleContentExtension, bool bCreatingNewType) {
1303 //copy all attributes from the complex type to the simple content
1305 ICollection sourceCollection;
1306 if (!bCreatingNewType && ct.AttributeUses.Count > 0) {
1307 sourceCollection = ct.AttributeUses.Values;
1309 else {
1310 sourceCollection = ct.Attributes;
1313 foreach (XmlSchemaAttribute attr in sourceCollection) {
1314 simpleContentExtension.Attributes.Add(attr);
1316 ct.Attributes.Clear(); //Clear from pre-compiled property, post compiled will be cleared on Re-process and Compile()
1319 internal XmlSchemaAttribute FindAttribute(ICollection attributes, string attrName)
1321 foreach(XmlSchemaObject xsa in attributes)
1323 XmlSchemaAttribute schemaAttribute = xsa as XmlSchemaAttribute;
1324 if (schemaAttribute != null)
1326 if (schemaAttribute.Name == attrName)
1328 return schemaAttribute;
1333 return null;
1336 internal XmlSchemaElement FindGlobalElement(string namespaceURI, string localName, out XmlSchema parentSchema)
1338 ICollection col = this.schemaSet.Schemas(namespaceURI);
1339 XmlSchemaElement xse = null;
1340 parentSchema = null;
1341 foreach(XmlSchema schema in col)
1343 xse = FindElement(schema.Items, localName);
1344 if (xse != null)
1346 parentSchema = schema;
1347 return xse;
1350 return null;
1354 internal XmlSchemaElement FindElement(XmlSchemaObjectCollection elements, string elementName)
1356 for (int i = 0; i < elements.Count; ++i)
1358 XmlSchemaElement xse = elements[i] as XmlSchemaElement;
1359 if (xse != null && xse.RefName != null)
1361 if (xse.Name == elementName)
1363 return xse;
1367 return null;
1370 internal XmlSchemaAttribute FindAttributeRef(ICollection attributes, string attributeName, string nsURI)
1372 foreach(XmlSchemaObject xsa in attributes)
1374 XmlSchemaAttribute schemaAttribute = xsa as XmlSchemaAttribute;
1375 if (schemaAttribute != null)
1377 if (schemaAttribute.RefName.Name == attributeName && schemaAttribute.RefName.Namespace == nsURI) {
1378 return schemaAttribute;
1383 return null;
1386 internal XmlSchemaElement FindElementRef(XmlSchemaObjectCollection elements, string elementName, string nsURI)
1388 for (int i = 0; i < elements.Count; ++i)
1390 XmlSchemaElement xse = elements[i] as XmlSchemaElement;
1391 if (xse != null && xse.RefName != null)
1393 if (xse.RefName.Name == elementName && xse.RefName.Namespace == nsURI)
1395 return xse;
1399 return null;
1402 internal void MakeExistingAttributesOptional(XmlSchemaComplexType ct, XmlSchemaObjectCollection attributesInInstance) {
1403 if (ct == null) {
1404 throw new XmlSchemaInferenceException(Res.SchInf_noct, 0, 0);
1406 if (ct.ContentModel != null) {
1407 XmlSchemaSimpleContentExtension xssce = CheckSimpleContentExtension(ct);
1408 SwitchUseToOptional(xssce.Attributes, attributesInInstance);
1410 else { //either <xs:attribute> as child of xs:complexType or the attributes are within the content model
1411 SwitchUseToOptional(ct.Attributes, attributesInInstance);
1415 private void SwitchUseToOptional(XmlSchemaObjectCollection attributes, XmlSchemaObjectCollection attributesInInstance) {
1416 for (int i = 0; i < attributes.Count; ++i)
1418 XmlSchemaAttribute attr = attributes[i] as XmlSchemaAttribute;
1419 if (attr != null) {
1420 if (attributesInInstance != null) {
1421 if (attr.RefName.Name.Length == 0) { //If the attribute is not present in this instance, make it optional
1422 if (null == FindAttribute(attributesInInstance, attr.Name)) {
1423 attr.Use = XmlSchemaUse.Optional;
1426 else {
1427 if (null == FindAttributeRef(attributesInInstance, attr.RefName.Name, attr.RefName.Namespace)) {
1428 attr.Use = XmlSchemaUse.Optional;
1432 else {
1433 attr.Use = XmlSchemaUse.Optional;
1439 internal XmlQualifiedName RefineSimpleType(string s, ref int iTypeFlags)
1441 bool bNeedsRangeCheck = false;
1442 s = s.Trim();
1443 if (iTypeFlags == TF_string || this.typeInference == InferenceOption.Relaxed)
1444 return ST_string;
1445 iTypeFlags &= InferSimpleType(s, ref bNeedsRangeCheck);
1446 if (iTypeFlags == TF_string)
1447 return ST_string;
1448 if (bNeedsRangeCheck)
1450 if ((iTypeFlags & TF_byte) != 0)
1454 XmlConvert.ToSByte(s);
1455 //sbyte.Parse(s);
1456 if ((iTypeFlags & TF_unsignedByte) != 0)
1457 return ST_unsignedByte; //number is positive and fits byte -> it also fits unsignedByte
1458 else
1459 return ST_byte;
1461 catch (FormatException)
1463 catch (OverflowException)
1465 iTypeFlags &= (~TF_byte);
1467 if ((iTypeFlags & TF_unsignedByte) != 0)
1471 XmlConvert.ToByte(s);
1472 //byte.Parse(s);
1473 return ST_unsignedByte;
1475 catch (FormatException)
1477 catch (OverflowException)
1479 iTypeFlags &= (~TF_unsignedByte);
1481 if ((iTypeFlags & TF_short) != 0)
1485 XmlConvert.ToInt16(s);
1486 //short.Parse(s);
1487 if ((iTypeFlags & TF_unsignedShort) != 0)
1488 return ST_unsignedShort; //number is positive and fits short -> it also fits unsignedShort
1489 else
1490 return ST_short;
1492 catch (FormatException)
1494 catch (OverflowException)
1496 iTypeFlags &= (~TF_short);
1498 if ((iTypeFlags & TF_unsignedShort) != 0)
1502 XmlConvert.ToUInt16(s);
1503 //ushort.Parse(s);
1504 return ST_unsignedShort;
1506 catch (FormatException)
1508 catch (OverflowException)
1510 iTypeFlags &= (~TF_unsignedShort);
1512 if ((iTypeFlags & TF_int) != 0)
1516 XmlConvert.ToInt32(s);
1517 //int.Parse(s);
1518 if ((iTypeFlags & TF_unsignedInt) != 0)
1519 return ST_unsignedInt; //number is positive and fits int -> it also fits unsignedInt
1520 else
1521 return ST_int;
1523 catch (FormatException)
1525 catch (OverflowException)
1527 iTypeFlags &= (~TF_int);
1529 if ((iTypeFlags & TF_unsignedInt) != 0)
1533 XmlConvert.ToUInt32(s);
1534 //uint.Parse(s);
1535 return ST_unsignedInt;
1537 catch (FormatException)
1539 catch (OverflowException)
1541 iTypeFlags &= (~TF_unsignedInt);
1543 if ((iTypeFlags & TF_long) != 0)
1547 XmlConvert.ToInt64(s);
1548 //long.Parse(s);
1549 if ((iTypeFlags & TF_unsignedLong) != 0)
1550 return ST_unsignedLong; //number is positive and fits long -> it also fits unsignedLong
1551 else
1552 return ST_long;
1554 catch (FormatException)
1556 catch (OverflowException)
1558 iTypeFlags &= (~TF_long);
1560 if ((iTypeFlags & TF_unsignedLong) != 0)
1564 XmlConvert.ToUInt64(s);
1565 //ulong.Parse(s);
1566 return ST_unsignedLong;
1568 catch (FormatException)
1570 catch (OverflowException)
1572 iTypeFlags &= (~TF_unsignedLong);
1574 if ((iTypeFlags & TF_double) != 0)
1578 double dbValue = XmlConvert.ToDouble(s);
1579 if ((iTypeFlags & TF_integer) != 0)
1580 return ST_integer;
1581 else if ((iTypeFlags & TF_decimal) != 0)
1582 return ST_decimal;
1583 else {
1584 // The value fits into double, but it could be float as well
1585 if ((iTypeFlags & TF_float) != 0) {
1586 // We used to default to float in this case, so try to fit it into float first
1587 try {
1588 float flValue = XmlConvert.ToSingle(s);
1589 // Compare the float and double values. We can't do simple value comparison
1590 // as conversion from float to double introduces imprecissions which cause problems.
1591 // Instead we will convert both back to string and compare the strings.
1592 if (string.Compare(XmlConvert.ToString(flValue), XmlConvert.ToString(dbValue),
1593 StringComparison.OrdinalIgnoreCase) == 0) {
1594 // If we can convert the original string to the exact same value
1595 // and it still fits into float then we treat it as float
1596 return ST_float;
1599 catch (FormatException)
1601 catch (OverflowException)
1604 iTypeFlags &= (~TF_float);
1605 return ST_double;
1608 catch (FormatException)
1610 catch (OverflowException)
1612 iTypeFlags &= (~TF_double);
1614 if ((iTypeFlags & TF_float) != 0) {
1615 try {
1616 XmlConvert.ToSingle(s);
1617 if ((iTypeFlags & TF_integer) != 0)
1618 return ST_integer;
1619 else if ((iTypeFlags & TF_decimal) != 0)
1620 return ST_decimal;
1621 else
1622 return ST_float;
1624 catch (FormatException) { }
1625 catch (OverflowException) { }
1626 iTypeFlags &= (~TF_float);
1628 if ((iTypeFlags & TF_integer) != 0)
1629 return ST_integer;
1630 else if ((iTypeFlags & TF_decimal) != 0)
1631 return ST_decimal;
1632 else if (iTypeFlags == (TF_gYearMonth | TF_string) )
1636 XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind);
1637 return ST_gYearMonth;
1639 catch (FormatException)
1641 catch (OverflowException)
1643 iTypeFlags = TF_string;
1644 return ST_string;
1646 else if (iTypeFlags == (TF_duration | TF_string) )
1650 XmlConvert.ToTimeSpan(s);
1651 return ST_duration;
1653 catch (FormatException)
1655 catch (OverflowException)
1657 iTypeFlags = TF_string;
1658 return ST_string;
1660 else if (iTypeFlags == (TF_boolean | TF_string))
1662 return ST_boolean;
1667 switch (iTypeFlags)
1669 case TF_string:
1670 return ST_string;
1671 case TF_boolean:
1672 return ST_boolean;
1673 case TF_byte:
1674 return ST_byte;
1675 case TF_unsignedByte:
1676 return ST_unsignedByte;
1677 case TF_short:
1678 return ST_short;
1679 case TF_unsignedShort:
1680 return ST_unsignedShort;
1681 case TF_int:
1682 return ST_int;
1683 case TF_unsignedInt:
1684 return ST_unsignedInt;
1685 case TF_long:
1686 return ST_long;
1687 case TF_unsignedLong:
1688 return ST_unsignedLong;
1689 case TF_integer:
1690 return ST_integer;
1691 case TF_decimal:
1692 return ST_decimal;
1693 case TF_float:
1694 return ST_float;
1695 case TF_double:
1696 return ST_double;
1697 case TF_duration:
1698 return ST_duration;
1699 case TF_dateTime:
1700 return ST_dateTime;
1701 case TF_time:
1702 return ST_time;
1703 case TF_date:
1704 return ST_date;
1705 case TF_gYearMonth:
1706 return ST_gYearMonth;
1708 case TF_boolean | TF_string:
1709 return ST_boolean;
1710 case TF_dateTime | TF_string:
1711 return ST_dateTime;
1712 case TF_date | TF_string:
1713 return ST_date;
1714 case TF_time | TF_string:
1715 return ST_time;
1716 case TF_float | TF_double | TF_string:
1717 return ST_float;
1718 case TF_double | TF_string:
1719 return ST_double;
1721 default:
1722 Debug.Assert(false, "Expected type not matched");
1723 return ST_string;
1725 /* if (currentType == null)
1726 return SimpleTypes[newType];
1727 else
1728 return SimpleTypes[ST_Map[newType,(short) ST_Codes[currentType]]];
1732 internal static int InferSimpleType(string s, ref bool bNeedsRangeCheck)
1734 bool bNegative = false;
1735 bool bPositive = false;
1736 bool bDate = false;
1737 bool bTime = false;
1738 bool bMissingDay = false;
1740 #if !BOOTSTRAP_BASIC
1741 if (s.Length==0) return TF_string;
1742 int i = 0;
1743 switch (s[i])
1745 case 't':
1746 case 'f':
1747 if (s == "true")
1748 return TF_boolean | TF_string;
1749 else if (s == "false")
1750 return TF_boolean | TF_string;
1751 else
1752 return TF_string;
1753 case 'N': //try to match "NaN"
1754 if (s == "NaN")
1755 return TF_float | TF_double | TF_string;
1756 else
1757 return TF_string;
1758 //else
1759 case 'I': //try to match "INF"
1760 INF:
1761 if (s.Substring(i) == "INF")
1762 return TF_float | TF_double | TF_string;
1763 else return TF_string;
1764 case '.': //try to match ".9999" decimal/float/double
1765 FRACTION:
1766 bNeedsRangeCheck = true;
1767 i++;
1768 if (i==s.Length)
1770 if ((i==1) || (i==2 && (bPositive || bNegative))) //"." "-." "+."
1771 return TF_string;
1772 else
1773 return TF_decimal | TF_float | TF_double | TF_string;
1775 switch (s[i])
1777 case 'e':
1778 case 'E':
1779 goto EXPONENT;
1780 default:
1781 if (s[i]>='0' && s[i]<='9')
1782 goto DEC_PART;
1783 else
1784 return TF_string;
1786 DEC_PART:
1787 i++; if (i==s.Length) return TF_decimal | TF_float | TF_double | TF_string; //"9999.9" was matched
1788 switch (s[i])
1790 case 'e':
1791 case 'E':
1792 goto EXPONENT;
1793 default:
1794 if (s[i]>='0' && s[i]<='9')
1795 goto DEC_PART;
1796 else
1797 return TF_string;
1799 EXPONENT:
1800 i++; if (i==s.Length) return TF_string;
1801 switch (s[i])
1803 case '+':
1804 case '-':
1805 goto E1;
1806 default:
1807 if (s[i]>='0' && s[i]<='9')
1808 goto EXP_PART;
1809 else
1810 return TF_string;
1813 i++; if (i==s.Length) return TF_string; //".9999e+" was matched
1814 if (s[i]>='0' && s[i]<='9')
1815 goto EXP_PART;
1816 else
1817 return TF_string; //".999e+X was matched
1818 EXP_PART:
1819 i++; if (i==s.Length) return TF_float | TF_double | TF_string; //".9999e+99" was matched
1820 if (s[i]>='0' && s[i]<='9') //".9999e+9
1821 goto EXP_PART;
1822 else
1823 return TF_string; //".9999e+999X" was matched
1824 case '-':
1825 bNegative = true;
1826 i++; if (i==s.Length) return TF_string;
1827 switch (s[i])
1829 case 'I': //try to match "-INF"
1830 goto INF;
1831 case '.': //try to match "-.9999"
1832 goto FRACTION;
1833 case 'P':
1834 goto DURATION;
1835 default:
1836 if (s[i]>='0' && s[i]<='9') //-9
1837 goto NUMBER;
1838 else return TF_string;
1840 case '+':
1841 bPositive = true;
1842 i++; if (i==s.Length) return TF_string;
1843 switch (s[i])
1845 case '.': //try to match "+.9999"
1846 goto FRACTION;
1847 case 'P':
1848 goto DURATION;
1849 default:
1850 if (s[i]>='0' && s[i]<='9') //"+9
1851 goto NUMBER;
1852 else return TF_string;
1854 case 'P': //try to match duration
1855 DURATION:
1856 i++; if (i==s.Length) return TF_string;
1857 switch (s[i])
1859 case 'T':
1860 goto D7;
1861 default:
1862 if (s[i]>='0' && s[i]<='9') //"P9"
1863 goto D1;
1864 else return TF_string;
1867 i++; if (i==s.Length) return TF_string; //"P999" was matched
1868 switch (s[i])
1870 case 'Y':
1871 goto D2;
1872 case 'M':
1873 goto D4;
1874 case 'D':
1875 goto D6;
1876 default:
1877 if (s[i]>='0' && s[i]<='9')
1878 goto D1;
1879 else
1880 return TF_string;
1883 i++;
1884 if (i==s.Length)
1886 bNeedsRangeCheck = true;
1887 return TF_duration | TF_string; //"P999Y" was matched
1889 switch (s[i])
1891 case 'T':
1892 goto D7;
1893 default:
1894 if (s[i]>='0' && s[i]<='9')
1895 goto D3;
1896 else
1897 return TF_string;
1900 i++; if (i==s.Length) return TF_string; //"P999Y9" was matched
1901 switch (s[i])
1903 case 'M':
1904 goto D4;
1905 case 'D':
1906 goto D6;
1907 default:
1908 if (s[i]>='0' && s[i]<='9')
1909 goto D3;
1910 else
1911 return TF_string;
1914 i++;
1915 if (i==s.Length)
1917 bNeedsRangeCheck = true;
1918 return TF_duration | TF_string; //"P999Y999M" was matched
1920 switch (s[i])
1922 case 'T':
1923 goto D7;
1924 default:
1925 if (s[i]>='0' && s[i]<='9')
1926 goto D5;
1927 else
1928 return TF_string;
1931 i++; if (i==s.Length) return TF_string; //"P999Y999M9" was matched
1932 switch (s[i])
1934 case 'D':
1935 goto D6;
1936 default:
1937 if (s[i]>='0' && s[i]<='9')
1938 goto D5;
1939 else
1940 return TF_string;
1943 i++;
1944 if (i==s.Length)
1946 bNeedsRangeCheck = true;
1947 return TF_duration | TF_string; //"P999Y999M999D" was matched
1949 switch (s[i])
1951 case 'T':
1952 goto D7;
1953 default:
1954 return TF_string;
1957 i++; if (i==s.Length) return TF_string; //"P999Y999M9999DT" was matched
1958 if (s[i]>='0' && s[i]<='9')
1959 goto D8;
1960 else
1961 return TF_string;
1963 i++; if (i==s.Length) return TF_string; //"___T9" was matched
1964 switch (s[i])
1966 case 'H':
1967 goto D9;
1968 case 'M':
1969 goto D11;
1970 case '.':
1971 goto D13;
1972 case 'S':
1973 goto D15;
1974 default:
1975 if (s[i]>='0' && s[i]<='9')
1976 goto D8;
1977 else
1978 return TF_string;
1981 i++;
1982 if (i==s.Length)
1984 bNeedsRangeCheck = true;
1985 return TF_duration | TF_string; //"___T999H" was matched
1987 if (s[i]>='0' && s[i]<='9')
1988 goto D10;
1989 else
1990 return TF_string;
1991 D10:
1992 i++; if (i==s.Length) return TF_string; //"___T999H9" was matched
1993 switch (s[i])
1995 case 'M':
1996 goto D11;
1997 case '.':
1998 goto D13;
1999 case 'S':
2000 goto D15;
2001 default:
2002 if (s[i]>='0' && s[i]<='9')
2003 goto D10;
2004 else
2005 return TF_string;
2007 D11:
2008 i++;
2009 if (i==s.Length)
2011 bNeedsRangeCheck = true;
2012 return TF_duration | TF_string; //"___T999H999M" was matched
2014 if (s[i]>='0' && s[i]<='9')
2015 goto D12;
2016 else
2017 return TF_string;
2018 D12:
2019 i++; if (i==s.Length) return TF_string; //"___T999H999M9" was matched
2020 switch (s[i])
2022 case '.':
2023 goto D13;
2024 case 'S':
2025 goto D15;
2026 default:
2027 if (s[i]>='0' && s[i]<='9')
2028 goto D12;
2029 else
2030 return TF_string;
2032 D13:
2033 i++;
2034 if (i==s.Length)
2036 bNeedsRangeCheck = true;
2037 return TF_duration | TF_string; //"___T999H999M999." was matched
2039 if (s[i]>='0' && s[i]<='9')
2040 goto D14;
2041 else
2042 return TF_string;
2043 D14:
2044 i++; if (i==s.Length) return TF_string; //"___T999H999M999.9" was matched
2045 switch (s[i])
2047 case 'S':
2048 goto D15;
2049 default:
2050 if (s[i]>='0' && s[i]<='9')
2051 goto D14;
2052 else
2053 return TF_string;
2055 D15:
2056 i++;
2057 if (i==s.Length)
2059 bNeedsRangeCheck = true;
2060 return TF_duration | TF_string; //"___T999H999M999.999S" was matched
2062 else return TF_string;
2063 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
2064 NUMBER:
2065 i++;
2066 if (i==s.Length)
2068 bNeedsRangeCheck = true;
2069 if (bNegative || bPositive)
2070 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
2071 else
2073 if (s=="0" || s=="1")
2074 return TF_boolean | TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2075 TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2076 else
2077 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2078 TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2081 switch (s[i])
2083 case '.':
2084 goto FRACTION;
2085 case 'e':
2086 case 'E':
2087 bNeedsRangeCheck = true;
2088 return TF_float | TF_double | TF_string;
2089 default:
2090 if (s[i]>='0' && s[i]<='9')
2091 goto N2;
2092 else
2093 return TF_string;
2096 i++;
2097 if (i==s.Length)
2099 bNeedsRangeCheck = true;
2100 if (bNegative || bPositive)
2101 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
2102 else
2103 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2104 TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2106 switch (s[i])
2108 case '.':
2109 goto FRACTION;
2110 case ':':
2111 bTime = true;
2112 goto MINUTE;
2113 case 'e':
2114 case 'E':
2115 bNeedsRangeCheck = true;
2116 return TF_float | TF_double | TF_string;
2117 default:
2118 if (s[i]>='0' && s[i]<='9')
2119 goto N3;
2120 else
2121 return TF_string;
2125 i++;
2126 if (i==s.Length)
2128 bNeedsRangeCheck = true; //three digits may not fit byte and unsignedByte
2129 if (bNegative || bPositive)
2130 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
2131 else
2132 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2133 TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2135 switch (s[i])
2137 case '.':
2138 goto FRACTION;
2139 case 'e':
2140 case 'E':
2141 bNeedsRangeCheck = true;
2142 return TF_float | TF_double | TF_string;
2143 default:
2144 if (s[i]>='0' && s[i]<='9')
2145 goto N4;
2146 else
2147 return TF_string;
2150 i++;
2151 if (i==s.Length)
2153 bNeedsRangeCheck = true;
2154 if (bNegative || bPositive)
2155 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
2156 else
2157 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2158 TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2161 switch (s[i])
2163 case '-':
2164 bDate = true;
2165 goto DATE;
2166 case '.':
2167 goto FRACTION;
2168 case 'e':
2169 case 'E':
2170 bNeedsRangeCheck = true;
2171 return TF_float | TF_double | TF_string;
2172 default:
2173 if (s[i]>='0' && s[i]<='9')
2174 goto N4;
2175 else
2176 return TF_string;
2178 DATE:
2179 i++; if (i==s.Length) return TF_string; //"9999-"
2180 if (s[i]<'0' || s[i]>'9')
2181 return TF_string;
2182 i++; if (i==s.Length) return TF_string; //"9999-9"
2183 if (s[i]<'0' || s[i]>'9')
2184 return TF_string;
2185 i++;
2186 if (i==s.Length)
2188 bNeedsRangeCheck = true;
2189 return TF_gYearMonth | TF_string; //"9999-99"
2191 switch (s[i])
2193 case '-':
2194 goto DAY;
2195 case 'Z':
2196 case 'z':
2197 bMissingDay = true;
2198 goto ZULU;
2199 case '+':
2200 bMissingDay = true;
2201 goto ZONE_SHIFT;
2202 default:
2203 return TF_string;
2205 DAY:
2206 i++; if (i==s.Length) return TF_string; //"9999-99-"
2207 if (s[i]<'0' || s[i]>'9')
2208 return TF_string;
2209 i++; if (i==s.Length) return TF_string; //"9999-99-9"
2210 if (s[i]<'0' || s[i]>'9')
2211 return TF_string;
2212 i++; if (i==s.Length) return DateTime(s, bDate, bTime); //"9999-99-99"
2213 switch (s[i])
2215 case 'Z':
2216 case 'z':
2217 goto ZULU;
2218 case '+':
2219 case '-':
2220 goto ZONE_SHIFT;
2221 case 'T':
2222 bTime=true;
2223 goto TIME;
2224 case ':':
2225 bMissingDay = true;
2226 goto ZONE_SHIFT_MINUTE;
2227 default:
2228 return TF_string;
2230 ZULU:
2231 i++;
2232 if (i==s.Length)
2234 if (bMissingDay)
2236 bNeedsRangeCheck=true;
2237 return TF_gYearMonth | TF_string;
2239 else
2241 return DateTime(s, bDate, bTime);
2244 else
2245 return TF_string;
2246 ZONE_SHIFT:
2247 i++; if (i==s.Length) return TF_string;
2248 if (s[i]<'0' || s[i]>'9')
2249 return TF_string;
2250 i++; if (i==s.Length) return TF_string;
2251 if (s[i]<'0' || s[i]>'9')
2252 return TF_string;
2253 i++; if (i==s.Length) return TF_string;
2254 if (s[i] != ':')
2255 return TF_string;
2256 ZONE_SHIFT_MINUTE:
2257 i++; if (i==s.Length) return TF_string;
2258 if (s[i]<'0' || s[i]>'9')
2259 return TF_string;
2260 i++; if (i==s.Length) return TF_string;
2261 if (s[i]<'0' || s[i]>'9')
2262 return TF_string;
2263 i++;
2264 if (i==s.Length)
2266 if (bMissingDay)
2268 bNeedsRangeCheck=true;
2269 return TF_gYearMonth | TF_string;
2271 else
2273 return DateTime(s, bDate, bTime);
2276 else return TF_string;
2277 TIME:
2278 i++; if (i==s.Length) return TF_string;
2279 if (s[i]<'0' || s[i]>'9')
2280 return TF_string;
2281 i++; if (i==s.Length) return TF_string;
2282 if (s[i]<'0' || s[i]>'9')
2283 return TF_string;
2284 i++; if (i==s.Length) return TF_string;
2285 if (s[i] != ':')
2286 return TF_string;
2287 MINUTE:
2288 i++; if (i==s.Length) return TF_string;
2289 if (s[i]<'0' || s[i]>'9')
2290 return TF_string;
2291 i++; if (i==s.Length) return TF_string;
2292 if (s[i]<'0' || s[i]>'9')
2293 return TF_string;
2294 i++; if (i==s.Length) return TF_string;
2295 if (s[i] != ':')
2296 return TF_string;
2297 i++; if (i==s.Length) return TF_string;
2298 if (s[i]<'0' || s[i]>'9')
2299 return TF_string;
2300 i++; if (i==s.Length) return TF_string;
2301 if (s[i]<'0' || s[i]>'9')
2302 return TF_string;
2303 i++; if (i==s.Length) return DateTime(s, bDate, bTime);
2304 switch (s[i])
2306 case 'Z':
2307 case 'z':
2308 goto ZULU;
2309 case '+':
2310 case '-':
2311 goto ZONE_SHIFT;
2312 case '.':
2313 goto SECOND_FRACTION;
2314 default:
2315 return TF_string;
2317 SECOND_FRACTION:
2318 i++; if (i==s.Length) return TF_string;
2319 if (s[i]<'0' || s[i]>'9')
2320 return TF_string;
2321 FRACT_DIGITS:
2322 i++; if (i==s.Length) return DateTime(s, bDate, bTime);
2323 switch (s[i])
2325 case 'Z':
2326 case 'z':
2327 goto ZULU;
2328 case '+':
2329 case '-':
2330 goto ZONE_SHIFT;
2331 default:
2332 if (s[i]>='0' && s[i]<='9')
2333 goto FRACT_DIGITS;
2334 else
2335 return TF_string;
2338 default:
2339 return TF_string;
2341 #else // BOOTSTRAP_BASIC
2342 return TF_string;
2343 #endif
2346 internal static int DateTime(string s, bool bDate, bool bTime)
2350 XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind);
2352 catch (FormatException)
2354 return TF_string;
2356 if (bDate && bTime)
2357 return TF_dateTime | TF_string;
2358 else if (bDate)
2359 return TF_date | TF_string;
2360 else if (bTime)
2361 return TF_time | TF_string;
2362 else
2364 Debug.Assert(false, "Expected date, time or dateTime");
2365 return TF_string;
2368 XmlSchemaElement CreateNewElementforChoice(XmlSchemaElement copyElement)
2370 XmlSchemaElement newElement = new XmlSchemaElement();
2371 newElement.Annotation = copyElement.Annotation;
2372 newElement.Block = copyElement.Block;
2373 newElement.DefaultValue = copyElement.DefaultValue;
2374 newElement.Final = copyElement.Final;
2375 newElement.FixedValue = copyElement.FixedValue;
2376 newElement.Form = copyElement.Form;
2377 newElement.Id = copyElement.Id;
2378 // newElement.IsAbstract = copyElement.IsAbstract;
2379 if (copyElement.IsNillable)
2381 newElement.IsNillable = copyElement.IsNillable;
2383 newElement.LineNumber = copyElement.LineNumber;
2384 newElement.LinePosition = copyElement.LinePosition;
2385 newElement.Name = copyElement.Name;
2386 newElement.Namespaces = copyElement.Namespaces;
2387 newElement.RefName = copyElement.RefName;
2388 newElement.SchemaType = copyElement.SchemaType;
2389 newElement.SchemaTypeName = copyElement.SchemaTypeName;
2390 newElement.SourceUri = copyElement.SourceUri;
2391 newElement.SubstitutionGroup = copyElement.SubstitutionGroup;
2392 newElement.UnhandledAttributes = copyElement.UnhandledAttributes;
2393 if (copyElement.MinOccurs != Decimal.One && this.Occurrence == InferenceOption.Relaxed)
2395 newElement.MinOccurs = copyElement.MinOccurs;
2397 if (copyElement.MaxOccurs != Decimal.One) {
2398 newElement.MaxOccurs = copyElement.MaxOccurs;
2400 return newElement;
2403 private static int GetSchemaType(XmlQualifiedName qname)
2405 if (qname == SimpleTypes[HC_ST_boolean])
2407 return TF_boolean | TF_string;
2409 if (qname == SimpleTypes[HC_ST_byte])
2411 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
2413 if (qname == SimpleTypes[HC_ST_unsignedByte])
2415 return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2416 TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2418 if (qname == SimpleTypes[HC_ST_short])
2420 return TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
2422 if (qname == SimpleTypes[HC_ST_unsignedShort])
2424 return TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2425 TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
2427 if (qname == SimpleTypes[HC_ST_int])
2429 return TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
2431 if (qname == SimpleTypes[HC_ST_unsignedInt])
2433 return TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2434 TF_unsignedInt | TF_unsignedLong | TF_string;
2436 if (qname == SimpleTypes[HC_ST_long])
2438 return TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
2440 if (qname == SimpleTypes[HC_ST_unsignedLong])
2442 return TF_long | TF_integer | TF_decimal | TF_float | TF_double |
2443 TF_unsignedLong | TF_string;
2445 if (qname == SimpleTypes[HC_ST_integer])
2447 return TF_integer |TF_decimal | TF_float | TF_double | TF_string;
2449 if (qname == SimpleTypes[HC_ST_decimal])
2451 return TF_decimal | TF_float | TF_double | TF_string;
2453 if (qname == SimpleTypes[HC_ST_float])
2455 return TF_float | TF_double | TF_string;
2457 if (qname == SimpleTypes[HC_ST_double])
2459 return TF_double | TF_string;
2461 if (qname == SimpleTypes[HC_ST_duration])
2463 return TF_duration | TF_string;
2465 if (qname == SimpleTypes[HC_ST_dateTime])
2467 return TF_dateTime | TF_string;
2469 if (qname == SimpleTypes[HC_ST_time])
2471 return TF_time | TF_string;
2473 if (qname == SimpleTypes[HC_ST_date])
2475 return TF_date;
2477 if (qname == SimpleTypes[HC_ST_gYearMonth])
2479 return TF_gYearMonth;
2481 if (qname == SimpleTypes[HC_ST_string])
2483 return TF_string;
2485 if (qname == null || qname.IsEmpty) {
2486 return -1;
2488 throw new XmlSchemaInferenceException(Res.SchInf_schematype, 0, 0);
2491 internal void SetMinMaxOccurs(XmlSchemaElement el, bool setMaxOccurs)
2493 if (this.Occurrence == InferenceOption.Relaxed)
2495 if (setMaxOccurs || el.MaxOccurs > 1)
2497 el.MaxOccurs = decimal.MaxValue; //set it to unbounded
2499 el.MinOccurs = 0;
2501 else if (el.MinOccurs > 1)
2503 el.MinOccurs = 1;