2 // System.Xml.Schema.XmlSchemaElement.cs
\r
5 // Dwivedi, Ajay kumar Adwiv@Yahoo.com
\r
6 // Enomoto, Atsushi ginga@kit.hi-ho.ne.jp
\r
9 using System.Collections;
\r
11 using System.Xml.Serialization;
\r
12 using System.ComponentModel;
\r
14 namespace System.Xml.Schema
\r
17 /// Summary description for XmlSchemaElement.
\r
19 public class XmlSchemaElement : XmlSchemaParticle
\r
21 private XmlSchemaDerivationMethod block;
\r
22 private XmlSchemaDerivationMethod blockResolved;
\r
23 private XmlSchemaObjectCollection constraints;
\r
24 private string defaultValue;
\r
25 private object elementType;
\r
26 private XmlSchemaDerivationMethod final;
\r
27 private XmlSchemaDerivationMethod finalResolved;
\r
28 private string fixedValue;
\r
29 private XmlSchemaForm form;
\r
30 private bool isAbstract;
\r
31 private bool isNillable;
\r
32 private string name;
\r
33 private XmlQualifiedName qName;
\r
34 private XmlQualifiedName refName;
\r
35 private XmlSchemaType schemaType;
\r
36 private XmlQualifiedName schemaTypeName;
\r
37 private XmlQualifiedName substitutionGroup;
\r
38 internal bool parentIsSchema = false;
\r
39 private string validatedDefaultValue;
\r
40 private string validatedFixedValue;
\r
41 private bool actualIsAbstract;
\r
42 private bool actualIsNillable;
\r
43 private XmlSchemaElement substitutionGroupElement;
\r
44 private ArrayList substitutingElements = new ArrayList ();
\r
45 private XmlSchemaElement referencedElement;
\r
47 // Post compilation items. It should be added on all schema components.
\r
50 private static string xmlname = "element";
\r
52 public XmlSchemaElement()
\r
54 block = XmlSchemaDerivationMethod.None;
\r
55 final = XmlSchemaDerivationMethod.None;
\r
56 constraints = new XmlSchemaObjectCollection();
\r
57 qName = XmlQualifiedName.Empty;
\r
58 refName = XmlQualifiedName.Empty;
\r
59 schemaTypeName = XmlQualifiedName.Empty;
\r
60 substitutionGroup = XmlQualifiedName.Empty;
\r
61 substitutionGroup = XmlQualifiedName.Empty;
\r
66 [DefaultValue(false)]
\r
67 [System.Xml.Serialization.XmlAttribute("abstract")]
\r
68 public bool IsAbstract
\r
70 get{ return isAbstract; }
\r
71 set{ isAbstract = value; }
\r
74 [DefaultValue(XmlSchemaDerivationMethod.None)]
\r
75 [System.Xml.Serialization.XmlAttribute("block")]
\r
76 public XmlSchemaDerivationMethod Block
\r
78 get{ return block; }
\r
79 set{ block = value; }
\r
82 [DefaultValue(null)]
\r
83 [System.Xml.Serialization.XmlAttribute("default")]
\r
84 public string DefaultValue
\r
86 get{ return defaultValue; }
\r
87 set{ defaultValue = value; }
\r
90 [DefaultValue(XmlSchemaDerivationMethod.None)]
\r
91 [System.Xml.Serialization.XmlAttribute("final")]
\r
92 public XmlSchemaDerivationMethod Final
\r
94 get{ return final; }
\r
95 set{ final = value; }
\r
98 [DefaultValue(null)]
\r
99 [System.Xml.Serialization.XmlAttribute("fixed")]
\r
100 public string FixedValue
\r
102 get{ return fixedValue; }
\r
103 set{ fixedValue = value; }
\r
105 [DefaultValue(XmlSchemaForm.None)]
\r
106 [System.Xml.Serialization.XmlAttribute("form")]
\r
107 public XmlSchemaForm Form
\r
109 get{ return form; }
\r
110 set{ form = value; }
\r
113 [DefaultValue(null)]
\r
114 [System.Xml.Serialization.XmlAttribute("name")]
\r
115 public string Name
\r
117 get{ return name; }
\r
118 set{ name = value; }
\r
121 [DefaultValue(false)]
\r
122 [System.Xml.Serialization.XmlAttribute("nillable")]
\r
123 public bool IsNillable
\r
125 get{ return isNillable; }
\r
126 set{ isNillable = value; }
\r
129 [System.Xml.Serialization.XmlAttribute("ref")]
\r
130 public XmlQualifiedName RefName
\r
132 get{ return refName; }
\r
133 set{ refName = value;}
\r
136 [System.Xml.Serialization.XmlAttribute("substitutionGroup")]
\r
137 public XmlQualifiedName SubstitutionGroup
\r
139 get{ return substitutionGroup; }
\r
140 set{ substitutionGroup = value; }
\r
143 [System.Xml.Serialization.XmlAttribute("type")]
\r
144 public XmlQualifiedName SchemaTypeName
\r
146 get{ return schemaTypeName; }
\r
147 set{ schemaTypeName = value; }
\r
153 [XmlElement("simpleType",typeof(XmlSchemaSimpleType),Namespace="http://www.w3.org/2001/XMLSchema")]
\r
154 [XmlElement("complexType",typeof(XmlSchemaComplexType),Namespace="http://www.w3.org/2001/XMLSchema")]
\r
155 public XmlSchemaType SchemaType
\r
157 get{ return schemaType; }
\r
158 set{ schemaType = value; }
\r
161 [XmlElement("unique",typeof(XmlSchemaUnique),Namespace="http://www.w3.org/2001/XMLSchema")]
\r
162 [XmlElement("key",typeof(XmlSchemaKey),Namespace="http://www.w3.org/2001/XMLSchema")]
\r
163 [XmlElement("keyref",typeof(XmlSchemaKeyref),Namespace="http://www.w3.org/2001/XMLSchema")]
\r
164 public XmlSchemaObjectCollection Constraints
\r
166 get{ return constraints; }
\r
170 #region Post Compilation Schema Info
\r
172 public XmlQualifiedName QualifiedName
\r
174 get{ return qName; }
\r
178 public object ElementType
\r
181 if (referencedElement != null)
\r
182 return referencedElement.ElementType;
\r
184 return elementType;
\r
189 public XmlSchemaDerivationMethod BlockResolved
\r
192 if (referencedElement != null)
\r
193 return referencedElement.BlockResolved;
\r
195 return blockResolved;
\r
200 public XmlSchemaDerivationMethod FinalResolved
\r
203 if (referencedElement != null)
\r
204 return referencedElement.FinalResolved;
\r
206 return finalResolved;
\r
210 internal bool ActualIsNillable {
\r
212 if (referencedElement != null)
\r
213 return referencedElement.ActualIsNillable;
\r
215 return actualIsNillable;
\r
219 internal bool ActualIsAbstract {
\r
221 if (referencedElement != null)
\r
222 return referencedElement.ActualIsAbstract;
\r
224 return actualIsAbstract;
\r
228 // Post compilation default value (normalized)
\r
229 internal string ValidatedDefaultValue {
\r
231 if (referencedElement != null)
\r
232 return referencedElement.ValidatedDefaultValue;
\r
234 return validatedDefaultValue;
\r
238 // Post compilation fixed value (normalized)
\r
239 internal string ValidatedFixedValue {
\r
241 if (referencedElement != null)
\r
242 return referencedElement.ValidatedFixedValue;
\r
244 return validatedFixedValue;
\r
248 internal ArrayList SubstitutingElements {
\r
250 if (referencedElement != null)
\r
251 return referencedElement.SubstitutingElements;
\r
253 return this.substitutingElements;
\r
257 internal XmlSchemaElement SubstitutionGroupElement {
\r
259 if (referencedElement != null)
\r
260 return referencedElement.SubstitutionGroupElement;
\r
262 return substitutionGroupElement;
\r
268 private XmlSchemaParticle substChoice;
\r
271 /// a) If Element has parent as schema:
\r
272 /// 1. name must be present and of type NCName.
\r
273 /// 2. ref must be absent
\r
274 /// 3. form must be absent
\r
275 /// 4. minOccurs must be absent
\r
276 /// 5. maxOccurs must be absent
\r
277 /// b) If Element has parent is not schema and ref is absent
\r
278 /// 1. name must be present and of type NCName.
\r
279 /// 2. if form equals qualified or form is absent and schema's formdefault is qualifed,
\r
280 /// targetNamespace is schema's targetnamespace else empty.
\r
281 /// 3. type and either <simpleType> or <complexType> are mutually exclusive
\r
282 /// 4. default and fixed must not both be present.
\r
283 /// 5. substitutiongroup must be absent
\r
284 /// 6. final must be absent
\r
285 /// 7. abstract must be absent
\r
286 /// c) if the parent is not schema and ref is set
\r
287 /// 1. name must not be present
\r
288 /// 2. all of <simpleType>,<complexType>, <key>, <keyref>, <unique>, nillable,
\r
289 /// default, fixed, form, block and type, must be absent.
\r
290 /// 3. substitutiongroup is prohibited
\r
291 /// 4. final is prohibited
\r
292 /// 5. abstract is prohibited
\r
293 /// 6. default and fixed must not both be present.(Actually both are absent)
\r
295 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
\r
297 // If this is already compiled this time, simply skip.
\r
298 if (this.IsComplied (schema.CompilationId))
\r
300 this.schema = schema;
\r
302 if(this.defaultValue != null && this.fixedValue != null)
\r
303 error(h,"both default and fixed can't be present");
\r
305 if(parentIsSchema || isRedefineChild)
\r
307 if(this.refName != null && !RefName.IsEmpty)
\r
308 error(h,"ref must be absent");
\r
310 if(this.name == null) //b1
\r
311 error(h,"Required attribute name must be present");
\r
312 else if(!XmlSchemaUtil.CheckNCName(this.name)) // b1.2
\r
313 error(h,"attribute name must be NCName");
\r
315 this.qName = new XmlQualifiedName (this.name, schema.TargetNamespace);
\r
317 if(form != XmlSchemaForm.None)
\r
318 error(h,"form must be absent");
\r
319 if(MinOccursString != null)
\r
320 error(h,"minOccurs must be absent");
\r
321 if(MaxOccursString != null)
\r
322 error(h,"maxOccurs must be absent");
\r
324 XmlSchemaDerivationMethod allfinal = (XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Restriction);
\r
325 if(final == XmlSchemaDerivationMethod.All)
\r
326 finalResolved = allfinal;
\r
327 else if(final == XmlSchemaDerivationMethod.None)
\r
328 finalResolved = XmlSchemaDerivationMethod.Empty;
\r
331 // if((final & ~allfinal) != 0)
\r
332 if ((final | XmlSchemaUtil.FinalAllowed) != XmlSchemaUtil.FinalAllowed)
\r
333 error (h,"some values for final are invalid in this context");
\r
334 finalResolved = final & allfinal;
\r
337 if(schemaType != null && schemaTypeName != null && !schemaTypeName.IsEmpty)
\r
339 error(h,"both schemaType and content can't be present");
\r
342 //Even if both are present, read both of them.
\r
343 if(schemaType != null)
\r
345 if(schemaType is XmlSchemaSimpleType)
\r
347 errorCount += ((XmlSchemaSimpleType)schemaType).Compile(h,schema);
\r
349 else if(schemaType is XmlSchemaComplexType)
\r
351 errorCount += ((XmlSchemaComplexType)schemaType).Compile(h,schema);
\r
354 error(h,"only simpletype or complextype is allowed");
\r
356 if(schemaTypeName != null && !schemaTypeName.IsEmpty)
\r
358 if(!XmlSchemaUtil.CheckQName(SchemaTypeName))
\r
359 error(h,"SchemaTypeName must be an XmlQualifiedName");
\r
361 if(SubstitutionGroup != null && !SubstitutionGroup.IsEmpty)
\r
363 if(!XmlSchemaUtil.CheckQName(SubstitutionGroup))
\r
364 error(h,"SubstitutionGroup must be a valid XmlQualifiedName");
\r
367 foreach(XmlSchemaObject obj in constraints)
\r
369 if(obj is XmlSchemaUnique)
\r
370 errorCount += ((XmlSchemaUnique)obj).Compile(h,schema);
\r
371 else if(obj is XmlSchemaKey)
\r
372 errorCount += ((XmlSchemaKey)obj).Compile(h,schema);
\r
373 else if(obj is XmlSchemaKeyref)
\r
374 errorCount += ((XmlSchemaKeyref)obj).Compile(h,schema);
\r
379 if(substitutionGroup != null && !substitutionGroup.IsEmpty)
\r
380 error(h,"substitutionGroup must be absent");
\r
381 if(final != XmlSchemaDerivationMethod.None)
\r
382 error(h,"final must be absent");
\r
384 CompileOccurence (h, schema);
\r
386 if(refName == null || RefName.IsEmpty)
\r
388 string targetNamespace = String.Empty;
\r
390 if(form == XmlSchemaForm.Qualified || (form == XmlSchemaForm.None && schema.ElementFormDefault == XmlSchemaForm.Qualified))
\r
391 targetNamespace = schema.TargetNamespace;
\r
393 if(this.name == null) //b1
\r
394 error(h,"Required attribute name must be present");
\r
395 else if(!XmlSchemaUtil.CheckNCName(this.name)) // b1.2
\r
396 error(h,"attribute name must be NCName");
\r
398 this.qName = new XmlQualifiedName(this.name, targetNamespace);
\r
400 if(schemaType != null && schemaTypeName != null && !schemaTypeName.IsEmpty)
\r
402 error(h,"both schemaType and content can't be present");
\r
405 //Even if both are present, read both of them.
\r
406 if(schemaType != null)
\r
408 if(schemaType is XmlSchemaSimpleType)
\r
410 errorCount += ((XmlSchemaSimpleType)schemaType).Compile(h,schema);
\r
412 else if(schemaType is XmlSchemaComplexType)
\r
414 errorCount += ((XmlSchemaComplexType)schemaType).Compile(h,schema);
\r
417 error(h,"only simpletype or complextype is allowed");
\r
419 if(schemaTypeName != null && !schemaTypeName.IsEmpty)
\r
421 if(!XmlSchemaUtil.CheckQName(SchemaTypeName))
\r
422 error(h,"SchemaTypeName must be an XmlQualifiedName");
\r
424 if(SubstitutionGroup != null && !SubstitutionGroup.IsEmpty)
\r
426 if(!XmlSchemaUtil.CheckQName(SubstitutionGroup))
\r
427 error(h,"SubstitutionGroup must be a valid XmlQualifiedName");
\r
430 foreach(XmlSchemaObject obj in constraints)
\r
432 if(obj is XmlSchemaUnique)
\r
433 errorCount += ((XmlSchemaUnique)obj).Compile(h,schema);
\r
434 else if(obj is XmlSchemaKey)
\r
435 errorCount += ((XmlSchemaKey)obj).Compile(h,schema);
\r
436 else if(obj is XmlSchemaKeyref)
\r
437 errorCount += ((XmlSchemaKeyref)obj).Compile(h,schema);
\r
442 if(!XmlSchemaUtil.CheckQName(RefName))
\r
443 error(h,"RefName must be a XmlQualifiedName");
\r
446 error(h,"name must not be present when ref is present");
\r
447 if(Constraints.Count != 0)
\r
448 error(h,"key, keyref and unique must be absent");
\r
450 error(h,"nillable must be absent");
\r
451 if(defaultValue != null)
\r
452 error(h,"default must be absent");
\r
453 if(fixedValue != null)
\r
454 error(h,"fixed must be null");
\r
455 if(form != XmlSchemaForm.None)
\r
456 error(h,"form must be absent");
\r
457 if(block != XmlSchemaDerivationMethod.None)
\r
458 error(h,"block must be absent");
\r
459 if(schemaTypeName != null && !schemaTypeName.IsEmpty)
\r
460 error(h,"type must be absent");
\r
461 if(SchemaType != null)
\r
462 error(h,"simpleType or complexType must be absent");
\r
469 case XmlSchemaDerivationMethod.All:
\r
470 blockResolved = XmlSchemaDerivationMethod.All;
\r
472 case XmlSchemaDerivationMethod.None:
\r
473 blockResolved = XmlSchemaDerivationMethod.Empty;
\r
476 if ((block | XmlSchemaUtil.ElementBlockAllowed) != XmlSchemaUtil.ElementBlockAllowed)
\r
477 error (h,"Some of the values for block are invalid in this context");
\r
478 blockResolved = block;
\r
482 if (Constraints != null) {
\r
483 XmlSchemaObjectTable table = new XmlSchemaObjectTable ();
\r
484 foreach (XmlSchemaIdentityConstraint c in Constraints) {
\r
485 XmlSchemaUtil.AddToTable (table, c, c.QualifiedName, h);
\r
489 XmlSchemaUtil.CompileID(Id,this,schema.IDCollection,h);
\r
491 this.CompilationId = schema.CompilationId;
\r
495 [MonoTODO ("Return clone in case when it returns itself")]
\r
496 internal override XmlSchemaParticle GetOptimizedParticle (bool isTop)
\r
498 if (OptimizedParticle != null)
\r
499 return OptimizedParticle;
\r
500 if (RefName != null && RefName != XmlQualifiedName.Empty) {
\r
501 referencedElement = schema.Elements [RefName] as XmlSchemaElement;
\r
504 // if (this.referencedElement != null)
\r
505 // OptimizedParticle = referencedElement.GetOptimizedParticle (isTop);
\r
507 if (ValidatedMaxOccurs == 0)
\r
508 OptimizedParticle = XmlSchemaParticle.Empty;
\r
509 // Substitution Group
\r
510 else if (SubstitutingElements != null && SubstitutingElements.Count > 0) {
\r
511 XmlSchemaChoice choice = new XmlSchemaChoice ();
\r
512 choice.MinOccurs = MinOccurs;
\r
513 choice.MaxOccurs = MaxOccurs;
\r
514 substChoice = choice;
\r
515 choice.Compile (null, schema); // compute Validated Min/Max Occurs.
\r
516 XmlSchemaElement item = this.MemberwiseClone () as XmlSchemaElement;
\r
517 item.MinOccurs = 1;
\r
518 item.MaxOccurs = 1;
\r
519 item.substitutionGroupElement = null;
\r
520 item.substitutingElements = null;
\r
521 for (int i = 0; i < SubstitutingElements.Count; i++) {
\r
522 XmlSchemaElement se = SubstitutingElements [i] as XmlSchemaElement;
\r
523 // choice.Items.Add (se);
\r
524 // choice.CompiledItems.Add (se);
\r
525 this.AddSubstElementRecursively (choice.Items, se);
\r
526 this.AddSubstElementRecursively (choice.CompiledItems, se);
\r
528 if (!choice.Items.Contains (item)) {
\r
529 choice.Items.Add (item);
\r
530 choice.CompiledItems.Add (item);
\r
532 OptimizedParticle = choice;
\r
535 OptimizedParticle = this;//.MemberwiseClone () as XmlSchemaElement;
\r
536 return OptimizedParticle;
\r
539 private void AddSubstElementRecursively (XmlSchemaObjectCollection col, XmlSchemaElement el)
\r
541 if (el.SubstitutingElements != null)
\r
542 for (int i = 0; i < el.SubstitutingElements.Count; i++)
\r
543 this.AddSubstElementRecursively (col, el.SubstitutingElements [i] as XmlSchemaElement);
\r
544 if (!col.Contains (el))
\r
548 internal void FillSubstitutionElementInfo ()
\r
550 if (this.substitutionGroupElement != null)
\r
553 if (this.SubstitutionGroup != XmlQualifiedName.Empty) {
\r
554 XmlSchemaElement substElem = schema.Elements [SubstitutionGroup] as XmlSchemaElement;
\r
555 this.substitutionGroupElement = substElem;
\r
556 if (substElem != null)
\r
557 substElem.substitutingElements.Add (this);
\r
561 internal override int Validate(ValidationEventHandler h, XmlSchema schema)
\r
563 if (IsValidated (schema.CompilationId))
\r
566 // See XML Schema Structures 3.6 for the complete description.
\r
568 // Element Declaration Properties Correct
\r
569 // 1. = 3.3.1 (modulo 5.3)
\r
572 // {annotation} is as is.
\r
573 // {name}, {target namespace}, {scope}, {disallowed substitution},
\r
574 // {substitution group exclusions} (handled the same as 'disallowed substitution')
\r
575 // and {identity-constraint-definitions} are Compile()d.
\r
576 // {value constraint} is going to be filled in step 2.
\r
578 // actual {nillable}, {abstract}
\r
579 this.actualIsNillable = IsNillable;
\r
580 this.actualIsAbstract = IsAbstract;
\r
582 // Before determining element type, we need to validate substituting element
\r
583 if (this.SubstitutionGroup != XmlQualifiedName.Empty) {
\r
584 XmlSchemaElement substElem = substitutionGroupElement;
\r
585 if (substElem != null)
\r
586 substElem.Validate (h, schema);
\r
589 // {type} from here
\r
590 XmlSchemaDatatype datatype = null;
\r
591 if (schemaType != null)
\r
592 elementType = schemaType;
\r
593 else if (SchemaTypeName != XmlQualifiedName.Empty) {
\r
594 XmlSchemaType type = schema.SchemaTypes [SchemaTypeName] as XmlSchemaType;
\r
595 // If el is null, then it is missing sub components .
\r
596 if (type != null) {
\r
597 type.Validate (h, schema);
\r
598 elementType = type;
\r
600 else if (SchemaTypeName == XmlSchemaComplexType.AnyTypeName)
\r
601 elementType = XmlSchemaComplexType.AnyType;
602 else if (SchemaTypeName.Namespace == XmlSchema.Namespace) {
\r
603 datatype = XmlSchemaDatatype.FromName (SchemaTypeName);
\r
604 if (datatype == null)
\r
605 error (h, "Invalid schema datatype was specified.");
\r
607 elementType = datatype;
\r
609 // otherwise, it might be missing sub components.
\r
610 else if (!schema.IsNamespaceAbsent (SchemaTypeName.Namespace))
\r
611 error (h, "Referenced element schema type " + SchemaTypeName + " was not found in the corresponding schema.");
\r
613 else if (RefName != XmlQualifiedName.Empty)
\r
615 XmlSchemaElement refElem = schema.Elements [RefName] as XmlSchemaElement;
\r
616 // If el is null, then it is missing sub components .
\r
617 if (refElem != null) {
\r
618 this.referencedElement = refElem;
\r
619 errorCount += refElem.Validate (h, schema);
\r
621 // otherwise, it might be missing sub components.
\r
622 else if (!schema.IsNamespaceAbsent (RefName.Namespace))
\r
623 error (h, "Referenced element " + RefName + " was not found in the corresponding schema.");
\r
626 // Otherwise if there are substitution group, then the type of the substitution group element.
\r
627 if (referencedElement == null) {
\r
628 if (elementType == null && this.substitutionGroupElement != null)
\r
629 elementType = substitutionGroupElement.ElementType;
\r
630 // Otherwise, the -ur type- definition.
\r
631 if (elementType == null)
\r
632 elementType = XmlSchemaComplexType.AnyType;
\r
635 XmlSchemaType xsType = elementType as XmlSchemaType;
\r
636 if (xsType != null) {
\r
637 errorCount += xsType.Validate (h, schema);
\r
638 datatype = xsType.Datatype;
\r
640 // basic {type} is now filled, except for derivation by {substitution group}.
\r
642 // {substitution group affiliation}
\r
643 // 3. subsitution group's type derivation check.
\r
644 if (this.SubstitutionGroup != XmlQualifiedName.Empty) {
\r
645 XmlSchemaElement substElem = schema.Elements [SubstitutionGroup] as XmlSchemaElement;
\r
646 // If el is null, then it is missing sub components .
\r
647 if (substElem != null) {
\r
648 XmlSchemaType substSchemaType = substElem.ElementType as XmlSchemaType;
\r
649 if (substSchemaType != null) {
\r
650 // 3.3.6 Properties Correct 3.
\r
651 if ((substElem.FinalResolved & XmlSchemaDerivationMethod.Substitution) != 0)
\r
652 error (h, "Substituted element blocks substitution.");
\r
653 if (xsType != null && (substElem.FinalResolved & xsType.DerivedBy) != 0)
\r
654 error (h, "Invalid derivation was found. Substituted element prohibits this derivation method: " + xsType.DerivedBy + ".");
\r
656 XmlSchemaComplexType xsComplexType = xsType as XmlSchemaComplexType;
\r
657 if (xsComplexType != null)
\r
658 xsComplexType.ValidateTypeDerivationOK (substElem.ElementType, h, schema);
\r
660 XmlSchemaSimpleType xsSimpleType = xsType as XmlSchemaSimpleType;
\r
661 if (xsSimpleType != null)
\r
662 xsSimpleType.ValidateTypeDerivationOK (substElem.ElementType, h, schema, true);
\r
666 // otherwise, it might be missing sub components.
\r
667 else if (!schema.IsNamespaceAbsent (SubstitutionGroup.Namespace))
\r
668 error (h, "Referenced element type " + SubstitutionGroup + " was not found in the corresponding schema.");
\r
671 // 2. ElementDefaultValid
\r
672 // 4. ID with {value constraint} is prohibited.
\r
673 if (defaultValue != null || fixedValue != null) {
\r
674 ValidateElementDefaultValidImmediate (h, schema);
\r
675 if (datatype != null && // Such situation is basically an error. For ValidationEventHandler.
\r
676 datatype.TokenizedType == XmlTokenizedType.ID)
\r
677 error (h, "Element type is ID, which does not allows default or fixed values.");
\r
680 // Identity constraints (3.11.3 / 3.11.6)
\r
681 foreach (XmlSchemaIdentityConstraint ident in Constraints)
\r
682 ident.Validate (h, schema);
\r
684 ValidationId = schema.ValidationId;
\r
688 internal override bool ParticleEquals (XmlSchemaParticle other)
\r
690 XmlSchemaElement element = other as XmlSchemaElement;
\r
691 if (element == null)
\r
693 if (this.ValidatedMaxOccurs != element.ValidatedMaxOccurs ||
\r
694 this.ValidatedMinOccurs != element.ValidatedMinOccurs)
\r
696 if (this.QualifiedName != element.QualifiedName ||
\r
697 this.ElementType != element.ElementType ||
\r
698 this.Constraints.Count != element.Constraints.Count)
\r
700 for (int i = 0; i < this.Constraints.Count; i++) {
\r
701 XmlSchemaIdentityConstraint c1 = Constraints [i] as XmlSchemaIdentityConstraint;
\r
702 XmlSchemaIdentityConstraint c2 = element.Constraints [i] as XmlSchemaIdentityConstraint;
\r
703 if (c1.QualifiedName != c2.QualifiedName ||
\r
704 c1.Selector.XPath != c2.Selector.XPath ||
\r
705 c1.Fields.Count != c2.Fields.Count)
\r
707 for (int f = 0; f < c1.Fields.Count; f++) {
\r
708 XmlSchemaXPath f1 = c1.Fields [f] as XmlSchemaXPath;
\r
709 XmlSchemaXPath f2 = c2.Fields [f] as XmlSchemaXPath;
\r
710 if (f1.XPath != f2.XPath)
\r
714 if (this.BlockResolved != element.BlockResolved ||
\r
715 this.FinalResolved != element.FinalResolved ||
\r
716 this.ValidatedDefaultValue != element.ValidatedDefaultValue ||
\r
717 this.ValidatedFixedValue != element.ValidatedFixedValue)
\r
722 internal override bool ValidateDerivationByRestriction (XmlSchemaParticle baseParticle,
\r
723 ValidationEventHandler h, XmlSchema schema, bool raiseError)
\r
725 // element - NameAndTypeOK
\r
726 XmlSchemaElement baseElement = baseParticle as XmlSchemaElement;
\r
727 if (baseElement != null) {
\r
728 return ValidateDerivationByRestrictionNameAndTypeOK (baseElement, h, schema, raiseError);
\r
732 XmlSchemaAny baseAny = baseParticle as XmlSchemaAny;
\r
733 if (baseAny != null) {
\r
735 if (!baseAny.ValidateWildcardAllowsNamespaceName (this.QualifiedName.Namespace, h, schema, raiseError))
\r
737 return ValidateOccurenceRangeOK (baseAny, h, schema, raiseError);
\r
741 // choice - RecurseAsIfGroup
\r
742 XmlSchemaGroupBase gb = null;
\r
743 if (baseParticle is XmlSchemaSequence)
\r
744 gb = new XmlSchemaSequence ();
\r
745 else if (baseParticle is XmlSchemaChoice)
\r
746 gb = new XmlSchemaChoice ();
\r
747 else if (baseParticle is XmlSchemaAll)
\r
748 gb = new XmlSchemaAll ();
\r
751 gb.Items.Add (this);
\r
752 gb.Compile (h, schema);
\r
753 gb.Validate (h, schema);
\r
754 // It looks weird, but here we never think about
\r
755 // _pointlessness_ of this groupbase particle.
\r
756 return gb.ValidateDerivationByRestriction (baseParticle, h, schema, raiseError);
\r
762 private bool ValidateDerivationByRestrictionNameAndTypeOK (XmlSchemaElement baseElement,
\r
763 ValidationEventHandler h, XmlSchema schema, bool raiseError)
\r
766 if (this.QualifiedName != baseElement.QualifiedName) {
\r
768 error (h, "Invalid derivation by restriction of particle was found. Both elements must have the same name.");
\r
772 if (this.isNillable && !baseElement.isNillable) {
\r
774 error (h, "Invalid element derivation by restriction of particle was found. Base element is not nillable and derived type is nillable.");
\r
778 if (!ValidateOccurenceRangeOK (baseElement, h, schema, raiseError))
\r
781 if (baseElement.ValidatedFixedValue != null &&
\r
782 baseElement.ValidatedFixedValue != this.ValidatedFixedValue) {
\r
784 error (h, "Invalid element derivation by restriction of particle was found. Both fixed value must be the same.");
\r
787 // 5. TODO: What is "identity constraints subset" ???
\r
790 if ((baseElement.BlockResolved | this.BlockResolved) != this.BlockResolved) {
\r
792 error (h, "Invalid derivation by restriction of particle was found. Derived element must contain all of the base element's block value.");
\r
796 if (baseElement.ElementType != null) {
\r
797 XmlSchemaComplexType derivedCType = this.ElementType as XmlSchemaComplexType;
\r
798 if (derivedCType != null) {
\r
799 // FIXME: W3C REC says that it is Type Derivation OK to be check, but
\r
800 // in fact it should be DerivationValid (Restriction, Complex).
\r
801 derivedCType.ValidateDerivationValidRestriction (
\r
802 baseElement.ElementType as XmlSchemaComplexType, h, schema);
\r
803 derivedCType.ValidateTypeDerivationOK (baseElement.ElementType, h, schema);
\r
805 XmlSchemaSimpleType derivedSType = this.ElementType as XmlSchemaSimpleType;
\r
806 if (derivedSType != null)
\r
807 derivedSType.ValidateTypeDerivationOK (baseElement.ElementType, h, schema, true);
\r
808 else if (baseElement.ElementType != XmlSchemaComplexType.AnyType && baseElement.ElementType != this.ElementType) {
\r
810 error (h, "Invalid element derivation by restriction of particle was found. Both primitive types differ.");
\r
818 internal override void CheckRecursion (int depth, ValidationEventHandler h, XmlSchema schema)
\r
820 XmlSchemaComplexType ct = this.ElementType as XmlSchemaComplexType;
\r
821 if (ct == null || ct.Particle == null)
\r
823 ct.Particle.CheckRecursion (depth + 1, h, schema);
\r
826 internal override void ValidateUniqueParticleAttribution (XmlSchemaObjectTable qnames, ArrayList nsNames,
\r
827 ValidationEventHandler h, XmlSchema schema)
\r
829 if (qnames.Contains (this.QualifiedName))// && !this.ParticleEquals ((XmlSchemaParticle) qnames [this.QualifiedName]))
\r
830 error (h, "Ambiguous element label was detected: " + this.QualifiedName);
\r
832 foreach (XmlSchemaAny any in nsNames) {
\r
833 if (any.ValidatedMaxOccurs == 0)
\r
835 if (any.HasValueAny ||
\r
836 any.HasValueLocal && this.QualifiedName.Namespace == "" ||
\r
837 any.HasValueOther && this.QualifiedName.Namespace != this.QualifiedName.Namespace ||
\r
838 any.HasValueTargetNamespace && this.QualifiedName.Namespace == this.QualifiedName.Namespace) {
\r
839 error (h, "Ambiguous element label which is contained by -any- particle was detected: " + this.QualifiedName);
\r
841 } else if (!any.HasValueOther) {
\r
843 foreach (string ns in any.ResolvedNamespaces) {
\r
844 if (ns == this.QualifiedName.Namespace) {
\r
850 error (h, "Ambiguous element label which is contained by -any- particle was detected: " + this.QualifiedName);
\r
854 if (any.TargetNamespace.Length == 0 ||
\r
855 any.TargetNamespace != this.QualifiedName.Namespace)
\r
856 error (h, "Ambiguous element label which is contained by -any- particle with ##other value was detected: " + this.QualifiedName);
\r
859 qnames.Add (this.QualifiedName, this);
\r
863 internal override void ValidateUniqueTypeAttribution (XmlSchemaObjectTable labels,
\r
864 ValidationEventHandler h, XmlSchema schema)
\r
866 XmlSchemaElement labeled = labels [this.QualifiedName] as XmlSchemaElement;
\r
867 if (labeled == null)
\r
868 labels.Add (this.QualifiedName, this);
\r
869 else if (labeled.ElementType != this.ElementType)
\r
870 error (h, "Different types are specified on the same named elements in the same sequence. Element name is " + QualifiedName);
\r
874 // 3.3.6 Element Default Valid (Immediate)
\r
875 private void ValidateElementDefaultValidImmediate (ValidationEventHandler h, XmlSchema schema)
\r
877 // This presumes that ElementType is already filled.
\r
879 XmlSchemaDatatype datatype = elementType as XmlSchemaDatatype;
\r
880 XmlSchemaSimpleType simpleType = elementType as XmlSchemaSimpleType;
\r
881 if (simpleType != null)
\r
882 datatype = simpleType.Datatype;
\r
884 if (datatype == null) {
\r
885 XmlSchemaComplexType complexType = elementType as XmlSchemaComplexType;
\r
886 switch (complexType.ContentType) {
\r
887 case XmlSchemaContentType.Empty:
\r
888 case XmlSchemaContentType.ElementOnly:
\r
889 error (h, "Element content type must be simple type or mixed.");
\r
892 datatype = XmlSchemaSimpleType.AnySimpleType;
\r
895 XmlNamespaceManager nsmgr = null;
\r
896 if (datatype.TokenizedType == XmlTokenizedType.QName) {
\r
897 if (this.Namespaces != null)
\r
898 foreach (XmlQualifiedName qname in Namespaces.ToArray ())
\r
899 nsmgr.AddNamespace (qname.Name, qname.Namespace);
\r
903 if (defaultValue != null) {
\r
904 validatedDefaultValue = datatype.Normalize (defaultValue);
\r
905 datatype.ParseValue (validatedDefaultValue, null, nsmgr);
\r
907 } catch (Exception ex) {
\r
908 // FIXME: This is not a good way to handle exception, but
\r
909 // I think there is no remedy for such Framework specification.
\r
910 error (h, "The Element's default value is invalid with respect to its type definition.", ex);
\r
913 if (fixedValue != null) {
\r
914 validatedFixedValue = datatype.Normalize (fixedValue);
\r
915 datatype.ParseValue (validatedFixedValue, null, nsmgr);
\r
917 } catch (Exception ex) {
\r
918 // FIXME: This is not a good way to handle exception.
\r
919 error (h, "The Element's fixed value is invalid with its type definition.", ex);
\r
924 // abstract = boolean : false
\r
925 // block = (#all | List of (extension | restriction | substitution))
\r
926 // default = string
\r
927 // final = (#all | List of (extension | restriction))
\r
929 // form = (qualified | unqualified)
\r
931 // maxOccurs = (nonNegativeInteger | unbounded) : 1
\r
932 // minOccurs = nonNegativeInteger : 1
\r
934 // nillable = boolean : false
\r
936 // substitutionGroup = QName
\r
938 // {any attributes with non-schema namespace . . .}>
\r
939 // Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
\r
942 internal static XmlSchemaElement Read(XmlSchemaReader reader, ValidationEventHandler h)
\r
944 XmlSchemaElement element = new XmlSchemaElement();
\r
946 reader.MoveToElement();
\r
948 if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname)
\r
950 error(h,"Should not happen :1: XmlSchemaElement.Read, name="+reader.Name,null);
\r
955 element.LineNumber = reader.LineNumber;
\r
956 element.LinePosition = reader.LinePosition;
\r
957 element.SourceUri = reader.BaseURI;
\r
959 while(reader.MoveToNextAttribute())
\r
961 if(reader.Name == "abstract")
\r
963 element.IsAbstract = XmlSchemaUtil.ReadBoolAttribute(reader,out innerex);
\r
964 if(innerex != null)
\r
965 error(h,reader.Value + " is invalid value for abstract",innerex);
\r
967 else if(reader.Name == "block")
\r
969 element.block = XmlSchemaUtil.ReadDerivationAttribute(reader,out innerex, "block",
\r
970 XmlSchemaUtil.ElementBlockAllowed);
\r
971 if(innerex != null)
\r
972 error (h,"some invalid values for block attribute were found",innerex);
\r
974 else if(reader.Name == "default")
\r
976 element.defaultValue = reader.Value;
\r
978 else if(reader.Name == "final")
\r
980 element.Final = XmlSchemaUtil.ReadDerivationAttribute(reader,out innerex, "final",
\r
981 XmlSchemaUtil.FinalAllowed);
\r
982 if(innerex != null)
\r
983 error (h,"some invalid values for final attribute were found",innerex);
\r
985 else if(reader.Name == "fixed")
\r
987 element.fixedValue = reader.Value;
\r
989 else if(reader.Name == "form")
\r
991 element.form = XmlSchemaUtil.ReadFormAttribute(reader,out innerex);
\r
992 if(innerex != null)
\r
993 error(h,reader.Value + " is an invalid value for form attribute",innerex);
\r
995 else if(reader.Name == "id")
\r
997 element.Id = reader.Value;
\r
999 else if(reader.Name == "maxOccurs")
\r
1003 element.MaxOccursString = reader.Value;
\r
1005 catch(Exception e)
\r
1007 error(h,reader.Value + " is an invalid value for maxOccurs",e);
\r
1010 else if(reader.Name == "minOccurs")
\r
1014 element.MinOccursString = reader.Value;
\r
1016 catch(Exception e)
\r
1018 error(h,reader.Value + " is an invalid value for minOccurs",e);
\r
1021 else if(reader.Name == "name")
\r
1023 element.Name = reader.Value;
\r
1025 else if(reader.Name == "nillable")
\r
1027 element.IsNillable = XmlSchemaUtil.ReadBoolAttribute(reader,out innerex);
\r
1028 if(innerex != null)
\r
1029 error(h,reader.Value + "is not a valid value for nillable",innerex);
\r
1031 else if(reader.Name == "ref")
\r
1033 element.refName = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex);
\r
1034 if(innerex != null)
\r
1035 error(h, reader.Value + " is not a valid value for ref attribute",innerex);
\r
1037 else if(reader.Name == "substitutionGroup")
\r
1039 element.substitutionGroup = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex);
\r
1040 if(innerex != null)
\r
1041 error(h, reader.Value + " is not a valid value for substitutionGroup attribute",innerex);
\r
1043 else if(reader.Name == "type")
\r
1045 element.SchemaTypeName = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex);
\r
1046 if(innerex != null)
\r
1047 error(h, reader.Value + " is not a valid value for type attribute",innerex);
\r
1049 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
\r
1051 error(h,reader.Name + " is not a valid attribute for element",null);
\r
1055 XmlSchemaUtil.ReadUnhandledAttribute(reader,element);
\r
1059 reader.MoveToElement();
\r
1060 if(reader.IsEmptyElement)
\r
1063 // Content: annotation?,
\r
1064 // (simpleType | complexType)?,
\r
1065 // (unique | key | keyref)*
\r
1067 while(reader.ReadNextElement())
\r
1069 if(reader.NodeType == XmlNodeType.EndElement)
\r
1071 if(reader.LocalName != xmlname)
\r
1072 error(h,"Should not happen :2: XmlSchemaElement.Read, name="+reader.Name,null);
\r
1075 if(level <= 1 && reader.LocalName == "annotation")
\r
1077 level = 2; //Only one annotation
\r
1078 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
\r
1079 if(annotation != null)
\r
1080 element.Annotation = annotation;
\r
1085 if(reader.LocalName == "simpleType")
\r
1088 XmlSchemaSimpleType simple = XmlSchemaSimpleType.Read(reader,h);
\r
1089 if(simple != null)
\r
1090 element.SchemaType = simple;
\r
1093 if(reader.LocalName == "complexType")
\r
1096 XmlSchemaComplexType complex = XmlSchemaComplexType.Read(reader,h);
\r
1097 if(complex != null)
\r
1099 element.SchemaType = complex;
\r
1106 if(reader.LocalName == "unique")
\r
1109 XmlSchemaUnique unique = XmlSchemaUnique.Read(reader,h);
\r
1110 if(unique != null)
\r
1111 element.constraints.Add(unique);
\r
1114 else if(reader.LocalName == "key")
\r
1117 XmlSchemaKey key = XmlSchemaKey.Read(reader,h);
\r
1119 element.constraints.Add(key);
\r
1122 else if(reader.LocalName == "keyref")
\r
1125 XmlSchemaKeyref keyref = XmlSchemaKeyref.Read(reader,h);
\r
1126 if(keyref != null)
\r
1127 element.constraints.Add(keyref);
\r
1131 reader.RaiseInvalidElementError();
\r