1 // Author: Dwivedi, Ajay kumar
\r
5 // Permission is hereby granted, free of charge, to any person obtaining
\r
6 // a copy of this software and associated documentation files (the
\r
7 // "Software"), to deal in the Software without restriction, including
\r
8 // without limitation the rights to use, copy, modify, merge, publish,
\r
9 // distribute, sublicense, and/or sell copies of the Software, and to
\r
10 // permit persons to whom the Software is furnished to do so, subject to
\r
11 // the following conditions:
\r
13 // The above copyright notice and this permission notice shall be
\r
14 // included in all copies or substantial portions of the Software.
\r
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
25 using System.Collections;
\r
27 using System.Text.RegularExpressions;
\r
29 using System.Xml.Serialization;
\r
30 using Mono.Xml.Schema;
\r
31 using System.Globalization;
\r
33 namespace System.Xml.Schema
\r
36 /// Summary description for XmlSchemaSimpleTypeRestriction.
\r
38 public class XmlSchemaSimpleTypeRestriction : XmlSchemaSimpleTypeContent
\r
40 private XmlSchemaSimpleType baseType;
\r
41 private XmlQualifiedName baseTypeName;
\r
42 private XmlSchemaObjectCollection facets;
\r
43 const string xmlname = "restriction";
\r
44 private string [] enumarationFacetValues;
\r
45 private string [] patternFacetValues;
\r
46 private Regex [] rexPatterns;
\r
47 private decimal lengthFacet;
\r
48 private decimal maxLengthFacet;
\r
49 private decimal minLengthFacet;
\r
50 private decimal fractionDigitsFacet;
\r
51 private decimal totalDigitsFacet;
\r
52 private object maxInclusiveFacet ;
\r
53 private object maxExclusiveFacet ;
\r
54 private object minInclusiveFacet ;
\r
55 private object minExclusiveFacet ;
\r
56 private XmlSchemaFacet.Facet fixedFacets = XmlSchemaFacet.Facet.None;
\r
57 private static NumberStyles lengthStyle = NumberStyles.Integer;
\r
60 public XmlSchemaSimpleTypeRestriction()
\r
62 baseTypeName = XmlQualifiedName.Empty;
\r
63 facets = new XmlSchemaObjectCollection();
\r
66 [System.Xml.Serialization.XmlAttribute("base")]
\r
67 public XmlQualifiedName BaseTypeName
\r
69 get{ return baseTypeName; }
\r
70 set{ baseTypeName = value; }
\r
73 [XmlElement("simpleType", Type=typeof (XmlSchemaSimpleType))]
\r
74 public XmlSchemaSimpleType BaseType
\r
76 get{ return baseType; }
\r
77 set{ baseType = value; }
\r
80 [XmlElement("minExclusive",typeof(XmlSchemaMinExclusiveFacet))]
\r
81 [XmlElement("minInclusive",typeof(XmlSchemaMinInclusiveFacet))]
\r
82 [XmlElement("maxExclusive",typeof(XmlSchemaMaxExclusiveFacet))]
\r
83 [XmlElement("maxInclusive",typeof(XmlSchemaMaxInclusiveFacet))]
\r
84 [XmlElement("totalDigits",typeof(XmlSchemaTotalDigitsFacet))]
\r
85 [XmlElement("fractionDigits",typeof(XmlSchemaFractionDigitsFacet))]
\r
86 [XmlElement("length",typeof(XmlSchemaLengthFacet))]
\r
87 [XmlElement("minLength",typeof(XmlSchemaMinLengthFacet))]
\r
88 [XmlElement("maxLength",typeof(XmlSchemaMaxLengthFacet))]
\r
89 [XmlElement("enumeration",typeof(XmlSchemaEnumerationFacet))]
\r
90 [XmlElement("whiteSpace",typeof(XmlSchemaWhiteSpaceFacet))]
\r
91 [XmlElement("pattern",typeof(XmlSchemaPatternFacet))]
\r
92 public XmlSchemaObjectCollection Facets
\r
94 get{ return facets; }
\r
98 /// 1. One of base or simpletype must be present but not both
\r
99 /// 2. id must be a valid ID
\r
100 /// 3. base must be a valid QName *NO CHECK REQUIRED*
\r
102 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
\r
104 // If this is already compiled this time, simply skip.
\r
105 if (this.IsComplied (schema.CompilationId))
\r
109 if (BaseType != null)
\r
110 BaseType.Parent = this;
\r
111 foreach (XmlSchemaObject obj in Facets)
\r
117 if(this.baseType != null && !this.BaseTypeName.IsEmpty)
\r
118 error(h, "both base and simpletype can't be set");
\r
119 if(this.baseType == null && this.BaseTypeName.IsEmpty)
\r
120 error(h, "one of basetype or simpletype must be present");
\r
121 if(this.baseType != null)
\r
123 errorCount += this.baseType.Compile(h,schema);
\r
125 if(!XmlSchemaUtil.CheckQName(BaseTypeName))
\r
126 error(h,"BaseTypeName must be a XmlQualifiedName");
\r
128 XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);
\r
130 for (int i = 0; i < this.Facets.Count; i++)
\r
131 if (! (Facets [i] is XmlSchemaFacet))
\r
132 error (h, "Only XmlSchemaFacet objects are allowed for Facets property");
\r
133 this.CompilationId = schema.CompilationId;
\r
137 /** Checks if this facet is valid on this restriction. Does not check that it has
\r
138 * not been fixed in the baseType. That is done elsewhere.
\r
141 private static readonly XmlSchemaFacet.Facet listFacets =
\r
142 XmlSchemaFacet.Facet.length | XmlSchemaFacet.Facet.minLength |
\r
143 XmlSchemaFacet.Facet.maxLength | XmlSchemaFacet.Facet.pattern |
\r
144 XmlSchemaFacet.Facet.enumeration | XmlSchemaFacet.Facet.whiteSpace;
\r
147 private bool IsAllowedFacet(XmlSchemaFacet xsf) {
\r
148 /* Must be called after this.ValidateActualType, as it uses actualBaseSchemaType */
\r
150 XsdAnySimpleType ast = ActualBaseSchemaType as XsdAnySimpleType;
\r
152 // Based directly on an xsd type
\r
153 return ast.AllowsFacet(xsf);
\r
156 XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType)ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
\r
158 XmlSchemaSimpleTypeRestriction str = st as XmlSchemaSimpleTypeRestriction;
\r
159 if (str != null && str != this) {
\r
160 return str.IsAllowedFacet(xsf);
\r
162 XmlSchemaSimpleTypeList stl = st as XmlSchemaSimpleTypeList;
\r
164 return ((xsf.ThisFacet & listFacets) != 0);
\r
167 XmlSchemaSimpleTypeUnion stu = st as XmlSchemaSimpleTypeUnion;
\r
169 return (xsf is XmlSchemaPatternFacet ||
\r
170 xsf is XmlSchemaEnumerationFacet);
\r
175 // TODO: Should this be either a XmlSchemaSimpleType or XmlSchemaDatatype ?
\r
176 // If so report error
\r
179 // Not sure it could ever get here
\r
185 internal override int Validate(ValidationEventHandler h, XmlSchema schema)
\r
188 if (IsValidated (schema.ValidationId))
\r
191 this.ValidateActualType (h, schema);
\r
194 lengthFacet = maxLengthFacet = minLengthFacet = fractionDigitsFacet = totalDigitsFacet = -1;
\r
196 XmlSchemaSimpleTypeRestriction baseSTR = null;
\r
198 if (ActualBaseSchemaType is XmlSchemaSimpleType) {
\r
199 XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType)ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
\r
200 baseSTR = st as XmlSchemaSimpleTypeRestriction;
\r
204 if (baseSTR != null) {
\r
205 fixedFacets = baseSTR.fixedFacets;
\r
206 lengthFacet = baseSTR.lengthFacet;
\r
207 maxLengthFacet = baseSTR.maxLengthFacet;
\r
208 minLengthFacet = baseSTR.minLengthFacet;
\r
209 fractionDigitsFacet = baseSTR.fractionDigitsFacet;
\r
210 totalDigitsFacet = baseSTR.totalDigitsFacet;
\r
211 maxInclusiveFacet = baseSTR.maxInclusiveFacet;
\r
212 maxExclusiveFacet = baseSTR.maxExclusiveFacet;
\r
213 minInclusiveFacet = baseSTR.minInclusiveFacet;
\r
214 minExclusiveFacet = baseSTR.minExclusiveFacet;
\r
217 enumarationFacetValues = patternFacetValues = null;
\r
218 rexPatterns = null;
\r
220 XmlSchemaFacet.Facet facetsDefined = XmlSchemaFacet.Facet.None;
\r
222 ArrayList enums = null;
\r
223 ArrayList patterns = null;
\r
224 for (int i = 0; i < facets.Count; i++) {
\r
226 XmlSchemaFacet facet = facets[i] as XmlSchemaFacet;
\r
227 if (facet != null) {
\r
228 if (!IsAllowedFacet(facet)) {
\r
229 facet.error(h, facet.ThisFacet +" is not a valid facet for this type");
\r
234 // Other than XmlSchemaFacet; already reported at Compile()
\r
239 XmlSchemaEnumerationFacet ef = facets [i] as XmlSchemaEnumerationFacet;
\r
242 enums = new ArrayList ();
\r
243 enums.Add (ef.Value);
\r
246 XmlSchemaPatternFacet pf = facets [i] as XmlSchemaPatternFacet;
\r
248 if (patterns == null)
\r
249 patterns = new ArrayList ();
\r
250 patterns.Add (pf.Value);
\r
254 // Put this test here, as pattern and enumeration
\r
255 // can occur multiple times.
\r
256 if ( (facetsDefined & facet.ThisFacet) !=0) {
\r
257 facet.error (h, "This is a duplicate '" + facet.ThisFacet + "' facet.");
\r
261 facetsDefined |= facet.ThisFacet;
\r
268 if (facet is XmlSchemaLengthFacet) {
\r
269 checkLengthFacet((XmlSchemaLengthFacet)facet, facetsDefined, h);
\r
271 else if (facet is XmlSchemaMaxLengthFacet) {
\r
272 checkMaxLengthFacet((XmlSchemaMaxLengthFacet)facet, facetsDefined, h);
\r
274 else if (facet is XmlSchemaMinLengthFacet) {
\r
275 checkMinLengthFacet((XmlSchemaMinLengthFacet)facet, facetsDefined, h);
\r
278 else if (facet is XmlSchemaMinInclusiveFacet) {
\r
279 checkMinMaxFacet((XmlSchemaMinInclusiveFacet)facet, ref minInclusiveFacet, h);
\r
281 else if (facet is XmlSchemaMaxInclusiveFacet) {
\r
282 checkMinMaxFacet((XmlSchemaMaxInclusiveFacet)facet, ref maxInclusiveFacet, h);
\r
284 else if (facet is XmlSchemaMinExclusiveFacet) {
\r
285 checkMinMaxFacet((XmlSchemaMinExclusiveFacet)facet, ref minExclusiveFacet, h);
\r
287 else if (facet is XmlSchemaMaxExclusiveFacet) {
\r
288 checkMinMaxFacet((XmlSchemaMaxExclusiveFacet)facet, ref maxExclusiveFacet, h);
\r
290 else if (facet is XmlSchemaFractionDigitsFacet) {
\r
291 checkFractionDigitsFacet((XmlSchemaFractionDigitsFacet)facet, h);
\r
293 else if (facet is XmlSchemaTotalDigitsFacet) {
\r
294 checkTotalDigitsFacet((XmlSchemaTotalDigitsFacet)facet, h);
\r
297 if (facet.IsFixed) {
\r
298 fixedFacets |= facet.ThisFacet;
\r
304 this.enumarationFacetValues = enums.ToArray (typeof (string)) as string [];
\r
305 if (patterns != null) {
\r
306 this.patternFacetValues = patterns.ToArray (typeof (string)) as string [];
\r
307 this.rexPatterns = new Regex [patterns.Count];
\r
308 for (int i = 0; i < patternFacetValues.Length; i++) {
\r
310 string src = patternFacetValues [i];
\r
311 StringBuilder sb = null;
\r
313 for (int c = 0; c < src.Length; c++) {
\r
314 if (src [c] == '\\' && src.Length > i + 1) {
\r
315 string subst = null;
\r
316 switch (src [c + 1]) {
\r
318 subst = "[\\p{L}_]";
\r
321 subst = "[^\\p{L}_]";
\r
324 subst = "[\\p{L}\\p{N}_\\.\\-:]";
\r
327 subst = "[^\\p{L}\\p{N}_\\.\\-:]";
\r
330 if (subst != null) {
\r
332 sb = new StringBuilder ();
\r
333 sb.Append (src, start, c - start);
\r
340 sb.Append (src, start, src.Length - start);
\r
341 src = sb.ToString ();
\r
343 // src = src.Replace ("\\i", "[\\p{L}_]").Replace ("\\I", "[^\\p{L}_]").Replace ("\\c", "[\\p{L}\\p{N}_\\.\\-:]").Replace ("\\C", "[^\\p{L}\\p{N}_\\.\\-:]");
\r
344 Regex rex = new Regex ("^" + src + "$");
\r
345 rexPatterns [i] = rex;
\r
346 } catch (Exception ex) {
\r
347 error (h, "Invalid regular expression pattern was specified.", ex);
\r
355 ValidationId = schema.ValidationId;
\r
357 Console.WriteLine("Facets:\n defined\t{10}\n fixed\t{0}\n length\t{1}\n maxLen\t{2}\n minLen\t{3}\n " +
\r
358 "frac\t{4}\n tot\t{5}\n maxI\t{6}\n maxE\t{7}\n minI\t{8}\n minE\t{9}\n",
\r
363 fractionDigitsFacet ,
\r
365 maxInclusiveFacet ,
\r
366 maxExclusiveFacet ,
\r
367 minInclusiveFacet ,
\r
368 minExclusiveFacet ,
\r
375 internal void ValidateActualType (ValidationEventHandler h, XmlSchema schema)
\r
377 GetActualType (h, schema, true);
\r
380 internal object GetActualType (ValidationEventHandler h, XmlSchema schema, bool validate)
\r
382 object actualBaseSchemaType = null;
\r
384 XmlSchemaSimpleType type = baseType;
\r
386 type = schema.SchemaTypes [baseTypeName] as XmlSchemaSimpleType;
\r
387 if (type != null) {
\r
389 errorCount += type.Validate (h, schema);
\r
390 actualBaseSchemaType = type;
\r
391 } else if (baseTypeName == XmlSchemaComplexType.AnyTypeName) {
\r
392 actualBaseSchemaType = XmlSchemaSimpleType.AnySimpleType;
\r
393 } else if (baseTypeName.Namespace == XmlSchema.Namespace ||
\r
394 baseTypeName.Namespace == XmlSchema.XdtNamespace) {
\r
395 actualBaseSchemaType = XmlSchemaDatatype.FromName (baseTypeName);
\r
396 if (actualBaseSchemaType == null)
\r
398 error (h, "Invalid schema type name was specified: " + baseTypeName);
\r
400 // otherwise, it might be missing sub components.
\r
401 else if (!schema.IsNamespaceAbsent (baseTypeName.Namespace))
\r
403 error (h, "Referenced base schema type " + baseTypeName + " was not found in the corresponding schema.");
\r
405 return actualBaseSchemaType;
\r
409 private void checkTotalDigitsFacet (XmlSchemaTotalDigitsFacet totf,
\r
410 ValidationEventHandler h) {
\r
411 if (totf != null) {
\r
412 /* totalDigits is the maximum number of digits in values of datatypes
\r
413 * derived from decimal. The value of totalDigits must be a
\r
414 * positiveInteger. */
\r
416 decimal newTotalDigits = decimal.Parse (totf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
\r
417 if (newTotalDigits <= 0)
\r
418 totf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is an invalid totalDigits value", newTotalDigits));
\r
419 // Valid restriction
\r
420 if ((totalDigitsFacet > 0) && (newTotalDigits > totalDigitsFacet)) {
\r
421 totf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a valid restriction of the base totalDigits facet '{1}'", newTotalDigits, totalDigitsFacet));
\r
423 totalDigitsFacet = newTotalDigits;
\r
425 catch (FormatException ) {
\r
426 totf.error(h, String.Format("The value '{0}' is an invalid totalDigits facet specification", totf.Value.Trim () ));
\r
432 private void checkFractionDigitsFacet (XmlSchemaFractionDigitsFacet fracf,
\r
433 ValidationEventHandler h) {
\r
435 if (fracf != null) {
\r
437 decimal newFractionDigits = decimal.Parse (fracf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
\r
438 if (newFractionDigits< 0)
\r
439 fracf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is an invalid fractionDigits value", newFractionDigits));
\r
441 if ((fractionDigitsFacet >= 0) && (newFractionDigits > fractionDigitsFacet)) {
\r
442 fracf.error(h, String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a valid restriction of the base fractionDigits facet '{1}'", newFractionDigits, fractionDigitsFacet));
\r
444 fractionDigitsFacet = newFractionDigits;
\r
446 catch (FormatException ) {
\r
447 fracf.error(h, String.Format("The value '{0}' is an invalid fractionDigits facet specification", fracf.Value.Trim () ));
\r
454 private void checkMinMaxFacet(XmlSchemaFacet facet,
\r
455 ref object baseFacet,
\r
456 ValidationEventHandler h) {
\r
457 // Is it a valid instance of the base type.
\r
458 object newValue = ValidateValueWithDatatype(facet.Value);
\r
459 if (newValue != null) {
\r
460 // Is the base fixed - if so is it the same
\r
461 if (((fixedFacets & facet.ThisFacet) != 0) && (baseFacet != null)){
\r
462 XsdAnySimpleType dt = getDatatype();
\r
463 if (dt.Compare (newValue, baseFacet) != XsdOrdering.Equal) {
\r
465 String.Format(CultureInfo.InvariantCulture, "{0} is not the same as fixed parent {1} facet.",
\r
466 facet.Value, facet.ThisFacet));
\r
469 baseFacet = newValue;
\r
473 String.Format("The value '{0}' is not valid against the base type.", facet.Value));
\r
479 private void checkLengthFacet(XmlSchemaLengthFacet lf,
\r
480 XmlSchemaFacet.Facet facetsDefined,
\r
481 ValidationEventHandler h) {
\r
484 if ((facetsDefined & (XmlSchemaFacet.Facet.minLength | XmlSchemaFacet.Facet.maxLength)) != 0)
\r
485 lf.error(h, "It is an error for both length and minLength or maxLength to be present.");
\r
487 lengthFacet = decimal.Parse (lf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
\r
488 /* TODO: Check that it is between inherited max/min lengths */
\r
489 if (lengthFacet < 0)
\r
490 lf.error(h, "The value '" + lengthFacet + "' is an invalid length");
\r
492 } catch (FormatException) { // FIXME: better catch ;-(
\r
493 lf.error (h, "The value '" + lf.Value + "' is an invalid length facet specification");
\r
498 private void checkMaxLengthFacet(XmlSchemaMaxLengthFacet maxlf,
\r
499 XmlSchemaFacet.Facet facetsDefined,
\r
500 ValidationEventHandler h) {
\r
501 if (maxlf != null) {
\r
503 if ((facetsDefined & XmlSchemaFacet.Facet.length) != 0)
\r
504 maxlf.error(h, "It is an error for both length and minLength or maxLength to be present.");
\r
506 decimal newMaxLengthFacet = decimal.Parse (maxlf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
\r
508 if (((fixedFacets & XmlSchemaFacet.Facet.maxLength)!=0) && (newMaxLengthFacet != maxLengthFacet))
\r
509 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));
\r
510 if ((maxLengthFacet >0) && (newMaxLengthFacet > maxLengthFacet))
\r
511 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));
\r
513 maxLengthFacet = newMaxLengthFacet;
\r
514 if (maxLengthFacet < 0)
\r
515 maxlf.error(h, "The value '" + maxLengthFacet + "' is an invalid maxLength");
\r
516 if (minLengthFacet >=0 && minLengthFacet > maxLengthFacet)
\r
517 maxlf.error(h, "minLength is greater than maxLength.");
\r
520 } catch (FormatException) {
\r
521 maxlf.error (h, "The value '" + maxlf.Value+ "' is an invalid maxLength facet specification");
\r
526 private void checkMinLengthFacet(XmlSchemaMinLengthFacet minlf,
\r
527 XmlSchemaFacet.Facet facetsDefined,
\r
528 ValidationEventHandler h) {
\r
529 if (minlf != null) {
\r
531 if (lengthFacet >=0)
\r
532 minlf.error(h, "It is an error for both length and minLength or maxLength to be present.");
\r
534 decimal newMinLengthFacet = decimal.Parse (minlf.Value.Trim (), lengthStyle, CultureInfo.InvariantCulture);
\r
536 if (((fixedFacets & XmlSchemaFacet.Facet.minLength)!=0) && (newMinLengthFacet != minLengthFacet))
\r
537 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));
\r
538 if (newMinLengthFacet < minLengthFacet)
\r
539 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));
\r
541 minLengthFacet = newMinLengthFacet;
\r
542 if (minLengthFacet < 0)
\r
543 minlf.error(h, "The value '" + minLengthFacet + "' is an invalid minLength");
\r
544 if (maxLengthFacet >=0 && minLengthFacet > maxLengthFacet)
\r
545 minlf.error(h, "minLength is greater than maxLength.");
\r
547 } catch (FormatException) {
\r
548 minlf.error (h, "The value '" + minlf.Value + "' is an invalid minLength facet specification");
\r
554 private XsdAnySimpleType getDatatype() {
\r
555 XsdAnySimpleType ast = ActualBaseSchemaType as XsdAnySimpleType;
\r
557 // Based directly on an xsd type
\r
560 XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType)ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
\r
562 if (st is XmlSchemaSimpleTypeRestriction) {
\r
563 return ((XmlSchemaSimpleTypeRestriction)st).getDatatype();
\r
565 else if ((st is XmlSchemaSimpleTypeList) ||
\r
566 (st is XmlSchemaSimpleTypeUnion)) {
\r
573 private object ValidateValueWithDatatype(string value) {
\r
574 XsdAnySimpleType dt = getDatatype();
\r
576 // Console.WriteLine("DT: " + dt);
\r
579 /* I think we can parse null here, as the types
\r
580 * that use the nametable and nsmgr are ones that
\r
581 * we don't need to parse here.
\r
583 ret = dt.ParseValue (value, null, null);
\r
584 // Console.WriteLine("Ret: " + ret);
\r
585 // If we are based on something with facets, check that we are valid
\r
586 if (ActualBaseSchemaType is XmlSchemaSimpleType) {
\r
587 XmlSchemaSimpleTypeContent st = ((XmlSchemaSimpleType) ActualBaseSchemaType).Content as XmlSchemaSimpleTypeContent;
\r
588 if (st is XmlSchemaSimpleTypeRestriction) {
\r
589 if (((XmlSchemaSimpleTypeRestriction)st).ValidateValueWithFacets(value, null)) {
\r
597 } catch (Exception) {
\r
604 internal bool ValidateValueWithFacets (string value, XmlNameTable nt)
\r
607 * FIXME: Shouldn't this be recursing more? What if this is a
\r
608 * restriction of a restriction of a list type?
\r
610 XmlSchemaSimpleType baseST = this.ActualBaseSchemaType as XmlSchemaSimpleType;
\r
611 XmlSchemaSimpleTypeList listType = baseST != null ? baseST.Content as XmlSchemaSimpleTypeList : null;
\r
614 if (listType != null)
\r
615 return ValidateListValueWithFacets (value, nt);
\r
617 return ValidateNonListValueWithFacets (value, nt);
\r
620 private bool ValidateListValueWithFacets (string value, XmlNameTable nt)
\r
622 string [] list = ((XsdAnySimpleType) XmlSchemaDatatype.FromName ("anySimpleType", XmlSchema.Namespace)).ParseListValue (value, nt);
\r
625 if (this.patternFacetValues != null) {
\r
626 for (int l = 0; l < list.Length; l++) {
\r
627 for (int i = 0; i < this.patternFacetValues.Length; i++)
\r
628 if (rexPatterns [i] != null && !rexPatterns [i].IsMatch (list [l]))
\r
633 if (this.enumarationFacetValues != null) {
\r
634 for (int l = 0; l < list.Length; l++) {
\r
635 bool matched = false;
\r
636 for (int i = 0; i < this.enumarationFacetValues.Length; i++) {
\r
637 if (list [l] == this.enumarationFacetValues [i]) {
\r
649 if (lengthFacet >= 0 && list.Length != lengthFacet)
\r
652 if (maxLengthFacet >= 0 && list.Length > maxLengthFacet)
\r
655 if (minLengthFacet >= 0 && list.Length < minLengthFacet)
\r
661 private bool ValidateNonListValueWithFacets (string value, XmlNameTable nt)
\r
664 // Patterns are the only facets that need to be checked on this
\r
665 // type and its base types. We should probably separate them, then
\r
666 // do base-type pattern validation.
\r
667 if (this.patternFacetValues != null) {
\r
668 bool matched = false;
\r
669 for (int i = 0; i < this.patternFacetValues.Length; i++)
\r
670 if (rexPatterns [i] != null && rexPatterns [i].IsMatch (value)) {
\r
678 if (this.enumarationFacetValues != null) {
\r
679 bool matched = false;
\r
680 for (int i = 0; i < this.enumarationFacetValues.Length; i++) {
\r
681 if (value == this.enumarationFacetValues [i]) {
\r
689 XsdAnySimpleType dt = getDatatype ();
\r
691 // Need to skip length tests for
\r
692 // types derived from QName or NOTATION
\r
693 // see errata: E2-36 Clarification
\r
695 if (! ( (dt is XsdQName) || (dt is XsdNotation))) {
\r
696 // Length potentially slower now, so only calculate if needed
\r
697 if (! ((lengthFacet == -1) && (maxLengthFacet == -1) && (minLengthFacet == -1))) {
\r
702 int length = dt.Length(value);
\r
704 if (lengthFacet >= 0 && length != lengthFacet)
\r
707 if (maxLengthFacet >= 0 && length > maxLengthFacet)
\r
710 if (minLengthFacet >= 0 && length < minLengthFacet)
\r
716 if ((totalDigitsFacet >=0) || (fractionDigitsFacet >=0)) {
\r
717 String newValue = value.Trim(new Char [] { '+', '-', '0', '.' });
\r
718 int fractionDigits = 0;
\r
719 int totalDigits = newValue.Length;
\r
720 int point = newValue.IndexOf(".");
\r
723 fractionDigits = newValue.Length - point -1;
\r
725 if ((totalDigitsFacet >=0) && (totalDigits > totalDigitsFacet))
\r
727 if ((fractionDigitsFacet >=0) && (fractionDigits > fractionDigitsFacet))
\r
731 if ((maxInclusiveFacet != null) ||
\r
732 (maxExclusiveFacet != null) ||
\r
733 (minInclusiveFacet != null) ||
\r
734 (minExclusiveFacet != null)) {
\r
738 parsed = dt.ParseValue (value, nt, null);
\r
739 } catch (OverflowException ) {
\r
740 /* This appears to be what .NET does */
\r
742 } catch (FormatException ) {
\r
743 /* This appears to be what .NET does */
\r
747 if (maxInclusiveFacet != null) {
\r
748 XsdOrdering result = dt.Compare (parsed, maxInclusiveFacet);
\r
749 if ((result != XsdOrdering.LessThan) &&
\r
750 (result != XsdOrdering.Equal))
\r
753 if (maxExclusiveFacet != null) {
\r
755 XsdOrdering result = dt.Compare (parsed, maxExclusiveFacet);
\r
756 if (result != XsdOrdering.LessThan)
\r
759 if (minInclusiveFacet != null) {
\r
760 XsdOrdering result = dt.Compare (parsed, minInclusiveFacet);
\r
761 if ((result != XsdOrdering.GreaterThan) &&
\r
762 (result != XsdOrdering.Equal))
\r
765 if (minExclusiveFacet != null) {
\r
766 XsdOrdering result = dt.Compare (parsed, minExclusiveFacet);
\r
767 if (result != XsdOrdering.GreaterThan)
\r
781 // {any attributes with non-schema namespace . . .}>
\r
782 // Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))
\r
784 internal static XmlSchemaSimpleTypeRestriction Read(XmlSchemaReader reader, ValidationEventHandler h)
\r
786 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
\r
787 reader.MoveToElement();
\r
789 if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
\r
791 error(h,"Should not happen :1: XmlSchemaSimpleTypeRestriction.Read, name="+reader.Name,null);
\r
796 restriction.LineNumber = reader.LineNumber;
\r
797 restriction.LinePosition = reader.LinePosition;
\r
798 restriction.SourceUri = reader.BaseURI;
\r
800 while(reader.MoveToNextAttribute())
\r
802 if(reader.Name == "id")
\r
804 restriction.Id = reader.Value;
\r
806 else if(reader.Name == "base")
\r
809 restriction.baseTypeName = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex);
\r
810 if(innerex != null)
\r
811 error(h, reader.Value + " is not a valid value for base attribute",innerex);
\r
813 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
\r
815 error(h,reader.Name + " is not a valid attribute for restriction",null);
\r
819 XmlSchemaUtil.ReadUnhandledAttribute(reader,restriction);
\r
823 reader.MoveToElement();
\r
824 if(reader.IsEmptyElement)
\r
825 return restriction;
\r
827 // Content: annotation?, simpleType?, (minExclusive |. .. | pattern)*
\r
829 while(reader.ReadNextElement())
\r
831 if(reader.NodeType == XmlNodeType.EndElement)
\r
833 if(reader.LocalName != xmlname)
\r
834 error(h,"Should not happen :2: XmlSchemaSimpleTypeRestriction.Read, name="+reader.Name,null);
\r
837 if(level <= 1 && reader.LocalName == "annotation")
\r
839 level = 2; //Only one annotation
\r
840 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
\r
841 if(annotation != null)
\r
842 restriction.Annotation = annotation;
\r
845 if(level <= 2 && reader.LocalName == "simpleType")
\r
848 XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);
\r
850 restriction.baseType = stype;
\r
855 if(reader.LocalName == "minExclusive")
\r
858 XmlSchemaMinExclusiveFacet minex = XmlSchemaMinExclusiveFacet.Read(reader,h);
\r
860 restriction.facets.Add(minex);
\r
863 else if(reader.LocalName == "minInclusive")
\r
866 XmlSchemaMinInclusiveFacet mini = XmlSchemaMinInclusiveFacet.Read(reader,h);
\r
868 restriction.facets.Add(mini);
\r
871 else if(reader.LocalName == "maxExclusive")
\r
874 XmlSchemaMaxExclusiveFacet maxex = XmlSchemaMaxExclusiveFacet.Read(reader,h);
\r
876 restriction.facets.Add(maxex);
\r
879 else if(reader.LocalName == "maxInclusive")
\r
882 XmlSchemaMaxInclusiveFacet maxi = XmlSchemaMaxInclusiveFacet.Read(reader,h);
\r
884 restriction.facets.Add(maxi);
\r
887 else if(reader.LocalName == "totalDigits")
\r
890 XmlSchemaTotalDigitsFacet total = XmlSchemaTotalDigitsFacet.Read(reader,h);
\r
892 restriction.facets.Add(total);
\r
895 else if(reader.LocalName == "fractionDigits")
\r
898 XmlSchemaFractionDigitsFacet fraction = XmlSchemaFractionDigitsFacet.Read(reader,h);
\r
899 if(fraction != null)
\r
900 restriction.facets.Add(fraction);
\r
903 else if(reader.LocalName == "length")
\r
906 XmlSchemaLengthFacet length = XmlSchemaLengthFacet.Read(reader,h);
\r
908 restriction.facets.Add(length);
\r
911 else if(reader.LocalName == "minLength")
\r
914 XmlSchemaMinLengthFacet minlen = XmlSchemaMinLengthFacet.Read(reader,h);
\r
916 restriction.facets.Add(minlen);
\r
919 else if(reader.LocalName == "maxLength")
\r
922 XmlSchemaMaxLengthFacet maxlen = XmlSchemaMaxLengthFacet.Read(reader,h);
\r
924 restriction.facets.Add(maxlen);
\r
927 else if(reader.LocalName == "enumeration")
\r
930 XmlSchemaEnumerationFacet enumeration = XmlSchemaEnumerationFacet.Read(reader,h);
\r
931 if(enumeration != null)
\r
932 restriction.facets.Add(enumeration);
\r
935 else if(reader.LocalName == "whiteSpace")
\r
938 XmlSchemaWhiteSpaceFacet ws = XmlSchemaWhiteSpaceFacet.Read(reader,h);
\r
940 restriction.facets.Add(ws);
\r
943 else if(reader.LocalName == "pattern")
\r
946 XmlSchemaPatternFacet pattern = XmlSchemaPatternFacet.Read(reader,h);
\r
947 if(pattern != null)
\r
948 restriction.facets.Add(pattern);
\r
952 reader.RaiseInvalidElementError();
\r
954 return restriction;
\r