Parser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / fx / src / Xml / System / Xml / schema / Parser.cs / 3 / 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 
        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();
                    } 
                    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); 
                    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.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

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