xdrvalidator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / schema / xdrvalidator.cs / 1305376 / xdrvalidator.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Xml.Schema { 

    using System.IO; 
    using System.Text;
    using System.Collections;
    using System.Diagnostics;
    using System.Globalization; 
    using System.Runtime.Versioning;
 
#pragma warning disable 618 
    internal sealed class XdrValidator : BaseValidator {
 
        private const int        STACK_INCREMENT = 10;
        private HWStack          validationStack;  // validaton contexts
        private Hashtable        attPresence;
        private XmlQualifiedName name = XmlQualifiedName.Empty; 
        private XmlNamespaceManager  nsManager;
        private bool isProcessContents = false; 
        private Hashtable       IDs; 
        private IdRefNode       idRefListHead;
        private Parser  inlineSchemaParser = null; 
        private const string     x_schema = "x-schema:";

        internal XdrValidator(BaseValidator validator) : base(validator) {
            Init(); 
        }
 
        internal XdrValidator(XmlValidatingReaderImpl reader, XmlSchemaCollection schemaCollection, IValidationEventHandling eventHandling) : base(reader, schemaCollection, eventHandling) { 
            Init();
        } 

        private void Init() {
            nsManager = reader.NamespaceManager;
            if (nsManager == null) { 
                nsManager = new XmlNamespaceManager(NameTable);
                isProcessContents = true; 
            } 
            validationStack = new HWStack(STACK_INCREMENT);
            textValue = new StringBuilder(); 
            name = XmlQualifiedName.Empty;
            attPresence = new Hashtable();
            Push(XmlQualifiedName.Empty);
            schemaInfo = new SchemaInfo(); 
            checkDatatype = false;
        } 
 
        public override void Validate() {
            if (IsInlineSchemaStarted) { 
                ProcessInlineSchema();
            }
            else {
                switch (reader.NodeType) { 
                    case XmlNodeType.Element:
                        ValidateElement(); 
                        if (reader.IsEmptyElement) { 
                            goto case XmlNodeType.EndElement;
                        } 
                        break;
                    case XmlNodeType.Whitespace:
                        ValidateWhitespace();
                        break; 
                    case XmlNodeType.Text:          // text inside a node
                    case XmlNodeType.CDATA:         //  
                    case XmlNodeType.SignificantWhitespace: 
                        ValidateText();
                        break; 
                    case XmlNodeType.EndElement:
                        ValidateEndElement();
                        break;
                } 
            }
        } 
 
        private void ValidateElement() {
            elementName.Init(reader.LocalName, XmlSchemaDatatype.XdrCanonizeUri(reader.NamespaceURI, NameTable, SchemaNames)); 
            ValidateChildElement();
            if (SchemaNames.IsXDRRoot(elementName.Name, elementName.Namespace) && reader.Depth > 0) {
                inlineSchemaParser = new Parser(SchemaType.XDR, NameTable, SchemaNames, EventHandler);
                inlineSchemaParser.StartParsing(reader, null); 
                inlineSchemaParser.ParseReaderNode();
            } 
            else { 
                ProcessElement();
            } 
        }

        private void ValidateChildElement() {
            if (context.NeedValidateChildren) { 
                int errorCode = 0;
                context.ElementDecl.ContentValidator.ValidateElement(elementName, context, out errorCode); 
                if (errorCode < 0) { 
                    XmlSchemaValidator.ElementValidationError(elementName, context, EventHandler, reader, reader.BaseURI, PositionInfo.LineNumber, PositionInfo.LinePosition, null);
                } 
            }
        }

        private bool IsInlineSchemaStarted { 
            get { return inlineSchemaParser != null; }
        } 
 
        private void ProcessInlineSchema() {
            if (!inlineSchemaParser.ParseReaderNode()) { // Done 
                    inlineSchemaParser.FinishParsing();
                    SchemaInfo xdrSchema = inlineSchemaParser.XdrSchema;
                    if (xdrSchema != null && xdrSchema.ErrorCount == 0) {
                        foreach(string inlineNS in xdrSchema.TargetNamespaces.Keys) { 
                            if (!this.schemaInfo.HasSchema(inlineNS)) {
                                schemaInfo.Add(xdrSchema, EventHandler); 
                                SchemaCollection.Add(inlineNS, xdrSchema, null, false); 
                                break;
                            } 
                        }
                    }
                    inlineSchemaParser = null;
            } 
        }
 
        private void ProcessElement() { 
            Push(elementName);
            if (isProcessContents) { 
                nsManager.PopScope();
            }
            context.ElementDecl = ThoroughGetElementDecl();
            if (context.ElementDecl != null) { 
                ValidateStartElement();
                ValidateEndStartElement(); 
                context.NeedValidateChildren = true; 
                context.ElementDecl.ContentValidator.InitValidation(context);
            } 
        }

         private void ValidateEndElement() {
            if (isProcessContents) { 
                nsManager.PopScope();
            } 
            if (context.ElementDecl != null) { 
                if (context.NeedValidateChildren) {
                    if(!context.ElementDecl.ContentValidator.CompleteValidation(context)) { 
                        XmlSchemaValidator.CompleteValidationError(context, EventHandler, reader, reader.BaseURI, PositionInfo.LineNumber, PositionInfo.LinePosition, null);
                    }
                }
                if (checkDatatype) { 
                    string stringValue = !hasSibling ? textString : textValue.ToString();  // only for identity-constraint exception reporting
                    CheckValue(stringValue, null); 
                    checkDatatype = false; 
                    textValue.Length = 0; // cleanup
                    textString = string.Empty; 
                }
            }
            Pop();
 
        }
 
         // SxS: This method processes resource names read from the source document and does not expose 
         // any resources to the caller. It is fine to suppress the SxS warning.
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.None)]
        private SchemaElementDecl ThoroughGetElementDecl() {
            if (reader.Depth == 0) {
                LoadSchema(string.Empty); 
            }
            if (reader.MoveToFirstAttribute()) { 
                do { 
                    string objectNs = reader.NamespaceURI;
                    string objectName = reader.LocalName; 
                    if (Ref.Equal(objectNs, SchemaNames.NsXmlNs)) {
                        LoadSchema(reader.Value);
                        if (isProcessContents) {
                            nsManager.AddNamespace(reader.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value); 
                        }
                    } 
                    if ( 
                        Ref.Equal(objectNs, SchemaNames.QnDtDt.Namespace) &&
                        Ref.Equal(objectName, SchemaNames.QnDtDt.Name) 
                    ) {
                        reader.SchemaTypeObject = XmlSchemaDatatype.FromXdrName(reader.Value);
                    }
 
                } while(reader.MoveToNextAttribute());
                reader.MoveToElement(); 
            } 
            SchemaElementDecl elementDecl = schemaInfo.GetElementDecl(elementName);
            if(elementDecl == null) { 
                if(schemaInfo.TargetNamespaces.ContainsKey(context.Namespace)) {
                    SendValidationEvent(Res.Sch_UndeclaredElement, XmlSchemaValidator.QNameString(context.LocalName, context.Namespace));
                }
            } 
            return elementDecl;
        } 
 
        private void ValidateStartElement() {
            if (context.ElementDecl != null) { 
                if (context.ElementDecl.SchemaType != null) {
                    reader.SchemaTypeObject =  context.ElementDecl.SchemaType;
                }
                else { 
                    reader.SchemaTypeObject =  context.ElementDecl.Datatype;
                } 
                if (reader.IsEmptyElement && !context.IsNill && context.ElementDecl.DefaultValueTyped != null) { 
                   reader.TypedValueObject = context.ElementDecl.DefaultValueTyped;
                   context.IsNill = true; // reusing IsNill 
                }
                if (this.context.ElementDecl.HasRequiredAttribute) {
                    attPresence.Clear();
                } 
            }
 
            if (reader.MoveToFirstAttribute()) { 
                do {
                    if ((object)reader.NamespaceURI == (object)SchemaNames.NsXmlNs) { 
                        continue;
                    }

                    try { 
                        reader.SchemaTypeObject = null;
                        SchemaAttDef attnDef = schemaInfo.GetAttributeXdr(context.ElementDecl, QualifiedName(reader.LocalName, reader.NamespaceURI)); 
                        if (attnDef != null) { 
                            if (context.ElementDecl != null && context.ElementDecl.HasRequiredAttribute) {
                                attPresence.Add(attnDef.Name, attnDef); 
                            }
                            reader.SchemaTypeObject = (attnDef.SchemaType != null) ? (object)attnDef.SchemaType : (object)attnDef.Datatype;
                            if (attnDef.Datatype != null) {
                                string attributeValue = reader.Value; 
                                // need to check the contents of this attribute to make sure
                                // it is valid according to the specified attribute type. 
                                CheckValue(attributeValue, attnDef); 
                            }
                        } 
                    }
                    catch (XmlSchemaException e) {
                        e.SetSource(reader.BaseURI, PositionInfo.LineNumber, PositionInfo.LinePosition);
                        SendValidationEvent(e); 
                    }
                } while(reader.MoveToNextAttribute()); 
                reader.MoveToElement(); 
            }
        } 

        private void ValidateEndStartElement() {

            if (context.ElementDecl.HasDefaultAttribute) { 
                for (int i = 0; i < context.ElementDecl.DefaultAttDefs.Count; ++i) {
                    reader.AddDefaultAttribute((SchemaAttDef)context.ElementDecl.DefaultAttDefs[i]); 
               } 
            }
            if (context.ElementDecl.HasRequiredAttribute) { 
                try {
                    context.ElementDecl.CheckAttributes(attPresence, reader.StandAlone);
                }
                catch (XmlSchemaException e) { 
                    e.SetSource(reader.BaseURI, PositionInfo.LineNumber, PositionInfo.LinePosition);
                    SendValidationEvent(e); 
                } 

            } 
            if (context.ElementDecl.Datatype != null) {
                checkDatatype = true;
                hasSibling = false;
                textString = string.Empty; 
                textValue.Length = 0;
            } 
        } 

        [ResourceConsumption(ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.Machine)]
        private void LoadSchemaFromLocation(string uri) {
            // is x-schema
            if (!XdrBuilder.IsXdrSchema(uri)) { 
                return;
            } 
            string url = uri.Substring(x_schema.Length); 
            XmlReader reader = null;
            SchemaInfo xdrSchema = null; 
            try {
                Uri ruri = this.XmlResolver.ResolveUri(BaseUri, url);
                Stream stm = (Stream)this.XmlResolver.GetEntity(ruri,null,null);
                reader = new XmlTextReader(ruri.ToString(), stm, NameTable); 
                ((XmlTextReader)reader).XmlResolver = this.XmlResolver;
                Parser parser = new Parser(SchemaType.XDR, NameTable, SchemaNames, EventHandler); 
                parser.XmlResolver = this.XmlResolver; 
                parser.Parse(reader, uri);
                while(reader.Read());// wellformness check 
                xdrSchema = parser.XdrSchema;
            }
            catch(XmlSchemaException e) {
                SendValidationEvent(Res.Sch_CannotLoadSchema, new string[] {uri, e.Message}, XmlSeverityType.Error); 
            }
            catch(Exception e) { 
                SendValidationEvent(Res.Sch_CannotLoadSchema, new string[] {uri, e.Message}, XmlSeverityType.Warning); 
            }
            finally { 
                if (reader != null) {
                    reader.Close();
                }
            } 
            if (xdrSchema != null && xdrSchema.ErrorCount == 0) {
                schemaInfo.Add(xdrSchema, EventHandler); 
                SchemaCollection.Add(uri, xdrSchema, null, false); 
            }
        } 

        [ResourceConsumption(ResourceScope.Machine)]
        [ResourceExposure(ResourceScope.Machine)]
        private void LoadSchema(string uri) { 
            if (this.schemaInfo.TargetNamespaces.ContainsKey(uri)) {
                return; 
            } 
            if (this.XmlResolver == null) {
                return; 
            }

            SchemaInfo schemaInfo = null;
            if (SchemaCollection != null) 
                schemaInfo = SchemaCollection.GetSchemaInfo(uri);
            if (schemaInfo != null) { 
                if(schemaInfo.SchemaType != SchemaType.XDR) { 
                    throw new XmlException(Res.Xml_MultipleValidaitonTypes, string.Empty, this.PositionInfo.LineNumber, this.PositionInfo.LinePosition);
                } 
                this.schemaInfo.Add(schemaInfo, EventHandler);
                return;
            }
            LoadSchemaFromLocation(uri); 
        }
 
        private bool HasSchema { get { return schemaInfo.SchemaType != SchemaType.None;}} 

        public override bool PreserveWhitespace { 
            get { return context.ElementDecl != null ? context.ElementDecl.ContentValidator.PreserveWhitespace : false; }
        }

        void ProcessTokenizedType( 
            XmlTokenizedType    ttype,
            string              name 
        ) { 
            switch(ttype) {
            case XmlTokenizedType.ID: 
                if (FindId(name) != null) {
                    SendValidationEvent(Res.Sch_DupId, name);
                }
                else { 
                    AddID(name, context.LocalName);
                } 
                break; 
            case XmlTokenizedType.IDREF:
                object p = FindId(name); 
                if (p == null) { // add it to linked list to check it later
                    idRefListHead = new IdRefNode(idRefListHead, name, this.PositionInfo.LineNumber, this.PositionInfo.LinePosition);
                }
                break; 
            case XmlTokenizedType.ENTITY:
                ProcessEntity(schemaInfo, name, this, EventHandler, reader.BaseURI, PositionInfo.LineNumber, PositionInfo.LinePosition); 
                break; 
            default:
                break; 
            }
        }

 
        public override void CompleteValidation() {
            if (HasSchema) { 
                CheckForwardRefs(); 
            }
            else { 
                SendValidationEvent(new XmlSchemaException(Res.Xml_NoValidation, string.Empty), XmlSeverityType.Warning);
            }
        }
 

        private void CheckValue( 
            string              value, 
            SchemaAttDef        attdef
        ) { 
            try {
                reader.TypedValueObject = null;
                bool isAttn = attdef != null;
                XmlSchemaDatatype dtype = isAttn ? attdef.Datatype : context.ElementDecl.Datatype; 
                if (dtype == null) {
                    return; // no reason to check 
                } 

                if (dtype.TokenizedType != XmlTokenizedType.CDATA) { 
                    value = value.Trim();
                }
                if (value.Length == 0) {
                    return; // don't need to check 
                }
 
 
                object typedValue = dtype.ParseValue(value, NameTable, nsManager);
                reader.TypedValueObject = typedValue; 
                // Check special types
                XmlTokenizedType ttype = dtype.TokenizedType;
                if (ttype == XmlTokenizedType.ENTITY || ttype == XmlTokenizedType.ID || ttype == XmlTokenizedType.IDREF) {
                    if (dtype.Variety == XmlSchemaDatatypeVariety.List) { 
                        string[] ss = (string[])typedValue;
                        for (int i = 0; i < ss.Length; ++i) { 
                            ProcessTokenizedType(dtype.TokenizedType, ss[i]); 
                        }
                    } 
                    else {
                        ProcessTokenizedType(dtype.TokenizedType, (string)typedValue);
                    }
                } 

                SchemaDeclBase decl = isAttn ? (SchemaDeclBase)attdef : (SchemaDeclBase)context.ElementDecl; 
 
                if (decl.MaxLength != uint.MaxValue) {
                    if(value.Length > decl.MaxLength) { 
                        SendValidationEvent(Res.Sch_MaxLengthConstraintFailed, value);
                    }
                }
                if (decl.MinLength != uint.MaxValue) { 
                    if(value.Length < decl.MinLength) {
                        SendValidationEvent(Res.Sch_MinLengthConstraintFailed, value); 
                    } 
                }
                if (decl.Values != null && !decl.CheckEnumeration(typedValue)) { 
                    if (dtype.TokenizedType == XmlTokenizedType.NOTATION) {
                        SendValidationEvent(Res.Sch_NotationValue, typedValue.ToString());
                    }
                    else { 
                        SendValidationEvent(Res.Sch_EnumerationValue, typedValue.ToString());
                    } 
 
                }
                if (!decl.CheckValue(typedValue)) { 
                    if (isAttn) {
                        SendValidationEvent(Res.Sch_FixedAttributeValue, attdef.Name.ToString());
                    }
                    else { 
                        SendValidationEvent(Res.Sch_FixedElementValue, XmlSchemaValidator.QNameString(context.LocalName, context.Namespace));
                    } 
                } 
            }
            catch (XmlSchemaException) { 
                if (attdef != null) {
                    SendValidationEvent(Res.Sch_AttributeValueDataType, attdef.Name.ToString());
                }
                else { 
                    SendValidationEvent(Res.Sch_ElementValueDataType, XmlSchemaValidator.QNameString(context.LocalName, context.Namespace));
                } 
            } 
        }
 
        public static void CheckDefaultValue(
            string              value,
            SchemaAttDef        attdef,
            SchemaInfo          sinfo, 
            XmlNamespaceManager     nsManager,
            XmlNameTable        NameTable, 
            object              sender, 
            ValidationEventHandler  eventhandler,
            string              baseUri, 
            int                 lineNo,
            int                 linePos
        ) {
            try { 

                XmlSchemaDatatype dtype = attdef.Datatype; 
                if (dtype == null) { 
                    return; // no reason to check
                } 

                if (dtype.TokenizedType != XmlTokenizedType.CDATA) {
                    value = value.Trim();
                } 
                if (value.Length == 0) {
                    return; // don't need to check 
                } 
                object typedValue = dtype.ParseValue(value, NameTable, nsManager);
 
                // Check special types
                XmlTokenizedType ttype = dtype.TokenizedType;
                if (ttype == XmlTokenizedType.ENTITY) {
                    if (dtype.Variety == XmlSchemaDatatypeVariety.List) { 
                        string[] ss = (string[])typedValue;
                        for (int i = 0; i < ss.Length; ++i) { 
                            ProcessEntity(sinfo, ss[i], sender, eventhandler, baseUri, lineNo, linePos); 
                        }
                    } 
                    else {
                        ProcessEntity(sinfo, (string)typedValue, sender, eventhandler, baseUri, lineNo, linePos);
                    }
                } 
                else if (ttype == XmlTokenizedType.ENUMERATION) {
                    if (!attdef.CheckEnumeration(typedValue)) { 
                        XmlSchemaException e = new XmlSchemaException(Res.Sch_EnumerationValue, typedValue.ToString(), baseUri, lineNo, linePos); 
                        if (eventhandler != null) {
                            eventhandler(sender, new ValidationEventArgs(e)); 
                        }
                        else {
                            throw e;
                        } 
                    }
                } 
                attdef.DefaultValueTyped = typedValue; 
            }
#if DEBUG 
            catch (XmlSchemaException ex) {
                Debug.WriteLineIf(DiagnosticsSwitches.XmlSchema.TraceError, ex.Message);
#else
            catch  { 
#endif
                XmlSchemaException e = new XmlSchemaException(Res.Sch_AttributeDefaultDataType, attdef.Name.ToString(), baseUri, lineNo, linePos); 
                if (eventhandler != null) { 
                    eventhandler(sender, new ValidationEventArgs(e));
                } 
                else {
                    throw e;
                }
            } 
        }
 
        internal void AddID(string name, object node) { 
            // Note: It used to be true that we only called this if _fValidate was true,
            // but due to the fact that you can now dynamically type somethign as an ID 
            // that is no longer true.
            if (IDs == null) {
                IDs = new Hashtable();
            } 

            IDs.Add(name, node); 
        } 

        public override object  FindId(string name) { 
            return IDs == null ? null : IDs[name];
        }

        private    void Push(XmlQualifiedName elementName) { 
            context = (ValidationState)validationStack.Push();
            if (context == null) { 
                context = new ValidationState(); 
                validationStack.AddToTop(context);
            } 
            context.LocalName = elementName.Name;
            context.Namespace = elementName.Namespace;
            context.HasMatched = false;
            context.IsNill = false; 
            context.NeedValidateChildren = false;
        } 
 
        private    void Pop() {
            if (validationStack.Length > 1) { 
                validationStack.Pop();
                context = (ValidationState)validationStack.Peek();
            }
        } 

        private void CheckForwardRefs() { 
            IdRefNode next = idRefListHead; 
            while (next != null) {
                if(FindId(next.Id) == null) { 
                    SendValidationEvent(new XmlSchemaException(Res.Sch_UndeclaredId, next.Id, reader.BaseURI, next.LineNo, next.LinePos));
                }
                IdRefNode ptr = next.Next;
                next.Next = null; // unhook each object so it is cleaned up by Garbage Collector 
                next = ptr;
            } 
            // not needed any more. 
            idRefListHead = null;
        } 

        private XmlQualifiedName QualifiedName(string name, string ns) {
            return new XmlQualifiedName(name, XmlSchemaDatatype.XdrCanonizeUri(ns, NameTable, SchemaNames));
        } 

    }; 
#pragma warning restore 618 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK