2 // System.Xml.Schema.XmlSchemaSimpleType.cs
\r
5 // Dwivedi, Ajay kumar Adwiv@Yahoo.com
\r
6 // Atsushi Enomoto ginga@kit.hi-ho.ne.jp
\r
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Xml.Serialization;
\r
32 using Mono.Xml.Schema;
\r
34 namespace System.Xml.Schema
\r
37 /// Summary description for XmlSchemaSimpleType.
\r
39 public class XmlSchemaSimpleType : XmlSchemaType
\r
41 const string xmlname = "simpleType";
\r
42 private static XmlSchemaSimpleType schemaLocationType;
\r
44 private XmlSchemaSimpleTypeContent content;
\r
46 internal bool islocal = true; // Assuming local means we have to specify islocal=false only in XmlSchema
\r
47 private bool recursed;
\r
48 private XmlSchemaDerivationMethod variety;
\r
50 static XmlSchemaSimpleType ()
\r
52 // This is not used in the meantime.
\r
53 XmlSchemaSimpleType st = new XmlSchemaSimpleType ();
\r
54 XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList ();
\r
55 list.ItemTypeName = new XmlQualifiedName ("anyURI", XmlSchema.Namespace);
\r
57 st.BaseXmlSchemaTypeInternal = null;
\r
58 st.variety = XmlSchemaDerivationMethod.List;
\r
59 schemaLocationType = st;
\r
62 internal static XsdAnySimpleType AnySimpleType {
\r
63 get { return XsdAnySimpleType.Instance; }
\r
66 internal static XmlSchemaSimpleType SchemaLocationType {
\r
67 get { return schemaLocationType; }
\r
70 public XmlSchemaSimpleType()
\r
74 [XmlElement("restriction",typeof(XmlSchemaSimpleTypeRestriction),Namespace=XmlSchema.Namespace)]
\r
75 [XmlElement("list",typeof(XmlSchemaSimpleTypeList),Namespace=XmlSchema.Namespace)]
\r
76 [XmlElement("union",typeof(XmlSchemaSimpleTypeUnion),Namespace=XmlSchema.Namespace)]
\r
77 public XmlSchemaSimpleTypeContent Content
\r
79 get{ return content; }
\r
80 set{ content = value; }
\r
83 internal XmlSchemaDerivationMethod Variety
\r
85 get{ return variety; }
\r
89 /// For a simple Type:
\r
90 /// 1. Content must be present
\r
91 /// 2. id if present, must have be a valid ID
\r
92 /// a) If the simpletype is local
\r
93 /// 1- are from <xs:complexType name="simpleType"> and <xs:complexType name="localSimpleType">
\r
94 /// 1. name is prohibited
\r
95 /// 2. final is prohibited
\r
96 /// b) If the simpletype is toplevel
\r
97 /// 1- are from <xs:complexType name="simpleType"> and <xs:complexType name="topLevelSimpleType">
\r
98 /// 1. name is required, type must be NCName
\r
99 /// 2. Content is required
\r
100 /// 3. final can have values : #all | (list | union | restriction)
\r
101 /// 4. If final is set, finalResolved is same as final (but within the values of b.3)
\r
102 /// 5. If final is not set, the finalDefault of the schema (ie. only #all and restriction)
\r
103 /// 6. Base type is:
\r
104 /// 4.1 If restriction is chosen,the base type of restriction or elements
\r
105 /// 4.2 otherwise simple ur-type
\r
107 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
\r
109 // If this is already compiled this time, simply skip.
\r
110 if (this.IsComplied (schema.CompilationId))
\r
115 if(this.islocal) // a
\r
117 if(this.Name != null) // a.1
\r
118 error(h,"Name is prohibited in a local simpletype");
\r
120 this.QNameInternal = new XmlQualifiedName(this.Name,schema.TargetNamespace);
\r
121 if(this.Final != XmlSchemaDerivationMethod.None) //a.2
\r
122 error(h,"Final is prohibited in a local simpletype");
\r
126 if(this.Name == null) //b.1
\r
127 error(h,"Name is required in top level simpletype");
\r
128 else if(!XmlSchemaUtil.CheckNCName(this.Name)) // b.1.2
\r
129 error(h,"name attribute of a simpleType must be NCName");
\r
131 this.QNameInternal = new XmlQualifiedName(this.Name,schema.TargetNamespace);
\r
133 //NOTE: Although the FinalResolved can be Empty, it is not a valid value for Final
\r
134 //DEVIATION: If an error occurs, the finaldefault is always consulted. This deviates
\r
135 // from the way MS implementation works.
\r
136 switch(this.Final) //b.3, b.4
\r
138 case XmlSchemaDerivationMethod.All:
\r
139 this.finalResolved = XmlSchemaDerivationMethod.All;
\r
141 case XmlSchemaDerivationMethod.List:
\r
142 case XmlSchemaDerivationMethod.Union:
\r
143 case XmlSchemaDerivationMethod.Restriction:
\r
144 this.finalResolved = Final;
\r
147 error(h,"The value of final attribute is not valid for simpleType");
\r
148 goto case XmlSchemaDerivationMethod.None;
\r
149 // use assignment from finaldefault on schema.
\r
150 case XmlSchemaDerivationMethod.None: // b.5
\r
151 XmlSchemaDerivationMethod flags =
\r
152 (XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.List |
\r
153 XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Union );
\r
154 switch (schema.FinalDefault) {
\r
155 case XmlSchemaDerivationMethod.All:
\r
156 finalResolved = XmlSchemaDerivationMethod.All;
\r
158 case XmlSchemaDerivationMethod.None:
\r
159 finalResolved = XmlSchemaDerivationMethod.Empty;
\r
162 finalResolved = schema.FinalDefault & flags;
\r
169 XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);
\r
171 if (Content != null)
\r
172 Content.OwnerType = this;
\r
174 if(this.Content == null) //a.3,b.2
\r
175 error(h,"Content is required in a simpletype");
\r
176 else if(Content is XmlSchemaSimpleTypeRestriction)
\r
178 this.resolvedDerivedBy = XmlSchemaDerivationMethod.Restriction;
\r
179 errorCount += ((XmlSchemaSimpleTypeRestriction)Content).Compile(h,schema);
\r
181 else if(Content is XmlSchemaSimpleTypeList)
\r
183 this.resolvedDerivedBy = XmlSchemaDerivationMethod.List;
\r
184 errorCount += ((XmlSchemaSimpleTypeList)Content).Compile(h,schema);
\r
186 else if(Content is XmlSchemaSimpleTypeUnion)
\r
188 this.resolvedDerivedBy = XmlSchemaDerivationMethod.Union;
\r
189 errorCount += ((XmlSchemaSimpleTypeUnion)Content).Compile(h,schema);
\r
192 this.CompilationId = schema.CompilationId;
\r
196 internal void CollectBaseType (ValidationEventHandler h, XmlSchema schema)
\r
198 if (Content is XmlSchemaSimpleTypeRestriction) {
\r
199 object o = ((XmlSchemaSimpleTypeRestriction) Content).GetActualType (h, schema, false);
\r
200 BaseXmlSchemaTypeInternal = o as XmlSchemaSimpleType;
\r
201 if (BaseXmlSchemaTypeInternal != null)
\r
202 DatatypeInternal = BaseXmlSchemaTypeInternal.Datatype;
\r
204 DatatypeInternal = o as XmlSchemaDatatype;
\r
206 // otherwise, actualBaseSchemaType is null
\r
208 DatatypeInternal = XmlSchemaSimpleType.AnySimpleType;
\r
211 internal override int Validate(ValidationEventHandler h, XmlSchema schema)
\r
213 // 3.14.6 Properties Correct.
\r
215 // 1. Post Compilation Properties
\r
216 // {name}, {target namespace} => QNameInternal. Already Compile()d.
\r
217 // {base type definition} => baseSchemaTypeInternal
\r
218 // {final} => finalResolved. Already Compile()d.
\r
219 // {variety} => resolvedDerivedBy. Already Compile()d.
\r
221 // 2. Should be checked by "recursed" field.
\r
223 if(IsValidated (schema.ValidationId))
\r
227 error (h, "Circular type reference was found.");
\r
232 CollectBaseType (h, schema);
\r
234 if (content != null)
\r
235 errorCount += content.Validate (h, schema);
\r
238 // BaseSchemaType property
\r
239 BaseXmlSchemaTypeInternal = content.ActualBaseSchemaType as XmlSchemaType;
\r
240 if (this.BaseXmlSchemaTypeInternal == null)
\r
241 this.DatatypeInternal = content.ActualBaseSchemaType as XmlSchemaDatatype;
\r
244 // Datatype property
\r
245 XmlSchemaSimpleType simple = BaseXmlSchemaType as XmlSchemaSimpleType;
\r
246 if (simple != null)
\r
247 this.DatatypeInternal = simple.Datatype;
\r
249 // DatatypeInternal = BaseSchemaType as XmlSchemaDatatype;
\r
252 XmlSchemaSimpleType baseSType = BaseXmlSchemaType as XmlSchemaSimpleType;
\r
253 if (baseSType != null) {
\r
254 if ((baseSType.FinalResolved & this.resolvedDerivedBy) != 0)
\r
255 error (h, "Specified derivation is prohibited by the base simple type.");
\r
259 if (this.resolvedDerivedBy == XmlSchemaDerivationMethod.Restriction &&
\r
261 this.variety = baseSType.Variety;
\r
263 this.variety = this.resolvedDerivedBy;
\r
265 // 3.14.6 Derivation Valid (Restriction, Simple)
\r
266 XmlSchemaSimpleTypeRestriction r = Content as XmlSchemaSimpleTypeRestriction;
\r
267 object baseType = BaseXmlSchemaType != null ? (object) BaseXmlSchemaType : Datatype;
\r
269 ValidateDerivationValid (baseType, r.Facets, h, schema);
\r
271 // TODO: describe which validation term this belongs to.
\r
272 XmlSchemaSimpleTypeList l = Content as XmlSchemaSimpleTypeList;
\r
274 XmlSchemaSimpleType itemSimpleType = l.ValidatedListItemType as XmlSchemaSimpleType;
\r
275 if (itemSimpleType != null && itemSimpleType.Content is XmlSchemaSimpleTypeList)
\r
276 error (h, "List type must not be derived from another list type.");
\r
280 ValidationId = schema.ValidationId;
\r
284 // 3.14.6 Derivation Valid (RestrictionSimple)
285 internal void ValidateDerivationValid (object baseType, XmlSchemaObjectCollection facets,
286 ValidationEventHandler h, XmlSchema schema)
289 XmlSchemaSimpleType baseSimpleType = baseType as XmlSchemaSimpleType;
290 switch (this.Variety) {
292 case XmlSchemaDerivationMethod.Restriction:
294 if (baseSimpleType != null && baseSimpleType.resolvedDerivedBy != XmlSchemaDerivationMethod.Restriction)
295 error (h, "Base schema type is not either atomic type or primitive type.");
297 if (baseSimpleType != null &&
298 (baseSimpleType.FinalResolved & XmlSchemaDerivationMethod.Restriction) != 0)
299 error (h, "Derivation by restriction is prohibited by the base simple type.");
300 // TODO: 1.3 facet restriction valid.
302 case XmlSchemaDerivationMethod.List:
303 XmlSchemaSimpleTypeList thisList = Content as XmlSchemaSimpleTypeList;
305 // 2.1 item list type not allowed
306 if (baseSimpleType != null && baseSimpleType.resolvedDerivedBy == XmlSchemaDerivationMethod.List)
307 error (h, "Base list schema type is not allowed.");
308 XmlSchemaSimpleTypeUnion baseUnion = baseSimpleType.Content as XmlSchemaSimpleTypeUnion;
309 if (baseUnion != null) {
310 bool errorFound = false;
311 foreach (object memberType in baseUnion.ValidatedTypes) {
312 XmlSchemaSimpleType memberST = memberType as XmlSchemaSimpleType;
313 if (memberST != null && memberST.resolvedDerivedBy == XmlSchemaDerivationMethod.List)
317 error (h, "Base union schema type should not contain list types.");
320 // 2.2 facets limited
322 foreach (XmlSchemaFacet facet in facets) {
323 if (facet is XmlSchemaLengthFacet ||
324 facet is XmlSchemaMaxLengthFacet ||
325 facet is XmlSchemaMinLengthFacet ||
326 facet is XmlSchemaEnumerationFacet ||
327 facet is XmlSchemaPatternFacet)
330 error (h, "Not allowed facet was found on this simple type which derives list type.");
333 case XmlSchemaDerivationMethod.Union:
338 foreach (XmlSchemaFacet facet in facets) {
339 if (facet is XmlSchemaEnumerationFacet ||
340 facet is XmlSchemaPatternFacet)
343 error (h, "Not allowed facet was found on this simple type which derives list type.");
349 // 3.14.6 Type Derivation OK (Simple)
350 internal bool ValidateTypeDerivationOK (object baseType,
351 ValidationEventHandler h, XmlSchema schema, bool raiseError)
354 // Note that anyType should also be allowed as anySimpleType.
355 if (this == baseType || baseType == XmlSchemaSimpleType.AnySimpleType ||
356 baseType == XmlSchemaComplexType.AnyType)
360 XmlSchemaSimpleType baseSimpleType = baseType as XmlSchemaSimpleType;
361 if (baseSimpleType != null &&
362 (baseSimpleType.FinalResolved & resolvedDerivedBy) != 0) {
364 error (h, "Specified derivation is prohibited by the base type.");
369 if (BaseXmlSchemaType == baseType || Datatype == baseType)
373 XmlSchemaSimpleType thisBaseSimpleType = BaseXmlSchemaType as XmlSchemaSimpleType;
374 if (thisBaseSimpleType != null) {
375 if (thisBaseSimpleType.ValidateTypeDerivationOK (baseType, h, schema, false))
381 case XmlSchemaDerivationMethod.Union:
382 case XmlSchemaDerivationMethod.List:
383 if (baseType == XmlSchemaSimpleType.AnySimpleType)
388 // 2.2.4 validly derived from one of the union member type.
389 if (baseSimpleType != null && baseSimpleType.Variety == XmlSchemaDerivationMethod.Union) {
390 foreach (object memberType in ((XmlSchemaSimpleTypeUnion) baseSimpleType.Content).ValidatedTypes)
391 if (this.ValidateTypeDerivationOK (memberType, h, schema, false))
396 error(h, "Invalid simple type derivation was found.");
400 internal string Normalize (string s, XmlNameTable nt, XmlNamespaceManager nsmgr)
402 return Content.Normalize (s, nt, nsmgr);
406 // final = (#all | (list | union | restriction))
\r
409 // {any attributes with non-schema namespace . . .}>
\r
410 // Content: (annotation?, (restriction | list | union))
\r
412 internal static XmlSchemaSimpleType Read(XmlSchemaReader reader, ValidationEventHandler h)
\r
414 XmlSchemaSimpleType stype = new XmlSchemaSimpleType();
\r
415 reader.MoveToElement();
\r
417 if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
\r
419 error(h,"Should not happen :1: XmlSchemaGroup.Read, name="+reader.Name,null);
\r
424 stype.LineNumber = reader.LineNumber;
\r
425 stype.LinePosition = reader.LinePosition;
\r
426 stype.SourceUri = reader.BaseURI;
\r
428 while(reader.MoveToNextAttribute())
\r
430 if(reader.Name == "final")
\r
433 stype.Final = XmlSchemaUtil.ReadDerivationAttribute(reader, out innerex, "final",
\r
434 XmlSchemaUtil.FinalAllowed);
\r
435 if(innerex != null)
\r
436 error(h, "some invalid values not a valid value for final", innerex);
\r
438 else if(reader.Name == "id")
\r
440 stype.Id = reader.Value;
\r
442 else if(reader.Name == "name")
\r
444 stype.Name = reader.Value;
\r
446 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
\r
448 error(h,reader.Name + " is not a valid attribute for simpleType",null);
\r
452 XmlSchemaUtil.ReadUnhandledAttribute(reader,stype);
\r
456 reader.MoveToElement();
\r
457 if(reader.IsEmptyElement)
\r
460 // Content: (annotation?, (restriction | list | union))
\r
462 while(reader.ReadNextElement())
\r
464 if(reader.NodeType == XmlNodeType.EndElement)
\r
466 if(reader.LocalName != xmlname)
\r
467 error(h,"Should not happen :2: XmlSchemaSimpleType.Read, name="+reader.Name,null);
\r
470 if(level <= 1 && reader.LocalName == "annotation")
\r
472 level = 2; //Only one annotation
\r
473 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
\r
474 if(annotation != null)
\r
475 stype.Annotation = annotation;
\r
480 if(reader.LocalName == "restriction")
\r
483 XmlSchemaSimpleTypeRestriction restriction = XmlSchemaSimpleTypeRestriction.Read(reader,h);
\r
484 if(restriction != null)
\r
485 stype.content = restriction;
\r
488 if(reader.LocalName == "list")
\r
491 XmlSchemaSimpleTypeList list = XmlSchemaSimpleTypeList.Read(reader,h);
\r
493 stype.content = list;
\r
496 if(reader.LocalName == "union")
\r
499 XmlSchemaSimpleTypeUnion union = XmlSchemaSimpleTypeUnion.Read(reader,h);
\r
501 stype.content = union;
\r
505 reader.RaiseInvalidElementError();
\r