Parser.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 / Parser.cs / 1305376 / Parser.cs

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

    using System; 
    using System.Collections;
    using System.Globalization;
    using System.Text;
    using System.IO; 
    using System.Diagnostics;
 
    internal sealed class Parser { 

        SchemaType schemaType; 
        XmlNameTable nameTable;
        SchemaNames schemaNames;
        ValidationEventHandler eventHandler;
        XmlNamespaceManager namespaceManager; 
        XmlReader reader;
        PositionInfo positionInfo; 
        bool isProcessNamespaces; 
        int schemaXmlDepth = 0;
        int markupDepth; 
        SchemaBuilder builder;
        XmlSchema schema;
        SchemaInfo xdrSchema;
        XmlResolver xmlResolver = null; //to be used only by XDRBuilder 

        //xs:Annotation perf fix 
        XmlDocument dummyDocument; 
        bool processMarkup;
        XmlNode parentNode; 
        XmlNamespaceManager annotationNSManager;
        string xmlns;

        //Whitespace check for text nodes 
        XmlCharType xmlCharType = XmlCharType.Instance;
 
        public Parser(SchemaType schemaType, XmlNameTable nameTable, SchemaNames schemaNames, ValidationEventHandler eventHandler) { 
            this.schemaType = schemaType;
            this.nameTable = nameTable; 
            this.schemaNames = schemaNames;
            this.eventHandler = eventHandler;
            this.xmlResolver = new XmlUrlResolver();
            processMarkup = true; 
            dummyDocument = new XmlDocument();
        } 
 
        public SchemaType Parse(XmlReader reader, string targetNamespace) {
            StartParsing(reader, targetNamespace); 
            while(ParseReaderNode() && reader.Read()) {}
            return FinishParsing();
        }
 
        public void StartParsing(XmlReader reader, string targetNamespace) {
            this.reader = reader; 
            positionInfo = PositionInfo.GetPositionInfo(reader); 
            namespaceManager = reader.NamespaceManager;
            if (namespaceManager == null) { 
                namespaceManager = new XmlNamespaceManager(nameTable);
                isProcessNamespaces = true;
            }
            else { 
                isProcessNamespaces = false;
            } 
            while (reader.NodeType != XmlNodeType.Element && reader.Read()) {} 

            markupDepth = int.MaxValue; 
            schemaXmlDepth = reader.Depth;
            SchemaType rootType = schemaNames.SchemaTypeFromRoot(reader.LocalName, reader.NamespaceURI);

            string code; 
            if (!CheckSchemaRoot(rootType, out code)) {
                throw new XmlSchemaException(code, reader.BaseURI, positionInfo.LineNumber, positionInfo.LinePosition); 
            } 

            if (schemaType == SchemaType.XSD) { 
                schema = new XmlSchema();
                schema.BaseUri = new Uri(reader.BaseURI, UriKind.RelativeOrAbsolute);
                builder = new XsdBuilder(reader, namespaceManager, schema, nameTable, schemaNames, eventHandler);
            } 
            else {
                Debug.Assert(schemaType == SchemaType.XDR); 
                xdrSchema = new SchemaInfo(); 
                xdrSchema.SchemaType = SchemaType.XDR;
                builder = new XdrBuilder(reader, namespaceManager, xdrSchema, targetNamespace, nameTable, schemaNames, eventHandler); 
                ((XdrBuilder)builder).XmlResolver = xmlResolver;
            }
        }
 
        private bool CheckSchemaRoot(SchemaType rootType, out string code) {
            code = null; 
            if (schemaType == SchemaType.None) { 
                schemaType = rootType;
            } 
            switch (rootType) {
                case SchemaType.XSD:
                    if (schemaType != SchemaType.XSD) {
                        code = Res.Sch_MixSchemaTypes; 
                        return false;
                    } 
                break; 

                case SchemaType.XDR: 
                    if (schemaType == SchemaType.XSD) {
                        code = Res.Sch_XSDSchemaOnly;
                        return false;
                    } 
                    else if (schemaType != SchemaType.XDR) {
                        code = Res.Sch_MixSchemaTypes; 
                        return false; 
                    }
                break; 

                case SchemaType.DTD: //Did not detect schema type that can be parsed by this parser
                case SchemaType.None:
                    code = Res.Sch_SchemaRootExpected; 
                    if (schemaType == SchemaType.XSD) {
                        code = Res.Sch_XSDSchemaRootExpected; 
                    } 
                    return false;
 
                default:
                    Debug.Assert(false);
                    break;
            } 
            return true;
        } 
 
        public SchemaType FinishParsing() {
            return schemaType; 
        }

        public XmlSchema XmlSchema {
            get { return schema; } 
        }
 
        internal XmlResolver XmlResolver { 
            set {
                xmlResolver = value; 
            }
        }

        public SchemaInfo XdrSchema { 
            get { return xdrSchema; }
        } 
 

        public bool ParseReaderNode() { 
            if (reader.Depth > markupDepth) {
                if (processMarkup) {
                    ProcessAppInfoDocMarkup(false);
                } 
                return true;
            } 
            else if (reader.NodeType == XmlNodeType.Element) { 
                if (builder.ProcessElement(reader.Prefix, reader.LocalName, reader.NamespaceURI)) {
                    namespaceManager.PushScope(); 
                    if (reader.MoveToFirstAttribute()) {
                        do {
                            builder.ProcessAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.Value);
                            if (Ref.Equal(reader.NamespaceURI, schemaNames.NsXmlNs) && isProcessNamespaces) { 
                                namespaceManager.AddNamespace(reader.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value);
                            } 
                        } 
                        while (reader.MoveToNextAttribute());
                        reader.MoveToElement(); // get back to the element 
                    }
                    builder.StartChildren();
                    if (reader.IsEmptyElement) {
                        namespaceManager.PopScope(); 
                        builder.EndChildren();
                        if (reader.Depth == schemaXmlDepth) { 
                            return false; // done 
                        }
                    } 
                    else if (!builder.IsContentParsed()) { //AppInfo and Documentation
                        markupDepth = reader.Depth;
                        processMarkup = true;
                        if (annotationNSManager == null) { 
                            annotationNSManager = new XmlNamespaceManager(nameTable);
                            xmlns = nameTable.Add("xmlns"); 
                        } 
                        ProcessAppInfoDocMarkup(true);
                    } 
                }
                else if (!reader.IsEmptyElement) { //UnsupportedElement in that context
                    markupDepth = reader.Depth;
                    processMarkup = false; //Hack to not process unsupported elements 
                }
            } 
            else if (reader.NodeType == XmlNodeType.Text) { //Check for whitespace 
                if (!xmlCharType.IsOnlyWhitespace(reader.Value)) {
                    builder.ProcessCData(reader.Value); 
                }
            }
            else if (reader.NodeType == XmlNodeType.EntityReference ||
                reader.NodeType == XmlNodeType.SignificantWhitespace || 
                reader.NodeType == XmlNodeType.CDATA) {
                builder.ProcessCData(reader.Value); 
            } 
            else if (reader.NodeType == XmlNodeType.EndElement) {
 
                if (reader.Depth == markupDepth) {
                    if (processMarkup) {
                        Debug.Assert(parentNode != null);
                        XmlNodeList list = parentNode.ChildNodes; 
                        XmlNode[] markup = new XmlNode[list.Count];
                        for (int i = 0; i < list.Count; i ++) { 
                            markup[i] = list[i]; 
                        }
                        builder.ProcessMarkup(markup); 
                        namespaceManager.PopScope();
                        builder.EndChildren();
                    }
                    markupDepth = int.MaxValue; 
                }
                else { 
                    namespaceManager.PopScope(); 
                    builder.EndChildren();
                } 
                if(reader.Depth == schemaXmlDepth) {
                    return false; // done
                }
            } 
            return true;
        } 
 

        private void ProcessAppInfoDocMarkup(bool root) { 
            //First time reader is positioned on AppInfo or Documentation element
            XmlNode currentNode = null;

            switch (reader.NodeType) { 
                case XmlNodeType.Element:
                    annotationNSManager.PushScope(); 
                    currentNode = LoadElementNode(root); 
                    //  Dev10 (TFS) #479761: The following code was to address the issue of where an in-scope namespace delaration attribute
                    //      was not added when an element follows an empty element. This fix will result in persisting schema in a consistent form 
                    //      although it does not change the semantic meaning of the schema.
                    //      Since it is as a breaking change and Dev10 needs to maintain the backward compatibility, this fix is being reverted.
                    //  if (reader.IsEmptyElement) {
                    //      annotationNSManager.PopScope(); 
                    //  }
                    break; 
 
                case XmlNodeType.Text:
                    currentNode = dummyDocument.CreateTextNode( reader.Value ); 
                    goto default;

                case XmlNodeType.SignificantWhitespace:
                    currentNode = dummyDocument.CreateSignificantWhitespace( reader.Value ); 
                    goto default;
 
                case XmlNodeType.CDATA: 
                    currentNode = dummyDocument.CreateCDataSection( reader.Value );
                    goto default; 

                case XmlNodeType.EntityReference:
                    currentNode = dummyDocument.CreateEntityReference( reader.Name );
                    goto default; 

                case XmlNodeType.Comment: 
                    currentNode = dummyDocument.CreateComment( reader.Value ); 
                    goto default;
 
                case XmlNodeType.ProcessingInstruction:
                    currentNode = dummyDocument.CreateProcessingInstruction( reader.Name, reader.Value );
                    goto default;
 
                case XmlNodeType.EndEntity:
                    break; 
 
                case XmlNodeType.Whitespace:
                    break; 

                case XmlNodeType.EndElement:
                    annotationNSManager.PopScope();
                    parentNode = parentNode.ParentNode; 
                    break;
 
                default: //other possible node types: Document/DocType/DocumentFrag/Entity/Notation/Xmldecl cannot appear as children of xs:appInfo or xs:doc 
                    Debug.Assert(currentNode != null);
                    Debug.Assert(parentNode != null); 
                    parentNode.AppendChild(currentNode);
                    break;
            }
        } 

        private XmlElement LoadElementNode(bool root) { 
            Debug.Assert( reader.NodeType == XmlNodeType.Element ); 

            XmlReader r = reader; 
            bool fEmptyElement = r.IsEmptyElement;

            XmlElement element = dummyDocument.CreateElement( r.Prefix, r.LocalName, r.NamespaceURI );
            element.IsEmpty = fEmptyElement; 

            if (root) { 
                parentNode = element; 
            }
            else { 
                XmlAttributeCollection attributes = element.Attributes;
                if (r.MoveToFirstAttribute()) {
                    do {
                        if (Ref.Equal(r.NamespaceURI, schemaNames.NsXmlNs)) { //Namespace Attribute 
                            annotationNSManager.AddNamespace(r.Prefix.Length == 0 ? string.Empty : reader.LocalName, reader.Value);
                        } 
                        XmlAttribute attr = LoadAttributeNode(); 
                        attributes.Append( attr );
                    } while(r.MoveToNextAttribute()); 
                }
                r.MoveToElement();
                string ns = annotationNSManager.LookupNamespace(r.Prefix);
                if (ns == null) { 
                    XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, namespaceManager.LookupNamespace(r.Prefix));
                    attributes.Append(attr); 
                } 
                else if (ns.Length == 0) { //string.Empty prefix is mapped to string.Empty NS by default
                    string elemNS = namespaceManager.LookupNamespace(r.Prefix); 
                    if (elemNS != string.Empty) {
                        XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, elemNS);
                        attributes.Append(attr);
                    } 
                }
 
                while (r.MoveToNextAttribute()) { 
                    if (r.Prefix.Length != 0) {
                        string attNS = annotationNSManager.LookupNamespace(r.Prefix); 
                        if (attNS == null) {
                            XmlAttribute attr = CreateXmlNsAttribute(r.Prefix, namespaceManager.LookupNamespace(r.Prefix));
                            attributes.Append(attr);
                        } 
                    }
                } 
                r.MoveToElement(); 

                parentNode.AppendChild(element); 
                if (!r.IsEmptyElement) {
                    parentNode = element;
                }
            } 
            return element;
        } 
 

        private XmlAttribute CreateXmlNsAttribute(string prefix, string value) { 
            XmlAttribute attr;
            if (prefix.Length == 0) {
                attr = dummyDocument.CreateAttribute(string.Empty, xmlns, XmlReservedNs.NsXmlNs);
            } 
            else {
                attr = dummyDocument.CreateAttribute(xmlns, prefix, XmlReservedNs.NsXmlNs); 
            } 
            attr.AppendChild(dummyDocument.CreateTextNode(value));
            annotationNSManager.AddNamespace(prefix, value); 
            return attr;
        }

        private XmlAttribute LoadAttributeNode() { 
            Debug.Assert(reader.NodeType == XmlNodeType.Attribute);
 
            XmlReader r = reader; 

            XmlAttribute attr = dummyDocument.CreateAttribute(r.Prefix, r.LocalName, r.NamespaceURI); 

            while (r.ReadAttributeValue() ) {
                switch (r.NodeType) {
                    case XmlNodeType.Text: 
                        attr.AppendChild(dummyDocument.CreateTextNode(r.Value));
                        continue; 
                    case XmlNodeType.EntityReference: 
                        attr.AppendChild(LoadEntityReferenceInAttribute());
                        continue; 
                    default:
                        throw XmlLoader.UnexpectedNodeType( r.NodeType );
                }
            } 

            return attr; 
        } 

 
        private XmlEntityReference LoadEntityReferenceInAttribute() {
            Debug.Assert(reader.NodeType == XmlNodeType.EntityReference);

            XmlEntityReference eref = dummyDocument.CreateEntityReference( reader.LocalName ); 
            if ( !reader.CanResolveEntity ) {
                return eref; 
            } 
            reader.ResolveEntity();
 
            while (reader.ReadAttributeValue()) {
                switch (reader.NodeType) {
                    case XmlNodeType.Text:
                        eref.AppendChild(dummyDocument.CreateTextNode(reader.Value)); 
                        continue;
                    case XmlNodeType.EndEntity: 
                        if ( eref.ChildNodes.Count == 0 ) { 
                            eref.AppendChild(dummyDocument.CreateTextNode(String.Empty));
                        } 
                        return eref;
                    case XmlNodeType.EntityReference:
                        eref.AppendChild(LoadEntityReferenceInAttribute());
                        break; 
                    default:
                        throw XmlLoader.UnexpectedNodeType( reader.NodeType ); 
                } 
            }
 
            return eref;
        }

 
    };
 
} // namespace System.Xml 

// 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