1 // Author: Dwivedi, Ajay kumar
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 using System
.Collections
;
27 using System
.Text
.RegularExpressions
;
29 using System
.Xml
.Serialization
;
30 using Mono
.Xml
.Schema
;
31 using System
.Globalization
;
34 using NSResolver
= System
.Xml
.IXmlNamespaceResolver
;
36 using NSResolver
= System
.Xml
.XmlNamespaceManager
;
39 namespace System
.Xml
.Schema
42 /// Summary description for XmlSchemaSimpleTypeRestriction.
44 public class XmlSchemaSimpleTypeRestriction
: XmlSchemaSimpleTypeContent
46 private XmlSchemaSimpleType baseType
;
47 private XmlQualifiedName baseTypeName
;
48 private XmlSchemaObjectCollection facets
;
49 const string xmlname
= "restriction";
50 private string [] enumarationFacetValues
;
51 private string [] patternFacetValues
;
52 private Regex
[] rexPatterns
;
53 private decimal lengthFacet
;
54 private decimal maxLengthFacet
;
55 private decimal minLengthFacet
;
56 private decimal fractionDigitsFacet
;
57 private decimal totalDigitsFacet
;
58 private object maxInclusiveFacet
;
59 private object maxExclusiveFacet
;
60 private object minInclusiveFacet
;
61 private object minExclusiveFacet
;
62 private XmlSchemaFacet
.Facet fixedFacets
= XmlSchemaFacet
.Facet
.None
;
63 private static NumberStyles lengthStyle
= NumberStyles
.Integer
;
66 public XmlSchemaSimpleTypeRestriction()
68 baseTypeName
= XmlQualifiedName
.Empty
;
69 facets
= new XmlSchemaObjectCollection();
72 [System
.Xml
.Serialization
.XmlAttribute("base")]
73 public XmlQualifiedName BaseTypeName
75 get{ return baseTypeName; }
76 set{ baseTypeName = value; }
79 [XmlElement("simpleType", Type
=typeof (XmlSchemaSimpleType
))]
80 public XmlSchemaSimpleType BaseType
82 get{ return baseType; }
83 set{ baseType = value; }
86 [XmlElement("minExclusive",typeof(XmlSchemaMinExclusiveFacet
))]
87 [XmlElement("minInclusive",typeof(XmlSchemaMinInclusiveFacet
))]
88 [XmlElement("maxExclusive",typeof(XmlSchemaMaxExclusiveFacet
))]
89 [XmlElement("maxInclusive",typeof(XmlSchemaMaxInclusiveFacet
))]
90 [XmlElement("totalDigits",typeof(XmlSchemaTotalDigitsFacet
))]
91 [XmlElement("fractionDigits",typeof(XmlSchemaFractionDigitsFacet
))]
92 [XmlElement("length",typeof(XmlSchemaLengthFacet
))]
93 [XmlElement("minLength",typeof(XmlSchemaMinLengthFacet
))]
94 [XmlElement("maxLength",typeof(XmlSchemaMaxLengthFacet
))]
95 [XmlElement("enumeration",typeof(XmlSchemaEnumerationFacet
))]
96 [XmlElement("whiteSpace",typeof(XmlSchemaWhiteSpaceFacet
))]
97 [XmlElement("pattern",typeof(XmlSchemaPatternFacet
))]
98 public XmlSchemaObjectCollection Facets
100 get{ return facets; }
103 internal override void SetParent (XmlSchemaObject parent
)
105 base.SetParent (parent
);
106 if (BaseType
!= null)
107 BaseType
.SetParent (this);
108 foreach (XmlSchemaObject obj
in Facets
)
109 obj
.SetParent (this);
113 /// 1. One of base or simpletype must be present but not both
114 /// 2. id must be a valid ID
115 /// 3. base must be a valid QName *NO CHECK REQUIRED*
117 internal override int Compile(ValidationEventHandler h
, XmlSchema schema
)
119 // If this is already compiled this time, simply skip.
120 if (CompilationId
== schema
.CompilationId
)
125 if(this.baseType
!= null && !this.BaseTypeName
.IsEmpty
)
126 error(h
, "both base and simpletype can't be set");
127 if(this.baseType
== null && this.BaseTypeName
.IsEmpty
)
128 error(h
, "one of basetype or simpletype must be present");
129 if(this.baseType
!= null)
131 errorCount
+= this.baseType
.Compile(h
,schema
);
133 if(!XmlSchemaUtil
.CheckQName(BaseTypeName
))
134 error(h
,"BaseTypeName must be a XmlQualifiedName");
136 XmlSchemaUtil
.CompileID(Id
,this,schema
.IDCollection
,h
);
138 for (int i
= 0; i
< this.Facets
.Count
; i
++)
139 if (! (Facets
[i
] is XmlSchemaFacet
))
140 error (h
, "Only XmlSchemaFacet objects are allowed for Facets property");
141 this.CompilationId
= schema
.CompilationId
;
145 /** Checks if this facet is valid on this restriction. Does not check that it has
146 * not been fixed in the baseType. That is done elsewhere.
149 private static readonly XmlSchemaFacet
.Facet listFacets
=
150 XmlSchemaFacet
.Facet
.length
| XmlSchemaFacet
.Facet
.minLength
|
151 XmlSchemaFacet
.Facet
.maxLength
| XmlSchemaFacet
.Facet
.pattern
|
152 XmlSchemaFacet
.Facet
.enumeration
| XmlSchemaFacet
.Facet
.whiteSpace
;
155 private bool IsAllowedFacet(XmlSchemaFacet xsf
) {
156 /* Must be called after this.ValidateActualType, as it uses actualBaseSchemaType */
158 XsdAnySimpleType ast
= ActualBaseSchemaType
as XsdAnySimpleType
;
160 // Based directly on an xsd type
161 return ast
.AllowsFacet(xsf
);
164 XmlSchemaSimpleTypeContent st
= ((XmlSchemaSimpleType
)ActualBaseSchemaType
).Content
as XmlSchemaSimpleTypeContent
;
166 XmlSchemaSimpleTypeRestriction str
= st
as XmlSchemaSimpleTypeRestriction
;
167 if (str
!= null && str
!= this) {
168 return str
.IsAllowedFacet(xsf
);
170 XmlSchemaSimpleTypeList stl
= st
as XmlSchemaSimpleTypeList
;
172 return ((xsf
.ThisFacet
& listFacets
) != 0);
175 XmlSchemaSimpleTypeUnion stu
= st
as XmlSchemaSimpleTypeUnion
;
177 return (xsf
is XmlSchemaPatternFacet
||
178 xsf
is XmlSchemaEnumerationFacet
);
183 // TODO: Should this be either a XmlSchemaSimpleType or XmlSchemaDatatype ?
184 // If so report error
187 // Not sure it could ever get here
193 internal override int Validate(ValidationEventHandler h
, XmlSchema schema
)
196 if (IsValidated (schema
.ValidationId
))
199 this.ValidateActualType (h
, schema
);
202 lengthFacet
= maxLengthFacet
= minLengthFacet
= fractionDigitsFacet
= totalDigitsFacet
= -1;
204 XmlSchemaSimpleTypeRestriction baseSTR
= null;
206 if (ActualBaseSchemaType
is XmlSchemaSimpleType
) {
207 XmlSchemaSimpleTypeContent st
= ((XmlSchemaSimpleType
)ActualBaseSchemaType
).Content
as XmlSchemaSimpleTypeContent
;
208 baseSTR
= st
as XmlSchemaSimpleTypeRestriction
;
212 if (baseSTR
!= null) {
213 fixedFacets
= baseSTR
.fixedFacets
;
214 lengthFacet
= baseSTR
.lengthFacet
;
215 maxLengthFacet
= baseSTR
.maxLengthFacet
;
216 minLengthFacet
= baseSTR
.minLengthFacet
;
217 fractionDigitsFacet
= baseSTR
.fractionDigitsFacet
;
218 totalDigitsFacet
= baseSTR
.totalDigitsFacet
;
219 maxInclusiveFacet
= baseSTR
.maxInclusiveFacet
;
220 maxExclusiveFacet
= baseSTR
.maxExclusiveFacet
;
221 minInclusiveFacet
= baseSTR
.minInclusiveFacet
;
222 minExclusiveFacet
= baseSTR
.minExclusiveFacet
;
225 enumarationFacetValues
= patternFacetValues
= null;
228 XmlSchemaFacet
.Facet facetsDefined
= XmlSchemaFacet
.Facet
.None
;
230 ArrayList enums
= null;
231 ArrayList patterns
= null;
232 for (int i
= 0; i
< facets
.Count
; i
++) {
234 XmlSchemaFacet facet
= facets
[i
] as XmlSchemaFacet
;
236 if (!IsAllowedFacet(facet
)) {
237 facet
.error(h
, facet
.ThisFacet
+" is not a valid facet for this type");
242 // Other than XmlSchemaFacet; already reported at Compile()
247 XmlSchemaEnumerationFacet ef
= facets
[i
] as XmlSchemaEnumerationFacet
;
250 enums
= new ArrayList ();
251 enums
.Add (ef
.Value
);
254 XmlSchemaPatternFacet pf
= facets
[i
] as XmlSchemaPatternFacet
;
256 if (patterns
== null)
257 patterns
= new ArrayList ();
258 patterns
.Add (pf
.Value
);
262 // Put this test here, as pattern and enumeration
263 // can occur multiple times.
264 if ( (facetsDefined
& facet
.ThisFacet
) !=0) {
265 facet
.error (h
, "This is a duplicate '" + facet
.ThisFacet
+ "' facet.");
269 facetsDefined
|= facet
.ThisFacet
;
276 if (facet
is XmlSchemaLengthFacet
) {
277 checkLengthFacet((XmlSchemaLengthFacet
)facet
, facetsDefined
, h
);
279 else if (facet
is XmlSchemaMaxLengthFacet
) {
280 checkMaxLengthFacet((XmlSchemaMaxLengthFacet
)facet
, facetsDefined
, h
);
282 else if (facet
is XmlSchemaMinLengthFacet
) {
283 checkMinLengthFacet((XmlSchemaMinLengthFacet
)facet
, facetsDefined
, h
);
286 else if (facet
is XmlSchemaMinInclusiveFacet
) {
287 checkMinMaxFacet((XmlSchemaMinInclusiveFacet
)facet
, ref minInclusiveFacet
, h
);
289 else if (facet
is XmlSchemaMaxInclusiveFacet
) {
290 checkMinMaxFacet((XmlSchemaMaxInclusiveFacet
)facet
, ref maxInclusiveFacet
, h
);
292 else if (facet
is XmlSchemaMinExclusiveFacet
) {
293 checkMinMaxFacet((XmlSchemaMinExclusiveFacet
)facet
, ref minExclusiveFacet
, h
);
295 else if (facet
is XmlSchemaMaxExclusiveFacet
) {
296 checkMinMaxFacet((XmlSchemaMaxExclusiveFacet
)facet
, ref maxExclusiveFacet
, h
);
298 else if (facet
is XmlSchemaFractionDigitsFacet
) {
299 checkFractionDigitsFacet((XmlSchemaFractionDigitsFacet
)facet
, h
);
301 else if (facet
is XmlSchemaTotalDigitsFacet
) {
302 checkTotalDigitsFacet((XmlSchemaTotalDigitsFacet
)facet
, h
);
306 fixedFacets
|= facet
.ThisFacet
;
312 this.enumarationFacetValues
= enums
.ToArray (typeof (string)) as string [];
313 if (patterns
!= null) {
314 this.patternFacetValues
= patterns
.ToArray (typeof (string)) as string [];
315 this.rexPatterns
= new Regex
[patterns
.Count
];
316 for (int i
= 0; i
< patternFacetValues
.Length
; i
++) {
318 string src
= patternFacetValues
[i
];
319 StringBuilder sb
= null;
321 for (int c
= 0; c
< src
.Length
; c
++) {
322 if (src
[c
] == '\\' && src
.Length
> i
+ 1) {
324 switch (src
[c
+ 1]) {
329 subst
= "[^\\p{L}_]";
332 subst
= "[\\p{L}\\p{N}_\\.\\-:]";
335 subst
= "[^\\p{L}\\p{N}_\\.\\-:]";
340 sb
= new StringBuilder ();
341 sb
.Append (src
, start
, c
- start
);
348 sb
.Append (src
, start
, src
.Length
- start
);
349 src
= sb
.ToString ();
351 // src = src.Replace ("\\i", "[\\p{L}_]").Replace ("\\I", "[^\\p{L}_]").Replace ("\\c", "[\\p{L}\\p{N}_\\.\\-:]").Replace ("\\C", "[^\\p{L}\\p{N}_\\.\\-:]");
352 Regex rex
= new Regex ("^" + src
+ "$");
353 rexPatterns
[i
] = rex
;
354 } catch (Exception ex
) {
355 error (h
, "Invalid regular expression pattern was specified.", ex
);
363 ValidationId
= schema
.ValidationId
;
365 Console.WriteLine("Facets:\n defined\t{10}\n fixed\t{0}\n length\t{1}\n maxLen\t{2}\n minLen\t{3}\n " +
366 "frac\t{4}\n tot\t{5}\n maxI\t{6}\n maxE\t{7}\n minI\t{8}\n minE\t{9}\n",
371 fractionDigitsFacet ,
383 internal void ValidateActualType (ValidationEventHandler h
, XmlSchema schema
)
385 GetActualType (h
, schema
, true);
388 internal object GetActualType (ValidationEventHandler h
, XmlSchema schema
, bool validate
)
390 object actualBaseSchemaType
= null;
392 XmlSchemaSimpleType type
= baseType
;
394 type
= schema
.FindSchemaType (baseTypeName
) as XmlSchemaSimpleType
;
397 errorCount
+= type
.Validate (h
, schema
);
398 actualBaseSchemaType
= type
;
399 } else if (baseTypeName
== XmlSchemaComplexType
.AnyTypeName
) {
400 actualBaseSchemaType
= XmlSchemaSimpleType
.AnySimpleType
;
401 } else if (baseTypeName
.Namespace
== XmlSchema
.Namespace
||
402 baseTypeName
.Namespace
== XmlSchema
.XdtNamespace
) {
403 actualBaseSchemaType
= XmlSchemaDatatype
.FromName (baseTypeName
);
404 if (actualBaseSchemaType
== null)
406 error (h
, "Invalid schema type name was specified: " + baseTypeName
);
408 // otherwise, it might be missing sub components.
409 else if (!schema
.IsNamespaceAbsent (baseTypeName
.Namespace
))
411 error (h
, "Referenced base schema type " + baseTypeName
+ " was not found in the corresponding schema.");
413 return actualBaseSchemaType
;
417 private void checkTotalDigitsFacet (XmlSchemaTotalDigitsFacet totf
,
418 ValidationEventHandler h
) {
420 /* totalDigits is the maximum number of digits in values of datatypes
421 * derived from decimal. The value of totalDigits must be a
422 * positiveInteger. */
424 decimal newTotalDigits
= decimal.Parse (totf
.Value
.Trim (), lengthStyle
, CultureInfo
.InvariantCulture
);
425 if (newTotalDigits
<= 0)
426 totf
.error(h
, String
.Format(CultureInfo
.InvariantCulture
, "The value '{0}' is an invalid totalDigits value", newTotalDigits
));
428 if ((totalDigitsFacet
> 0) && (newTotalDigits
> totalDigitsFacet
)) {
429 totf
.error(h
, String
.Format(CultureInfo
.InvariantCulture
, "The value '{0}' is not a valid restriction of the base totalDigits facet '{1}'", newTotalDigits
, totalDigitsFacet
));
431 totalDigitsFacet
= newTotalDigits
;
433 catch (FormatException
) {
434 totf
.error(h
, String
.Format("The value '{0}' is an invalid totalDigits facet specification", totf
.Value
.Trim () ));
440 private void checkFractionDigitsFacet (XmlSchemaFractionDigitsFacet fracf
,
441 ValidationEventHandler h
) {
445 decimal newFractionDigits
= decimal.Parse (fracf
.Value
.Trim (), lengthStyle
, CultureInfo
.InvariantCulture
);
446 if (newFractionDigits
< 0)
447 fracf
.error(h
, String
.Format(CultureInfo
.InvariantCulture
, "The value '{0}' is an invalid fractionDigits value", newFractionDigits
));
449 if ((fractionDigitsFacet
>= 0) && (newFractionDigits
> fractionDigitsFacet
)) {
450 fracf
.error(h
, String
.Format(CultureInfo
.InvariantCulture
, "The value '{0}' is not a valid restriction of the base fractionDigits facet '{1}'", newFractionDigits
, fractionDigitsFacet
));
452 fractionDigitsFacet
= newFractionDigits
;
454 catch (FormatException
) {
455 fracf
.error(h
, String
.Format("The value '{0}' is an invalid fractionDigits facet specification", fracf
.Value
.Trim () ));
462 private void checkMinMaxFacet(XmlSchemaFacet facet
,
463 ref object baseFacet
,
464 ValidationEventHandler h
) {
465 // Is it a valid instance of the base type.
466 object newValue
= ValidateValueWithDatatype(facet
.Value
);
467 if (newValue
!= null) {
468 // Is the base fixed - if so is it the same
469 if (((fixedFacets
& facet
.ThisFacet
) != 0) && (baseFacet
!= null)){
470 XsdAnySimpleType dt
= getDatatype();
471 if (dt
.Compare (newValue
, baseFacet
) != XsdOrdering
.Equal
) {
473 String
.Format(CultureInfo
.InvariantCulture
, "{0} is not the same as fixed parent {1} facet.",
474 facet
.Value
, facet
.ThisFacet
));
477 baseFacet
= newValue
;
481 String
.Format("The value '{0}' is not valid against the base type.", facet
.Value
));
487 private void checkLengthFacet(XmlSchemaLengthFacet lf
,
488 XmlSchemaFacet
.Facet facetsDefined
,
489 ValidationEventHandler h
) {
492 if ((facetsDefined
& (XmlSchemaFacet
.Facet
.minLength
| XmlSchemaFacet
.Facet
.maxLength
)) != 0)
493 lf
.error(h
, "It is an error for both length and minLength or maxLength to be present.");
495 lengthFacet
= decimal.Parse (lf
.Value
.Trim (), lengthStyle
, CultureInfo
.InvariantCulture
);
496 /* TODO: Check that it is between inherited max/min lengths */
498 lf
.error(h
, "The value '" + lengthFacet
+ "' is an invalid length");
500 } catch (FormatException
) { // FIXME: better catch ;-(
501 lf
.error (h
, "The value '" + lf
.Value
+ "' is an invalid length facet specification");
506 private void checkMaxLengthFacet(XmlSchemaMaxLengthFacet maxlf
,
507 XmlSchemaFacet
.Facet facetsDefined
,
508 ValidationEventHandler h
) {
511 if ((facetsDefined
& XmlSchemaFacet
.Facet
.length
) != 0)
512 maxlf
.error(h
, "It is an error for both length and minLength or maxLength to be present.");
514 decimal newMaxLengthFacet
= decimal.Parse (maxlf
.Value
.Trim (), lengthStyle
, CultureInfo
.InvariantCulture
);
516 if (((fixedFacets
& XmlSchemaFacet
.Facet
.maxLength
)!=0) && (newMaxLengthFacet
!= maxLengthFacet
))
517 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
));
518 if ((maxLengthFacet
>0) && (newMaxLengthFacet
> maxLengthFacet
))
519 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
));
521 maxLengthFacet
= newMaxLengthFacet
;
522 if (maxLengthFacet
< 0)
523 maxlf
.error(h
, "The value '" + maxLengthFacet
+ "' is an invalid maxLength");
524 if (minLengthFacet
>=0 && minLengthFacet
> maxLengthFacet
)
525 maxlf
.error(h
, "minLength is greater than maxLength.");
528 } catch (FormatException
) {
529 maxlf
.error (h
, "The value '" + maxlf
.Value
+ "' is an invalid maxLength facet specification");
534 private void checkMinLengthFacet(XmlSchemaMinLengthFacet minlf
,
535 XmlSchemaFacet
.Facet facetsDefined
,
536 ValidationEventHandler h
) {
540 minlf
.error(h
, "It is an error for both length and minLength or maxLength to be present.");
542 decimal newMinLengthFacet
= decimal.Parse (minlf
.Value
.Trim (), lengthStyle
, CultureInfo
.InvariantCulture
);
544 if (((fixedFacets
& XmlSchemaFacet
.Facet
.minLength
)!=0) && (newMinLengthFacet
!= minLengthFacet
))
545 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
));
546 if (newMinLengthFacet
< minLengthFacet
)
547 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
));
549 minLengthFacet
= newMinLengthFacet
;
550 if (minLengthFacet
< 0)
551 minlf
.error(h
, "The value '" + minLengthFacet
+ "' is an invalid minLength");
552 if (maxLengthFacet
>=0 && minLengthFacet
> maxLengthFacet
)
553 minlf
.error(h
, "minLength is greater than maxLength.");
555 } catch (FormatException
) {
556 minlf
.error (h
, "The value '" + minlf
.Value
+ "' is an invalid minLength facet specification");
562 private XsdAnySimpleType
getDatatype() {
563 XsdAnySimpleType ast
= ActualBaseSchemaType
as XsdAnySimpleType
;
565 // Based directly on an xsd type
568 XmlSchemaSimpleTypeContent st
= ((XmlSchemaSimpleType
)ActualBaseSchemaType
).Content
as XmlSchemaSimpleTypeContent
;
570 if (st
is XmlSchemaSimpleTypeRestriction
) {
571 return ((XmlSchemaSimpleTypeRestriction
)st
).getDatatype();
573 else if ((st
is XmlSchemaSimpleTypeList
) ||
574 (st
is XmlSchemaSimpleTypeUnion
)) {
581 private object ValidateValueWithDatatype(string value) {
582 XsdAnySimpleType dt
= getDatatype();
584 // Console.WriteLine("DT: " + dt);
587 /* I think we can parse null here, as the types
588 * that use the nametable and nsmgr are ones that
589 * we don't need to parse here.
591 ret
= dt
.ParseValue (value, null, null);
592 // Console.WriteLine("Ret: " + ret);
593 // If we are based on something with facets, check that we are valid
594 if (ActualBaseSchemaType
is XmlSchemaSimpleType
) {
595 XmlSchemaSimpleTypeContent st
= ((XmlSchemaSimpleType
) ActualBaseSchemaType
).Content
as XmlSchemaSimpleTypeContent
;
596 if (st
is XmlSchemaSimpleTypeRestriction
) {
597 if (((XmlSchemaSimpleTypeRestriction
)st
).ValidateValueWithFacets(value, null, null)) {
605 } catch (Exception
) {
612 internal bool ValidateValueWithFacets (string value, XmlNameTable nt
, NSResolver nsmgr
)
615 * FIXME: Shouldn't this be recursing more? What if this is a
616 * restriction of a restriction of a list type?
618 XmlSchemaSimpleType baseST
= this.ActualBaseSchemaType
as XmlSchemaSimpleType
;
619 XmlSchemaSimpleTypeList listType
= baseST
!= null ? baseST
.Content
as XmlSchemaSimpleTypeList
: null;
622 if (listType
!= null)
623 return ValidateListValueWithFacets (value, nt
, nsmgr
);
625 return ValidateNonListValueWithFacets (value, nt
, nsmgr
);
628 private bool ValidateListValueWithFacets (string value, XmlNameTable nt
, NSResolver nsmgr
)
631 return ValidateListValueWithFacetsCore (value, nt
, nsmgr
);
632 } catch (Exception
) { // this is for datatype ParseValue()
637 private bool ValidateListValueWithFacetsCore (string value, XmlNameTable nt
, NSResolver nsmgr
)
639 string [] list
= ((XsdAnySimpleType
) XmlSchemaDatatype
.FromName ("anySimpleType", XmlSchema
.Namespace
)).ParseListValue (value, nt
);
642 if (this.patternFacetValues
!= null) {
643 for (int l
= 0; l
< list
.Length
; l
++) {
644 for (int i
= 0; i
< this.patternFacetValues
.Length
; i
++)
645 if (rexPatterns
[i
] != null && !rexPatterns
[i
].IsMatch (list
[l
]))
650 bool enumMatched
= false;
652 // enumeration - lexical space comparison
654 // I'm not sure if allowing literally-equivalent values
655 // without parsing (because it will cause trouble when
656 // you try to get TypedValue anyways), but at least it
657 // avoids extraneous validation errors ...
658 if (this.enumarationFacetValues
!= null) {
659 for (int l
= 0; l
< list
.Length
; l
++) {
660 for (int i
= 0; i
< this.enumarationFacetValues
.Length
; i
++) {
661 if (list
[l
] == this.enumarationFacetValues
[i
]) {
669 // enumeration - value space comparison
670 if (!enumMatched
&& this.enumarationFacetValues
!= null) {
671 for (int l
= 0; l
< list
.Length
; l
++) {
673 XsdAnySimpleType dt
= getDatatype ();
675 dt
= (XsdAnySimpleType
) XmlSchemaDatatype
.FromName ("anySimpleType", XmlSchema
.Namespace
);
676 object v
= dt
.ParseValue (list
[l
], nt
, nsmgr
);
678 for (int i
= 0; i
< this.enumarationFacetValues
.Length
; i
++) {
679 if (XmlSchemaUtil
.AreSchemaDatatypeEqual (dt
, v
, dt
, dt
.ParseValue (this.enumarationFacetValues
[i
], nt
, nsmgr
))) {
691 if (lengthFacet
>= 0 && list
.Length
!= lengthFacet
)
694 if (maxLengthFacet
>= 0 && list
.Length
> maxLengthFacet
)
697 if (minLengthFacet
>= 0 && list
.Length
< minLengthFacet
)
703 private bool ValidateNonListValueWithFacets (string value, XmlNameTable nt
, NSResolver nsmgr
)
706 return ValidateNonListValueWithFacetsCore (value, nt
, nsmgr
);
707 } catch (Exception
) { // this is for datatype ParseValue()
712 private bool ValidateNonListValueWithFacetsCore (string value, XmlNameTable nt
, NSResolver nsmgr
)
715 // Patterns are the only facets that need to be checked on this
716 // type and its base types. We should probably separate them, then
717 // do base-type pattern validation.
718 if (this.patternFacetValues
!= null) {
719 bool matched
= false;
720 for (int i
= 0; i
< this.patternFacetValues
.Length
; i
++)
721 if (rexPatterns
[i
] != null && rexPatterns
[i
].IsMatch (value)) {
729 XsdAnySimpleType dt
= getDatatype ();
731 bool enumMatched
= false;
734 // enumeration - lexical space comparison
736 // I'm not sure if allowing literally-equivalent values
737 // without parsing (because it will cause trouble when
738 // you try to get TypedValue anyways), but at least it
739 // avoids extraneous validation errors ...
740 if (this.enumarationFacetValues
!= null) {
741 for (int i
= 0; i
< this.enumarationFacetValues
.Length
; i
++) {
742 if (value == this.enumarationFacetValues
[i
]) {
749 // enumeration - value space comparison
750 if (!enumMatched
&& this.enumarationFacetValues
!= null) {
751 XsdAnySimpleType edt
= dt
;
753 edt
= (XsdAnySimpleType
) XmlSchemaDatatype
.FromName ("anySimpleType", XmlSchema
.Namespace
);
754 object v
= edt
.ParseValue (value, nt
, nsmgr
);
755 for (int i
= 0; i
< this.enumarationFacetValues
.Length
; i
++) {
756 if (XmlSchemaUtil
.AreSchemaDatatypeEqual (edt
, v
, edt
, edt
.ParseValue (this.enumarationFacetValues
[i
], nt
, nsmgr
))) {
765 // Need to skip length tests for
766 // types derived from QName or NOTATION
767 // see errata: E2-36 Clarification
769 if (! ( (dt
is XsdQName
) || (dt
is XsdNotation
))) {
770 // Length potentially slower now, so only calculate if needed
771 if (! ((lengthFacet
== -1) && (maxLengthFacet
== -1) && (minLengthFacet
== -1))) {
776 int length
= dt
.Length(value);
778 if (lengthFacet
>= 0 && length
!= lengthFacet
)
781 if (maxLengthFacet
>= 0 && length
> maxLengthFacet
)
784 if (minLengthFacet
>= 0 && length
< minLengthFacet
)
790 if ((totalDigitsFacet
>=0) || (fractionDigitsFacet
>=0)) {
791 String newValue
= value.Trim(new Char
[] { '+', '-', '0', '.' }
);
792 int fractionDigits
= 0;
793 int totalDigits
= newValue
.Length
;
794 int point
= newValue
.IndexOf(".");
797 fractionDigits
= newValue
.Length
- point
-1;
799 if ((totalDigitsFacet
>=0) && (totalDigits
> totalDigitsFacet
))
801 if ((fractionDigitsFacet
>=0) && (fractionDigits
> fractionDigitsFacet
))
805 if ((maxInclusiveFacet
!= null) ||
806 (maxExclusiveFacet
!= null) ||
807 (minInclusiveFacet
!= null) ||
808 (minExclusiveFacet
!= null)) {
812 parsed
= dt
.ParseValue (value, nt
, null);
813 } catch (OverflowException
) {
814 /* This appears to be what .NET does */
816 } catch (FormatException
) {
817 /* This appears to be what .NET does */
821 if (maxInclusiveFacet
!= null) {
822 XsdOrdering result
= dt
.Compare (parsed
, maxInclusiveFacet
);
823 if ((result
!= XsdOrdering
.LessThan
) &&
824 (result
!= XsdOrdering
.Equal
))
827 if (maxExclusiveFacet
!= null) {
829 XsdOrdering result
= dt
.Compare (parsed
, maxExclusiveFacet
);
830 if (result
!= XsdOrdering
.LessThan
)
833 if (minInclusiveFacet
!= null) {
834 XsdOrdering result
= dt
.Compare (parsed
, minInclusiveFacet
);
835 if ((result
!= XsdOrdering
.GreaterThan
) &&
836 (result
!= XsdOrdering
.Equal
))
839 if (minExclusiveFacet
!= null) {
840 XsdOrdering result
= dt
.Compare (parsed
, minExclusiveFacet
);
841 if (result
!= XsdOrdering
.GreaterThan
)
855 // {any attributes with non-schema namespace . . .}>
856 // Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))
858 internal static XmlSchemaSimpleTypeRestriction
Read(XmlSchemaReader reader
, ValidationEventHandler h
)
860 XmlSchemaSimpleTypeRestriction restriction
= new XmlSchemaSimpleTypeRestriction();
861 reader
.MoveToElement();
863 if(reader
.NamespaceURI
!= XmlSchema
.Namespace
|| reader
.LocalName
!= xmlname
)
865 error(h
,"Should not happen :1: XmlSchemaSimpleTypeRestriction.Read, name="+reader
.Name
,null);
870 restriction
.LineNumber
= reader
.LineNumber
;
871 restriction
.LinePosition
= reader
.LinePosition
;
872 restriction
.SourceUri
= reader
.BaseURI
;
874 while(reader
.MoveToNextAttribute())
876 if(reader
.Name
== "id")
878 restriction
.Id
= reader
.Value
;
880 else if(reader
.Name
== "base")
883 restriction
.baseTypeName
= XmlSchemaUtil
.ReadQNameAttribute(reader
,out innerex
);
885 error(h
, reader
.Value
+ " is not a valid value for base attribute",innerex
);
887 else if((reader
.NamespaceURI
== "" && reader
.Name
!= "xmlns") || reader
.NamespaceURI
== XmlSchema
.Namespace
)
889 error(h
,reader
.Name
+ " is not a valid attribute for restriction",null);
893 XmlSchemaUtil
.ReadUnhandledAttribute(reader
,restriction
);
897 reader
.MoveToElement();
898 if(reader
.IsEmptyElement
)
901 // Content: annotation?, simpleType?, (minExclusive |. .. | pattern)*
903 while(reader
.ReadNextElement())
905 if(reader
.NodeType
== XmlNodeType
.EndElement
)
907 if(reader
.LocalName
!= xmlname
)
908 error(h
,"Should not happen :2: XmlSchemaSimpleTypeRestriction.Read, name="+reader
.Name
,null);
911 if(level
<= 1 && reader
.LocalName
== "annotation")
913 level
= 2; //Only one annotation
914 XmlSchemaAnnotation annotation
= XmlSchemaAnnotation
.Read(reader
,h
);
915 if(annotation
!= null)
916 restriction
.Annotation
= annotation
;
919 if(level
<= 2 && reader
.LocalName
== "simpleType")
922 XmlSchemaSimpleType stype
= XmlSchemaSimpleType
.Read(reader
,h
);
924 restriction
.baseType
= stype
;
929 if(reader
.LocalName
== "minExclusive")
932 XmlSchemaMinExclusiveFacet minex
= XmlSchemaMinExclusiveFacet
.Read(reader
,h
);
934 restriction
.facets
.Add(minex
);
937 else if(reader
.LocalName
== "minInclusive")
940 XmlSchemaMinInclusiveFacet mini
= XmlSchemaMinInclusiveFacet
.Read(reader
,h
);
942 restriction
.facets
.Add(mini
);
945 else if(reader
.LocalName
== "maxExclusive")
948 XmlSchemaMaxExclusiveFacet maxex
= XmlSchemaMaxExclusiveFacet
.Read(reader
,h
);
950 restriction
.facets
.Add(maxex
);
953 else if(reader
.LocalName
== "maxInclusive")
956 XmlSchemaMaxInclusiveFacet maxi
= XmlSchemaMaxInclusiveFacet
.Read(reader
,h
);
958 restriction
.facets
.Add(maxi
);
961 else if(reader
.LocalName
== "totalDigits")
964 XmlSchemaTotalDigitsFacet total
= XmlSchemaTotalDigitsFacet
.Read(reader
,h
);
966 restriction
.facets
.Add(total
);
969 else if(reader
.LocalName
== "fractionDigits")
972 XmlSchemaFractionDigitsFacet fraction
= XmlSchemaFractionDigitsFacet
.Read(reader
,h
);
974 restriction
.facets
.Add(fraction
);
977 else if(reader
.LocalName
== "length")
980 XmlSchemaLengthFacet length
= XmlSchemaLengthFacet
.Read(reader
,h
);
982 restriction
.facets
.Add(length
);
985 else if(reader
.LocalName
== "minLength")
988 XmlSchemaMinLengthFacet minlen
= XmlSchemaMinLengthFacet
.Read(reader
,h
);
990 restriction
.facets
.Add(minlen
);
993 else if(reader
.LocalName
== "maxLength")
996 XmlSchemaMaxLengthFacet maxlen
= XmlSchemaMaxLengthFacet
.Read(reader
,h
);
998 restriction
.facets
.Add(maxlen
);
1001 else if(reader
.LocalName
== "enumeration")
1004 XmlSchemaEnumerationFacet enumeration
= XmlSchemaEnumerationFacet
.Read(reader
,h
);
1005 if(enumeration
!= null)
1006 restriction
.facets
.Add(enumeration
);
1009 else if(reader
.LocalName
== "whiteSpace")
1012 XmlSchemaWhiteSpaceFacet ws
= XmlSchemaWhiteSpaceFacet
.Read(reader
,h
);
1014 restriction
.facets
.Add(ws
);
1017 else if(reader
.LocalName
== "pattern")
1020 XmlSchemaPatternFacet pattern
= XmlSchemaPatternFacet
.Read(reader
,h
);
1022 restriction
.facets
.Add(pattern
);
1026 reader
.RaiseInvalidElementError();