private void CompileElement(XmlSchemaElement xe) {
if (xe.IsProcessing) {
SendValidationEvent(Res.Sch_ElementCircularRef, xe);
return;
}
if (xe.ElementDecl != null) {
return;
}
xe.IsProcessing = true;
SchemaElementDecl decl = null;
try {
if (!xe.RefName.IsEmpty) {
XmlSchemaElement e = (XmlSchemaElement)elements[xe.RefName];
if (e == null) {
throw new XmlSchemaException(Res.Sch_UndeclaredElement, xe.RefName.ToString(), xe);
}
CompileElement(e);
if (e.ElementDecl == null) {
throw new XmlSchemaException(Res.Sch_RefInvalidElement, xe.RefName.ToString(), xe);
}
xe.SetElementType(e.ElementSchemaType);
decl = e.ElementDecl.Clone();
}
else {
if (xe.SchemaType != null) {
xe.SetElementType(xe.SchemaType);
}
else if (!xe.SchemaTypeName.IsEmpty) {
xe.SetElementType(GetAnySchemaType(xe.SchemaTypeName));
if (xe.ElementSchemaType == null) {
throw new XmlSchemaException(Res.Sch_UndeclaredType, xe.SchemaTypeName.ToString(), xe);
}
}
else if (!xe.SubstitutionGroup.IsEmpty) {
XmlSchemaElement examplar = (XmlSchemaElement)elements[xe.SubstitutionGroup];
if (examplar == null) {
throw new XmlSchemaException(Res.Sch_UndeclaredEquivClass, xe.SubstitutionGroup.Name.ToString(CultureInfo.InvariantCulture), xe);
}
if (examplar.IsProcessing) { //Circular subst group; already detected by now
return;
}
CompileElement(examplar);
if (examplar.ElementDecl == null) { //If head is invalid, fall back to AnyType
xe.SetElementType(XmlSchemaComplexType.AnyType);
decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
}
else {
xe.SetElementType(examplar.ElementSchemaType);
decl = examplar.ElementDecl.Clone();
}
}
else {
xe.SetElementType(XmlSchemaComplexType.AnyType);
decl = XmlSchemaComplexType.AnyType.ElementDecl.Clone();
}
if (decl == null) {
Debug.Assert(xe.ElementSchemaType != null);
if (xe.ElementSchemaType is XmlSchemaComplexType) {
XmlSchemaComplexType complexType = (XmlSchemaComplexType)xe.ElementSchemaType;
CompileComplexType(complexType);
if (complexType.ElementDecl != null) {
decl = complexType.ElementDecl.Clone();
// decl.LocalElements = complexType.LocalElementDecls;
}
}
else if (xe.ElementSchemaType is XmlSchemaSimpleType) {
XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)xe.ElementSchemaType;
CompileSimpleType(simpleType);
if (simpleType.ElementDecl != null) {
decl = simpleType.ElementDecl.Clone();
}
}
}
Debug.Assert(decl != null);
decl.Name = xe.QualifiedName;
decl.IsAbstract = xe.IsAbstract;
XmlSchemaComplexType ct = xe.ElementSchemaType as XmlSchemaComplexType;
if (ct != null) {
decl.IsAbstract |= ct.IsAbstract;
}
decl.IsNillable = xe.IsNillable;
decl.Block |= xe.BlockResolved;
}
if (decl.Datatype != null) {
decl.Datatype.VerifySchemaValid(notations, xe);
}
if (xe.DefaultValue != null || xe.FixedValue != null) {
if (decl.ContentValidator != null) {
if (decl.ContentValidator.ContentType == XmlSchemaContentType.TextOnly || (decl.ContentValidator.ContentType == XmlSchemaContentType.Mixed && decl.ContentValidator.IsEmptiable)) {
if (xe.DefaultValue != null) {
decl.Presence = SchemaDeclBase.Use.Default;
decl.DefaultValueRaw = xe.DefaultValue;
}
else {
decl.Presence = SchemaDeclBase.Use.Fixed;
decl.DefaultValueRaw = xe.FixedValue;
}
if (decl.Datatype != null) {
if (decl.Datatype.TypeCode == XmlTypeCode.Id) {
SendValidationEvent(Res.Sch_DefaultIdValue, xe);
}
else {
decl.DefaultValueTyped = decl.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe), true);
}
}
else { //Mixed with emptiable particle
decl.DefaultValueTyped = DatatypeImplementation.AnySimpleType.Datatype.ParseValue(decl.DefaultValueRaw, NameTable, new SchemaNamespaceManager(xe));
}
}
else {
throw new XmlSchemaException(Res.Sch_ElementCannotHaveValue, xe);
}
}
}
if (xe.HasConstraints) {
XmlSchemaObjectCollection constraints = xe.Constraints;
CompiledIdentityConstraint[] compiledConstraints = new CompiledIdentityConstraint[constraints.Count];
int idx = 0;
foreach(XmlSchemaIdentityConstraint constraint in constraints) {
CompileIdentityConstraint (constraint);
compiledConstraints[idx ++] = constraint.CompiledConstraint;
}
decl.Constraints = compiledConstraints;
}
decl.SchemaElement = xe; //So this is available for PSVI
xe.ElementDecl = decl;
}
catch (XmlSchemaException e) {
if (e.SourceSchemaObject == null) {
e.SetSource(xe);
}
SendValidationEvent(e);
xe.ElementDecl = SchemaElementDecl.Empty;
}
finally {
xe.IsProcessing = false;
}
}