//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // Microsoft //------------------------------------------------------------------------------ namespace System.Xml.Schema { using System.IO; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.ComponentModel; using System.Globalization; using System.Runtime.Versioning; /* * The XdrBuilder class parses the XDR Schema and * builds internal validation information */ internal sealed class XdrBuilder : SchemaBuilder { private const int XdrSchema = 1; private const int XdrElementType = 2; private const int XdrAttributeType = 3; private const int XdrElement = 4; private const int XdrAttribute = 5; private const int XdrGroup = 6; private const int XdrElementDatatype = 7; private const int XdrAttributeDatatype = 8; private const int SchemaFlagsNs = 0x0100; private const int StackIncrement = 10; private const int SchemaOrderNone = 0; private const int SchemaOrderMany = 1; private const int SchemaOrderSequence = 2; private const int SchemaOrderChoice = 3; private const int SchemaOrderAll = 4; private const int SchemaContentNone = 0; private const int SchemaContentEmpty = 1; private const int SchemaContentText = 2; private const int SchemaContentMixed = 3; private const int SchemaContentElement = 4; private sealed class DeclBaseInfo { // used for e1 has to have a () internal bool _ExistTerminal; // when there exist a terminal, we need to addOrder before // we can add another terminal internal bool _AllowDataType; // must have textOnly if we have datatype internal bool _HasDataType; // got data type // for = x_schema.Length && 0 == string.Compare(uri, 0, x_schema, 0, x_schema.Length, StringComparison.Ordinal) && !uri.StartsWith("x-schema:#", StringComparison.Ordinal); } internal override bool IsContentParsed() { return true; } internal override void ProcessMarkup(XmlNode[] markup) { throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation)); // should never be called } internal override void ProcessCData(string value) { if (_CurState._AllowText) { _Text = value; } else { SendValidationEvent(Res.Sch_TextNotAllowed, value); } } internal override void StartChildren() { if (_CurState._BeginChildFunc != null) { (this._CurState._BeginChildFunc)(this); } } internal override void EndChildren() { if (_CurState._EndChildFunc != null) { (this._CurState._EndChildFunc)(this); } Pop(); } // // State stack push & pop // private void Push() { _StateHistory.Push(); _StateHistory[_StateHistory.Length - 1] = _CurState; _CurState = _NextState; } private void Pop() { _CurState = (XdrEntry)_StateHistory.Pop(); } // // Group stack push & pop // private void PushGroupInfo() { _GroupStack.Push(); _GroupStack[_GroupStack.Length - 1] = GroupContent.Copy(_GroupDef); } private void PopGroupInfo() { _GroupDef = (GroupContent)_GroupStack.Pop(); Debug.Assert(_GroupDef != null); } // // XDR Schema // private static void XDR_InitRoot(XdrBuilder builder, object obj) { builder._SchemaInfo.SchemaType = SchemaType.XDR; builder._ElementDef._ElementDecl = null; builder._ElementDef._AttDefList = null; builder._AttributeDef._AttDef = null; } private static void XDR_BuildRoot_Name(XdrBuilder builder, object obj, string prefix) { builder._XdrName = (string) obj; builder._XdrPrefix = prefix; } private static void XDR_BuildRoot_ID(XdrBuilder builder, object obj, string prefix) { } private static void XDR_BeginRoot(XdrBuilder builder) { if (builder._TargetNamespace == null) { // inline xdr schema if (builder._XdrName != null) { builder._TargetNamespace = builder._NameTable.Add("x-schema:#" + builder._XdrName); } else { builder._TargetNamespace = String.Empty; } } builder._SchemaInfo.TargetNamespaces.Add(builder._TargetNamespace, true); } private static void XDR_EndRoot(XdrBuilder builder) { // // check undefined attribute types // We already checked local attribute types, so only need to check global attribute types here // while (builder._UndefinedAttributeTypes != null) { XmlQualifiedName gname = builder._UndefinedAttributeTypes._TypeName; // if there is no URN in this name then the name is local to the // schema, but the global attribute was still URN qualified, so // we need to qualify this name now. if (gname.Namespace.Length == 0) { gname = new XmlQualifiedName(gname.Name, builder._TargetNamespace); } SchemaAttDef ad; if (builder._SchemaInfo.AttributeDecls.TryGetValue(gname, out ad)) { builder._UndefinedAttributeTypes._Attdef = (SchemaAttDef)ad.Clone(); builder._UndefinedAttributeTypes._Attdef.Name = gname; builder.XDR_CheckAttributeDefault(builder._UndefinedAttributeTypes, builder._UndefinedAttributeTypes._Attdef); } else { builder.SendValidationEvent(Res.Sch_UndeclaredAttribute, gname.Name); } builder._UndefinedAttributeTypes = builder._UndefinedAttributeTypes._Next; } foreach (SchemaElementDecl ed in builder._UndeclaredElements.Values) { builder.SendValidationEvent(Res.Sch_UndeclaredElement, XmlQualifiedName.ToString(ed.Name.Name, ed.Prefix)); } } // // XDR ElementType // private static void XDR_InitElementType(XdrBuilder builder, object obj) { builder._ElementDef._ElementDecl = new SchemaElementDecl(); builder._contentValidator = new ParticleContentValidator(XmlSchemaContentType.Mixed); builder._contentValidator.IsOpen = true; builder._ElementDef._ContentAttr = SchemaContentNone; builder._ElementDef._OrderAttr = SchemaOrderNone; builder._ElementDef._MasterGroupRequired = false; builder._ElementDef._ExistTerminal = false; builder._ElementDef._AllowDataType = true; builder._ElementDef._HasDataType = false; builder._ElementDef._EnumerationRequired= false; builder._ElementDef._AttDefList = new Hashtable(); builder._ElementDef._MaxLength = uint.MaxValue; builder._ElementDef._MinLength = uint.MaxValue; // builder._AttributeDef._HasDataType = false; // builder._AttributeDef._Default = null; } private static void XDR_BuildElementType_Name(XdrBuilder builder, object obj, string prefix) { XmlQualifiedName qname = (XmlQualifiedName) obj; if (builder._SchemaInfo.ElementDecls.ContainsKey(qname)) { builder.SendValidationEvent(Res.Sch_DupElementDecl, XmlQualifiedName.ToString(qname.Name, prefix)); } builder._ElementDef._ElementDecl.Name = qname; builder._ElementDef._ElementDecl.Prefix = prefix; builder._SchemaInfo.ElementDecls.Add(qname, builder._ElementDef._ElementDecl); if (builder._UndeclaredElements[qname] != null) { builder._UndeclaredElements.Remove(qname); } } private static void XDR_BuildElementType_Content(XdrBuilder builder, object obj, string prefix) { builder._ElementDef._ContentAttr = builder.GetContent((XmlQualifiedName)obj); } private static void XDR_BuildElementType_Model(XdrBuilder builder, object obj, string prefix) { builder._contentValidator.IsOpen = builder.GetModel((XmlQualifiedName)obj); } private static void XDR_BuildElementType_Order(XdrBuilder builder, object obj, string prefix) { builder._ElementDef._OrderAttr = builder._GroupDef._Order = builder.GetOrder((XmlQualifiedName)obj); } private static void XDR_BuildElementType_DtType(XdrBuilder builder, object obj, string prefix) { builder._ElementDef._HasDataType = true; string s = ((string)obj).Trim(); if (s.Length == 0) { builder.SendValidationEvent(Res.Sch_MissDtvalue); } else { XmlSchemaDatatype dtype = XmlSchemaDatatype.FromXdrName(s); if (dtype == null) { builder.SendValidationEvent(Res.Sch_UnknownDtType, s); } builder._ElementDef._ElementDecl.Datatype = dtype; } } private static void XDR_BuildElementType_DtValues(XdrBuilder builder, object obj, string prefix) { builder._ElementDef._EnumerationRequired = true; builder._ElementDef._ElementDecl.Values = new List((string[]) obj); } private static void XDR_BuildElementType_DtMaxLength(XdrBuilder builder, object obj, string prefix) { ParseDtMaxLength(ref builder._ElementDef._MaxLength, obj, builder); } private static void XDR_BuildElementType_DtMinLength(XdrBuilder builder, object obj, string prefix) { ParseDtMinLength(ref builder._ElementDef._MinLength, obj, builder); } private static void XDR_BeginElementType(XdrBuilder builder) { string code = null; string msg = null; // // check name attribute // if (builder._ElementDef._ElementDecl.Name.IsEmpty) { code = Res.Sch_MissAttribute; msg = "name"; goto cleanup; } // // check dt:type attribute // if (builder._ElementDef._HasDataType) { if (!builder._ElementDef._AllowDataType) { code = Res.Sch_DataTypeTextOnly; goto cleanup; } else { builder._ElementDef._ContentAttr = SchemaContentText; } } else if (builder._ElementDef._ContentAttr == SchemaContentNone) { switch (builder._ElementDef._OrderAttr) { case SchemaOrderNone: builder._ElementDef._ContentAttr = SchemaContentMixed; builder._ElementDef._OrderAttr = SchemaOrderMany; break; case SchemaOrderSequence: builder._ElementDef._ContentAttr = SchemaContentElement; break; case SchemaOrderChoice: builder._ElementDef._ContentAttr = SchemaContentElement; break; case SchemaOrderMany: builder._ElementDef._ContentAttr = SchemaContentMixed; break; } } //save the model value from the base bool tempOpen = builder._contentValidator.IsOpen; ElementContent def = builder._ElementDef; switch (builder._ElementDef._ContentAttr) { case SchemaContentText: builder._ElementDef._ElementDecl.ContentValidator = ContentValidator.TextOnly; builder._GroupDef._Order = SchemaOrderMany; builder._contentValidator = null; break; case SchemaContentElement: builder._contentValidator = new ParticleContentValidator(XmlSchemaContentType.ElementOnly); if (def._OrderAttr == SchemaOrderNone) { builder._GroupDef._Order = SchemaOrderSequence; } def._MasterGroupRequired = true; builder._contentValidator.IsOpen = tempOpen; break; case SchemaContentEmpty: builder._ElementDef._ElementDecl.ContentValidator = ContentValidator.Empty; builder._contentValidator = null; break; case SchemaContentMixed: if (def._OrderAttr == SchemaOrderNone || def._OrderAttr == SchemaOrderMany) { builder._GroupDef._Order = SchemaOrderMany; } else { code = Res.Sch_MixedMany; goto cleanup; } def._MasterGroupRequired = true; builder._contentValidator.IsOpen = tempOpen; break; } if (def._ContentAttr == SchemaContentMixed || def._ContentAttr == SchemaContentElement) { builder._contentValidator.Start(); builder._contentValidator.OpenGroup(); } cleanup: if (code != null) { builder.SendValidationEvent(code, msg); } } private static void XDR_EndElementType(XdrBuilder builder) { SchemaElementDecl ed = builder._ElementDef._ElementDecl; // check undefined attribute types first if (builder._UndefinedAttributeTypes != null && builder._ElementDef._AttDefList != null) { DeclBaseInfo patt = builder._UndefinedAttributeTypes; DeclBaseInfo p1 = patt; while (patt != null) { SchemaAttDef pAttdef = null; if (patt._ElementDecl == ed) { XmlQualifiedName pName = patt._TypeName; pAttdef = (SchemaAttDef)builder._ElementDef._AttDefList[pName]; if (pAttdef != null) { patt._Attdef = (SchemaAttDef)pAttdef.Clone(); patt._Attdef.Name = pName; builder.XDR_CheckAttributeDefault(patt, pAttdef); // remove it from _pUndefinedAttributeTypes if (patt == builder._UndefinedAttributeTypes) { patt = builder._UndefinedAttributeTypes = patt._Next; p1 = patt; } else { p1._Next = patt._Next; patt = p1._Next; } } } if (pAttdef == null) { if (patt != builder._UndefinedAttributeTypes) p1 = p1._Next; patt = patt._Next; } } } if (builder._ElementDef._MasterGroupRequired) { // if the content is mixed, there is a group that need to be closed builder._contentValidator.CloseGroup(); if (!builder._ElementDef._ExistTerminal) { if (builder._contentValidator.IsOpen) { builder._ElementDef._ElementDecl.ContentValidator = ContentValidator.Any; builder._contentValidator = null; } else { if(builder._ElementDef._ContentAttr != SchemaContentMixed) builder.SendValidationEvent(Res.Sch_ElementMissing); } } else { if (builder._GroupDef._Order == SchemaOrderMany) { builder._contentValidator.AddStar(); } } } if (ed.Datatype != null) { XmlTokenizedType ttype = ed.Datatype.TokenizedType; if (ttype == XmlTokenizedType.ENUMERATION && !builder._ElementDef._EnumerationRequired) { builder.SendValidationEvent(Res.Sch_MissDtvaluesAttribute); } if (ttype != XmlTokenizedType.ENUMERATION && builder._ElementDef._EnumerationRequired) { builder.SendValidationEvent(Res.Sch_RequireEnumeration); } } CompareMinMaxLength(builder._ElementDef._MinLength, builder._ElementDef._MaxLength, builder); ed.MaxLength = (long)builder._ElementDef._MaxLength; ed.MinLength = (long)builder._ElementDef._MinLength; if (builder._contentValidator != null) { builder._ElementDef._ElementDecl.ContentValidator = builder._contentValidator.Finish(true); builder._contentValidator = null; } builder._ElementDef._ElementDecl = null; builder._ElementDef._AttDefList = null; } // // XDR AttributeType // private static void XDR_InitAttributeType(XdrBuilder builder, object obj) { AttributeContent ad = builder._AttributeDef; ad._AttDef = new SchemaAttDef(XmlQualifiedName.Empty, null); ad._Required = false; ad._Prefix = null; ad._Default = null; ad._MinVal = 0; // optional by default. ad._MaxVal = 1; // used for datatype ad._EnumerationRequired = false; ad._HasDataType = false; ad._Global = (builder._StateHistory.Length == 2); ad._MaxLength = uint.MaxValue; ad._MinLength = uint.MaxValue; } private static void XDR_BuildAttributeType_Name(XdrBuilder builder, object obj, string prefix) { XmlQualifiedName qname = (XmlQualifiedName) obj; builder._AttributeDef._Name = qname; builder._AttributeDef._Prefix = prefix; builder._AttributeDef._AttDef.Name = qname; if (builder._ElementDef._ElementDecl != null) { // Local AttributeType if (builder._ElementDef._AttDefList[qname] == null) { builder._ElementDef._AttDefList.Add(qname, builder._AttributeDef._AttDef); } else { builder.SendValidationEvent(Res.Sch_DupAttribute, XmlQualifiedName.ToString(qname.Name, prefix)); } } else { // Global AttributeType // Global AttributeTypes are URN qualified so that we can look them up across schemas. qname = new XmlQualifiedName(qname.Name, builder._TargetNamespace); builder._AttributeDef._AttDef.Name = qname; if (!builder._SchemaInfo.AttributeDecls.ContainsKey(qname)) { builder._SchemaInfo.AttributeDecls.Add(qname, builder._AttributeDef._AttDef); } else { builder.SendValidationEvent(Res.Sch_DupAttribute, XmlQualifiedName.ToString(qname.Name, prefix)); } } } private static void XDR_BuildAttributeType_Required(XdrBuilder builder, object obj, string prefix) { builder._AttributeDef._Required = IsYes(obj, builder); } private static void XDR_BuildAttributeType_Default(XdrBuilder builder, object obj, string prefix) { builder._AttributeDef._Default = obj; } private static void XDR_BuildAttributeType_DtType(XdrBuilder builder, object obj, string prefix) { XmlQualifiedName qname = (XmlQualifiedName)obj; builder._AttributeDef._HasDataType = true; builder._AttributeDef._AttDef.Datatype = builder.CheckDatatype(qname.Name); } private static void XDR_BuildAttributeType_DtValues(XdrBuilder builder, object obj, string prefix) { builder._AttributeDef._EnumerationRequired = true; builder._AttributeDef._AttDef.Values = new List((string[]) obj); } private static void XDR_BuildAttributeType_DtMaxLength(XdrBuilder builder, object obj, string prefix) { ParseDtMaxLength(ref builder._AttributeDef._MaxLength, obj, builder); } private static void XDR_BuildAttributeType_DtMinLength(XdrBuilder builder, object obj, string prefix) { ParseDtMinLength(ref builder._AttributeDef._MinLength, obj, builder); } private static void XDR_BeginAttributeType(XdrBuilder builder) { if (builder._AttributeDef._Name.IsEmpty) { builder.SendValidationEvent(Res.Sch_MissAttribute); } } private static void XDR_EndAttributeType(XdrBuilder builder) { string code = null; if (builder._AttributeDef._HasDataType && builder._AttributeDef._AttDef.Datatype != null) { XmlTokenizedType ttype = builder._AttributeDef._AttDef.Datatype.TokenizedType; if (ttype == XmlTokenizedType.ENUMERATION && !builder._AttributeDef._EnumerationRequired) { code = Res.Sch_MissDtvaluesAttribute; goto cleanup; } if (ttype != XmlTokenizedType.ENUMERATION && builder._AttributeDef._EnumerationRequired) { code = Res.Sch_RequireEnumeration; goto cleanup; } // a attributes of type id is not supposed to have a default value if (builder._AttributeDef._Default != null && ttype == XmlTokenizedType.ID) { code = Res.Sch_DefaultIdValue; goto cleanup; } } else { builder._AttributeDef._AttDef.Datatype = XmlSchemaDatatype.FromXmlTokenizedType(XmlTokenizedType.CDATA); } // // constraints // CompareMinMaxLength(builder._AttributeDef._MinLength, builder._AttributeDef._MaxLength, builder); builder._AttributeDef._AttDef.MaxLength = builder._AttributeDef._MaxLength; builder._AttributeDef._AttDef.MinLength = builder._AttributeDef._MinLength; // // checkAttributeType // if (builder._AttributeDef._Default != null) { builder._AttributeDef._AttDef.DefaultValueRaw = builder._AttributeDef._AttDef.DefaultValueExpanded = (string)builder._AttributeDef._Default; builder.CheckDefaultAttValue(builder._AttributeDef._AttDef); } builder.SetAttributePresence(builder._AttributeDef._AttDef, builder._AttributeDef._Required); cleanup: if (code != null) { builder.SendValidationEvent(code); } } // // XDR Element // private static void XDR_InitElement(XdrBuilder builder, object obj) { if (builder._ElementDef._HasDataType || (builder._ElementDef._ContentAttr == SchemaContentEmpty) || (builder._ElementDef._ContentAttr == SchemaContentText)) { builder.SendValidationEvent(Res.Sch_ElementNotAllowed); } builder._ElementDef._AllowDataType = false; builder._ElementDef._HasType = false; builder._ElementDef._MinVal = 1; builder._ElementDef._MaxVal = 1; } private static void XDR_BuildElement_Type(XdrBuilder builder, object obj, string prefix) { XmlQualifiedName qname = (XmlQualifiedName) obj; if (!builder._SchemaInfo.ElementDecls.ContainsKey(qname)) { SchemaElementDecl ed = (SchemaElementDecl)builder._UndeclaredElements[qname]; if (ed == null) { ed = new SchemaElementDecl(qname, prefix); builder._UndeclaredElements.Add(qname, ed); } } builder._ElementDef._HasType = true; if (builder._ElementDef._ExistTerminal) builder.AddOrder(); else builder._ElementDef._ExistTerminal = true; builder._contentValidator.AddName(qname, null); } private static void XDR_BuildElement_MinOccurs(XdrBuilder builder, object obj, string prefix) { builder._ElementDef._MinVal = ParseMinOccurs(obj, builder); } private static void XDR_BuildElement_MaxOccurs(XdrBuilder builder, object obj, string prefix) { builder._ElementDef._MaxVal = ParseMaxOccurs(obj, builder); } // private static void XDR_BeginElement(XdrBuilder builder) // { // // } private static void XDR_EndElement(XdrBuilder builder) { if (builder._ElementDef._HasType) { HandleMinMax(builder._contentValidator, builder._ElementDef._MinVal, builder._ElementDef._MaxVal); } else { builder.SendValidationEvent(Res.Sch_MissAttribute); } } // // XDR Attribute // private static void XDR_InitAttribute(XdrBuilder builder, object obj) { if (builder._BaseDecl == null) builder._BaseDecl = new DeclBaseInfo(); builder._BaseDecl._MinOccurs = 0; } private static void XDR_BuildAttribute_Type(XdrBuilder builder, object obj, string prefix) { builder._BaseDecl._TypeName = (XmlQualifiedName)obj; builder._BaseDecl._Prefix = prefix; } private static void XDR_BuildAttribute_Required(XdrBuilder builder, object obj, string prefix) { if (IsYes(obj, builder)) { builder._BaseDecl._MinOccurs = 1; } } private static void XDR_BuildAttribute_Default(XdrBuilder builder, object obj, string prefix) { builder._BaseDecl._Default = obj; } private static void XDR_BeginAttribute(XdrBuilder builder) { if (builder._BaseDecl._TypeName.IsEmpty) { builder.SendValidationEvent(Res.Sch_MissAttribute); } SchemaAttDef attdef = null; XmlQualifiedName qname = builder._BaseDecl._TypeName; string prefix = builder._BaseDecl._Prefix; // local? if (builder._ElementDef._AttDefList != null) { attdef = (SchemaAttDef)builder._ElementDef._AttDefList[qname]; } // global? if (attdef == null) { // if there is no URN in this name then the name is local to the // schema, but the global attribute was still URN qualified, so // we need to qualify this name now. XmlQualifiedName gname = qname; if (prefix.Length == 0) gname = new XmlQualifiedName(qname.Name, builder._TargetNamespace); SchemaAttDef ad; if (builder._SchemaInfo.AttributeDecls.TryGetValue(gname, out ad)) { attdef = (SchemaAttDef)ad.Clone(); attdef.Name = qname; } else if (prefix.Length != 0) { builder.SendValidationEvent(Res.Sch_UndeclaredAttribute, XmlQualifiedName.ToString(qname.Name, prefix)); } } if (attdef != null) { builder.XDR_CheckAttributeDefault(builder._BaseDecl, attdef); } else { // will process undeclared types later attdef = new SchemaAttDef(qname, prefix); DeclBaseInfo decl = new DeclBaseInfo(); decl._Checking = true; decl._Attdef = attdef; decl._TypeName = builder._BaseDecl._TypeName; decl._ElementDecl = builder._ElementDef._ElementDecl; decl._MinOccurs = builder._BaseDecl._MinOccurs; decl._Default = builder._BaseDecl._Default; // add undefined attribute types decl._Next = builder._UndefinedAttributeTypes; builder._UndefinedAttributeTypes = decl; } builder._ElementDef._ElementDecl.AddAttDef(attdef); } private static void XDR_EndAttribute(XdrBuilder builder) { builder._BaseDecl.Reset(); } // // XDR Group // private static void XDR_InitGroup(XdrBuilder builder, object obj) { if (builder._ElementDef._ContentAttr == SchemaContentEmpty || builder._ElementDef._ContentAttr == SchemaContentText ) { builder.SendValidationEvent(Res.Sch_GroupDisabled); } builder.PushGroupInfo(); builder._GroupDef._MinVal = 1; builder._GroupDef._MaxVal = 1; builder._GroupDef._HasMaxAttr = false; builder._GroupDef._HasMinAttr = false; if (builder._ElementDef._ExistTerminal) builder.AddOrder(); // now we are in a group so we reset fExistTerminal builder._ElementDef._ExistTerminal = false; builder._contentValidator.OpenGroup(); } private static void XDR_BuildGroup_Order(XdrBuilder builder, object obj, string prefix) { builder._GroupDef._Order = builder.GetOrder((XmlQualifiedName)obj); if (builder._ElementDef._ContentAttr == SchemaContentMixed && builder._GroupDef._Order != SchemaOrderMany) { builder.SendValidationEvent(Res.Sch_MixedMany); } } private static void XDR_BuildGroup_MinOccurs(XdrBuilder builder, object obj, string prefix) { builder._GroupDef._MinVal = ParseMinOccurs(obj, builder); builder._GroupDef._HasMinAttr = true; } private static void XDR_BuildGroup_MaxOccurs(XdrBuilder builder, object obj, string prefix) { builder._GroupDef._MaxVal = ParseMaxOccurs(obj, builder); builder._GroupDef._HasMaxAttr = true; } // private static void XDR_BeginGroup(XdrBuilder builder) // { // // } private static void XDR_EndGroup(XdrBuilder builder) { if (!builder._ElementDef._ExistTerminal) { builder.SendValidationEvent(Res.Sch_ElementMissing); } builder._contentValidator.CloseGroup(); if (builder._GroupDef._Order == SchemaOrderMany) { builder._contentValidator.AddStar(); } if (SchemaOrderMany == builder._GroupDef._Order && builder._GroupDef._HasMaxAttr && builder._GroupDef._MaxVal != uint.MaxValue) { builder.SendValidationEvent(Res.Sch_ManyMaxOccurs); } HandleMinMax(builder._contentValidator, builder._GroupDef._MinVal, builder._GroupDef._MaxVal); builder.PopGroupInfo(); } // // DataType // private static void XDR_InitElementDtType(XdrBuilder builder, object obj) { if (builder._ElementDef._HasDataType) { builder.SendValidationEvent(Res.Sch_DupDtType); } if (!builder._ElementDef._AllowDataType) { builder.SendValidationEvent(Res.Sch_DataTypeTextOnly); } } private static void XDR_EndElementDtType(XdrBuilder builder) { if (!builder._ElementDef._HasDataType) { builder.SendValidationEvent(Res.Sch_MissAttribute); } builder._ElementDef._ElementDecl.ContentValidator = ContentValidator.TextOnly; builder._ElementDef._ContentAttr = SchemaContentText; builder._ElementDef._MasterGroupRequired = false; builder._contentValidator = null; } private static void XDR_InitAttributeDtType(XdrBuilder builder, object obj) { if (builder._AttributeDef._HasDataType) { builder.SendValidationEvent(Res.Sch_DupDtType); } } private static void XDR_EndAttributeDtType(XdrBuilder builder) { string code = null; if (!builder._AttributeDef._HasDataType) { code = Res.Sch_MissAttribute; } else { if(builder._AttributeDef._AttDef.Datatype != null) { XmlTokenizedType ttype = builder._AttributeDef._AttDef.Datatype.TokenizedType; if (ttype == XmlTokenizedType.ENUMERATION && !builder._AttributeDef._EnumerationRequired) { code = Res.Sch_MissDtvaluesAttribute; } else if (ttype != XmlTokenizedType.ENUMERATION && builder._AttributeDef._EnumerationRequired) { code = Res.Sch_RequireEnumeration; } } } if (code != null) { builder.SendValidationEvent(code); } } // // private utility methods // private bool GetNextState(XmlQualifiedName qname) { if (_CurState._NextStates != null) { for (int i = 0; i < _CurState._NextStates.Length; i ++) { if (_SchemaNames.TokenToQName[(int)S_SchemaEntries[_CurState._NextStates[i]]._Name].Equals(qname)) { _NextState = S_SchemaEntries[_CurState._NextStates[i]]; return true; } } } return false; } private bool IsSkipableElement(XmlQualifiedName qname) { string ns = qname.Namespace; if (ns != null && ! Ref.Equal(ns, _SchemaNames.NsXdr)) return true; // skip description && extends if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.XdrDescription].Equals(qname) || _SchemaNames.TokenToQName[(int)SchemaNames.Token.XdrExtends].Equals(qname)) return true; return false; } private bool IsSkipableAttribute(XmlQualifiedName qname) { string ns = qname.Namespace; if ( ns.Length != 0 && ! Ref.Equal(ns, _SchemaNames.NsXdr) && ! Ref.Equal(ns, _SchemaNames.NsDataType) ) { return true; } if (Ref.Equal(ns, _SchemaNames.NsDataType) && _CurState._Name == SchemaNames.Token.XdrDatatype && (_SchemaNames.QnDtMax.Equals(qname) || _SchemaNames.QnDtMin.Equals(qname) || _SchemaNames.QnDtMaxExclusive.Equals(qname) || _SchemaNames.QnDtMinExclusive.Equals(qname) )) { return true; } return false; } private int GetOrder(XmlQualifiedName qname) { int order = 0; if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaSeq].Equals(qname)) { order = SchemaOrderSequence; } else if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaOne].Equals(qname)) { order = SchemaOrderChoice; } else if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaMany].Equals(qname)) { order = SchemaOrderMany; } else { SendValidationEvent(Res.Sch_UnknownOrder, qname.Name); } return order; } private void AddOrder() { // additional order can be add on by changing the setOrder and addOrder switch (_GroupDef._Order) { case SchemaOrderSequence: _contentValidator.AddSequence(); break; case SchemaOrderChoice: case SchemaOrderMany: _contentValidator.AddChoice(); break; default: case SchemaOrderAll: throw new XmlException(Res.Xml_UnexpectedToken, "NAME"); } } private static bool IsYes(object obj, XdrBuilder builder) { XmlQualifiedName qname = (XmlQualifiedName)obj; bool fYes = false; if (qname.Name == "yes") { fYes = true; } else if (qname.Name != "no") { builder.SendValidationEvent(Res.Sch_UnknownRequired); } return fYes; } private static uint ParseMinOccurs(object obj, XdrBuilder builder) { uint cVal = 1; if (!ParseInteger((string) obj, ref cVal) || (cVal != 0 && cVal != 1)) { builder.SendValidationEvent(Res.Sch_MinOccursInvalid); } return cVal; } private static uint ParseMaxOccurs(object obj, XdrBuilder builder) { uint cVal = uint.MaxValue; string s = (string)obj; if (!s.Equals("*") && (!ParseInteger(s, ref cVal) || (cVal != uint.MaxValue && cVal != 1))) { builder.SendValidationEvent(Res.Sch_MaxOccursInvalid); } return cVal; } private static void HandleMinMax(ParticleContentValidator pContent, uint cMin, uint cMax) { if (pContent != null) { if (cMax == uint.MaxValue) { if (cMin == 0) pContent.AddStar(); // minOccurs="0" and maxOccurs="infinite" else pContent.AddPlus(); // minOccurs="1" and maxOccurs="infinite" } else if (cMin == 0) { // minOccurs="0" and maxOccurs="1") pContent.AddQMark(); } } } private static void ParseDtMaxLength(ref uint cVal, object obj, XdrBuilder builder) { if (uint.MaxValue != cVal) { builder.SendValidationEvent(Res.Sch_DupDtMaxLength); } if (!ParseInteger((string) obj, ref cVal) || cVal < 0) { builder.SendValidationEvent(Res.Sch_DtMaxLengthInvalid, obj.ToString()); } } private static void ParseDtMinLength(ref uint cVal, object obj, XdrBuilder builder) { if (uint.MaxValue != cVal) { builder.SendValidationEvent(Res.Sch_DupDtMinLength); } if (!ParseInteger((string)obj, ref cVal) || cVal < 0) { builder.SendValidationEvent(Res.Sch_DtMinLengthInvalid, obj.ToString()); } } private static void CompareMinMaxLength(uint cMin, uint cMax, XdrBuilder builder) { if (cMin != uint.MaxValue && cMax != uint.MaxValue && cMin > cMax) { builder.SendValidationEvent(Res.Sch_DtMinMaxLength); } } private static bool ParseInteger(string str, ref uint n) { return UInt32.TryParse(str,NumberStyles.AllowLeadingWhite|NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo, out n); } private void XDR_CheckAttributeDefault(DeclBaseInfo decl, SchemaAttDef pAttdef) { if (decl._Default != null || pAttdef.DefaultValueTyped != null) { if (decl._Default != null) { pAttdef.DefaultValueRaw = pAttdef.DefaultValueExpanded = (string)decl._Default; CheckDefaultAttValue(pAttdef); } } SetAttributePresence(pAttdef, 1 == decl._MinOccurs); } private void SetAttributePresence(SchemaAttDef pAttdef, bool fRequired) { if (SchemaDeclBase.Use.Fixed != pAttdef.Presence) { if (fRequired || SchemaDeclBase.Use.Required == pAttdef.Presence) { // If it is required and it has a default value then it is a FIXED attribute. if (pAttdef.DefaultValueTyped != null) pAttdef.Presence = SchemaDeclBase.Use.Fixed; else pAttdef.Presence = SchemaDeclBase.Use.Required; } else if (pAttdef.DefaultValueTyped != null) { pAttdef.Presence = SchemaDeclBase.Use.Default; } else { pAttdef.Presence = SchemaDeclBase.Use.Implied; } } } private int GetContent(XmlQualifiedName qname) { int content = 0; if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaEmpty].Equals(qname)) { content = SchemaContentEmpty; _ElementDef._AllowDataType = false; } else if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaElementOnly].Equals(qname)) { content = SchemaContentElement; _ElementDef._AllowDataType = false; } else if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaMixed].Equals(qname)) { content = SchemaContentMixed; _ElementDef._AllowDataType = false; } else if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaTextOnly].Equals(qname)) { content = SchemaContentText; } else { SendValidationEvent(Res.Sch_UnknownContent, qname.Name); } return content; } private bool GetModel(XmlQualifiedName qname) { bool fOpen = false; if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaOpen].Equals(qname)) fOpen = true; else if (_SchemaNames.TokenToQName[(int)SchemaNames.Token.SchemaClosed].Equals(qname)) fOpen = false; else SendValidationEvent(Res.Sch_UnknownModel, qname.Name); return fOpen; } private XmlSchemaDatatype CheckDatatype(string str) { XmlSchemaDatatype dtype = XmlSchemaDatatype.FromXdrName(str); if (dtype == null) { SendValidationEvent(Res.Sch_UnknownDtType, str); } else if (dtype.TokenizedType == XmlTokenizedType.ID) { if (! _AttributeDef._Global) { if (_ElementDef._ElementDecl.IsIdDeclared) { SendValidationEvent(Res.Sch_IdAttrDeclared, XmlQualifiedName.ToString(_ElementDef._ElementDecl.Name.Name, _ElementDef._ElementDecl.Prefix)); } _ElementDef._ElementDecl.IsIdDeclared = true; } } return dtype; } private void CheckDefaultAttValue(SchemaAttDef attDef) { string str = (attDef.DefaultValueRaw).Trim(); XdrValidator.CheckDefaultValue(str, attDef, _SchemaInfo, _CurNsMgr, _NameTable, null, validationEventHandler, _reader.BaseURI, positionInfo.LineNumber, positionInfo.LinePosition); } private bool IsGlobal(int flags) { return flags == SchemaFlagsNs; } private void SendValidationEvent(string code, string[] args, XmlSeverityType severity) { SendValidationEvent(new XmlSchemaException(code, args, this._reader.BaseURI, this.positionInfo.LineNumber, this.positionInfo.LinePosition), severity); } private void SendValidationEvent(string code) { SendValidationEvent(code, string.Empty); } private void SendValidationEvent(string code, string msg) { SendValidationEvent(new XmlSchemaException(code, msg, this._reader.BaseURI, this.positionInfo.LineNumber, this.positionInfo.LinePosition), XmlSeverityType.Error); } private void SendValidationEvent(XmlSchemaException e, XmlSeverityType severity) { _SchemaInfo.ErrorCount ++; if (validationEventHandler != null) { validationEventHandler(this, new ValidationEventArgs(e, severity)); } else if (severity == XmlSeverityType.Error) { throw e; } } }; // class XdrBuilder } // namespace System.Xml