PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeRestriction.cs

https://bitbucket.org/danipen/mono
C# | 1031 lines | 798 code | 113 blank | 120 comment | 354 complexity | 1d554481d176f7d851ce4ed3e2a6461a MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. // Author: Dwivedi, Ajay kumar
  2. // Adwiv@Yahoo.com
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining
  5. // a copy of this software and associated documentation files (the
  6. // "Software"), to deal in the Software without restriction, including
  7. // without limitation the rights to use, copy, modify, merge, publish,
  8. // distribute, sublicense, and/or sell copies of the Software, and to
  9. // permit persons to whom the Software is furnished to do so, subject to
  10. // the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be
  13. // included in all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. //
  23. using System;
  24. using System.Collections;
  25. using System.Text;
  26. using System.Text.RegularExpressions;
  27. using System.Xml;
  28. using System.Xml.Serialization;
  29. using Mono.Xml.Schema;
  30. using System.Globalization;
  31. #if NET_2_0
  32. using NSResolver = System.Xml.IXmlNamespaceResolver;
  33. #else
  34. using NSResolver = System.Xml.XmlNamespaceManager;
  35. #endif
  36. namespace System.Xml.Schema
  37. {
  38. /// <summary>
  39. /// Summary description for XmlSchemaSimpleTypeRestriction.
  40. /// </summary>
  41. public class XmlSchemaSimpleTypeRestriction : XmlSchemaSimpleTypeContent
  42. {
  43. private XmlSchemaSimpleType baseType;
  44. private XmlQualifiedName baseTypeName;
  45. private XmlSchemaObjectCollection facets;
  46. const string xmlname = "restriction";
  47. private string [] enumarationFacetValues;
  48. private string [] patternFacetValues;
  49. private Regex [] rexPatterns;
  50. private decimal lengthFacet;
  51. private decimal maxLengthFacet;
  52. private decimal minLengthFacet;
  53. private decimal fractionDigitsFacet;
  54. private decimal totalDigitsFacet;
  55. private object maxInclusiveFacet ;
  56. private object maxExclusiveFacet ;
  57. private object minInclusiveFacet ;
  58. private object minExclusiveFacet ;
  59. private XmlSchemaFacet.Facet fixedFacets = XmlSchemaFacet.Facet.None;
  60. private static NumberStyles lengthStyle = NumberStyles.Integer;
  61. public XmlSchemaSimpleTypeRestriction()
  62. {
  63. baseTypeName = XmlQualifiedName.Empty;
  64. facets = new XmlSchemaObjectCollection();
  65. }
  66. [System.Xml.Serialization.XmlAttribute("base")]
  67. public XmlQualifiedName BaseTypeName
  68. {
  69. get{ return baseTypeName; }
  70. set{ baseTypeName = value; }
  71. }
  72. [XmlElement("simpleType", Type=typeof (XmlSchemaSimpleType))]
  73. public XmlSchemaSimpleType BaseType
  74. {
  75. get{ return baseType; }
  76. set{ baseType = value; }
  77. }
  78. [XmlElement("minExclusive",typeof(XmlSchemaMinExclusiveFacet))]
  79. [XmlElement("minInclusive",typeof(XmlSchemaMinInclusiveFacet))]
  80. [XmlElement("maxExclusive",typeof(XmlSchemaMaxExclusiveFacet))]
  81. [XmlElement("maxInclusive",typeof(XmlSchemaMaxInclusiveFacet))]
  82. [XmlElement("totalDigits",typeof(XmlSchemaTotalDigitsFacet))]
  83. [XmlElement("fractionDigits",typeof(XmlSchemaFractionDigitsFacet))]
  84. [XmlElement("length",typeof(XmlSchemaLengthFacet))]
  85. [XmlElement("minLength",typeof(XmlSchemaMinLengthFacet))]
  86. [XmlElement("maxLength",typeof(XmlSchemaMaxLengthFacet))]
  87. [XmlElement("enumeration",typeof(XmlSchemaEnumerationFacet))]
  88. [XmlElement("whiteSpace",typeof(XmlSchemaWhiteSpaceFacet))]
  89. [XmlElement("pattern",typeof(XmlSchemaPatternFacet))]
  90. public XmlSchemaObjectCollection Facets
  91. {
  92. get{ return facets; }
  93. }
  94. internal override void SetParent (XmlSchemaObject parent)
  95. {
  96. base.SetParent (parent);
  97. if (BaseType != null)
  98. BaseType.SetParent (this);
  99. foreach (XmlSchemaObject obj in Facets)
  100. obj.SetParent (this);
  101. }
  102. /// <remarks>
  103. /// 1. One of base or simpletype must be present but not both
  104. /// 2. id must be a valid ID
  105. /// 3. base must be a valid QName *NO CHECK REQUIRED*
  106. /// </remarks>
  107. internal override int Compile(ValidationEventHandler h, XmlSchema schema)
  108. {
  109. // If this is already compiled this time, simply skip.
  110. if (CompilationId == schema.CompilationId)
  111. return 0;
  112. errorCount = 0;
  113. if(this.baseType != null && !this.BaseTypeName.IsEmpty)
  114. error(h, "both base and simpletype can't be set");
  115. if(this.baseType == null && this.BaseTypeName.IsEmpty)
  116. error(h, "one of basetype or simpletype must be present");
  117. if(this.baseType != null)
  118. {
  119. errorCount += this.baseType.Compile(h,schema);
  120. }
  121. if(!XmlSchemaUtil.CheckQName(BaseTypeName))
  122. error(h,"BaseTypeName must be a XmlQualifiedName");
  123. XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);
  124. for (int i = 0; i < this.Facets.Count; i++)
  125. if (! (Facets [i] is XmlSchemaFacet))
  126. error (h, "Only XmlSchemaFacet objects are allowed for Facets property");
  127. this.CompilationId = schema.CompilationId;
  128. return errorCount;
  129. }
  130. /** Checks if this facet is valid on this restriction. Does not check that it has
  131. * not been fixed in the baseType. That is done elsewhere.
  132. */
  133. private static readonly XmlSchemaFacet.Facet listFacets =
  134. XmlSchemaFacet.Facet.length | XmlSchemaFacet.Facet.minLength |
  135. XmlSchemaFacet.Facet.maxLength | XmlSchemaFacet.Facet.pattern |
  136. XmlSchemaFacet.Facet.enumeration | XmlSchemaFacet.Facet.whiteSpace;
  137. private bool IsAllowedFacet(XmlSchemaFacet xsf) {
  138. /* Must be called after this.ValidateActualType, as it uses actualBaseSchemaType */
  139. XsdAnySimpleType ast = ActualBaseSchemaType as XsdAnySimpleType;
  140. if (ast != null) {
  141. // Based directly on an xsd type
  142. return ast.AllowsFacet(xsf);
  143. }
  144. else {
  145. XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType)ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
  146. if (st != null) {
  147. XmlSchemaSimpleTypeRestriction str = st as XmlSchemaSimpleTypeRestriction;
  148. if (str != null && str != this) {
  149. return str.IsAllowedFacet(xsf);
  150. }
  151. XmlSchemaSimpleTypeList stl = st as XmlSchemaSimpleTypeList;
  152. if (stl != null) {
  153. return ((xsf.ThisFacet & listFacets) != 0);
  154. }
  155. XmlSchemaSimpleTypeUnion stu = st as XmlSchemaSimpleTypeUnion;
  156. if (stu != null) {
  157. return (xsf is XmlSchemaPatternFacet ||
  158. xsf is XmlSchemaEnumerationFacet);
  159. }
  160. }
  161. else {
  162. // TODO: Should this be either a XmlSchemaSimpleType or XmlSchemaDatatype ?
  163. // If so report error
  164. }
  165. }
  166. // Not sure it could ever get here
  167. return false;
  168. }
  169. internal override int Validate(ValidationEventHandler h, XmlSchema schema)
  170. {
  171. if (IsValidated (schema.ValidationId))
  172. return errorCount;
  173. this.ValidateActualType (h, schema);
  174. lengthFacet = maxLengthFacet = minLengthFacet = fractionDigitsFacet = totalDigitsFacet = -1;
  175. XmlSchemaSimpleTypeRestriction baseSTR = null;
  176. if (ActualBaseSchemaType is XmlSchemaSimpleType) {
  177. XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType)ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
  178. baseSTR = st as XmlSchemaSimpleTypeRestriction;
  179. }
  180. if (baseSTR != null) {
  181. fixedFacets = baseSTR.fixedFacets;
  182. lengthFacet = baseSTR.lengthFacet;
  183. maxLengthFacet = baseSTR.maxLengthFacet;
  184. minLengthFacet = baseSTR.minLengthFacet;
  185. fractionDigitsFacet = baseSTR.fractionDigitsFacet;
  186. totalDigitsFacet = baseSTR.totalDigitsFacet;
  187. maxInclusiveFacet = baseSTR.maxInclusiveFacet;
  188. maxExclusiveFacet = baseSTR.maxExclusiveFacet;
  189. minInclusiveFacet = baseSTR.minInclusiveFacet;
  190. minExclusiveFacet = baseSTR.minExclusiveFacet;
  191. }
  192. enumarationFacetValues = patternFacetValues = null;
  193. rexPatterns = null;
  194. XmlSchemaFacet.Facet facetsDefined = XmlSchemaFacet.Facet.None;
  195. ArrayList enums = null;
  196. ArrayList patterns = null;
  197. for (int i = 0; i < facets.Count; i++) {
  198. XmlSchemaFacet facet = facets[i] as XmlSchemaFacet;
  199. if (facet != null) {
  200. if (!IsAllowedFacet(facet)) {
  201. facet.error(h, facet.ThisFacet +" is not a valid facet for this type");
  202. continue;
  203. }
  204. }
  205. else {
  206. // Other than XmlSchemaFacet; already reported at Compile()
  207. continue;
  208. }
  209. XmlSchemaEnumerationFacet ef = facets [i] as XmlSchemaEnumerationFacet;
  210. if (ef != null) {
  211. if (enums == null)
  212. enums = new ArrayList ();
  213. enums.Add (ef.Value);
  214. continue;
  215. }
  216. XmlSchemaPatternFacet pf = facets [i] as XmlSchemaPatternFacet;
  217. if (pf != null) {
  218. if (patterns == null)
  219. patterns = new ArrayList ();
  220. patterns.Add (pf.Value);
  221. continue;
  222. }
  223. // Put this test here, as pattern and enumeration
  224. // can occur multiple times.
  225. if ( (facetsDefined & facet.ThisFacet) !=0) {
  226. facet.error (h, "This is a duplicate '" + facet.ThisFacet + "' facet.");
  227. continue;
  228. }
  229. else {
  230. facetsDefined |= facet.ThisFacet;
  231. }
  232. if (facet is XmlSchemaLengthFacet) {
  233. checkLengthFacet((XmlSchemaLengthFacet)facet, facetsDefined, h);
  234. }
  235. else if (facet is XmlSchemaMaxLengthFacet) {
  236. checkMaxLengthFacet((XmlSchemaMaxLengthFacet)facet, facetsDefined, h);
  237. }
  238. else if (facet is XmlSchemaMinLengthFacet) {
  239. checkMinLengthFacet((XmlSchemaMinLengthFacet)facet, facetsDefined, h);
  240. }
  241. else if (facet is XmlSchemaMinInclusiveFacet) {
  242. checkMinMaxFacet((XmlSchemaMinInclusiveFacet)facet, ref minInclusiveFacet, h);
  243. }
  244. else if (facet is XmlSchemaMaxInclusiveFacet) {
  245. checkMinMaxFacet((XmlSchemaMaxInclusiveFacet)facet, ref maxInclusiveFacet, h);
  246. }
  247. else if (facet is XmlSchemaMinExclusiveFacet) {
  248. checkMinMaxFacet((XmlSchemaMinExclusiveFacet)facet, ref minExclusiveFacet, h);
  249. }
  250. else if (facet is XmlSchemaMaxExclusiveFacet) {
  251. checkMinMaxFacet((XmlSchemaMaxExclusiveFacet)facet, ref maxExclusiveFacet, h);
  252. }
  253. else if (facet is XmlSchemaFractionDigitsFacet) {
  254. checkFractionDigitsFacet((XmlSchemaFractionDigitsFacet)facet, h);
  255. }
  256. else if (facet is XmlSchemaTotalDigitsFacet) {
  257. checkTotalDigitsFacet((XmlSchemaTotalDigitsFacet)facet, h);
  258. }
  259. if (facet.IsFixed) {
  260. fixedFacets |= facet.ThisFacet;
  261. }
  262. }
  263. if (enums != null)
  264. this.enumarationFacetValues = enums.ToArray (typeof (string)) as string [];
  265. if (patterns != null) {
  266. this.patternFacetValues = patterns.ToArray (typeof (string)) as string [];
  267. this.rexPatterns = new Regex [patterns.Count];
  268. for (int i = 0; i < patternFacetValues.Length; i++) {
  269. try {
  270. string src = patternFacetValues [i];
  271. StringBuilder sb = null;
  272. int start = 0;
  273. for (int c = 0; c < src.Length; c++) {
  274. if (src [c] == '\\' && src.Length > i + 1) {
  275. string subst = null;
  276. switch (src [c + 1]) {
  277. case 'i':
  278. subst = "[\\p{L}_]";
  279. break;
  280. case 'I':
  281. subst = "[^\\p{L}_]";
  282. break;
  283. case 'c':
  284. subst = "[\\p{L}\\p{N}_\\.\\-:]";
  285. break;
  286. case 'C':
  287. subst = "[^\\p{L}\\p{N}_\\.\\-:]";
  288. break;
  289. }
  290. if (subst != null) {
  291. if (sb == null)
  292. sb = new StringBuilder ();
  293. sb.Append (src, start, c - start);
  294. sb.Append (subst);
  295. start = c + 2;
  296. }
  297. }
  298. }
  299. if (sb != null) {
  300. sb.Append (src, start, src.Length - start);
  301. src = sb.ToString ();
  302. }
  303. // src = src.Replace ("\\i", "[\\p{L}_]").Replace ("\\I", "[^\\p{L}_]").Replace ("\\c", "[\\p{L}\\p{N}_\\.\\-:]").Replace ("\\C", "[^\\p{L}\\p{N}_\\.\\-:]");
  304. Regex rex = new Regex ("^" + src + "$");
  305. rexPatterns [i] = rex;
  306. } catch (Exception ex) {
  307. error (h, "Invalid regular expression pattern was specified.", ex);
  308. }
  309. }
  310. }
  311. ValidationId = schema.ValidationId;
  312. /*
  313. Console.WriteLine("Facets:\n defined\t{10}\n fixed\t{0}\n length\t{1}\n maxLen\t{2}\n minLen\t{3}\n " +
  314. "frac\t{4}\n tot\t{5}\n maxI\t{6}\n maxE\t{7}\n minI\t{8}\n minE\t{9}\n",
  315. fixedFacets ,
  316. lengthFacet,
  317. maxLengthFacet ,
  318. minLengthFacet ,
  319. fractionDigitsFacet ,
  320. totalDigitsFacet ,
  321. maxInclusiveFacet ,
  322. maxExclusiveFacet ,
  323. minInclusiveFacet ,
  324. minExclusiveFacet ,
  325. facetsDefined);
  326. */
  327. return errorCount;
  328. }
  329. internal void ValidateActualType (ValidationEventHandler h, XmlSchema schema)
  330. {
  331. GetActualType (h, schema, true);
  332. }
  333. internal object GetActualType (ValidationEventHandler h, XmlSchema schema, bool validate)
  334. {
  335. object actualBaseSchemaType = null;
  336. XmlSchemaSimpleType type = baseType;
  337. if (type == null)
  338. type = schema.FindSchemaType (baseTypeName) as XmlSchemaSimpleType;
  339. if (type != null) {
  340. if (validate)
  341. errorCount += type.Validate (h, schema);
  342. actualBaseSchemaType = type;
  343. } else if (baseTypeName == XmlSchemaComplexType.AnyTypeName) {
  344. actualBaseSchemaType = XmlSchemaSimpleType.AnySimpleType;
  345. } else if (baseTypeName.Namespace == XmlSchema.Namespace ||
  346. baseTypeName.Namespace == XmlSchema.XdtNamespace) {
  347. actualBaseSchemaType = XmlSchemaDatatype.FromName (baseTypeName);
  348. if (actualBaseSchemaType == null)
  349. if (validate)
  350. error (h, "Invalid schema type name was specified: " + baseTypeName);
  351. }
  352. // otherwise, it might be missing sub components.
  353. else if (!schema.IsNamespaceAbsent (baseTypeName.Namespace))
  354. if (validate)
  355. error (h, "Referenced base schema type " + baseTypeName + " was not found in the corresponding schema.");
  356. return actualBaseSchemaType;
  357. }
  358. private void checkTotalDigitsFacet (XmlSchemaTotalDigitsFacet totf,
  359. ValidationEventHandler h) {
  360. if (totf != null) {
  361. /* totalDigits is the maximum number of digits in values of datatypes
  362. * derived from decimal. The value of totalDigits must be a
  363. * positiveInteger. */
  364. try {
  365. decimal newTotalDigits = decimal.Parse (totf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
  366. if (newTotalDigits <= 0)
  367. totf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is an invalid totalDigits value", newTotalDigits));
  368. // Valid restriction
  369. if ((totalDigitsFacet > 0) && (newTotalDigits > totalDigitsFacet)) {
  370. totf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a valid restriction of the base totalDigits facet '{1}'", newTotalDigits, totalDigitsFacet));
  371. }
  372. totalDigitsFacet = newTotalDigits;
  373. }
  374. catch (FormatException ) {
  375. totf.error(h, String.Format("The value '{0}' is an invalid totalDigits facet specification", totf.Value.Trim () ));
  376. }
  377. }
  378. }
  379. private void checkFractionDigitsFacet (XmlSchemaFractionDigitsFacet fracf,
  380. ValidationEventHandler h) {
  381. if (fracf != null) {
  382. try {
  383. decimal newFractionDigits = decimal.Parse (fracf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
  384. if (newFractionDigits< 0)
  385. fracf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is an invalid fractionDigits value", newFractionDigits));
  386. if ((fractionDigitsFacet >= 0) && (newFractionDigits > fractionDigitsFacet)) {
  387. fracf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a valid restriction of the base fractionDigits facet '{1}'", newFractionDigits, fractionDigitsFacet));
  388. }
  389. fractionDigitsFacet = newFractionDigits;
  390. }
  391. catch (FormatException ) {
  392. fracf.error(h, String.Format("The value '{0}' is an invalid fractionDigits facet specification", fracf.Value.Trim () ));
  393. }
  394. }
  395. }
  396. private void checkMinMaxFacet(XmlSchemaFacet facet,
  397. ref object baseFacet,
  398. ValidationEventHandler h) {
  399. // Is it a valid instance of the base type.
  400. object newValue = ValidateValueWithDatatype(facet.Value);
  401. if (newValue != null) {
  402. // Is the base fixed - if so is it the same
  403. if (((fixedFacets & facet.ThisFacet) != 0) && (baseFacet != null)){
  404. XsdAnySimpleType dt = getDatatype();
  405. if (dt.Compare (newValue, baseFacet) != XsdOrdering.Equal) {
  406. facet.error (h,
  407. String.Format(CultureInfo.InvariantCulture, "{0} is not the same as fixed parent {1} facet.",
  408. facet.Value, facet.ThisFacet));
  409. }
  410. }
  411. baseFacet = newValue;
  412. }
  413. else {
  414. facet.error(h,
  415. String.Format("The value '{0}' is not valid against the base type.", facet.Value));
  416. }
  417. }
  418. private void checkLengthFacet(XmlSchemaLengthFacet lf,
  419. XmlSchemaFacet.Facet facetsDefined,
  420. ValidationEventHandler h) {
  421. if (lf != null) {
  422. try {
  423. if ((facetsDefined & (XmlSchemaFacet.Facet.minLength | XmlSchemaFacet.Facet.maxLength)) != 0)
  424. lf.error(h, "It is an error for both length and minLength or maxLength to be present.");
  425. else {
  426. lengthFacet = decimal.Parse (lf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
  427. /* TODO: Check that it is between inherited max/min lengths */
  428. if (lengthFacet < 0)
  429. lf.error(h, "The value '" + lengthFacet + "' is an invalid length");
  430. }
  431. } catch (FormatException) { // FIXME: better catch ;-(
  432. lf.error (h, "The value '" + lf.Value + "' is an invalid length facet specification");
  433. }
  434. }
  435. }
  436. private void checkMaxLengthFacet(XmlSchemaMaxLengthFacet maxlf,
  437. XmlSchemaFacet.Facet facetsDefined,
  438. ValidationEventHandler h) {
  439. if (maxlf != null) {
  440. try {
  441. if ((facetsDefined & XmlSchemaFacet.Facet.length) != 0)
  442. maxlf.error(h, "It is an error for both length and minLength or maxLength to be present.");
  443. else {
  444. decimal newMaxLengthFacet = decimal.Parse (maxlf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
  445. if (((fixedFacets & XmlSchemaFacet.Facet.maxLength)!=0) && (newMaxLengthFacet != maxLengthFacet))
  446. maxlf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not the same as the fixed value '{1}' on the base type", maxlf.Value.Trim (), maxLengthFacet));
  447. if ((maxLengthFacet >0) && (newMaxLengthFacet > maxLengthFacet))
  448. maxlf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a valid restriction of the value '{1}' on the base maxLength facet", maxlf.Value.Trim (), maxLengthFacet));
  449. else
  450. maxLengthFacet = newMaxLengthFacet;
  451. if (maxLengthFacet < 0)
  452. maxlf.error(h, "The value '" + maxLengthFacet + "' is an invalid maxLength");
  453. if (minLengthFacet >=0 && minLengthFacet > maxLengthFacet)
  454. maxlf.error(h, "minLength is greater than maxLength.");
  455. }
  456. } catch (FormatException) {
  457. maxlf.error (h, "The value '" + maxlf.Value+ "' is an invalid maxLength facet specification");
  458. }
  459. }
  460. }
  461. private void checkMinLengthFacet(XmlSchemaMinLengthFacet minlf,
  462. XmlSchemaFacet.Facet facetsDefined,
  463. ValidationEventHandler h) {
  464. if (minlf != null) {
  465. try {
  466. if (lengthFacet >=0)
  467. minlf.error(h, "It is an error for both length and minLength or maxLength to be present.");
  468. else {
  469. decimal newMinLengthFacet = decimal.Parse (minlf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
  470. if (((fixedFacets & XmlSchemaFacet.Facet.minLength)!=0) && (newMinLengthFacet != minLengthFacet))
  471. minlf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not the same as the fixed value '{1}' on the base type", minlf.Value.Trim (), minLengthFacet));
  472. if (newMinLengthFacet < minLengthFacet)
  473. minlf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a valid restriction of the value '{1}' on the base minLength facet", minlf.Value.Trim (), minLengthFacet));
  474. else
  475. minLengthFacet = newMinLengthFacet;
  476. if (minLengthFacet < 0)
  477. minlf.error(h, "The value '" + minLengthFacet + "' is an invalid minLength");
  478. if (maxLengthFacet >=0 && minLengthFacet > maxLengthFacet)
  479. minlf.error(h, "minLength is greater than maxLength.");
  480. }
  481. } catch (FormatException) {
  482. minlf.error (h, "The value '" + minlf.Value + "' is an invalid minLength facet specification");
  483. }
  484. }
  485. }
  486. private XsdAnySimpleType getDatatype() {
  487. XsdAnySimpleType ast = ActualBaseSchemaType as XsdAnySimpleType;
  488. if (ast != null) {
  489. // Based directly on an xsd type
  490. return ast;
  491. }
  492. XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType)ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
  493. if (st is XmlSchemaSimpleTypeRestriction) {
  494. return ((XmlSchemaSimpleTypeRestriction)st).getDatatype();
  495. }
  496. else if ((st is XmlSchemaSimpleTypeList) ||
  497. (st is XmlSchemaSimpleTypeUnion)) {
  498. return null;
  499. }
  500. return null;
  501. }
  502. private object ValidateValueWithDatatype(string value) {
  503. XsdAnySimpleType dt = getDatatype();
  504. object ret = null;
  505. // Console.WriteLine("DT: " + dt);
  506. if (dt != null) {
  507. try {
  508. /* I think we can parse null here, as the types
  509. * that use the nametable and nsmgr are ones that
  510. * we don't need to parse here.
  511. */
  512. ret = dt.ParseValue (value, null, null);
  513. // Console.WriteLine("Ret: " + ret);
  514. // If we are based on something with facets, check that we are valid
  515. if (ActualBaseSchemaType is XmlSchemaSimpleType) {
  516. XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType) ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
  517. if (st is XmlSchemaSimpleTypeRestriction) {
  518. if (((XmlSchemaSimpleTypeRestriction)st).ValidateValueWithFacets(value, null, null)) {
  519. return ret;
  520. } else {
  521. return null;
  522. }
  523. }
  524. }
  525. } catch (Exception) {
  526. return null;
  527. }
  528. }
  529. return ret;
  530. }
  531. internal bool ValidateValueWithFacets (string value, XmlNameTable nt, NSResolver nsmgr)
  532. {
  533. /*
  534. * FIXME: Shouldn't this be recursing more? What if this is a
  535. * restriction of a restriction of a list type?
  536. */
  537. XmlSchemaSimpleType baseST = this.ActualBaseSchemaType as XmlSchemaSimpleType;
  538. XmlSchemaSimpleTypeList listType = baseST != null ? baseST.Content as XmlSchemaSimpleTypeList : null;
  539. // numeric
  540. if (listType != null)
  541. return ValidateListValueWithFacets (value, nt, nsmgr);
  542. else
  543. return ValidateNonListValueWithFacets (value, nt, nsmgr);
  544. }
  545. private bool ValidateListValueWithFacets (string value, XmlNameTable nt, NSResolver nsmgr)
  546. {
  547. try {
  548. return ValidateListValueWithFacetsCore (value, nt, nsmgr);
  549. } catch (Exception) { // this is for datatype ParseValue()
  550. return false;
  551. }
  552. }
  553. private bool ValidateListValueWithFacetsCore (string value, XmlNameTable nt, NSResolver nsmgr)
  554. {
  555. string [] list = ((XsdAnySimpleType) XmlSchemaDatatype.FromName ("anySimpleType", XmlSchema.Namespace)).ParseListValue (value, nt);
  556. // pattern
  557. if (this.patternFacetValues != null) {
  558. for (int l = 0; l < list.Length; l++) {
  559. for (int i = 0; i < this.patternFacetValues.Length; i++)
  560. if (rexPatterns [i] != null && !rexPatterns [i].IsMatch (list [l]))
  561. return false;
  562. }
  563. }
  564. bool enumMatched = false;
  565. #if true
  566. // enumeration - lexical space comparison
  567. //
  568. // I'm not sure if allowing literally-equivalent values
  569. // without parsing (because it will cause trouble when
  570. // you try to get TypedValue anyways), but at least it
  571. // avoids extraneous validation errors ...
  572. if (this.enumarationFacetValues != null) {
  573. for (int l = 0; l < list.Length; l++) {
  574. for (int i = 0; i < this.enumarationFacetValues.Length; i++) {
  575. if (list [l] == this.enumarationFacetValues [i]) {
  576. enumMatched = true;
  577. break;
  578. }
  579. }
  580. }
  581. }
  582. #endif
  583. // enumeration - value space comparison
  584. if (!enumMatched && this.enumarationFacetValues != null) {
  585. for (int l = 0; l < list.Length; l++) {
  586. XsdAnySimpleType dt = getDatatype ();
  587. if (dt == null)
  588. dt = (XsdAnySimpleType) XmlSchemaDatatype.FromName ("anySimpleType", XmlSchema.Namespace);
  589. object v = dt.ParseValue (list [l], nt, nsmgr);
  590. for (int i = 0; i < this.enumarationFacetValues.Length; i++) {
  591. if (XmlSchemaUtil.AreSchemaDatatypeEqual (dt, v, dt, dt.ParseValue (this.enumarationFacetValues [i], nt, nsmgr))) {
  592. enumMatched = true;
  593. break;
  594. }
  595. }
  596. if (!enumMatched)
  597. return false;
  598. }
  599. }
  600. // numeric
  601. // : length
  602. if (lengthFacet >= 0 && list.Length != lengthFacet)
  603. return false;
  604. // : maxLength
  605. if (maxLengthFacet >= 0 && list.Length > maxLengthFacet)
  606. return false;
  607. // : minLength
  608. if (minLengthFacet >= 0 && list.Length < minLengthFacet)
  609. return false;
  610. return true;
  611. }
  612. private bool ValidateNonListValueWithFacets (string value, XmlNameTable nt, NSResolver nsmgr)
  613. {
  614. try {
  615. return ValidateNonListValueWithFacetsCore (value, nt, nsmgr);
  616. } catch (Exception) { // this is for datatype ParseValue()
  617. return false;
  618. }
  619. }
  620. private bool ValidateNonListValueWithFacetsCore (string value, XmlNameTable nt, NSResolver nsmgr)
  621. {
  622. // pattern
  623. // Patterns are the only facets that need to be checked on this
  624. // type and its base types. We should probably separate them, then
  625. // do base-type pattern validation.
  626. if (this.patternFacetValues != null) {
  627. bool matched = false;
  628. for (int i = 0; i < this.patternFacetValues.Length; i++)
  629. if (rexPatterns [i] != null && rexPatterns [i].IsMatch (value)) {
  630. matched = true;
  631. break;
  632. }
  633. if (!matched)
  634. return false;
  635. }
  636. XsdAnySimpleType dt = getDatatype ();
  637. bool enumMatched = false;
  638. #if true
  639. // enumeration - lexical space comparison
  640. //
  641. // I'm not sure if allowing literally-equivalent values
  642. // without parsing (because it will cause trouble when
  643. // you try to get TypedValue anyways), but at least it
  644. // avoids extraneous validation errors ...
  645. if (this.enumarationFacetValues != null) {
  646. for (int i = 0; i < this.enumarationFacetValues.Length; i++) {
  647. if (value == this.enumarationFacetValues [i]) {
  648. enumMatched = true;
  649. break;
  650. }
  651. }
  652. }
  653. #endif
  654. // enumeration - value space comparison
  655. if (!enumMatched && this.enumarationFacetValues != null) {
  656. XsdAnySimpleType edt = dt;
  657. if (edt == null)
  658. edt = (XsdAnySimpleType) XmlSchemaDatatype.FromName ("anySimpleType", XmlSchema.Namespace);
  659. object v = edt.ParseValue (value, nt, nsmgr);
  660. for (int i = 0; i < this.enumarationFacetValues.Length; i++) {
  661. if (XmlSchemaUtil.AreSchemaDatatypeEqual (edt, v, edt, edt.ParseValue (this.enumarationFacetValues [i], nt, nsmgr))) {
  662. enumMatched = true;
  663. break;
  664. }
  665. }
  666. if (!enumMatched)
  667. return false;
  668. }
  669. // Need to skip length tests for
  670. // types derived from QName or NOTATION
  671. // see errata: E2-36 Clarification
  672. if (! ( (dt is XsdQName) || (dt is XsdNotation))) {
  673. // Length potentially slower now, so only calculate if needed
  674. if (! ((lengthFacet == -1) && (maxLengthFacet == -1) && (minLengthFacet == -1))) {
  675. // numeric
  676. // : length
  677. int length = dt.Length(value);
  678. if (lengthFacet >= 0 && length != lengthFacet)
  679. return false;
  680. // : maxLength
  681. if (maxLengthFacet >= 0 && length > maxLengthFacet)
  682. return false;
  683. // : minLength
  684. if (minLengthFacet >= 0 && length < minLengthFacet)
  685. return false;
  686. }
  687. }
  688. if ((totalDigitsFacet >=0) || (fractionDigitsFacet >=0)) {
  689. String newValue = value.Trim(new Char [] { '+', '-', '0', '.' });
  690. int fractionDigits = 0;
  691. int totalDigits = newValue.Length;
  692. int point = newValue.IndexOf(".");
  693. if (point != -1) {
  694. totalDigits -= 1;
  695. fractionDigits = newValue.Length - point -1;
  696. }
  697. if ((totalDigitsFacet >=0) && (totalDigits > totalDigitsFacet))
  698. return false;
  699. if ((fractionDigitsFacet >=0) && (fractionDigits > fractionDigitsFacet))
  700. return false;
  701. }
  702. if ((maxInclusiveFacet != null) ||
  703. (maxExclusiveFacet != null) ||
  704. (minInclusiveFacet != null) ||
  705. (minExclusiveFacet != null)) {
  706. if (dt != null) {
  707. object parsed;
  708. try {
  709. parsed = dt.ParseValue (value, nt, null);
  710. } catch (OverflowException ) {
  711. /* This appears to be what .NET does */
  712. return false ;
  713. } catch (FormatException ) {
  714. /* This appears to be what .NET does */
  715. return false ;
  716. }
  717. if (maxInclusiveFacet != null) {
  718. XsdOrdering result = dt.Compare (parsed, maxInclusiveFacet);
  719. if ((result != XsdOrdering.LessThan) &&
  720. (result != XsdOrdering.Equal))
  721. return false;
  722. }
  723. if (maxExclusiveFacet != null) {
  724. XsdOrdering result = dt.Compare (parsed, maxExclusiveFacet);
  725. if (result != XsdOrdering.LessThan)
  726. return false;
  727. }
  728. if (minInclusiveFacet != null) {
  729. XsdOrdering result = dt.Compare (parsed, minInclusiveFacet);
  730. if ((result != XsdOrdering.GreaterThan) &&
  731. (result != XsdOrdering.Equal))
  732. return false;
  733. }
  734. if (minExclusiveFacet != null) {
  735. XsdOrdering result = dt.Compare (parsed, minExclusiveFacet);
  736. if (result != XsdOrdering.GreaterThan)
  737. return false;
  738. }
  739. }
  740. }
  741. // all passed
  742. return true;
  743. }
  744. //<restriction
  745. // base = QName
  746. // id = ID
  747. // {any attributes with non-schema namespace . . .}>
  748. // Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))
  749. //</restriction>
  750. internal static XmlSchemaSimpleTypeRestriction Read(XmlSchemaReader reader, ValidationEventHandler h)
  751. {
  752. XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
  753. reader.MoveToElement();
  754. if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
  755. {
  756. error(h,"Should not happen :1: XmlSchemaSimpleTypeRestriction.Read, name="+reader.Name,null);
  757. reader.Skip();
  758. return null;
  759. }
  760. restriction.LineNumber = reader.LineNumber;
  761. restriction.LinePosition = reader.LinePosition;
  762. restriction.SourceUri = reader.BaseURI;
  763. while(reader.MoveToNextAttribute())
  764. {
  765. if(reader.Name == "id")
  766. {
  767. restriction.Id = reader.Value;
  768. }
  769. else if(reader.Name == "base")
  770. {
  771. Exception innerex;
  772. restriction.baseTypeName = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex);
  773. if(innerex != null)
  774. error(h, reader.Value + " is not a valid value for base attribute",innerex);
  775. }
  776. else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
  777. {
  778. error(h,reader.Name + " is not a valid attribute for restriction",null);
  779. }
  780. else
  781. {
  782. XmlSchemaUtil.ReadUnhandledAttribute(reader,restriction);
  783. }
  784. }
  785. reader.MoveToElement();
  786. if(reader.IsEmptyElement)
  787. return restriction;
  788. // Content: annotation?, simpleType?, (minExclusive |. .. | pattern)*
  789. int level = 1;
  790. while(reader.ReadNextElement())
  791. {
  792. if(reader.NodeType == XmlNodeType.EndElement)
  793. {
  794. if(reader.LocalName != xmlname)
  795. error(h,"Should not happen :2: XmlSchemaSimpleTypeRestriction.Read, name="+reader.Name,null);
  796. break;
  797. }
  798. if(level <= 1 && reader.LocalName == "annotation")
  799. {
  800. level = 2; //Only one annotation
  801. XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
  802. if(annotation != null)
  803. restriction.Annotation = annotation;
  804. continue;
  805. }
  806. if(level <= 2 && reader.LocalName == "simpleType")
  807. {
  808. level = 3;
  809. XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);
  810. if(stype != null)
  811. restriction.baseType = stype;
  812. continue;
  813. }
  814. if(level <= 3)
  815. {
  816. if(reader.LocalName == "minExclusive")
  817. {
  818. level = 3;
  819. XmlSchemaMinExclusiveFacet minex = XmlSchemaMinExclusiveFacet.Read(reader,h);
  820. if(minex != null)
  821. restriction.facets.Add(minex);
  822. continue;
  823. }
  824. else if(reader.LocalName == "minInclusive")
  825. {
  826. level = 3;
  827. XmlSchemaMinInclusiveFacet mini = XmlSchemaMinInclusiveFacet.Read(reader,h);
  828. if(mini != null)
  829. restriction.facets.Add(mini);
  830. continue;
  831. }
  832. else if(reader.LocalName == "maxExclusive")
  833. {
  834. level = 3;
  835. XmlSchemaMaxExclusiveFacet maxex = XmlSchemaMaxExclusiveFacet.Read(reader,h);
  836. if(maxex != null)
  837. restriction.facets.Add(maxex);
  838. continue;
  839. }
  840. else if(reader.LocalName == "maxInclusive")
  841. {
  842. level = 3;
  843. XmlSchemaMaxInclusiveFacet maxi = XmlSchemaMaxInclusiveFacet.Read(reader,h);
  844. if(maxi != null)
  845. restriction.facets.Add(maxi);
  846. continue;
  847. }
  848. else if(reader.LocalName == "totalDigits")
  849. {
  850. level = 3;
  851. XmlSchemaTotalDigitsFacet total = XmlSchemaTotalDigitsFacet.Read(reader,h);
  852. if(total != null)
  853. restriction.facets.Add(total);
  854. continue;
  855. }
  856. else if(reader.LocalName == "fractionDigits")
  857. {
  858. level = 3;
  859. XmlSchemaFractionDigitsFacet fraction = XmlSchemaFractionDigitsFacet.Read(reader,h);
  860. if(fraction != null)
  861. restriction.facets.Add(fraction);
  862. continue;
  863. }
  864. else if(reader.LocalName == "length")
  865. {
  866. level = 3;
  867. XmlSchemaLengthFacet length = XmlSchemaLengthFacet.Read(reader,h);
  868. if(length != null)
  869. restriction.facets.Add(length);
  870. continue;
  871. }
  872. else if(reader.LocalName == "minLength")
  873. {
  874. level = 3;
  875. XmlSchemaMinLengthFacet minlen = XmlSchemaMinLengthFacet.Read(reader,h);
  876. if(minlen != null)
  877. restriction.facets.Add(minlen);
  878. continue;
  879. }
  880. else if(reader.LocalName == "maxLength")
  881. {
  882. level = 3;
  883. XmlSchemaMaxLengthFacet maxlen = XmlSchemaMaxLengthFacet.Read(reader,h);
  884. if(maxlen != null)
  885. restriction.facets.Add(maxlen);
  886. continue;
  887. }
  888. else if(reader.LocalName == "enumeration")
  889. {
  890. level = 3;
  891. XmlSchemaEnumerationFacet enumeration = XmlSchemaEnumerationFacet.Read(reader,h);
  892. if(enumeration != null)
  893. restriction.facets.Add(enumeration);
  894. continue;
  895. }
  896. else if(reader.LocalName == "whiteSpace")
  897. {
  898. level = 3;
  899. XmlSchemaWhiteSpaceFacet ws = XmlSchemaWhiteSpaceFacet.Read(reader,h);
  900. if(ws != null)
  901. restriction.facets.Add(ws);
  902. continue;
  903. }
  904. else if(reader.LocalName == "pattern")
  905. {
  906. level = 3;
  907. XmlSchemaPatternFacet pattern = XmlSchemaPatternFacet.Read(reader,h);
  908. if(pattern != null)
  909. restriction.facets.Add(pattern);
  910. continue;
  911. }
  912. }
  913. reader.RaiseInvalidElementError();
  914. }
  915. return restriction;
  916. }
  917. }
  918. }