PageRenderTime 61ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/referencesource/System.Xml/System/Xml/Schema/Inference/Infer.cs

http://github.com/mono/mono
C# | 2509 lines | 2265 code | 100 blank | 144 comment | 756 complexity | 8717547022fa98fcaf2dfcfb99dd04a2 MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Unlicense, Apache-2.0
  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. //------------------------------------------------------------------------------
  8. using System;
  9. using System.IO;
  10. using System.Xml;
  11. using System.Collections;
  12. using System.Diagnostics;
  13. using System.Globalization;
  14. using System.Security.Permissions;
  15. namespace System.Xml.Schema
  16. {
  17. /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer"]/*' />
  18. /// <summary>
  19. /// Infer class serves for infering XML Schema from given XML instance document.
  20. /// </summary>
  21. public sealed class XmlSchemaInference
  22. {
  23. internal static XmlQualifiedName ST_boolean = new XmlQualifiedName("boolean", XmlSchema.Namespace);
  24. internal static XmlQualifiedName ST_byte = new XmlQualifiedName("byte", XmlSchema.Namespace);
  25. internal static XmlQualifiedName ST_unsignedByte = new XmlQualifiedName("unsignedByte", XmlSchema.Namespace);
  26. internal static XmlQualifiedName ST_short = new XmlQualifiedName("short", XmlSchema.Namespace);
  27. internal static XmlQualifiedName ST_unsignedShort = new XmlQualifiedName("unsignedShort", XmlSchema.Namespace);
  28. internal static XmlQualifiedName ST_int = new XmlQualifiedName("int", XmlSchema.Namespace);
  29. internal static XmlQualifiedName ST_unsignedInt = new XmlQualifiedName("unsignedInt", XmlSchema.Namespace);
  30. internal static XmlQualifiedName ST_long = new XmlQualifiedName("long", XmlSchema.Namespace);
  31. internal static XmlQualifiedName ST_unsignedLong = new XmlQualifiedName("unsignedLong", XmlSchema.Namespace);
  32. internal static XmlQualifiedName ST_integer = new XmlQualifiedName("integer", XmlSchema.Namespace);
  33. internal static XmlQualifiedName ST_decimal = new XmlQualifiedName("decimal", XmlSchema.Namespace);
  34. internal static XmlQualifiedName ST_float = new XmlQualifiedName("float", XmlSchema.Namespace);
  35. internal static XmlQualifiedName ST_double = new XmlQualifiedName("double", XmlSchema.Namespace);
  36. internal static XmlQualifiedName ST_duration = new XmlQualifiedName("duration", XmlSchema.Namespace);
  37. internal static XmlQualifiedName ST_dateTime = new XmlQualifiedName("dateTime", XmlSchema.Namespace);
  38. internal static XmlQualifiedName ST_time = new XmlQualifiedName("time", XmlSchema.Namespace);
  39. internal static XmlQualifiedName ST_date = new XmlQualifiedName("date", XmlSchema.Namespace);
  40. internal static XmlQualifiedName ST_gYearMonth = new XmlQualifiedName("gYearMonth", XmlSchema.Namespace);
  41. internal static XmlQualifiedName ST_string = new XmlQualifiedName("string", XmlSchema.Namespace);
  42. internal static XmlQualifiedName ST_anySimpleType = new XmlQualifiedName("anySimpleType", XmlSchema.Namespace);
  43. internal static XmlQualifiedName[] SimpleTypes =
  44. {
  45. ST_boolean,
  46. ST_byte,
  47. ST_unsignedByte,
  48. ST_short,
  49. ST_unsignedShort,
  50. ST_int,
  51. ST_unsignedInt,
  52. ST_long,
  53. ST_unsignedLong,
  54. ST_integer,
  55. ST_decimal,
  56. ST_float,
  57. ST_double,
  58. ST_duration,
  59. ST_dateTime,
  60. ST_time,
  61. ST_date,
  62. ST_gYearMonth,
  63. ST_string
  64. };
  65. internal const short HC_ST_boolean = 0;
  66. internal const short HC_ST_byte = 1;
  67. internal const short HC_ST_unsignedByte = 2;
  68. internal const short HC_ST_short = 3;
  69. internal const short HC_ST_unsignedShort = 4;
  70. internal const short HC_ST_int = 5;
  71. internal const short HC_ST_unsignedInt = 6;
  72. internal const short HC_ST_long = 7;
  73. internal const short HC_ST_unsignedLong = 8;
  74. internal const short HC_ST_integer = 9;
  75. internal const short HC_ST_decimal = 10;
  76. internal const short HC_ST_float = 11;
  77. internal const short HC_ST_double = 12;
  78. internal const short HC_ST_duration = 13;
  79. internal const short HC_ST_dateTime = 14;
  80. internal const short HC_ST_time = 15;
  81. internal const short HC_ST_date = 16;
  82. internal const short HC_ST_gYearMonth = 17;
  83. internal const short HC_ST_string = 18;
  84. internal const short HC_ST_Count = HC_ST_string +1;
  85. internal const int TF_boolean = 1<<HC_ST_boolean;
  86. internal const int TF_byte = 1<<HC_ST_byte;
  87. internal const int TF_unsignedByte = 1<<HC_ST_unsignedByte;
  88. internal const int TF_short = 1<<HC_ST_short;
  89. internal const int TF_unsignedShort = 1<<HC_ST_unsignedShort;
  90. internal const int TF_int = 1<<HC_ST_int;
  91. internal const int TF_unsignedInt = 1<<HC_ST_unsignedInt;
  92. internal const int TF_long = 1<<HC_ST_long;
  93. internal const int TF_unsignedLong = 1<<HC_ST_unsignedLong;
  94. internal const int TF_integer = 1<<HC_ST_integer;
  95. internal const int TF_decimal = 1<<HC_ST_decimal;
  96. internal const int TF_float = 1<<HC_ST_float;
  97. internal const int TF_double = 1<<HC_ST_double;
  98. internal const int TF_duration = 1<<HC_ST_duration;
  99. internal const int TF_dateTime = 1<<HC_ST_dateTime;
  100. internal const int TF_time = 1<<HC_ST_time;
  101. internal const int TF_date = 1<<HC_ST_date;
  102. internal const int TF_gYearMonth = 1<<HC_ST_gYearMonth;
  103. internal const int TF_string = 1<<HC_ST_string;
  104. XmlSchema rootSchema = null; //(XmlSchema) xsc[TargetNamespace];
  105. private XmlSchemaSet schemaSet;
  106. private XmlReader xtr;
  107. private NameTable nametable;
  108. private string TargetNamespace;
  109. private XmlNamespaceManager NamespaceManager;
  110. //private Hashtable schemas; //contains collection of schemas before they get added to the XmlSchemaSet xsc
  111. //private bool bRefine = false; //indicates if we are going to infer or refine schema when InferSchema is called
  112. ArrayList schemaList;
  113. InferenceOption occurrence = InferenceOption.Restricted;
  114. InferenceOption typeInference = InferenceOption.Restricted;
  115. /* internal struct ReplaceList
  116. {
  117. internal XmlSchemaObjectCollection col;
  118. internal int position;
  119. internal ReplaceList(XmlSchemaObjectCollection col, int position)
  120. {
  121. this.col = col;
  122. this.position = position;
  123. }
  124. }*/
  125. /// <include file='doc\Infer.uex' path='docs/doc[@for="InferenceOption"]/*' />
  126. public enum InferenceOption
  127. {
  128. /// <include file='doc\Infer.uex' path='docs/doc[@for="InferenceOption.Restricted"]/*' />
  129. Restricted,
  130. /// <include file='doc\Infer.uex' path='docs/doc[@for="InferenceOption.Relaxed"]/*' />
  131. Relaxed
  132. };
  133. /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.Occurrence"]/*' />
  134. public InferenceOption Occurrence
  135. {
  136. set
  137. {
  138. this.occurrence = value;
  139. }
  140. get
  141. {
  142. return this.occurrence;
  143. }
  144. }
  145. /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.TypeInference"]/*' />
  146. public InferenceOption TypeInference
  147. {
  148. set
  149. {
  150. this.typeInference = value;
  151. }
  152. get
  153. {
  154. return this.typeInference;
  155. }
  156. }
  157. /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.Infer"]/*' />
  158. public XmlSchemaInference()
  159. {
  160. this.nametable = new NameTable();
  161. this.NamespaceManager = new XmlNamespaceManager(nametable);
  162. this.NamespaceManager.AddNamespace("xs", XmlSchema.Namespace);
  163. this.schemaList = new ArrayList();
  164. }
  165. /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.InferSchema"]/*' />
  166. public XmlSchemaSet InferSchema(XmlReader instanceDocument)
  167. {
  168. return InferSchema1(instanceDocument, new XmlSchemaSet(nametable));
  169. }
  170. /// <include file='doc\Infer.uex' path='docs/doc[@for="Infer.InferSchema1"]/*' />
  171. public XmlSchemaSet InferSchema(XmlReader instanceDocument, XmlSchemaSet schemas)
  172. {
  173. if (schemas == null)
  174. {
  175. schemas = new XmlSchemaSet(nametable);
  176. }
  177. return InferSchema1(instanceDocument, schemas);
  178. }
  179. internal XmlSchemaSet InferSchema1(XmlReader instanceDocument, XmlSchemaSet schemas)
  180. {
  181. if (instanceDocument == null)
  182. {
  183. throw new ArgumentNullException("instanceDocument");
  184. }
  185. this.rootSchema = null;
  186. xtr = instanceDocument;
  187. schemas.Compile();
  188. this.schemaSet = schemas;
  189. //schemas = new Hashtable();
  190. //while(xtr.Read())
  191. while (xtr.NodeType != XmlNodeType.Element && xtr.Read()) ;
  192. if (xtr.NodeType == XmlNodeType.Element)
  193. {
  194. //Create and process the root element
  195. TargetNamespace = xtr.NamespaceURI;
  196. if ( xtr.NamespaceURI == XmlSchema.Namespace)
  197. {
  198. throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
  199. }
  200. XmlSchemaElement xse = null;
  201. foreach (XmlSchemaElement elem in schemas.GlobalElements.Values)
  202. {
  203. if (elem.Name == xtr.LocalName && elem.QualifiedName.Namespace == xtr.NamespaceURI)
  204. {
  205. rootSchema = elem.Parent as XmlSchema;
  206. xse = elem;
  207. break;
  208. }
  209. }
  210. if (rootSchema == null)
  211. {
  212. //rootSchema = CreateXmlSchema(xtr.NamespaceURI);
  213. xse = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, null, null, -1);
  214. }
  215. else
  216. {
  217. //bRefine = true;
  218. InferElement(xse, false, rootSchema);
  219. }
  220. /* foreach (ReplaceList listItem in schemaList)
  221. {
  222. if (listItem.position < listItem.col.Count)
  223. {
  224. XmlSchemaElement particle = listItem.col[listItem.position] as XmlSchemaElement;
  225. if (particle != null && (particle.RefName.Namespace == XmlSchema.Namespace))
  226. {
  227. XmlSchemaAny any = new XmlSchemaAny();
  228. if (particle.MaxOccurs != 1)
  229. {
  230. any.MaxOccurs = particle.MaxOccurs;
  231. }
  232. if (particle.MinOccurs != 1)
  233. {
  234. any.MinOccurs = particle.MinOccurs;
  235. }
  236. any.ProcessContents = XmlSchemaContentProcessing.Skip;
  237. any.MinOccurs = decimal.Zero;
  238. any.Namespace = particle.RefName.Namespace;
  239. listItem.col[listItem.position] = any;
  240. }
  241. }
  242. }*/
  243. foreach(String prefix in this.NamespaceManager)
  244. {
  245. if (!prefix.Equals("xml") && !prefix.Equals("xmlns"))
  246. {
  247. String ns = this.NamespaceManager.LookupNamespace(this.nametable.Get(prefix));
  248. if (ns.Length != 0) { //Do not add xmlns=""
  249. rootSchema.Namespaces.Add(prefix, ns);
  250. }
  251. }
  252. }
  253. Debug.Assert(this.rootSchema != null, "rootSchema is null");
  254. schemas.Reprocess(rootSchema);
  255. schemas.Compile();
  256. //break;
  257. }
  258. else
  259. {
  260. throw new XmlSchemaInferenceException(Res.SchInf_NoElement, 0, 0);
  261. }
  262. return schemas;
  263. }
  264. private XmlSchemaAttribute AddAttribute(string localName, string prefix, string childURI, string attrValue, bool bCreatingNewType, XmlSchema parentSchema, XmlSchemaObjectCollection addLocation, XmlSchemaObjectTable compiledAttributes)
  265. {
  266. if (childURI == XmlSchema.Namespace)
  267. {
  268. throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
  269. }
  270. XmlSchemaAttribute xsa = null;
  271. int AttributeType = -1;
  272. XmlSchemaAttribute returnedAttribute = null; //this value will change to attributeReference if childURI!= parentURI
  273. XmlSchema xs = null;
  274. bool add = true;
  275. Debug.Assert(compiledAttributes != null); //AttributeUses is never null
  276. // First we need to look into the already compiled attributes
  277. // (they come from the schemaset which we got on input)
  278. // If there are none or we don't find it there, then we must search the list of attributes
  279. // where we are going to add a new one (if it doesn't exist).
  280. // This is necessary to avoid adding duplicate attribute declarations.
  281. ICollection searchCollectionPrimary, searchCollectionSecondary;
  282. if (compiledAttributes.Count > 0) {
  283. searchCollectionPrimary = compiledAttributes.Values;
  284. searchCollectionSecondary = addLocation;
  285. }
  286. else {
  287. searchCollectionPrimary = addLocation;
  288. searchCollectionSecondary = null;
  289. }
  290. if (childURI == XmlReservedNs.NsXml)
  291. {
  292. XmlSchemaAttribute attributeReference = null;
  293. //see if the reference exists
  294. attributeReference = FindAttributeRef(searchCollectionPrimary, localName, childURI);
  295. if (attributeReference == null && searchCollectionSecondary != null) {
  296. attributeReference = FindAttributeRef(searchCollectionSecondary, localName, childURI);
  297. }
  298. if (attributeReference == null)
  299. {
  300. attributeReference = new XmlSchemaAttribute();
  301. attributeReference.RefName = new XmlQualifiedName(localName, childURI);
  302. if (bCreatingNewType && this.Occurrence == InferenceOption.Restricted)
  303. {
  304. attributeReference.Use = XmlSchemaUse.Required;
  305. }
  306. else
  307. {
  308. attributeReference.Use = XmlSchemaUse.Optional;
  309. }
  310. addLocation.Add(attributeReference);
  311. }
  312. returnedAttribute = attributeReference;
  313. }
  314. else
  315. {
  316. if (childURI.Length == 0)
  317. {
  318. xs = parentSchema;
  319. add = false;
  320. }
  321. else if (childURI != null && !schemaSet.Contains(childURI))
  322. {
  323. /*if (parentSchema.AttributeFormDefault = XmlSchemaForm.Unqualified && childURI.Length == 0)
  324. {
  325. xs = parentSchema;
  326. add = false;
  327. break;
  328. }*/
  329. xs = new XmlSchema();
  330. xs.AttributeFormDefault = XmlSchemaForm.Unqualified;
  331. xs.ElementFormDefault = XmlSchemaForm.Qualified;
  332. if (childURI.Length != 0)
  333. xs.TargetNamespace = childURI;
  334. //schemas.Add(childURI, xs);
  335. this.schemaSet.Add(xs);
  336. if (prefix.Length != 0 && String.Compare(prefix, "xml", StringComparison.OrdinalIgnoreCase) != 0)
  337. NamespaceManager.AddNamespace(prefix, childURI);
  338. }
  339. else
  340. {
  341. ArrayList col = this.schemaSet.Schemas(childURI) as ArrayList;
  342. if (col != null && col.Count > 0)
  343. {
  344. xs = col[0] as XmlSchema;
  345. }
  346. }
  347. if (childURI.Length != 0) //
  348. {
  349. XmlSchemaAttribute attributeReference = null;
  350. //see if the reference exists
  351. attributeReference = FindAttributeRef(searchCollectionPrimary, localName, childURI);
  352. if (attributeReference == null & searchCollectionSecondary != null) {
  353. attributeReference = FindAttributeRef(searchCollectionSecondary, localName, childURI);
  354. }
  355. if (attributeReference == null)
  356. {
  357. attributeReference = new XmlSchemaAttribute();
  358. attributeReference.RefName = new XmlQualifiedName(localName, childURI);
  359. if (bCreatingNewType && this.Occurrence == InferenceOption.Restricted)
  360. {
  361. attributeReference.Use = XmlSchemaUse.Required;
  362. }
  363. else
  364. {
  365. attributeReference.Use = XmlSchemaUse.Optional;
  366. }
  367. addLocation.Add(attributeReference);
  368. }
  369. returnedAttribute = attributeReference;
  370. //see if the attribute exists on the global level
  371. xsa = FindAttribute(xs.Items, localName);
  372. if (xsa == null)
  373. {
  374. xsa = new XmlSchemaAttribute();
  375. xsa.Name = localName;
  376. xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
  377. xsa.LineNumber = AttributeType; //we use LineNumber to store flags of valid types
  378. xs.Items.Add(xsa);
  379. }
  380. else
  381. {
  382. if (xsa.Parent == null)
  383. {
  384. AttributeType = xsa.LineNumber; // we use LineNumber to store flags of valid types
  385. }
  386. else
  387. {
  388. AttributeType = GetSchemaType(xsa.SchemaTypeName);
  389. xsa.Parent = null;
  390. }
  391. xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
  392. xsa.LineNumber = AttributeType; // we use LineNumber to store flags of valid types
  393. }
  394. }
  395. else
  396. {
  397. xsa = FindAttribute(searchCollectionPrimary, localName);
  398. if (xsa == null && searchCollectionSecondary != null) {
  399. xsa = FindAttribute(searchCollectionSecondary, localName);
  400. }
  401. if (xsa == null)
  402. {
  403. xsa = new XmlSchemaAttribute();
  404. xsa.Name = localName;
  405. xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
  406. xsa.LineNumber = AttributeType; // we use LineNumber to store flags of valid types
  407. if (bCreatingNewType && this.Occurrence == InferenceOption.Restricted)
  408. xsa.Use = XmlSchemaUse.Required;
  409. else
  410. xsa.Use = XmlSchemaUse.Optional;
  411. addLocation.Add(xsa);
  412. if (xs.AttributeFormDefault != XmlSchemaForm.Unqualified)
  413. {
  414. xsa.Form = XmlSchemaForm.Unqualified;
  415. }
  416. }
  417. else
  418. {
  419. if (xsa.Parent == null)
  420. {
  421. AttributeType = xsa.LineNumber; // we use LineNumber to store flags of valid types
  422. }
  423. else
  424. {
  425. AttributeType = GetSchemaType(xsa.SchemaTypeName);
  426. xsa.Parent = null;
  427. }
  428. xsa.SchemaTypeName = RefineSimpleType(attrValue, ref AttributeType);
  429. xsa.LineNumber = AttributeType; // we use LineNumber to store flags of valid types
  430. }
  431. returnedAttribute = xsa;
  432. }
  433. }
  434. string nullString = null;
  435. if (add && childURI != parentSchema.TargetNamespace)
  436. {
  437. for (int i = 0; i < parentSchema.Includes.Count; ++i)
  438. {
  439. XmlSchemaImport import = parentSchema.Includes[i] as XmlSchemaImport;
  440. if (import == null)
  441. {
  442. continue;
  443. }
  444. if (import.Namespace == childURI)
  445. {
  446. add = false;
  447. }
  448. }
  449. if (add)
  450. {
  451. XmlSchemaImport import = new XmlSchemaImport();
  452. import.Schema = xs;
  453. if (childURI.Length != 0)
  454. {
  455. nullString = childURI;
  456. }
  457. import.Namespace = nullString;
  458. parentSchema.Includes.Add(import);
  459. }
  460. }
  461. return returnedAttribute;
  462. }
  463. private XmlSchema CreateXmlSchema(string targetNS)
  464. {
  465. Debug.Assert(targetNS == null || targetNS.Length > 0 , "targetns for schema is empty");
  466. XmlSchema xs = new XmlSchema();
  467. xs.AttributeFormDefault = XmlSchemaForm.Unqualified;
  468. xs.ElementFormDefault = XmlSchemaForm.Qualified;
  469. xs.TargetNamespace = targetNS;
  470. this.schemaSet.Add(xs);
  471. return xs;
  472. }
  473. private XmlSchemaElement AddElement(string localName, string prefix, string childURI, XmlSchema parentSchema, XmlSchemaObjectCollection addLocation, int positionWithinCollection)
  474. {
  475. if (childURI == XmlSchema.Namespace)
  476. {
  477. throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
  478. }
  479. XmlSchemaElement xse = null;
  480. XmlSchemaElement returnedElement = xse; //this value will change to elementReference if childURI!= parentURI
  481. XmlSchema xs = null;
  482. bool bCreatingNewType = true;
  483. if (childURI == String.Empty)
  484. {
  485. childURI = null;
  486. }
  487. // The new element belongs to the same ns as parent and addlocation is not null
  488. if (parentSchema != null && childURI == parentSchema.TargetNamespace)
  489. {
  490. xse = new XmlSchemaElement();
  491. xse.Name = localName;
  492. xs = parentSchema;
  493. if (xs.ElementFormDefault != XmlSchemaForm.Qualified && addLocation != null)
  494. {
  495. xse.Form = XmlSchemaForm.Qualified;
  496. }
  497. }
  498. else if (schemaSet.Contains(childURI))
  499. {
  500. xse = this.FindGlobalElement(childURI, localName, out xs);
  501. if (xse == null)
  502. {
  503. ArrayList col = this.schemaSet.Schemas(childURI)as ArrayList;
  504. if (col != null && col.Count > 0 )
  505. {
  506. xs = col[0] as XmlSchema;
  507. }
  508. xse = new XmlSchemaElement();
  509. xse.Name = localName;
  510. xs.Items.Add(xse);
  511. }
  512. else
  513. bCreatingNewType = false;
  514. }
  515. else
  516. {
  517. xs = CreateXmlSchema(childURI);
  518. if (prefix.Length!=0)
  519. NamespaceManager.AddNamespace(prefix, childURI);
  520. xse=new XmlSchemaElement();
  521. xse.Name = localName;
  522. xs.Items.Add(xse); //add global element declaration only when creating new schema
  523. }
  524. if (parentSchema == null)
  525. {
  526. parentSchema = xs;
  527. this.rootSchema = parentSchema;
  528. }
  529. if (childURI != parentSchema.TargetNamespace )
  530. {
  531. bool add = true;
  532. for (int i = 0; i < parentSchema.Includes.Count; ++i)
  533. {
  534. XmlSchemaImport import = parentSchema.Includes[i] as XmlSchemaImport;
  535. if (import == null)
  536. {
  537. continue;
  538. }
  539. //Debug.WriteLine(import.Schema.TargetNamespace);
  540. if (import.Namespace == childURI)
  541. {
  542. add = false;
  543. }
  544. }
  545. if (add)
  546. {
  547. XmlSchemaImport import = new XmlSchemaImport();
  548. import.Schema = xs;
  549. import.Namespace = childURI;
  550. parentSchema.Includes.Add(import);
  551. }
  552. }
  553. returnedElement = xse;
  554. if (addLocation != null)
  555. {
  556. if (childURI == parentSchema.TargetNamespace )
  557. {
  558. if (this.Occurrence == InferenceOption.Relaxed /*&& parentSchema.Items != addLocation*/)
  559. {
  560. xse.MinOccurs = 0;
  561. }
  562. if (positionWithinCollection == -1)
  563. {
  564. positionWithinCollection = addLocation.Add(xse);
  565. }
  566. else
  567. {
  568. addLocation.Insert(positionWithinCollection, xse);
  569. }
  570. }
  571. else
  572. {
  573. XmlSchemaElement elementReference = new XmlSchemaElement();
  574. elementReference.RefName = new XmlQualifiedName(localName, childURI);
  575. if (this.Occurrence == InferenceOption.Relaxed)
  576. {
  577. elementReference.MinOccurs = 0;
  578. }
  579. if (positionWithinCollection == -1)
  580. {
  581. positionWithinCollection = addLocation.Add(elementReference);
  582. }
  583. else
  584. {
  585. addLocation.Insert(positionWithinCollection, elementReference);
  586. }
  587. returnedElement = elementReference;
  588. /* if (childURI == XmlSchema.Namespace)
  589. {
  590. schemaList.Add(new ReplaceList(addLocation, positionWithinCollection));
  591. }*/
  592. }
  593. }
  594. InferElement(xse, bCreatingNewType, xs);
  595. return returnedElement;
  596. }
  597. /// <summary>
  598. /// Sets type of the xse based on the currently read element.
  599. /// If the type is already set, verifies that it matches the instance and if not, updates the type to validate the instance.
  600. /// </summary>
  601. /// <param name="xse">XmlSchemaElement corresponding to the element just read by the xtr XmlTextReader</param>
  602. /// <param name="bCreatingNewType">true if the type is newly created, false if the type already existed and matches the current element name</param>
  603. /// <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>
  604. internal void InferElement(XmlSchemaElement xse, bool bCreatingNewType, XmlSchema parentSchema)
  605. {
  606. bool bEmptyElement = xtr.IsEmptyElement;
  607. int lastUsedSeqItem = -1;
  608. Hashtable table = new Hashtable();
  609. XmlSchemaType schemaType = GetEffectiveSchemaType(xse, bCreatingNewType);
  610. XmlSchemaComplexType ct = schemaType as XmlSchemaComplexType;
  611. //infer type based on content of the current element
  612. if (xtr.MoveToFirstAttribute())
  613. {
  614. ProcessAttributes(ref xse, schemaType, bCreatingNewType, parentSchema);
  615. }
  616. else
  617. {
  618. if (!bCreatingNewType && ct != null)
  619. { //if type already exists and can potentially have attributes
  620. MakeExistingAttributesOptional(ct, null);
  621. }
  622. }
  623. if (ct == null || ct == XmlSchemaComplexType.AnyType) { //It was null or simple type, after processing attributes, this might have been set
  624. ct = xse.SchemaType as XmlSchemaComplexType;
  625. }
  626. //xse's type is set either to complex type if attributes exist or null
  627. if (bEmptyElement) //<element attr="3232" />
  628. {
  629. if (!bCreatingNewType)
  630. {
  631. if (null != ct)
  632. {
  633. if (null!= ct.Particle )
  634. {
  635. ct.Particle.MinOccurs = 0;
  636. }
  637. else if (null != ct.ContentModel)
  638. {
  639. XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
  640. sce.BaseTypeName = ST_string;
  641. sce.LineNumber = TF_string;
  642. }
  643. }
  644. else if (!xse.SchemaTypeName.IsEmpty)
  645. {
  646. xse.LineNumber = TF_string;
  647. xse.SchemaTypeName = ST_string;
  648. }
  649. }
  650. else
  651. {
  652. xse.LineNumber = TF_string;
  653. //xse.SchemaTypeName = ST_string; //My change
  654. }
  655. return; //We are done processing this element - all attributes are already added
  656. }
  657. bool bWhiteSpace = false;
  658. do
  659. {
  660. xtr.Read();
  661. if (xtr.NodeType == XmlNodeType.Whitespace)
  662. {
  663. bWhiteSpace = true;
  664. }
  665. if (xtr.NodeType == XmlNodeType.EntityReference)
  666. {
  667. throw new XmlSchemaInferenceException(Res.SchInf_entity, 0, 0);
  668. }
  669. } while( (!xtr.EOF) && (xtr.NodeType != XmlNodeType.EndElement) && (xtr.NodeType != XmlNodeType.CDATA)&&(xtr.NodeType != XmlNodeType.Element)&&(xtr.NodeType != XmlNodeType.Text) );
  670. if (xtr.NodeType == XmlNodeType.EndElement)
  671. {
  672. if (bWhiteSpace) {
  673. if (ct != null)
  674. {
  675. if (null != ct.ContentModel)
  676. {
  677. XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
  678. sce.BaseTypeName = ST_string;
  679. sce.LineNumber = TF_string;
  680. }
  681. else if (bCreatingNewType)
  682. {
  683. //attributes exist, but both Particle and ContentModel == null - this must be complex type with simpleContent extension
  684. XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
  685. ct.ContentModel = sc;
  686. XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
  687. sc.Content = sce;
  688. MoveAttributes(ct, sce, bCreatingNewType);
  689. sce.BaseTypeName = ST_string;
  690. sce.LineNumber = TF_string;
  691. }
  692. else
  693. ct.IsMixed = true;
  694. }
  695. else
  696. {
  697. xse.SchemaTypeName = ST_string;
  698. xse.LineNumber = TF_string;
  699. }
  700. }
  701. if (bCreatingNewType)
  702. {
  703. xse.LineNumber = TF_string;
  704. //xse.SchemaTypeName = ST_string; //my change
  705. }
  706. else
  707. {
  708. if (null != ct)
  709. {
  710. if (null!= ct.Particle)
  711. {
  712. ct.Particle.MinOccurs = 0;
  713. }
  714. else if (null != ct.ContentModel)
  715. {
  716. XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
  717. sce.BaseTypeName = ST_string;
  718. sce.LineNumber = TF_string;
  719. }
  720. }
  721. else if (!xse.SchemaTypeName.IsEmpty)
  722. {
  723. xse.LineNumber = TF_string;
  724. xse.SchemaTypeName = ST_string;
  725. }
  726. }
  727. return; //<element attr="232"></element>
  728. }
  729. int iChildNumber = 0;
  730. bool bCreatingNewSequence = false;
  731. while (!xtr.EOF && (xtr.NodeType != XmlNodeType.EndElement))
  732. {
  733. bool bNextNodeAlreadyRead = false; //In some cases we have to look ahead one node. If true means that we did look ahead.
  734. iChildNumber++;
  735. if ((xtr.NodeType == XmlNodeType.Text) || (xtr.NodeType == XmlNodeType.CDATA) ) //node can be simple type, complex with simple content or complex with mixed content
  736. {
  737. if (null != ct)
  738. {
  739. if (null != ct.Particle)
  740. {
  741. ct.IsMixed = true;
  742. if (iChildNumber==1)
  743. {
  744. //if this is the only child and other elements do not follow, we must set particle minOccurs="0"
  745. 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)));
  746. bNextNodeAlreadyRead = true;
  747. if (xtr.NodeType == XmlNodeType.EndElement)
  748. ct.Particle.MinOccurs=decimal.Zero;
  749. }
  750. }
  751. else if (null!=ct.ContentModel)
  752. { //complexType with simpleContent
  753. XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
  754. if ((xtr.NodeType == XmlNodeType.Text) && (iChildNumber==1))
  755. {
  756. int SimpleType = -1;
  757. if (xse.Parent == null)
  758. {
  759. SimpleType = sce.LineNumber; // we use LineNumber to represent valid type flags
  760. }
  761. else
  762. {
  763. SimpleType = GetSchemaType(sce.BaseTypeName);
  764. xse.Parent = null;
  765. }
  766. sce.BaseTypeName = RefineSimpleType(xtr.Value, ref SimpleType);
  767. sce.LineNumber = SimpleType; // we use LineNumber to represent valid type flags
  768. }
  769. else
  770. {
  771. sce.BaseTypeName = ST_string;
  772. sce.LineNumber = TF_string;
  773. }
  774. }
  775. else
  776. {
  777. //attributes exist, but both Particle and ContentModel == null - this must be complex type with simpleContent extension
  778. XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
  779. ct.ContentModel = sc;
  780. XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
  781. sc.Content = sce;
  782. MoveAttributes(ct, sce, bCreatingNewType);
  783. if (xtr.NodeType == XmlNodeType.Text)
  784. {
  785. int TypeFlags;
  786. if(!bCreatingNewType)
  787. //previously this was empty element
  788. TypeFlags=TF_string;
  789. else
  790. TypeFlags = -1;
  791. sce.BaseTypeName = RefineSimpleType(xtr.Value, ref TypeFlags);
  792. sce.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
  793. }
  794. else
  795. {
  796. sce.BaseTypeName = ST_string;
  797. sce.LineNumber = TF_string;
  798. }
  799. }
  800. }
  801. else
  802. { //node is currently empty or with SimpleType
  803. //node will become simple type
  804. if (iChildNumber>1)
  805. {
  806. //more than one consecutive text nodes probably with PI in between
  807. xse.SchemaTypeName = ST_string;
  808. xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
  809. }
  810. else
  811. {
  812. int TypeFlags = -1;
  813. if (bCreatingNewType)
  814. if (xtr.NodeType == XmlNodeType.Text)
  815. {
  816. xse.SchemaTypeName = RefineSimpleType(xtr.Value, ref TypeFlags);
  817. xse.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
  818. }
  819. else
  820. {
  821. xse.SchemaTypeName = ST_string;
  822. xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
  823. }
  824. else if (xtr.NodeType == XmlNodeType.Text)
  825. {
  826. if (xse.Parent == null)
  827. {
  828. TypeFlags = xse.LineNumber;
  829. }
  830. else
  831. {
  832. TypeFlags = GetSchemaType(xse.SchemaTypeName);
  833. if (TypeFlags == -1 && xse.LineNumber == TF_string) { //Since schemaTypeName is not set for empty elements (<e></e>)
  834. TypeFlags = TF_string;
  835. }
  836. xse.Parent = null;
  837. }
  838. xse.SchemaTypeName = RefineSimpleType(xtr.Value, ref TypeFlags); //simple type
  839. xse.LineNumber = TypeFlags; // we use LineNumber to store flags of valid types
  840. }
  841. else
  842. {
  843. xse.SchemaTypeName = ST_string;
  844. xse.LineNumber = TF_string;// we use LineNumber to store flags of valid types
  845. }
  846. }
  847. }
  848. }
  849. else if (xtr.NodeType == XmlNodeType.Element)
  850. {
  851. XmlQualifiedName qname = new XmlQualifiedName(xtr.LocalName, xtr.NamespaceURI);
  852. bool Maxoccursflag = false;
  853. if (table.Contains(qname))
  854. {
  855. Maxoccursflag = true;
  856. }
  857. else
  858. {
  859. table.Add(qname, null);
  860. }
  861. if (ct==null)
  862. { //untill now the element was empty or SimpleType - it now becomes complex type
  863. ct = new XmlSchemaComplexType();
  864. xse.SchemaType = ct;
  865. if (!xse.SchemaTypeName.IsEmpty) //
  866. {
  867. ct.IsMixed=true;
  868. xse.SchemaTypeName = XmlQualifiedName.Empty;
  869. }
  870. }
  871. if (ct.ContentModel !=null)
  872. { //type was previously identified as simple content extension - we need to convert it to sequence
  873. XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
  874. MoveAttributes(sce, ct);
  875. ct.ContentModel = null;
  876. ct.IsMixed = true;
  877. if (ct.Particle != null)
  878. throw new XmlSchemaInferenceException(Res.SchInf_particle, 0, 0);
  879. ct.Particle = new XmlSchemaSequence();
  880. bCreatingNewSequence = true;
  881. XmlSchemaElement subelement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema,((XmlSchemaSequence)ct.Particle).Items, -1);
  882. lastUsedSeqItem = 0;
  883. if (!bCreatingNewType)
  884. ct.Particle.MinOccurs=0; //previously this was simple type so subelements did not exist
  885. }
  886. else if (ct.Particle == null)
  887. {
  888. ct.Particle = new XmlSchemaSequence();
  889. bCreatingNewSequence = true;
  890. XmlSchemaElement subelement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema,((XmlSchemaSequence)ct.Particle).Items, -1);
  891. if (!bCreatingNewType)
  892. {
  893. ((XmlSchemaSequence)ct.Particle).MinOccurs = decimal.Zero;
  894. // subelement.MinOccurs = decimal.Zero;
  895. }
  896. lastUsedSeqItem = 0;
  897. }
  898. else
  899. {
  900. bool bParticleChanged = false;
  901. XmlSchemaElement subelement = FindMatchingElement(bCreatingNewType || bCreatingNewSequence, xtr, ct, ref lastUsedSeqItem, ref bParticleChanged, parentSchema, Maxoccursflag);
  902. }
  903. }
  904. else if (xtr.NodeType == XmlNodeType.Text)
  905. {
  906. if (ct==null)
  907. throw new XmlSchemaInferenceException(Res.SchInf_ct, 0, 0);
  908. ct.IsMixed = true;
  909. }
  910. do
  911. {
  912. if (xtr.NodeType == XmlNodeType.EntityReference)
  913. {
  914. throw new XmlSchemaInferenceException(Res.SchInf_entity, 0, 0);
  915. }
  916. if (!bNextNodeAlreadyRead)
  917. {
  918. xtr.Read();
  919. }
  920. else
  921. {
  922. bNextNodeAlreadyRead = false;
  923. }
  924. } while( (!xtr.EOF) && (xtr.NodeType != XmlNodeType.EndElement) && (xtr.NodeType != XmlNodeType.CDATA)&&(xtr.NodeType != XmlNodeType.Element)&&(xtr.NodeType != XmlNodeType.Text));
  925. }
  926. if (lastUsedSeqItem != -1)
  927. {
  928. //Verify if all elements in a sequence exist, if not set MinOccurs=0
  929. while (++lastUsedSeqItem < ((XmlSchemaSequence)ct.Particle).Items.Count)
  930. {
  931. if (((XmlSchemaSequence)ct.Particle).Items[lastUsedSeqItem].GetType() != typeof (XmlSchemaElement))
  932. throw new XmlSchemaInferenceException(Res.SchInf_seq, 0 , 0);
  933. XmlSchemaElement subElement = (XmlSchemaElement) ((XmlSchemaSequence)ct.Particle).Items[lastUsedSeqItem];
  934. subElement.MinOccurs = 0;
  935. }
  936. }
  937. }
  938. private XmlSchemaSimpleContentExtension CheckSimpleContentExtension(XmlSchemaComplexType ct) {
  939. XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
  940. if (sc == null) {
  941. throw new XmlSchemaInferenceException(Res.SchInf_simplecontent, 0, 0);
  942. }
  943. XmlSchemaSimpleContentExtension sce = sc.Content as XmlSchemaSimpleContentExtension;
  944. if (sce == null) {
  945. throw new XmlSchemaInferenceException(Res.SchInf_extension, 0, 0);
  946. }
  947. return sce;
  948. }
  949. private XmlSchemaType GetEffectiveSchemaType(XmlSchemaElement elem, bool bCreatingNewType) {
  950. XmlSchemaType effectiveSchemaType = null;
  951. if (!bCreatingNewType && elem.ElementSchemaType != null) {
  952. effectiveSchemaType = elem.ElementSchemaType;
  953. }
  954. else { //creating new type, hence look up pre-compiled info
  955. Debug.Assert(elem.ElementDecl == null);
  956. if (elem.SchemaType != null) {
  957. effectiveSchemaType = elem.SchemaType;
  958. }
  959. else if (elem.SchemaTypeName != XmlQualifiedName.Empty) {
  960. effectiveSchemaType = schemaSet.GlobalTypes[elem.SchemaTypeName] as XmlSchemaType;
  961. if (effectiveSchemaType == null) {
  962. effectiveSchemaType = XmlSchemaType.GetBuiltInSimpleType(elem.SchemaTypeName);
  963. }
  964. if (effectiveSchemaType == null) {
  965. effectiveSchemaType = XmlSchemaType.GetBuiltInComplexType(elem.SchemaTypeName);
  966. }
  967. }
  968. }
  969. return effectiveSchemaType;
  970. }
  971. /// <summary>
  972. /// Verifies that the current element has its corresponding element in the sequence and order is the same.
  973. /// If the order is not the same, it changes the particle from Sequence to Sequence with Choice.
  974. /// If there is more elements of the same kind in the sequence, sets maxOccurs to unbounded
  975. /// </summary>
  976. /// <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>
  977. /// <param name="xtr">text reader positioned to the current element</param>
  978. /// <param name="ct">complex type with Sequence or Choice Particle</param>
  979. /// <param name="lastUsedSeqItem">ordinal number in the sequence to indicate current sequence position</param>
  980. /// <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>
  981. /// <param name="bParticleChanged">This indicates to the caller if Sequence was changed to Choice</param>
  982. internal XmlSchemaElement FindMatchingElement(bool bCreatingNewType, XmlReader xtr,XmlSchemaComplexType ct, ref int lastUsedSeqItem, ref bool bParticleChanged, XmlSchema parentSchema, bool setMaxoccurs)
  983. {
  984. if (xtr.NamespaceURI == XmlSchema.Namespace)
  985. {
  986. throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
  987. }
  988. bool bItemNotUsedYet = ((lastUsedSeqItem == -1)? true: false);
  989. XmlSchemaObjectCollection minOccursCandidates = new XmlSchemaObjectCollection(); //elements that are skipped in the sequence and need minOccurs modified.
  990. if (ct.Particle.GetType() == typeof (XmlSchemaSequence))
  991. {
  992. string childURI = xtr.NamespaceURI;
  993. if (childURI.Length == 0)
  994. {
  995. childURI = null;
  996. }
  997. XmlSchemaSequence xss = (XmlSchemaSequence) ct.Particle;
  998. if (xss.Items.Count < 1 && !bCreatingNewType)
  999. {
  1000. lastUsedSeqItem = 0;
  1001. XmlSchemaElement e = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema, xss.Items,-1);
  1002. e.MinOccurs = 0;
  1003. return e;
  1004. }
  1005. if (xss.Items[0].GetType() == typeof (XmlSchemaChoice))
  1006. { // <sequence minOccurs="0" maxOccurs="unbounded"><choice><element>...</choice></sequence>
  1007. XmlSchemaChoice xsch = (XmlSchemaChoice) xss.Items[0];
  1008. for (int i = 0; i < xsch.Items.Count; ++i)
  1009. {
  1010. XmlSchemaElement el = xsch.Items[i] as XmlSchemaElement;
  1011. if (el == null)
  1012. {
  1013. throw new XmlSchemaInferenceException(Res.SchInf_UnknownParticle, 0, 0);
  1014. }
  1015. if ((el.Name == xtr.LocalName) &&( parentSchema.TargetNamespace == childURI))
  1016. { // element is in the same namespace
  1017. InferElement(el, false, parentSchema);
  1018. SetMinMaxOccurs(el, setMaxoccurs);
  1019. return el;
  1020. }
  1021. else if ((el.RefName.Name == xtr.LocalName) && (el.RefName.Namespace == xtr.NamespaceURI))
  1022. {
  1023. XmlSchemaElement referencedElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
  1024. InferElement(referencedElement, false, parentSchema);
  1025. SetMinMaxOccurs(el, setMaxoccurs);
  1026. return referencedElement;
  1027. }
  1028. }
  1029. XmlSchemaElement subElement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema, xsch.Items,-1);
  1030. return subElement;
  1031. }
  1032. else
  1033. { //this should be sequence of elements
  1034. int iSeqItem = 0; //iterator through schema sequence items
  1035. if (lastUsedSeqItem >= 0)
  1036. iSeqItem = lastUsedSeqItem;
  1037. XmlSchemaParticle particle = xss.Items[iSeqItem] as XmlSchemaParticle;
  1038. XmlSchemaElement el = particle as XmlSchemaElement;
  1039. if (el == null)
  1040. {
  1041. throw new XmlSchemaInferenceException(Res.SchInf_UnknownParticle, 0, 0);
  1042. }
  1043. if (el.Name == xtr.LocalName && parentSchema.TargetNamespace == childURI)
  1044. {
  1045. if (!bItemNotUsedYet) //read: if item was already used one or more times
  1046. el.MaxOccurs = decimal.MaxValue; //set it to unbounded
  1047. lastUsedSeqItem = iSeqItem;
  1048. InferElement(el, false, parentSchema);
  1049. SetMinMaxOccurs(el, false);
  1050. return el;
  1051. }
  1052. else if (el.RefName.Name == xtr.LocalName && el.RefName.Namespace == xtr.NamespaceURI)
  1053. {
  1054. if (!bItemNotUsedYet) //read: if item was already used one or more times
  1055. el.MaxOccurs = decimal.MaxValue; //set it to unbounded
  1056. lastUsedSeqItem = iSeqItem;
  1057. XmlSchemaElement referencedElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
  1058. InferElement(referencedElement, false, parentSchema);
  1059. SetMinMaxOccurs(el, false);
  1060. return el;
  1061. }
  1062. if (bItemNotUsedYet && el.MinOccurs!=decimal.Zero)
  1063. minOccursCandidates.Add(el);
  1064. iSeqItem++;
  1065. while (iSeqItem < xss.Items.Count)
  1066. {
  1067. particle = xss.Items[iSeqItem] as XmlSchemaParticle;
  1068. el = particle as XmlSchemaElement;
  1069. if (el == null)
  1070. {
  1071. throw new XmlSchemaInferenceException(Res.SchInf_UnknownParticle, 0, 0);
  1072. }
  1073. if (el.Name == xtr.LocalName && parentSchema.TargetNamespace == childURI)
  1074. {
  1075. lastUsedSeqItem = iSeqItem;
  1076. for (int i = 0; i < minOccursCandidates.Count; ++i)
  1077. {
  1078. ((XmlSchemaElement) minOccursCandidates[i]).MinOccurs = decimal.Zero;
  1079. }
  1080. InferElement(el, false, parentSchema);
  1081. SetMinMaxOccurs(el, setMaxoccurs);
  1082. return el;
  1083. }
  1084. else if (el.RefName.Name == xtr.LocalName && el.RefName.Namespace == xtr.NamespaceURI)
  1085. {
  1086. lastUsedSeqItem = iSeqItem;
  1087. for (int i = 0; i < minOccursCandidates.Count; ++i)
  1088. {
  1089. ((XmlSchemaElement) minOccursCandidates[i]).MinOccurs = decimal.Zero;
  1090. }
  1091. XmlSchemaElement referencedElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
  1092. InferElement(referencedElement, false, parentSchema);
  1093. SetMinMaxOccurs(el, setMaxoccurs);
  1094. return referencedElement;
  1095. }
  1096. minOccursCandidates.Add(el);
  1097. iSeqItem++;
  1098. }
  1099. //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
  1100. XmlSchemaElement subElement = null;
  1101. XmlSchemaElement actualElement = null;
  1102. //
  1103. if (parentSchema.TargetNamespace == childURI)
  1104. {
  1105. subElement = FindElement(xss.Items, xtr.LocalName);
  1106. actualElement = subElement;
  1107. }
  1108. else
  1109. {
  1110. subElement = FindElementRef(xss.Items, xtr.LocalName, xtr.NamespaceURI);
  1111. if (subElement != null)
  1112. {
  1113. actualElement = FindGlobalElement(childURI, xtr.LocalName, out parentSchema);
  1114. }
  1115. }
  1116. if (null != subElement)
  1117. {
  1118. XmlSchemaChoice xsc = new XmlSchemaChoice();
  1119. xsc.MaxOccurs = decimal.MaxValue;
  1120. SetMinMaxOccurs(subElement, setMaxoccurs);
  1121. InferElement(actualElement, false, parentSchema);
  1122. for (int i = 0; i < xss.Items.Count; ++i)
  1123. {
  1124. xsc.Items.Add(CreateNewElementforChoice((XmlSchemaElement) xss.Items[i]));
  1125. }
  1126. xss.Items.Clear();
  1127. xss.Items.Add(xsc);
  1128. return subElement;
  1129. }
  1130. else
  1131. {
  1132. subElement = AddElement(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, parentSchema, xss.Items, ++lastUsedSeqItem);
  1133. if (!bCreatingNewType)
  1134. subElement.MinOccurs = decimal.Zero;
  1135. return subElement;
  1136. }
  1137. }
  1138. }
  1139. else
  1140. {
  1141. throw new XmlSchemaInferenceException(Res.SchInf_noseq, 0, 0);
  1142. }
  1143. }
  1144. internal void ProcessAttributes(ref XmlSchemaElement xse, XmlSchemaType effectiveSchemaType, bool bCreatingNewType, XmlSchema parentSchema)
  1145. {
  1146. XmlSchemaObjectCollection attributesSeen = new XmlSchemaObjectCollection();
  1147. XmlSchemaComplexType ct = effectiveSchemaType as XmlSchemaComplexType;
  1148. Debug.Assert(xtr.NodeType == XmlNodeType.Attribute);
  1149. do
  1150. {
  1151. if (xtr.NamespaceURI == XmlSchema.Namespace)
  1152. {
  1153. throw new XmlSchemaInferenceException(Res.SchInf_schema, 0, 0);
  1154. }
  1155. if (xtr.NamespaceURI == XmlReservedNs.NsXmlNs)
  1156. {
  1157. if (xtr.Prefix=="xmlns")
  1158. NamespaceManager.AddNamespace(xtr.LocalName, xtr.Value);
  1159. }
  1160. else if (xtr.NamespaceURI == XmlReservedNs.NsXsi)
  1161. {
  1162. string localName = xtr.LocalName;
  1163. if (localName == "nil")
  1164. {
  1165. xse.IsNillable = true;
  1166. }
  1167. else if (localName != "type" && localName != "schemaLocation" && localName != "noNamespaceSchemaLocation")
  1168. {
  1169. throw new XmlSchemaInferenceException(Res.Sch_NotXsiAttribute,localName);
  1170. }
  1171. }
  1172. else
  1173. {
  1174. if (ct == null || ct == XmlSchemaComplexType.AnyType)
  1175. {
  1176. ct = new XmlSchemaComplexType();
  1177. xse.SchemaType = ct;
  1178. }
  1179. XmlSchemaAttribute xsa=null;
  1180. //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
  1181. //Check that it is a simple type by checking typeCode
  1182. //Switch to complex type simple content extension
  1183. if (effectiveSchemaType != null && effectiveSchemaType.Datatype != null && !xse.SchemaTypeName.IsEmpty)
  1184. {
  1185. //type was previously simple type, now it will become complex with simple type extension
  1186. Debug.Assert(ct != null);
  1187. XmlSchemaSimpleContent sc = new XmlSchemaSimpleContent();
  1188. ct.ContentModel = sc;
  1189. XmlSchemaSimpleContentExtension sce = new XmlSchemaSimpleContentExtension();
  1190. sc.Content = sce;
  1191. sce.BaseTypeName = xse.SchemaTypeName;
  1192. sce.LineNumber = xse.LineNumber;
  1193. xse.LineNumber = 0;
  1194. xse.SchemaTypeName = XmlQualifiedName.Empty; //re-set the name
  1195. }
  1196. 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
  1197. if (ct.ContentModel != null)
  1198. {
  1199. XmlSchemaSimpleContentExtension sce = CheckSimpleContentExtension(ct);
  1200. Debug.Assert(sce != null);
  1201. xsa = AddAttribute(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, xtr.Value, bCreatingNewType, parentSchema, sce.Attributes, ct.AttributeUses);
  1202. }
  1203. else //add atributes directly to complex type
  1204. {
  1205. xsa = AddAttribute(xtr.LocalName, xtr.Prefix, xtr.NamespaceURI, xtr.Value, bCreatingNewType, parentSchema, ct.Attributes, ct.AttributeUses);
  1206. }
  1207. if (xsa != null) {
  1208. attributesSeen.Add(xsa);
  1209. }
  1210. }
  1211. } while (xtr.MoveToNextAttribute());
  1212. if (!bCreatingNewType)
  1213. {
  1214. //make attributes that did not appear this time optional
  1215. if (ct!=null) {
  1216. MakeExistingAttributesOptional(ct, attributesSeen);
  1217. }
  1218. }
  1219. }
  1220. private void MoveAttributes(XmlSchemaSimpleContentExtension scExtension, XmlSchemaComplexType ct) {
  1221. //copy all attributes from the simple content to the complex type
  1222. //This is ok since when we move from complex type to simple content extension we copy from AttributeUses property
  1223. for (int i = 0; i < scExtension.Attributes.Count; ++i) //since simpleContent is being cleared
  1224. {
  1225. ct.Attributes.Add(scExtension.Attributes[i]);
  1226. }
  1227. }
  1228. private void MoveAttributes(XmlSchemaComplexType ct, XmlSchemaSimpleContentExtension simpleContentExtension, bool bCreatingNewType) {
  1229. //copy all attributes from the complex type to the simple content
  1230. ICollection sourceCollection;
  1231. if (!bCreatingNewType && ct.AttributeUses.Count > 0) {
  1232. sourceCollection = ct.AttributeUses.Values;
  1233. }
  1234. else {
  1235. sourceCollection = ct.Attributes;
  1236. }
  1237. foreach (XmlSchemaAttribute attr in sourceCollection) {
  1238. simpleContentExtension.Attributes.Add(attr);
  1239. }
  1240. ct.Attributes.Clear(); //Clear from pre-compiled property, post compiled will be cleared on Re-process and Compile()
  1241. }
  1242. internal XmlSchemaAttribute FindAttribute(ICollection attributes, string attrName)
  1243. {
  1244. foreach(XmlSchemaObject xsa in attributes)
  1245. {
  1246. XmlSchemaAttribute schemaAttribute = xsa as XmlSchemaAttribute;
  1247. if (schemaAttribute != null)
  1248. {
  1249. if (schemaAttribute.Name == attrName)
  1250. {
  1251. return schemaAttribute;
  1252. }
  1253. }
  1254. }
  1255. return null;
  1256. }
  1257. internal XmlSchemaElement FindGlobalElement(string namespaceURI, string localName, out XmlSchema parentSchema)
  1258. {
  1259. ICollection col = this.schemaSet.Schemas(namespaceURI);
  1260. XmlSchemaElement xse = null;
  1261. parentSchema = null;
  1262. foreach(XmlSchema schema in col)
  1263. {
  1264. xse = FindElement(schema.Items, localName);
  1265. if (xse != null)
  1266. {
  1267. parentSchema = schema;
  1268. return xse;
  1269. }
  1270. }
  1271. return null;
  1272. }
  1273. internal XmlSchemaElement FindElement(XmlSchemaObjectCollection elements, string elementName)
  1274. {
  1275. for (int i = 0; i < elements.Count; ++i)
  1276. {
  1277. XmlSchemaElement xse = elements[i] as XmlSchemaElement;
  1278. if (xse != null && xse.RefName != null)
  1279. {
  1280. if (xse.Name == elementName)
  1281. {
  1282. return xse;
  1283. }
  1284. }
  1285. }
  1286. return null;
  1287. }
  1288. internal XmlSchemaAttribute FindAttributeRef(ICollection attributes, string attributeName, string nsURI)
  1289. {
  1290. foreach(XmlSchemaObject xsa in attributes)
  1291. {
  1292. XmlSchemaAttribute schemaAttribute = xsa as XmlSchemaAttribute;
  1293. if (schemaAttribute != null)
  1294. {
  1295. if (schemaAttribute.RefName.Name == attributeName && schemaAttribute.RefName.Namespace == nsURI) {
  1296. return schemaAttribute;
  1297. }
  1298. }
  1299. }
  1300. return null;
  1301. }
  1302. internal XmlSchemaElement FindElementRef(XmlSchemaObjectCollection elements, string elementName, string nsURI)
  1303. {
  1304. for (int i = 0; i < elements.Count; ++i)
  1305. {
  1306. XmlSchemaElement xse = elements[i] as XmlSchemaElement;
  1307. if (xse != null && xse.RefName != null)
  1308. {
  1309. if (xse.RefName.Name == elementName && xse.RefName.Namespace == nsURI)
  1310. {
  1311. return xse;
  1312. }
  1313. }
  1314. }
  1315. return null;
  1316. }
  1317. internal void MakeExistingAttributesOptional(XmlSchemaComplexType ct, XmlSchemaObjectCollection attributesInInstance) {
  1318. if (ct == null) {
  1319. throw new XmlSchemaInferenceException(Res.SchInf_noct, 0, 0);
  1320. }
  1321. if (ct.ContentModel != null) {
  1322. XmlSchemaSimpleContentExtension xssce = CheckSimpleContentExtension(ct);
  1323. SwitchUseToOptional(xssce.Attributes, attributesInInstance);
  1324. }
  1325. else { //either <xs:attribute> as child of xs:complexType or the attributes are within the content model
  1326. SwitchUseToOptional(ct.Attributes, attributesInInstance);
  1327. }
  1328. }
  1329. private void SwitchUseToOptional(XmlSchemaObjectCollection attributes, XmlSchemaObjectCollection attributesInInstance) {
  1330. for (int i = 0; i < attributes.Count; ++i)
  1331. {
  1332. XmlSchemaAttribute attr = attributes[i] as XmlSchemaAttribute;
  1333. if (attr != null) {
  1334. if (attributesInInstance != null) {
  1335. if (attr.RefName.Name.Length == 0) { //If the attribute is not present in this instance, make it optional
  1336. if (null == FindAttribute(attributesInInstance, attr.Name)) {
  1337. attr.Use = XmlSchemaUse.Optional;
  1338. }
  1339. }
  1340. else {
  1341. if (null == FindAttributeRef(attributesInInstance, attr.RefName.Name, attr.RefName.Namespace)) {
  1342. attr.Use = XmlSchemaUse.Optional;
  1343. }
  1344. }
  1345. }
  1346. else {
  1347. attr.Use = XmlSchemaUse.Optional;
  1348. }
  1349. }
  1350. }
  1351. }
  1352. internal XmlQualifiedName RefineSimpleType(string s, ref int iTypeFlags)
  1353. {
  1354. bool bNeedsRangeCheck = false;
  1355. s = s.Trim();
  1356. if (iTypeFlags == TF_string || this.typeInference == InferenceOption.Relaxed)
  1357. return ST_string;
  1358. iTypeFlags &= InferSimpleType(s, ref bNeedsRangeCheck);
  1359. if (iTypeFlags == TF_string)
  1360. return ST_string;
  1361. if (bNeedsRangeCheck)
  1362. {
  1363. if ((iTypeFlags & TF_byte) != 0)
  1364. {
  1365. try
  1366. {
  1367. XmlConvert.ToSByte(s);
  1368. //sbyte.Parse(s);
  1369. if ((iTypeFlags & TF_unsignedByte) != 0)
  1370. return ST_unsignedByte; //number is positive and fits byte -> it also fits unsignedByte
  1371. else
  1372. return ST_byte;
  1373. }
  1374. catch (FormatException)
  1375. {}
  1376. catch (OverflowException)
  1377. {}
  1378. iTypeFlags &= (~TF_byte);
  1379. }
  1380. if ((iTypeFlags & TF_unsignedByte) != 0)
  1381. {
  1382. try
  1383. {
  1384. XmlConvert.ToByte(s);
  1385. //byte.Parse(s);
  1386. return ST_unsignedByte;
  1387. }
  1388. catch (FormatException)
  1389. {}
  1390. catch (OverflowException)
  1391. {}
  1392. iTypeFlags &= (~TF_unsignedByte);
  1393. }
  1394. if ((iTypeFlags & TF_short) != 0)
  1395. {
  1396. try
  1397. {
  1398. XmlConvert.ToInt16(s);
  1399. //short.Parse(s);
  1400. if ((iTypeFlags & TF_unsignedShort) != 0)
  1401. return ST_unsignedShort; //number is positive and fits short -> it also fits unsignedShort
  1402. else
  1403. return ST_short;
  1404. }
  1405. catch (FormatException)
  1406. {}
  1407. catch (OverflowException)
  1408. {}
  1409. iTypeFlags &= (~TF_short);
  1410. }
  1411. if ((iTypeFlags & TF_unsignedShort) != 0)
  1412. {
  1413. try
  1414. {
  1415. XmlConvert.ToUInt16(s);
  1416. //ushort.Parse(s);
  1417. return ST_unsignedShort;
  1418. }
  1419. catch (FormatException)
  1420. {}
  1421. catch (OverflowException)
  1422. {}
  1423. iTypeFlags &= (~TF_unsignedShort);
  1424. }
  1425. if ((iTypeFlags & TF_int) != 0)
  1426. {
  1427. try
  1428. {
  1429. XmlConvert.ToInt32(s);
  1430. //int.Parse(s);
  1431. if ((iTypeFlags & TF_unsignedInt) != 0)
  1432. return ST_unsignedInt; //number is positive and fits int -> it also fits unsignedInt
  1433. else
  1434. return ST_int;
  1435. }
  1436. catch (FormatException)
  1437. {}
  1438. catch (OverflowException)
  1439. {}
  1440. iTypeFlags &= (~TF_int);
  1441. }
  1442. if ((iTypeFlags & TF_unsignedInt) != 0)
  1443. {
  1444. try
  1445. {
  1446. XmlConvert.ToUInt32(s);
  1447. //uint.Parse(s);
  1448. return ST_unsignedInt;
  1449. }
  1450. catch (FormatException)
  1451. {}
  1452. catch (OverflowException)
  1453. {}
  1454. iTypeFlags &= (~TF_unsignedInt);
  1455. }
  1456. if ((iTypeFlags & TF_long) != 0)
  1457. {
  1458. try
  1459. {
  1460. XmlConvert.ToInt64(s);
  1461. //long.Parse(s);
  1462. if ((iTypeFlags & TF_unsignedLong) != 0)
  1463. return ST_unsignedLong; //number is positive and fits long -> it also fits unsignedLong
  1464. else
  1465. return ST_long;
  1466. }
  1467. catch (FormatException)
  1468. {}
  1469. catch (OverflowException)
  1470. {}
  1471. iTypeFlags &= (~TF_long);
  1472. }
  1473. if ((iTypeFlags & TF_unsignedLong) != 0)
  1474. {
  1475. try
  1476. {
  1477. XmlConvert.ToUInt64(s);
  1478. //ulong.Parse(s);
  1479. return ST_unsignedLong;
  1480. }
  1481. catch (FormatException)
  1482. {}
  1483. catch (OverflowException)
  1484. {}
  1485. iTypeFlags &= (~TF_unsignedLong);
  1486. }
  1487. if ((iTypeFlags & TF_double) != 0)
  1488. {
  1489. try
  1490. {
  1491. double dbValue = XmlConvert.ToDouble(s);
  1492. if ((iTypeFlags & TF_integer) != 0)
  1493. return ST_integer;
  1494. else if ((iTypeFlags & TF_decimal) != 0)
  1495. return ST_decimal;
  1496. else {
  1497. // The value fits into double, but it could be float as well
  1498. if ((iTypeFlags & TF_float) != 0) {
  1499. // We used to default to float in this case, so try to fit it into float first
  1500. try {
  1501. float flValue = XmlConvert.ToSingle(s);
  1502. // Compare the float and double values. We can't do simple value comparison
  1503. // as conversion from float to double introduces imprecissions which cause problems.
  1504. // Instead we will convert both back to string and compare the strings.
  1505. if (string.Compare(XmlConvert.ToString(flValue), XmlConvert.ToString(dbValue),
  1506. StringComparison.OrdinalIgnoreCase) == 0) {
  1507. // If we can convert the original string to the exact same value
  1508. // and it still fits into float then we treat it as float
  1509. return ST_float;
  1510. }
  1511. }
  1512. catch (FormatException)
  1513. {}
  1514. catch (OverflowException)
  1515. {}
  1516. }
  1517. iTypeFlags &= (~TF_float);
  1518. return ST_double;
  1519. }
  1520. }
  1521. catch (FormatException)
  1522. {}
  1523. catch (OverflowException)
  1524. {}
  1525. iTypeFlags &= (~TF_double);
  1526. }
  1527. if ((iTypeFlags & TF_float) != 0) {
  1528. try {
  1529. XmlConvert.ToSingle(s);
  1530. if ((iTypeFlags & TF_integer) != 0)
  1531. return ST_integer;
  1532. else if ((iTypeFlags & TF_decimal) != 0)
  1533. return ST_decimal;
  1534. else
  1535. return ST_float;
  1536. }
  1537. catch (FormatException) { }
  1538. catch (OverflowException) { }
  1539. iTypeFlags &= (~TF_float);
  1540. }
  1541. if ((iTypeFlags & TF_integer) != 0)
  1542. return ST_integer;
  1543. else if ((iTypeFlags & TF_decimal) != 0)
  1544. return ST_decimal;
  1545. else if (iTypeFlags == (TF_gYearMonth | TF_string) )
  1546. {
  1547. try
  1548. {
  1549. XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind);
  1550. return ST_gYearMonth;
  1551. }
  1552. catch (FormatException)
  1553. {}
  1554. catch (OverflowException)
  1555. {}
  1556. iTypeFlags = TF_string;
  1557. return ST_string;
  1558. }
  1559. else if (iTypeFlags == (TF_duration | TF_string) )
  1560. {
  1561. try
  1562. {
  1563. XmlConvert.ToTimeSpan(s);
  1564. return ST_duration;
  1565. }
  1566. catch (FormatException)
  1567. {}
  1568. catch (OverflowException)
  1569. {}
  1570. iTypeFlags = TF_string;
  1571. return ST_string;
  1572. }
  1573. else if (iTypeFlags == (TF_boolean | TF_string))
  1574. {
  1575. return ST_boolean;
  1576. }
  1577. }
  1578. switch (iTypeFlags)
  1579. {
  1580. case TF_string:
  1581. return ST_string;
  1582. case TF_boolean:
  1583. return ST_boolean;
  1584. case TF_byte:
  1585. return ST_byte;
  1586. case TF_unsignedByte:
  1587. return ST_unsignedByte;
  1588. case TF_short:
  1589. return ST_short;
  1590. case TF_unsignedShort:
  1591. return ST_unsignedShort;
  1592. case TF_int:
  1593. return ST_int;
  1594. case TF_unsignedInt:
  1595. return ST_unsignedInt;
  1596. case TF_long:
  1597. return ST_long;
  1598. case TF_unsignedLong:
  1599. return ST_unsignedLong;
  1600. case TF_integer:
  1601. return ST_integer;
  1602. case TF_decimal:
  1603. return ST_decimal;
  1604. case TF_float:
  1605. return ST_float;
  1606. case TF_double:
  1607. return ST_double;
  1608. case TF_duration:
  1609. return ST_duration;
  1610. case TF_dateTime:
  1611. return ST_dateTime;
  1612. case TF_time:
  1613. return ST_time;
  1614. case TF_date:
  1615. return ST_date;
  1616. case TF_gYearMonth:
  1617. return ST_gYearMonth;
  1618. case TF_boolean | TF_string:
  1619. return ST_boolean;
  1620. case TF_dateTime | TF_string:
  1621. return ST_dateTime;
  1622. case TF_date | TF_string:
  1623. return ST_date;
  1624. case TF_time | TF_string:
  1625. return ST_time;
  1626. case TF_float | TF_double | TF_string:
  1627. return ST_float;
  1628. case TF_double | TF_string:
  1629. return ST_double;
  1630. default:
  1631. Debug.Assert(false, "Expected type not matched");
  1632. return ST_string;
  1633. }
  1634. /* if (currentType == null)
  1635. return SimpleTypes[newType];
  1636. else
  1637. return SimpleTypes[ST_Map[newType,(short) ST_Codes[currentType]]];
  1638. */
  1639. }
  1640. internal static int InferSimpleType(string s, ref bool bNeedsRangeCheck)
  1641. {
  1642. bool bNegative = false;
  1643. bool bPositive = false;
  1644. bool bDate = false;
  1645. bool bTime = false;
  1646. bool bMissingDay = false;
  1647. #if !BOOTSTRAP_BASIC
  1648. if (s.Length==0) return TF_string;
  1649. int i = 0;
  1650. switch (s[i])
  1651. {
  1652. case 't':
  1653. case 'f':
  1654. if (s == "true")
  1655. return TF_boolean | TF_string;
  1656. else if (s == "false")
  1657. return TF_boolean | TF_string;
  1658. else
  1659. return TF_string;
  1660. case 'N': //try to match "NaN"
  1661. if (s == "NaN")
  1662. return TF_float | TF_double | TF_string;
  1663. else
  1664. return TF_string;
  1665. //else
  1666. case 'I': //try to match "INF"
  1667. INF:
  1668. if (s.Substring(i) == "INF")
  1669. return TF_float | TF_double | TF_string;
  1670. else return TF_string;
  1671. case '.': //try to match ".9999" decimal/float/double
  1672. FRACTION:
  1673. bNeedsRangeCheck = true;
  1674. i++;
  1675. if (i==s.Length)
  1676. {
  1677. if ((i==1) || (i==2 && (bPositive || bNegative))) //"." "-." "+."
  1678. return TF_string;
  1679. else
  1680. return TF_decimal | TF_float | TF_double | TF_string;
  1681. }
  1682. switch (s[i])
  1683. {
  1684. case 'e':
  1685. case 'E':
  1686. goto EXPONENT;
  1687. default:
  1688. if (s[i]>='0' && s[i]<='9')
  1689. goto DEC_PART;
  1690. else
  1691. return TF_string;
  1692. }
  1693. DEC_PART:
  1694. i++; if (i==s.Length) return TF_decimal | TF_float | TF_double | TF_string; //"9999.9" was matched
  1695. switch (s[i])
  1696. {
  1697. case 'e':
  1698. case 'E':
  1699. goto EXPONENT;
  1700. default:
  1701. if (s[i]>='0' && s[i]<='9')
  1702. goto DEC_PART;
  1703. else
  1704. return TF_string;
  1705. }
  1706. EXPONENT:
  1707. i++; if (i==s.Length) return TF_string;
  1708. switch (s[i])
  1709. {
  1710. case '+':
  1711. case '-':
  1712. goto E1;
  1713. default:
  1714. if (s[i]>='0' && s[i]<='9')
  1715. goto EXP_PART;
  1716. else
  1717. return TF_string;
  1718. }
  1719. E1:
  1720. i++; if (i==s.Length) return TF_string; //".9999e+" was matched
  1721. if (s[i]>='0' && s[i]<='9')
  1722. goto EXP_PART;
  1723. else
  1724. return TF_string; //".999e+X was matched
  1725. EXP_PART:
  1726. i++; if (i==s.Length) return TF_float | TF_double | TF_string; //".9999e+99" was matched
  1727. if (s[i]>='0' && s[i]<='9') //".9999e+9
  1728. goto EXP_PART;
  1729. else
  1730. return TF_string; //".9999e+999X" was matched
  1731. case '-':
  1732. bNegative = true;
  1733. i++; if (i==s.Length) return TF_string;
  1734. switch (s[i])
  1735. {
  1736. case 'I': //try to match "-INF"
  1737. goto INF;
  1738. case '.': //try to match "-.9999"
  1739. goto FRACTION;
  1740. case 'P':
  1741. goto DURATION;
  1742. default:
  1743. if (s[i]>='0' && s[i]<='9') //-9
  1744. goto NUMBER;
  1745. else return TF_string;
  1746. }
  1747. case '+':
  1748. bPositive = true;
  1749. i++; if (i==s.Length) return TF_string;
  1750. switch (s[i])
  1751. {
  1752. case '.': //try to match "+.9999"
  1753. goto FRACTION;
  1754. case 'P':
  1755. goto DURATION;
  1756. default:
  1757. if (s[i]>='0' && s[i]<='9') //"+9
  1758. goto NUMBER;
  1759. else return TF_string;
  1760. }
  1761. case 'P': //try to match duration
  1762. DURATION:
  1763. i++; if (i==s.Length) return TF_string;
  1764. switch (s[i])
  1765. {
  1766. case 'T':
  1767. goto D7;
  1768. default:
  1769. if (s[i]>='0' && s[i]<='9') //"P9"
  1770. goto D1;
  1771. else return TF_string;
  1772. }
  1773. D1:
  1774. i++; if (i==s.Length) return TF_string; //"P999" was matched
  1775. switch (s[i])
  1776. {
  1777. case 'Y':
  1778. goto D2;
  1779. case 'M':
  1780. goto D4;
  1781. case 'D':
  1782. goto D6;
  1783. default:
  1784. if (s[i]>='0' && s[i]<='9')
  1785. goto D1;
  1786. else
  1787. return TF_string;
  1788. }
  1789. D2:
  1790. i++;
  1791. if (i==s.Length)
  1792. {
  1793. bNeedsRangeCheck = true;
  1794. return TF_duration | TF_string; //"P999Y" was matched
  1795. }
  1796. switch (s[i])
  1797. {
  1798. case 'T':
  1799. goto D7;
  1800. default:
  1801. if (s[i]>='0' && s[i]<='9')
  1802. goto D3;
  1803. else
  1804. return TF_string;
  1805. }
  1806. D3:
  1807. i++; if (i==s.Length) return TF_string; //"P999Y9" was matched
  1808. switch (s[i])
  1809. {
  1810. case 'M':
  1811. goto D4;
  1812. case 'D':
  1813. goto D6;
  1814. default:
  1815. if (s[i]>='0' && s[i]<='9')
  1816. goto D3;
  1817. else
  1818. return TF_string;
  1819. }
  1820. D4:
  1821. i++;
  1822. if (i==s.Length)
  1823. {
  1824. bNeedsRangeCheck = true;
  1825. return TF_duration | TF_string; //"P999Y999M" was matched
  1826. }
  1827. switch (s[i])
  1828. {
  1829. case 'T':
  1830. goto D7;
  1831. default:
  1832. if (s[i]>='0' && s[i]<='9')
  1833. goto D5;
  1834. else
  1835. return TF_string;
  1836. }
  1837. D5:
  1838. i++; if (i==s.Length) return TF_string; //"P999Y999M9" was matched
  1839. switch (s[i])
  1840. {
  1841. case 'D':
  1842. goto D6;
  1843. default:
  1844. if (s[i]>='0' && s[i]<='9')
  1845. goto D5;
  1846. else
  1847. return TF_string;
  1848. }
  1849. D6:
  1850. i++;
  1851. if (i==s.Length)
  1852. {
  1853. bNeedsRangeCheck = true;
  1854. return TF_duration | TF_string; //"P999Y999M999D" was matched
  1855. }
  1856. switch (s[i])
  1857. {
  1858. case 'T':
  1859. goto D7;
  1860. default:
  1861. return TF_string;
  1862. }
  1863. D7:
  1864. i++; if (i==s.Length) return TF_string; //"P999Y999M9999DT" was matched
  1865. if (s[i]>='0' && s[i]<='9')
  1866. goto D8;
  1867. else
  1868. return TF_string;
  1869. D8:
  1870. i++; if (i==s.Length) return TF_string; //"___T9" was matched
  1871. switch (s[i])
  1872. {
  1873. case 'H':
  1874. goto D9;
  1875. case 'M':
  1876. goto D11;
  1877. case '.':
  1878. goto D13;
  1879. case 'S':
  1880. goto D15;
  1881. default:
  1882. if (s[i]>='0' && s[i]<='9')
  1883. goto D8;
  1884. else
  1885. return TF_string;
  1886. }
  1887. D9:
  1888. i++;
  1889. if (i==s.Length)
  1890. {
  1891. bNeedsRangeCheck = true;
  1892. return TF_duration | TF_string; //"___T999H" was matched
  1893. }
  1894. if (s[i]>='0' && s[i]<='9')
  1895. goto D10;
  1896. else
  1897. return TF_string;
  1898. D10:
  1899. i++; if (i==s.Length) return TF_string; //"___T999H9" was matched
  1900. switch (s[i])
  1901. {
  1902. case 'M':
  1903. goto D11;
  1904. case '.':
  1905. goto D13;
  1906. case 'S':
  1907. goto D15;
  1908. default:
  1909. if (s[i]>='0' && s[i]<='9')
  1910. goto D10;
  1911. else
  1912. return TF_string;
  1913. }
  1914. D11:
  1915. i++;
  1916. if (i==s.Length)
  1917. {
  1918. bNeedsRangeCheck = true;
  1919. return TF_duration | TF_string; //"___T999H999M" was matched
  1920. }
  1921. if (s[i]>='0' && s[i]<='9')
  1922. goto D12;
  1923. else
  1924. return TF_string;
  1925. D12:
  1926. i++; if (i==s.Length) return TF_string; //"___T999H999M9" was matched
  1927. switch (s[i])
  1928. {
  1929. case '.':
  1930. goto D13;
  1931. case 'S':
  1932. goto D15;
  1933. default:
  1934. if (s[i]>='0' && s[i]<='9')
  1935. goto D12;
  1936. else
  1937. return TF_string;
  1938. }
  1939. D13:
  1940. i++;
  1941. if (i==s.Length)
  1942. {
  1943. bNeedsRangeCheck = true;
  1944. return TF_duration | TF_string; //"___T999H999M999." was matched
  1945. }
  1946. if (s[i]>='0' && s[i]<='9')
  1947. goto D14;
  1948. else
  1949. return TF_string;
  1950. D14:
  1951. i++; if (i==s.Length) return TF_string; //"___T999H999M999.9" was matched
  1952. switch (s[i])
  1953. {
  1954. case 'S':
  1955. goto D15;
  1956. default:
  1957. if (s[i]>='0' && s[i]<='9')
  1958. goto D14;
  1959. else
  1960. return TF_string;
  1961. }
  1962. D15:
  1963. i++;
  1964. if (i==s.Length)
  1965. {
  1966. bNeedsRangeCheck = true;
  1967. return TF_duration | TF_string; //"___T999H999M999.999S" was matched
  1968. }
  1969. else return TF_string;
  1970. case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
  1971. NUMBER:
  1972. i++;
  1973. if (i==s.Length)
  1974. {
  1975. bNeedsRangeCheck = true;
  1976. if (bNegative || bPositive)
  1977. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
  1978. else
  1979. {
  1980. if (s=="0" || s=="1")
  1981. return TF_boolean | TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  1982. TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  1983. else
  1984. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  1985. TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  1986. }
  1987. }
  1988. switch (s[i])
  1989. {
  1990. case '.':
  1991. goto FRACTION;
  1992. case 'e':
  1993. case 'E':
  1994. bNeedsRangeCheck = true;
  1995. return TF_float | TF_double | TF_string;
  1996. default:
  1997. if (s[i]>='0' && s[i]<='9')
  1998. goto N2;
  1999. else
  2000. return TF_string;
  2001. }
  2002. N2:
  2003. i++;
  2004. if (i==s.Length)
  2005. {
  2006. bNeedsRangeCheck = true;
  2007. if (bNegative || bPositive)
  2008. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
  2009. else
  2010. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2011. TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  2012. }
  2013. switch (s[i])
  2014. {
  2015. case '.':
  2016. goto FRACTION;
  2017. case ':':
  2018. bTime = true;
  2019. goto MINUTE;
  2020. case 'e':
  2021. case 'E':
  2022. bNeedsRangeCheck = true;
  2023. return TF_float | TF_double | TF_string;
  2024. default:
  2025. if (s[i]>='0' && s[i]<='9')
  2026. goto N3;
  2027. else
  2028. return TF_string;
  2029. }
  2030. N3:
  2031. i++;
  2032. if (i==s.Length)
  2033. {
  2034. bNeedsRangeCheck = true; //three digits may not fit byte and unsignedByte
  2035. if (bNegative || bPositive)
  2036. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
  2037. else
  2038. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2039. TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  2040. }
  2041. switch (s[i])
  2042. {
  2043. case '.':
  2044. goto FRACTION;
  2045. case 'e':
  2046. case 'E':
  2047. bNeedsRangeCheck = true;
  2048. return TF_float | TF_double | TF_string;
  2049. default:
  2050. if (s[i]>='0' && s[i]<='9')
  2051. goto N4;
  2052. else
  2053. return TF_string;
  2054. }
  2055. N4:
  2056. i++;
  2057. if (i==s.Length)
  2058. {
  2059. bNeedsRangeCheck = true;
  2060. if (bNegative || bPositive)
  2061. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string; //"-9"
  2062. else
  2063. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2064. TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  2065. }
  2066. switch (s[i])
  2067. {
  2068. case '-':
  2069. bDate = true;
  2070. goto DATE;
  2071. case '.':
  2072. goto FRACTION;
  2073. case 'e':
  2074. case 'E':
  2075. bNeedsRangeCheck = true;
  2076. return TF_float | TF_double | TF_string;
  2077. default:
  2078. if (s[i]>='0' && s[i]<='9')
  2079. goto N4;
  2080. else
  2081. return TF_string;
  2082. }
  2083. DATE:
  2084. i++; if (i==s.Length) return TF_string; //"9999-"
  2085. if (s[i]<'0' || s[i]>'9')
  2086. return TF_string;
  2087. i++; if (i==s.Length) return TF_string; //"9999-9"
  2088. if (s[i]<'0' || s[i]>'9')
  2089. return TF_string;
  2090. i++;
  2091. if (i==s.Length)
  2092. {
  2093. bNeedsRangeCheck = true;
  2094. return TF_gYearMonth | TF_string; //"9999-99"
  2095. }
  2096. switch (s[i])
  2097. {
  2098. case '-':
  2099. goto DAY;
  2100. case 'Z':
  2101. case 'z':
  2102. bMissingDay = true;
  2103. goto ZULU;
  2104. case '+':
  2105. bMissingDay = true;
  2106. goto ZONE_SHIFT;
  2107. default:
  2108. return TF_string;
  2109. }
  2110. DAY:
  2111. i++; if (i==s.Length) return TF_string; //"9999-99-"
  2112. if (s[i]<'0' || s[i]>'9')
  2113. return TF_string;
  2114. i++; if (i==s.Length) return TF_string; //"9999-99-9"
  2115. if (s[i]<'0' || s[i]>'9')
  2116. return TF_string;
  2117. i++; if (i==s.Length) return DateTime(s, bDate, bTime); //"9999-99-99"
  2118. switch (s[i])
  2119. {
  2120. case 'Z':
  2121. case 'z':
  2122. goto ZULU;
  2123. case '+':
  2124. case '-':
  2125. goto ZONE_SHIFT;
  2126. case 'T':
  2127. bTime=true;
  2128. goto TIME;
  2129. case ':':
  2130. bMissingDay = true;
  2131. goto ZONE_SHIFT_MINUTE;
  2132. default:
  2133. return TF_string;
  2134. }
  2135. ZULU:
  2136. i++;
  2137. if (i==s.Length)
  2138. {
  2139. if (bMissingDay)
  2140. {
  2141. bNeedsRangeCheck=true;
  2142. return TF_gYearMonth | TF_string;
  2143. }
  2144. else
  2145. {
  2146. return DateTime(s, bDate, bTime);
  2147. }
  2148. }
  2149. else
  2150. return TF_string;
  2151. ZONE_SHIFT:
  2152. i++; if (i==s.Length) return TF_string;
  2153. if (s[i]<'0' || s[i]>'9')
  2154. return TF_string;
  2155. i++; if (i==s.Length) return TF_string;
  2156. if (s[i]<'0' || s[i]>'9')
  2157. return TF_string;
  2158. i++; if (i==s.Length) return TF_string;
  2159. if (s[i] != ':')
  2160. return TF_string;
  2161. ZONE_SHIFT_MINUTE:
  2162. i++; if (i==s.Length) return TF_string;
  2163. if (s[i]<'0' || s[i]>'9')
  2164. return TF_string;
  2165. i++; if (i==s.Length) return TF_string;
  2166. if (s[i]<'0' || s[i]>'9')
  2167. return TF_string;
  2168. i++;
  2169. if (i==s.Length)
  2170. {
  2171. if (bMissingDay)
  2172. {
  2173. bNeedsRangeCheck=true;
  2174. return TF_gYearMonth | TF_string;
  2175. }
  2176. else
  2177. {
  2178. return DateTime(s, bDate, bTime);
  2179. }
  2180. }
  2181. else return TF_string;
  2182. TIME:
  2183. i++; if (i==s.Length) return TF_string;
  2184. if (s[i]<'0' || s[i]>'9')
  2185. return TF_string;
  2186. i++; if (i==s.Length) return TF_string;
  2187. if (s[i]<'0' || s[i]>'9')
  2188. return TF_string;
  2189. i++; if (i==s.Length) return TF_string;
  2190. if (s[i] != ':')
  2191. return TF_string;
  2192. MINUTE:
  2193. i++; if (i==s.Length) return TF_string;
  2194. if (s[i]<'0' || s[i]>'9')
  2195. return TF_string;
  2196. i++; if (i==s.Length) return TF_string;
  2197. if (s[i]<'0' || s[i]>'9')
  2198. return TF_string;
  2199. i++; if (i==s.Length) return TF_string;
  2200. if (s[i] != ':')
  2201. return TF_string;
  2202. i++; if (i==s.Length) return TF_string;
  2203. if (s[i]<'0' || s[i]>'9')
  2204. return TF_string;
  2205. i++; if (i==s.Length) return TF_string;
  2206. if (s[i]<'0' || s[i]>'9')
  2207. return TF_string;
  2208. i++; if (i==s.Length) return DateTime(s, bDate, bTime);
  2209. switch (s[i])
  2210. {
  2211. case 'Z':
  2212. case 'z':
  2213. goto ZULU;
  2214. case '+':
  2215. case '-':
  2216. goto ZONE_SHIFT;
  2217. case '.':
  2218. goto SECOND_FRACTION;
  2219. default:
  2220. return TF_string;
  2221. }
  2222. SECOND_FRACTION:
  2223. i++; if (i==s.Length) return TF_string;
  2224. if (s[i]<'0' || s[i]>'9')
  2225. return TF_string;
  2226. FRACT_DIGITS:
  2227. i++; if (i==s.Length) return DateTime(s, bDate, bTime);
  2228. switch (s[i])
  2229. {
  2230. case 'Z':
  2231. case 'z':
  2232. goto ZULU;
  2233. case '+':
  2234. case '-':
  2235. goto ZONE_SHIFT;
  2236. default:
  2237. if (s[i]>='0' && s[i]<='9')
  2238. goto FRACT_DIGITS;
  2239. else
  2240. return TF_string;
  2241. }
  2242. default:
  2243. return TF_string;
  2244. }
  2245. #else // BOOTSTRAP_BASIC
  2246. return TF_string;
  2247. #endif
  2248. }
  2249. internal static int DateTime(string s, bool bDate, bool bTime)
  2250. {
  2251. try
  2252. {
  2253. XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind);
  2254. }
  2255. catch (FormatException)
  2256. {
  2257. return TF_string;
  2258. }
  2259. if (bDate && bTime)
  2260. return TF_dateTime | TF_string;
  2261. else if (bDate)
  2262. return TF_date | TF_string;
  2263. else if (bTime)
  2264. return TF_time | TF_string;
  2265. else
  2266. {
  2267. Debug.Assert(false, "Expected date, time or dateTime");
  2268. return TF_string;
  2269. }
  2270. }
  2271. XmlSchemaElement CreateNewElementforChoice(XmlSchemaElement copyElement)
  2272. {
  2273. XmlSchemaElement newElement = new XmlSchemaElement();
  2274. newElement.Annotation = copyElement.Annotation;
  2275. newElement.Block = copyElement.Block;
  2276. newElement.DefaultValue = copyElement.DefaultValue;
  2277. newElement.Final = copyElement.Final;
  2278. newElement.FixedValue = copyElement.FixedValue;
  2279. newElement.Form = copyElement.Form;
  2280. newElement.Id = copyElement.Id;
  2281. // newElement.IsAbstract = copyElement.IsAbstract;
  2282. if (copyElement.IsNillable)
  2283. {
  2284. newElement.IsNillable = copyElement.IsNillable;
  2285. }
  2286. newElement.LineNumber = copyElement.LineNumber;
  2287. newElement.LinePosition = copyElement.LinePosition;
  2288. newElement.Name = copyElement.Name;
  2289. newElement.Namespaces = copyElement.Namespaces;
  2290. newElement.RefName = copyElement.RefName;
  2291. newElement.SchemaType = copyElement.SchemaType;
  2292. newElement.SchemaTypeName = copyElement.SchemaTypeName;
  2293. newElement.SourceUri = copyElement.SourceUri;
  2294. newElement.SubstitutionGroup = copyElement.SubstitutionGroup;
  2295. newElement.UnhandledAttributes = copyElement.UnhandledAttributes;
  2296. if (copyElement.MinOccurs != Decimal.One && this.Occurrence == InferenceOption.Relaxed)
  2297. {
  2298. newElement.MinOccurs = copyElement.MinOccurs;
  2299. }
  2300. if (copyElement.MaxOccurs != Decimal.One) {
  2301. newElement.MaxOccurs = copyElement.MaxOccurs;
  2302. }
  2303. return newElement;
  2304. }
  2305. private static int GetSchemaType(XmlQualifiedName qname)
  2306. {
  2307. if (qname == SimpleTypes[HC_ST_boolean])
  2308. {
  2309. return TF_boolean | TF_string;
  2310. }
  2311. if (qname == SimpleTypes[HC_ST_byte])
  2312. {
  2313. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
  2314. }
  2315. if (qname == SimpleTypes[HC_ST_unsignedByte])
  2316. {
  2317. return TF_byte | TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2318. TF_unsignedByte | TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  2319. }
  2320. if (qname == SimpleTypes[HC_ST_short])
  2321. {
  2322. return TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
  2323. }
  2324. if (qname == SimpleTypes[HC_ST_unsignedShort])
  2325. {
  2326. return TF_short | TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2327. TF_unsignedShort | TF_unsignedInt | TF_unsignedLong | TF_string;
  2328. }
  2329. if (qname == SimpleTypes[HC_ST_int])
  2330. {
  2331. return TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
  2332. }
  2333. if (qname == SimpleTypes[HC_ST_unsignedInt])
  2334. {
  2335. return TF_int | TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2336. TF_unsignedInt | TF_unsignedLong | TF_string;
  2337. }
  2338. if (qname == SimpleTypes[HC_ST_long])
  2339. {
  2340. return TF_long | TF_integer | TF_decimal | TF_float | TF_double | TF_string;
  2341. }
  2342. if (qname == SimpleTypes[HC_ST_unsignedLong])
  2343. {
  2344. return TF_long | TF_integer | TF_decimal | TF_float | TF_double |
  2345. TF_unsignedLong | TF_string;
  2346. }
  2347. if (qname == SimpleTypes[HC_ST_integer])
  2348. {
  2349. return TF_integer |TF_decimal | TF_float | TF_double | TF_string;
  2350. }
  2351. if (qname == SimpleTypes[HC_ST_decimal])
  2352. {
  2353. return TF_decimal | TF_float | TF_double | TF_string;
  2354. }
  2355. if (qname == SimpleTypes[HC_ST_float])
  2356. {
  2357. return TF_float | TF_double | TF_string;
  2358. }
  2359. if (qname == SimpleTypes[HC_ST_double])
  2360. {
  2361. return TF_double | TF_string;
  2362. }
  2363. if (qname == SimpleTypes[HC_ST_duration])
  2364. {
  2365. return TF_duration | TF_string;
  2366. }
  2367. if (qname == SimpleTypes[HC_ST_dateTime])
  2368. {
  2369. return TF_dateTime | TF_string;
  2370. }
  2371. if (qname == SimpleTypes[HC_ST_time])
  2372. {
  2373. return TF_time | TF_string;
  2374. }
  2375. if (qname == SimpleTypes[HC_ST_date])
  2376. {
  2377. return TF_date;
  2378. }
  2379. if (qname == SimpleTypes[HC_ST_gYearMonth])
  2380. {
  2381. return TF_gYearMonth;
  2382. }
  2383. if (qname == SimpleTypes[HC_ST_string])
  2384. {
  2385. return TF_string;
  2386. }
  2387. if (qname == null || qname.IsEmpty) {
  2388. return -1;
  2389. }
  2390. throw new XmlSchemaInferenceException(Res.SchInf_schematype, 0, 0);
  2391. }
  2392. internal void SetMinMaxOccurs(XmlSchemaElement el, bool setMaxOccurs)
  2393. {
  2394. if (this.Occurrence == InferenceOption.Relaxed)
  2395. {
  2396. if (setMaxOccurs || el.MaxOccurs > 1)
  2397. {
  2398. el.MaxOccurs = decimal.MaxValue; //set it to unbounded
  2399. }
  2400. el.MinOccurs = 0;
  2401. }
  2402. else if (el.MinOccurs > 1)
  2403. {
  2404. el.MinOccurs = 1;
  2405. }
  2406. }
  2407. }
  2408. }