// Author: Dwivedi, Ajay kumar // Adwiv@Yahoo.com using System; using System.Xml; using System.Xml.Serialization; using System.ComponentModel; namespace System.Xml.Schema { /// /// Summary description for XmlSchemaElement. /// public class XmlSchemaElement : XmlSchemaParticle { private XmlSchemaDerivationMethod block; private XmlSchemaDerivationMethod blockResolved; private XmlSchemaObjectCollection constraints; private string defaultValue; private object elementType; private XmlSchemaDerivationMethod final; private XmlSchemaDerivationMethod finalResolved; private string fixedValue; private XmlSchemaForm form; private bool isAbstract; private bool isNillable; private string name; private XmlQualifiedName qName; private XmlQualifiedName refName; private XmlSchemaType schemaType; private XmlQualifiedName schemaTypeName; private XmlQualifiedName substitutionGroup; internal bool parentIsSchema = false; private string targetNamespace; private string hash; private static string xmlname = "element"; public XmlSchemaElement() { block = XmlSchemaDerivationMethod.None; final = XmlSchemaDerivationMethod.None; constraints = new XmlSchemaObjectCollection(); qName = XmlQualifiedName.Empty; refName = XmlQualifiedName.Empty; schemaTypeName = XmlQualifiedName.Empty; substitutionGroup = XmlQualifiedName.Empty; substitutionGroup = XmlQualifiedName.Empty; } #region Attributes [DefaultValue(false)] [System.Xml.Serialization.XmlAttribute("abstract")] public bool IsAbstract { get{ return isAbstract; } set{ isAbstract = value; } } [DefaultValue(XmlSchemaDerivationMethod.None)] [System.Xml.Serialization.XmlAttribute("block")] public XmlSchemaDerivationMethod Block { get{ return block; } set{ block = value; } } [DefaultValue(null)] [System.Xml.Serialization.XmlAttribute("default")] public string DefaultValue { get{ return defaultValue; } set{ defaultValue = value; } } [DefaultValue(XmlSchemaDerivationMethod.None)] [System.Xml.Serialization.XmlAttribute("final")] public XmlSchemaDerivationMethod Final { get{ return final; } set{ final = value; } } [DefaultValue(null)] [System.Xml.Serialization.XmlAttribute("fixed")] public string FixedValue { get{ return fixedValue; } set{ fixedValue = value; } } [DefaultValue(XmlSchemaForm.None)] [System.Xml.Serialization.XmlAttribute("form")] public XmlSchemaForm Form { get{ return form; } set{ form = value; } } [DefaultValue(null)] [System.Xml.Serialization.XmlAttribute("name")] public string Name { get{ return name; } set{ name = value; } } [DefaultValue(false)] [System.Xml.Serialization.XmlAttribute("nillable")] public bool IsNillable { get{ return isNillable; } set{ isNillable = value; } } [System.Xml.Serialization.XmlAttribute("ref")] public XmlQualifiedName RefName { get{ return refName; } set{ refName = value;} } [System.Xml.Serialization.XmlAttribute("substitutionGroup")] public XmlQualifiedName SubstitutionGroup { get{ return substitutionGroup; } set{ substitutionGroup = value; } } [System.Xml.Serialization.XmlAttribute("type")] public XmlQualifiedName SchemaTypeName { get{ return schemaTypeName; } set{ schemaTypeName = value; } } [XmlElement("simpleType",typeof(XmlSchemaSimpleType),Namespace="http://www.w3.org/2001/XMLSchema")] [XmlElement("complexType",typeof(XmlSchemaComplexType),Namespace="http://www.w3.org/2001/XMLSchema")] public XmlSchemaType SchemaType { get{ return schemaType; } set{ schemaType = value; } } [XmlElement("unique",typeof(XmlSchemaUnique),Namespace="http://www.w3.org/2001/XMLSchema")] [XmlElement("key",typeof(XmlSchemaKey),Namespace="http://www.w3.org/2001/XMLSchema")] [XmlElement("keyref",typeof(XmlSchemaKeyref),Namespace="http://www.w3.org/2001/XMLSchema")] public XmlSchemaObjectCollection Constraints { get{ return constraints; } } [XmlIgnore] public XmlQualifiedName QualifiedName { get{ return qName; } } [XmlIgnore] public object ElementType { get{ return elementType; } } [XmlIgnore] public XmlSchemaDerivationMethod BlockResolved { get{ return blockResolved; } } [XmlIgnore] public XmlSchemaDerivationMethod FinalResolved { get{ return finalResolved; } } #endregion /// /// a) If Element has parent as schema: /// 1. name must be present and of type NCName. /// 2. ref must be absent /// 3. form must be absent /// 4. minOccurs must be absent /// 5. maxOccurs must be absent /// b) If Element has parent is not schema and ref is absent /// 1. name must be present and of type NCName. /// 2. if form equals qualified or form is absent and schema's formdefault is qualifed, /// targetNamespace is schema's targetnamespace else empty. /// 3. type and either or are mutually exclusive /// 4. default and fixed must not both be present. /// 5. substitutiongroup must be absent /// 6. final must be absent /// 7. abstract must be absent /// c) if the parent is not schema and ref is set /// 1. name must not be present /// 2. all of ,, , , , nillable, /// default, fixed, form, block and type, must be absent. /// 3. substitutiongroup is prohibited /// 4. final is prohibited /// 5. abstract is prohibited /// 6. default and fixed must not both be present.(Actually both are absent) /// [MonoTODO] internal int Compile(ValidationEventHandler h, XmlSchemaInfo info) { if(this.defaultValue != null && this.fixedValue != null) error(h,"both default and fixed can't be present"); if(parentIsSchema) { if(this.refName != null && !RefName.IsEmpty) error(h,"ref must be absent"); if(this.name == null) //b1 error(h,"Required attribute name must be present"); else if(!XmlSchemaUtil.CheckNCName(this.name)) // b1.2 error(h,"attribute name must be NCName"); else this.qName = new XmlQualifiedName(this.name, info.TargetNamespace); if(form != XmlSchemaForm.None) error(h,"form must be absent"); if(MinOccursString != null) error(h,"minOccurs must be absent"); if(MaxOccursString != null) error(h,"maxOccurs must be absent"); XmlSchemaDerivationMethod allfinal = (XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Restriction); if(final == XmlSchemaDerivationMethod.All) finalResolved = allfinal; else if(final == XmlSchemaDerivationMethod.None) finalResolved = info.BlockDefault & allfinal; else { if((final & ~allfinal) != 0) warn(h,"some values for final are invalid in this context"); finalResolved = final & allfinal; } XmlSchemaDerivationMethod allblock = XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Substitution; if(block == XmlSchemaDerivationMethod.All) blockResolved = allblock; else if(block == XmlSchemaDerivationMethod.None) blockResolved = info.BlockDefault & allblock; else { if((block & ~allblock) != 0) warn(h,"Some of the values for block are invalid in this context"); blockResolved = block & allblock; } if(schemaType != null && schemaTypeName != null && !schemaTypeName.IsEmpty) { error(h,"both schemaType and content can't be present"); } //Even if both are present, read both of them. if(schemaType != null) { if(schemaType is XmlSchemaSimpleType) { errorCount += ((XmlSchemaSimpleType)schemaType).Compile(h,info); } else if(schemaType is XmlSchemaComplexType) { errorCount += ((XmlSchemaComplexType)schemaType).Compile(h,info); } else error(h,"only simpletype or complextype is allowed"); } if(schemaTypeName != null && !schemaTypeName.IsEmpty) { if(!XmlSchemaUtil.CheckQName(SchemaTypeName)) error(h,"SchemaTypeName must be an XmlQualifiedName"); } if(SubstitutionGroup != null && !SubstitutionGroup.IsEmpty) { if(!XmlSchemaUtil.CheckQName(SubstitutionGroup)) error(h,"SubstitutionGroup must be a valid XmlQualifiedName"); } foreach(XmlSchemaObject obj in constraints) { if(obj is XmlSchemaUnique) errorCount += ((XmlSchemaUnique)obj).Compile(h,info); else if(obj is XmlSchemaKey) errorCount += ((XmlSchemaKey)obj).Compile(h,info); else if(obj is XmlSchemaKeyref) errorCount += ((XmlSchemaKeyref)obj).Compile(h,info); } } else { if(substitutionGroup != null && !substitutionGroup.IsEmpty) error(h,"substitutionGroup must be absent"); if(final != XmlSchemaDerivationMethod.None) error(h,"final must be absent"); if(isAbstract) error(h,"abstract must be absent"); //FIXME: Should we reset the values if(MinOccurs > MaxOccurs) error(h,"minOccurs must be less than or equal to maxOccurs"); if(refName == null || RefName.IsEmpty) { if(form == XmlSchemaForm.Qualified || (form == XmlSchemaForm.None && info.ElementFormDefault == XmlSchemaForm.Qualified)) this.targetNamespace = info.TargetNamespace; else this.targetNamespace = string.Empty; if(this.name == null) //b1 error(h,"Required attribute name must be present"); else if(!XmlSchemaUtil.CheckNCName(this.name)) // b1.2 error(h,"attribute name must be NCName"); else this.qName = new XmlQualifiedName(this.name, this.targetNamespace); XmlSchemaDerivationMethod allblock = XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Substitution; if(block == XmlSchemaDerivationMethod.All) blockResolved = allblock; else if(block == XmlSchemaDerivationMethod.None) blockResolved = info.BlockDefault & allblock; else { if((block & ~allblock) != 0) warn(h,"Some of the values for block are invalid in this context"); blockResolved = block & allblock; } if(schemaType != null && schemaTypeName != null && !schemaTypeName.IsEmpty) { error(h,"both schemaType and content can't be present"); } //Even if both are present, read both of them. if(schemaType != null) { if(schemaType is XmlSchemaSimpleType) { errorCount += ((XmlSchemaSimpleType)schemaType).Compile(h,info); } else if(schemaType is XmlSchemaComplexType) { errorCount += ((XmlSchemaComplexType)schemaType).Compile(h,info); } else error(h,"only simpletype or complextype is allowed"); } if(schemaTypeName != null && !schemaTypeName.IsEmpty) { if(!XmlSchemaUtil.CheckQName(SchemaTypeName)) error(h,"SchemaTypeName must be an XmlQualifiedName"); } if(SubstitutionGroup != null && !SubstitutionGroup.IsEmpty) { if(!XmlSchemaUtil.CheckQName(SubstitutionGroup)) error(h,"SubstitutionGroup must be a valid XmlQualifiedName"); } foreach(XmlSchemaObject obj in constraints) { if(obj is XmlSchemaUnique) errorCount += ((XmlSchemaUnique)obj).Compile(h,info); else if(obj is XmlSchemaKey) errorCount += ((XmlSchemaKey)obj).Compile(h,info); else if(obj is XmlSchemaKeyref) errorCount += ((XmlSchemaKeyref)obj).Compile(h,info); } } else { if(!XmlSchemaUtil.CheckQName(RefName)) error(h,"RefName must be a XmlQualifiedName"); if(name != null) error(h,"name must not be present when ref is present"); if(Constraints.Count != 0) error(h,"key, keyref and unique must be absent"); if(isNillable) error(h,"nillable must be absent"); if(defaultValue != null) error(h,"default must be absent"); if(fixedValue != null) error(h,"fixed must be null"); if(form != XmlSchemaForm.None) error(h,"form must be absent"); if(block != XmlSchemaDerivationMethod.None) error(h,"block must be absent"); if(schemaTypeName != null && !schemaTypeName.IsEmpty) error(h,"type must be absent"); if(SchemaType != null) error(h,"simpleType or complexType must be absent"); } } XmlSchemaUtil.CompileID(Id,this,info.IDCollection,h); return errorCount; } [MonoTODO] internal int Validate(ValidationEventHandler h) { return errorCount; } // // Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*)) // internal static XmlSchemaElement Read(XmlSchemaReader reader, ValidationEventHandler h) { XmlSchemaElement element = new XmlSchemaElement(); Exception innerex; reader.MoveToElement(); if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != xmlname) { error(h,"Should not happen :1: XmlSchemaElement.Read, name="+reader.Name,null); reader.Skip(); return null; } element.LineNumber = reader.LineNumber; element.LinePosition = reader.LinePosition; element.SourceUri = reader.BaseURI; while(reader.MoveToNextAttribute()) { if(reader.Name == "abstract") { element.IsAbstract = XmlSchemaUtil.ReadBoolAttribute(reader,out innerex); if(innerex != null) error(h,reader.Value + " is invalid value for abstract",innerex); } else if(reader.Name == "block") { element.block = XmlSchemaUtil.ReadDerivationAttribute(reader,out innerex, "block"); if(innerex != null) warn(h,"some invalid values for block attribute were found",innerex); } else if(reader.Name == "default") { element.defaultValue = reader.Value; } else if(reader.Name == "final") { element.Final = XmlSchemaUtil.ReadDerivationAttribute(reader,out innerex, "block"); if(innerex != null) warn(h,"some invalid values for final attribute were found",innerex); } else if(reader.Name == "fixed") { element.fixedValue = reader.Value; } else if(reader.Name == "form") { element.form = XmlSchemaUtil.ReadFormAttribute(reader,out innerex); if(innerex != null) error(h,reader.Value + " is an invalid value for form attribute",innerex); } else if(reader.Name == "id") { element.Id = reader.Value; } else if(reader.Name == "maxOccurs") { try { element.MaxOccursString = reader.Value; } catch(Exception e) { error(h,reader.Value + " is an invalid value for maxOccurs",e); } } else if(reader.Name == "minOccurs") { try { element.MinOccursString = reader.Value; } catch(Exception e) { error(h,reader.Value + " is an invalid value for minOccurs",e); } } else if(reader.Name == "name") { element.Name = reader.Value; } else if(reader.Name == "nillable") { element.IsNillable = XmlSchemaUtil.ReadBoolAttribute(reader,out innerex); if(innerex != null) error(h,reader.Value + "is not a valid value for nillable",innerex); } else if(reader.Name == "ref") { element.refName = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex); if(innerex != null) error(h, reader.Value + " is not a valid value for ref attribute",innerex); } else if(reader.Name == "substitutionGroup") { element.substitutionGroup = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex); if(innerex != null) error(h, reader.Value + " is not a valid value for substitutionGroup attribute",innerex); } else if(reader.Name == "type") { element.SchemaTypeName = XmlSchemaUtil.ReadQNameAttribute(reader,out innerex); if(innerex != null) error(h, reader.Value + " is not a valid value for type attribute",innerex); } else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace) { error(h,reader.Name + " is not a valid attribute for element",null); } else { XmlSchemaUtil.ReadUnhandledAttribute(reader,element); } } reader.MoveToElement(); if(reader.IsEmptyElement) return element; // Content: annotation?, // (simpleType | complexType)?, // (unique | key | keyref)* int level = 1; while(reader.ReadNextElement()) { if(reader.NodeType == XmlNodeType.EndElement) { if(reader.LocalName != xmlname) error(h,"Should not happen :2: XmlSchemaElement.Read, name="+reader.Name,null); break; } if(level <= 1 && reader.LocalName == "annotation") { level = 2; //Only one annotation XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h); if(annotation != null) element.Annotation = annotation; continue; } if(level <= 2) { if(reader.LocalName == "simpleType") { level = 3; XmlSchemaSimpleType simple = XmlSchemaSimpleType.Read(reader,h); if(simple != null) element.SchemaType = simple; continue; } if(reader.LocalName == "complexType") { level = 3; XmlSchemaComplexType complex = XmlSchemaComplexType.Read(reader,h); if(complex != null) { element.SchemaType = complex; } continue; } } if(level <= 3) { if(reader.LocalName == "unique") { level = 3; XmlSchemaUnique unique = XmlSchemaUnique.Read(reader,h); if(unique != null) element.constraints.Add(unique); continue; } else if(reader.LocalName == "key") { level = 3; XmlSchemaKey key = XmlSchemaKey.Read(reader,h); if(key != null) element.constraints.Add(key); continue; } else if(reader.LocalName == "keyref") { level = 3; XmlSchemaKeyref keyref = XmlSchemaKeyref.Read(reader,h); if(keyref != null) element.constraints.Add(keyref); continue; } } reader.RaiseInvalidElementError(); } return element; } } }