File: FrameworkFork\Microsoft.Xml\Xml\Dom\XmlDocument.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace Microsoft.Xml
{
    using System;
    using System.Collections;
    using System.Diagnostics;
    using System.IO;
    using System.Text;
    using Microsoft.Xml.Schema;
    using Microsoft.Xml.XPath;
    using System.Security;
    // using System.Security.Permissions;
    using System.Globalization;
    using System.Runtime.Versioning;
 
    // Represents an entire document. An XmlDocument contains XML data.
    public class XmlDocument : XmlNode
    {
        private XmlImplementation _implementation;
        private DomNameTable _domNameTable; // hash table of XmlName
        private XmlLinkedNode _lastChild;
        private XmlNamedNodeMap _entities;
        private Hashtable _htElementIdMap;
        private Hashtable _htElementIDAttrDecl; //key: id; object: the ArrayList of the elements that have the same id (connected or disconnected)
        private SchemaInfo _schemaInfo;
        private XmlSchemaSet _schemas; // schemas associated with the cache
        private bool _reportValidity;
        //This variable represents the actual loading status. Since, IsLoading will
        //be manipulated soemtimes for adding content to EntityReference this variable
        //has been added which would always represent the loading status of document.
        private bool _actualLoadingStatus;
 
        private XmlNodeChangedEventHandler _onNodeInsertingDelegate;
        private XmlNodeChangedEventHandler _onNodeInsertedDelegate;
        private XmlNodeChangedEventHandler _onNodeRemovingDelegate;
        private XmlNodeChangedEventHandler _onNodeRemovedDelegate;
        private XmlNodeChangedEventHandler _onNodeChangingDelegate;
        private XmlNodeChangedEventHandler _onNodeChangedDelegate;
 
        // false if there are no ent-ref present, true if ent-ref nodes are or were present (i.e. if all ent-ref were removed, the doc will not clear this flag)
        internal bool fEntRefNodesPresent;
        internal bool fCDataNodesPresent;
 
        private bool _preserveWhitespace;
        private bool _isLoading;
 
        // special name strings for
        internal string strDocumentName;
        internal string strDocumentFragmentName;
        internal string strCommentName;
        internal string strTextName;
        internal string strCDataSectionName;
        internal string strEntityName;
        internal string strID;
        internal string strXmlns;
        internal string strXml;
        internal string strSpace;
        internal string strLang;
        internal string strEmpty;
 
        internal string strNonSignificantWhitespaceName;
        internal string strSignificantWhitespaceName;
        internal string strReservedXmlns;
        internal string strReservedXml;
 
        internal String baseURI;
 
        private XmlResolver _resolver;
        internal bool bSetResolver;
        internal object objLock;
 
        private XmlAttribute _namespaceXml;
 
        static internal EmptyEnumerator EmptyEnumerator = new EmptyEnumerator();
        static internal IXmlSchemaInfo NotKnownSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.NotKnown);
        static internal IXmlSchemaInfo ValidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Valid);
        static internal IXmlSchemaInfo InvalidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Invalid);
 
        // Initializes a new instance of the XmlDocument class.
        public XmlDocument() : this(new XmlImplementation())
        {
        }
 
        // Initializes a new instance
        // of the XmlDocument class with the specified XmlNameTable.
        public XmlDocument(XmlNameTable nt) : this(new XmlImplementation(nt))
        {
        }
 
        protected internal XmlDocument(XmlImplementation imp) : base()
        {
            _implementation = imp;
            _domNameTable = new DomNameTable(this);
 
            // force the following string instances to be default in the nametable
            XmlNameTable nt = this.NameTable;
            nt.Add(string.Empty);
            strDocumentName = nt.Add("#document");
            strDocumentFragmentName = nt.Add("#document-fragment");
            strCommentName = nt.Add("#comment");
            strTextName = nt.Add("#text");
            strCDataSectionName = nt.Add("#cdata-section");
            strEntityName = nt.Add("#entity");
            strID = nt.Add("id");
            strNonSignificantWhitespaceName = nt.Add("#whitespace");
            strSignificantWhitespaceName = nt.Add("#significant-whitespace");
            strXmlns = nt.Add("xmlns");
            strXml = nt.Add("xml");
            strSpace = nt.Add("space");
            strLang = nt.Add("lang");
            strReservedXmlns = nt.Add(XmlReservedNs.NsXmlNs);
            strReservedXml = nt.Add(XmlReservedNs.NsXml);
            strEmpty = nt.Add(String.Empty);
            baseURI = String.Empty;
 
            objLock = new object();
        }
 
        internal SchemaInfo DtdSchemaInfo
        {
            get { return _schemaInfo; }
            set { _schemaInfo = value; }
        }
 
        // NOTE: This does not correctly check start name char, but we cannot change it since it would be a breaking change.
        internal static void CheckName(String name)
        {
            int endPos = ValidateNames.ParseNmtoken(name, 0);
            if (endPos < name.Length)
            {
                throw new XmlException(ResXml.Xml_BadNameChar, XmlException.BuildCharExceptionArgs(name, endPos));
            }
        }
 
        internal XmlName AddXmlName(string prefix, string localName, string namespaceURI, IXmlSchemaInfo schemaInfo)
        {
            XmlName n = _domNameTable.AddName(prefix, localName, namespaceURI, schemaInfo);
            Debug.Assert((prefix == null) ? (n.Prefix.Length == 0) : (prefix == n.Prefix));
            Debug.Assert(n.LocalName == localName);
            Debug.Assert((namespaceURI == null) ? (n.NamespaceURI.Length == 0) : (n.NamespaceURI == namespaceURI));
            return n;
        }
 
        internal XmlName GetXmlName(string prefix, string localName, string namespaceURI, IXmlSchemaInfo schemaInfo)
        {
            XmlName n = _domNameTable.GetName(prefix, localName, namespaceURI, schemaInfo);
            Debug.Assert(n == null || ((prefix == null) ? (n.Prefix.Length == 0) : (prefix == n.Prefix)));
            Debug.Assert(n == null || n.LocalName == localName);
            Debug.Assert(n == null || ((namespaceURI == null) ? (n.NamespaceURI.Length == 0) : (n.NamespaceURI == namespaceURI)));
            return n;
        }
 
        internal XmlName AddAttrXmlName(string prefix, string localName, string namespaceURI, IXmlSchemaInfo schemaInfo)
        {
            XmlName xmlName = AddXmlName(prefix, localName, namespaceURI, schemaInfo);
            Debug.Assert((prefix == null) ? (xmlName.Prefix.Length == 0) : (prefix == xmlName.Prefix));
            Debug.Assert(xmlName.LocalName == localName);
            Debug.Assert((namespaceURI == null) ? (xmlName.NamespaceURI.Length == 0) : (xmlName.NamespaceURI == namespaceURI));
 
            if (!this.IsLoading)
            {
                // Use atomized versions instead of prefix, localName and nsURI
                object oPrefix = xmlName.Prefix;
                object oNamespaceURI = xmlName.NamespaceURI;
                object oLocalName = xmlName.LocalName;
                if ((oPrefix == (object)strXmlns || (oPrefix == (object)strEmpty && oLocalName == (object)strXmlns)) ^ (oNamespaceURI == (object)strReservedXmlns))
                    throw new ArgumentException(string.Format(ResXml.Xdom_Attr_Reserved_XmlNS, namespaceURI));
            }
            return xmlName;
        }
 
        internal bool AddIdInfo(XmlName eleName, XmlName attrName)
        {
            //when XmlLoader call XmlDocument.AddInfo, the element.XmlName and attr.XmlName 
            //have already been replaced with the ones that don't have namespace values (or just
            //string.Empty) because in DTD, the namespace is not supported
            if (_htElementIDAttrDecl == null || _htElementIDAttrDecl[eleName] == null)
            {
                if (_htElementIDAttrDecl == null)
                    _htElementIDAttrDecl = new Hashtable();
                _htElementIDAttrDecl.Add(eleName, attrName);
                return true;
            }
            return false;
        }
 
        private XmlName GetIDInfoByElement_(XmlName eleName)
        {
            //When XmlDocument is getting the IDAttribute for a given element, 
            //we need only compare the prefix and localname of element.XmlName with
            //the registered htElementIDAttrDecl.
            XmlName newName = GetXmlName(eleName.Prefix, eleName.LocalName, string.Empty, null);
            if (newName != null)
            {
                return (XmlName)(_htElementIDAttrDecl[newName]);
            }
            return null;
        }
 
        internal XmlName GetIDInfoByElement(XmlName eleName)
        {
            if (_htElementIDAttrDecl == null)
                return null;
            else
                return GetIDInfoByElement_(eleName);
        }
 
        private WeakReference GetElement(ArrayList elementList, XmlElement elem)
        {
            ArrayList gcElemRefs = new ArrayList();
            foreach (WeakReference elemRef in elementList)
            {
                if (!elemRef.IsAlive)
                    //take notes on the garbage collected nodes
                    gcElemRefs.Add(elemRef);
                else
                {
                    if ((XmlElement)(elemRef.Target) == elem)
                        return elemRef;
                }
            }
            //Clear out the gced elements
            foreach (WeakReference elemRef in gcElemRefs)
                elementList.Remove(elemRef);
            return null;
        }
 
        internal void AddElementWithId(string id, XmlElement elem)
        {
            if (_htElementIdMap == null || !_htElementIdMap.Contains(id))
            {
                if (_htElementIdMap == null)
                    _htElementIdMap = new Hashtable();
                ArrayList elementList = new ArrayList();
                elementList.Add(new WeakReference(elem));
                _htElementIdMap.Add(id, elementList);
            }
            else
            {
                // there are other element(s) that has the same id
                ArrayList elementList = (ArrayList)(_htElementIdMap[id]);
                if (GetElement(elementList, elem) == null)
                    elementList.Add(new WeakReference(elem));
            }
        }
 
        internal void RemoveElementWithId(string id, XmlElement elem)
        {
            if (_htElementIdMap != null && _htElementIdMap.Contains(id))
            {
                ArrayList elementList = (ArrayList)(_htElementIdMap[id]);
                WeakReference elemRef = GetElement(elementList, elem);
                if (elemRef != null)
                {
                    elementList.Remove(elemRef);
                    if (elementList.Count == 0)
                        _htElementIdMap.Remove(id);
                }
            }
        }
 
 
        // Creates a duplicate of this node.
        public override XmlNode CloneNode(bool deep)
        {
            XmlDocument clone = Implementation.CreateDocument();
            clone.SetBaseURI(this.baseURI);
            if (deep)
                clone.ImportChildren(this, clone, deep);
 
            return clone;
        }
 
        // Gets the type of the current node.
        public override XmlNodeType NodeType
        {
            get { return XmlNodeType.Document; }
        }
 
        public override XmlNode ParentNode
        {
            get { return null; }
        }
 
        // Gets the node for the DOCTYPE declaration.
        public virtual XmlDocumentType DocumentType
        {
            get { return (XmlDocumentType)FindChild(XmlNodeType.DocumentType); }
        }
 
        internal virtual XmlDeclaration Declaration
        {
            get
            {
                if (HasChildNodes)
                {
                    XmlDeclaration dec = FirstChild as XmlDeclaration;
                    return dec;
                }
                return null;
            }
        }
 
        // Gets the XmlImplementation object for this document.
        public XmlImplementation Implementation
        {
            get { return _implementation; }
        }
 
        // Gets the name of the node.
        public override String Name
        {
            get { return strDocumentName; }
        }
 
        // Gets the name of the current node without the namespace prefix.
        public override String LocalName
        {
            get { return strDocumentName; }
        }
 
        // Gets the root XmlElement for the document.
        public XmlElement DocumentElement
        {
            get { return (XmlElement)FindChild(XmlNodeType.Element); }
        }
 
        internal override bool IsContainer
        {
            get { return true; }
        }
 
        internal override XmlLinkedNode LastNode
        {
            get { return _lastChild; }
            set { _lastChild = value; }
        }
 
        // Gets the XmlDocument that contains this node.
        public override XmlDocument OwnerDocument
        {
            get { return null; }
        }
 
        public XmlSchemaSet Schemas
        {
            get
            {
                if (_schemas == null)
                {
                    _schemas = new XmlSchemaSet(NameTable);
                }
                return _schemas;
            }
 
            set
            {
                _schemas = value;
            }
        }
 
        internal bool CanReportValidity
        {
            get { return _reportValidity; }
        }
 
        internal bool HasSetResolver
        {
            get { return bSetResolver; }
        }
 
        internal XmlResolver GetResolver()
        {
            return _resolver;
        }
 
        public virtual XmlResolver XmlResolver
        {
            set
            {
                _resolver = value;
                if (!bSetResolver)
                    bSetResolver = true;
 
                XmlDocumentType dtd = this.DocumentType;
                if (dtd != null)
                {
                    dtd.DtdSchemaInfo = null;
                }
            }
        }
        internal override bool IsValidChildType(XmlNodeType type)
        {
            switch (type)
            {
                case XmlNodeType.ProcessingInstruction:
                case XmlNodeType.Comment:
                case XmlNodeType.Whitespace:
                case XmlNodeType.SignificantWhitespace:
                    return true;
 
                case XmlNodeType.DocumentType:
                    if (DocumentType != null)
                        throw new InvalidOperationException(ResXml.Xdom_DualDocumentTypeNode);
                    return true;
 
                case XmlNodeType.Element:
                    if (DocumentElement != null)
                        throw new InvalidOperationException(ResXml.Xdom_DualDocumentElementNode);
                    return true;
 
                case XmlNodeType.XmlDeclaration:
                    if (Declaration != null)
                        throw new InvalidOperationException(ResXml.Xdom_DualDeclarationNode);
                    return true;
 
                default:
                    return false;
            }
        }
        // the function examines all the siblings before the refNode
        //  if any of the nodes has type equals to "nt", return true; otherwise, return false;
        private bool HasNodeTypeInPrevSiblings(XmlNodeType nt, XmlNode refNode)
        {
            if (refNode == null)
                return false;
 
            XmlNode node = null;
            if (refNode.ParentNode != null)
                node = refNode.ParentNode.FirstChild;
            while (node != null)
            {
                if (node.NodeType == nt)
                    return true;
                if (node == refNode)
                    break;
                node = node.NextSibling;
            }
            return false;
        }
 
        // the function examines all the siblings after the refNode
        //  if any of the nodes has the type equals to "nt", return true; otherwise, return false;
        private bool HasNodeTypeInNextSiblings(XmlNodeType nt, XmlNode refNode)
        {
            XmlNode node = refNode;
            while (node != null)
            {
                if (node.NodeType == nt)
                    return true;
                node = node.NextSibling;
            }
            return false;
        }
 
        internal override bool CanInsertBefore(XmlNode newChild, XmlNode refChild)
        {
            if (refChild == null)
                refChild = FirstChild;
 
            if (refChild == null)
                return true;
 
            switch (newChild.NodeType)
            {
                case XmlNodeType.XmlDeclaration:
                    return (refChild == FirstChild);
 
                case XmlNodeType.ProcessingInstruction:
                case XmlNodeType.Comment:
                    return refChild.NodeType != XmlNodeType.XmlDeclaration;
 
                case XmlNodeType.DocumentType:
                    {
                        if (refChild.NodeType != XmlNodeType.XmlDeclaration)
                        {
                            //if refChild is not the XmlDeclaration node, only need to go through the sibling before and including refChild to
                            //  make sure no Element ( rootElem node ) before the current position
                            return !HasNodeTypeInPrevSiblings(XmlNodeType.Element, refChild.PreviousSibling);
                        }
                    }
                    break;
 
                case XmlNodeType.Element:
                    {
                        if (refChild.NodeType != XmlNodeType.XmlDeclaration)
                        {
                            //if refChild is not the XmlDeclaration node, only need to go through the siblings after and including the refChild to
                            //  make sure no DocType node and XmlDeclaration node after the current posistion.
                            return !HasNodeTypeInNextSiblings(XmlNodeType.DocumentType, refChild);
                        }
                    }
                    break;
            }
 
            return false;
        }
 
        internal override bool CanInsertAfter(XmlNode newChild, XmlNode refChild)
        {
            if (refChild == null)
                refChild = LastChild;
 
            if (refChild == null)
                return true;
 
            switch (newChild.NodeType)
            {
                case XmlNodeType.ProcessingInstruction:
                case XmlNodeType.Comment:
                case XmlNodeType.Whitespace:
                case XmlNodeType.SignificantWhitespace:
                    return true;
 
                case XmlNodeType.DocumentType:
                    {
                        //we will have to go through all the siblings before the refChild just to make sure no Element node ( rootElem )
                        //  before the current position
                        return !HasNodeTypeInPrevSiblings(XmlNodeType.Element, refChild);
                    }
 
                case XmlNodeType.Element:
                    {
                        return !HasNodeTypeInNextSiblings(XmlNodeType.DocumentType, refChild.NextSibling);
                    }
            }
 
            return false;
        }
 
        // Creates an XmlAttribute with the specified name.
        public XmlAttribute CreateAttribute(String name)
        {
            String prefix = String.Empty;
            String localName = String.Empty;
            String namespaceURI = String.Empty;
 
            SplitName(name, out prefix, out localName);
 
            SetDefaultNamespace(prefix, localName, ref namespaceURI);
 
            return CreateAttribute(prefix, localName, namespaceURI);
        }
 
        internal void SetDefaultNamespace(String prefix, String localName, ref String namespaceURI)
        {
            if (prefix == strXmlns || (prefix.Length == 0 && localName == strXmlns))
            {
                namespaceURI = strReservedXmlns;
            }
            else if (prefix == strXml)
            {
                namespaceURI = strReservedXml;
            }
        }
 
        // Creates a XmlCDataSection containing the specified data.
        public virtual XmlCDataSection CreateCDataSection(String data)
        {
            fCDataNodesPresent = true;
            return new XmlCDataSection(data, this);
        }
 
        // Creates an XmlComment containing the specified data.
        public virtual XmlComment CreateComment(String data)
        {
            return new XmlComment(data, this);
        }
 
        // Returns a new XmlDocumentType object.
        // [PermissionSetAttribute( SecurityAction.InheritanceDemand, Name = "FullTrust" )]
        public virtual XmlDocumentType CreateDocumentType(string name, string publicId, string systemId, string internalSubset)
        {
            return new XmlDocumentType(name, publicId, systemId, internalSubset, this);
        }
 
        // Creates an XmlDocumentFragment.
        public virtual XmlDocumentFragment CreateDocumentFragment()
        {
            return new XmlDocumentFragment(this);
        }
 
        // Creates an element with the specified name.
        public XmlElement CreateElement(String name)
        {
            string prefix = String.Empty;
            string localName = String.Empty;
            SplitName(name, out prefix, out localName);
            return CreateElement(prefix, localName, string.Empty);
        }
 
 
        internal void AddDefaultAttributes(XmlElement elem)
        {
            SchemaInfo schInfo = DtdSchemaInfo;
            SchemaElementDecl ed = GetSchemaElementDecl(elem);
            if (ed != null && ed.AttDefs != null)
            {
                IDictionaryEnumerator attrDefs = ed.AttDefs.GetEnumerator();
                while (attrDefs.MoveNext())
                {
                    SchemaAttDef attdef = (SchemaAttDef)attrDefs.Value;
                    if (attdef.Presence == SchemaDeclBase.Use.Default ||
                         attdef.Presence == SchemaDeclBase.Use.Fixed)
                    {
                        //build a default attribute and return
                        string attrPrefix = string.Empty;
                        string attrLocalname = attdef.Name.Name;
                        string attrNamespaceURI = string.Empty;
                        if (schInfo.SchemaType == SchemaType.DTD)
                            attrPrefix = attdef.Name.Namespace;
                        else
                        {
                            attrPrefix = attdef.Prefix;
                            attrNamespaceURI = attdef.Name.Namespace;
                        }
                        XmlAttribute defattr = PrepareDefaultAttribute(attdef, attrPrefix, attrLocalname, attrNamespaceURI);
                        elem.SetAttributeNode(defattr);
                    }
                }
            }
        }
 
        private SchemaElementDecl GetSchemaElementDecl(XmlElement elem)
        {
            SchemaInfo schInfo = DtdSchemaInfo;
            if (schInfo != null)
            {
                //build XmlQualifiedName used to identify the element schema declaration
                XmlQualifiedName qname = new XmlQualifiedName(elem.LocalName, schInfo.SchemaType == SchemaType.DTD ? elem.Prefix : elem.NamespaceURI);
                //get the schema info for the element
                SchemaElementDecl elemDecl;
                if (schInfo.ElementDecls.TryGetValue(qname, out elemDecl))
                {
                    return elemDecl;
                }
            }
            return null;
        }
 
        //Will be used by AddDeafulatAttributes() and GetDefaultAttribute() methods
        private XmlAttribute PrepareDefaultAttribute(SchemaAttDef attdef, string attrPrefix, string attrLocalname, string attrNamespaceURI)
        {
            SetDefaultNamespace(attrPrefix, attrLocalname, ref attrNamespaceURI);
            XmlAttribute defattr = CreateDefaultAttribute(attrPrefix, attrLocalname, attrNamespaceURI);
            //parsing the default value for the default attribute
            defattr.InnerXml = attdef.DefaultValueRaw;
            //during the expansion of the tree, the flag could be set to true, we need to set it back.
            XmlUnspecifiedAttribute unspAttr = defattr as XmlUnspecifiedAttribute;
            if (unspAttr != null)
            {
                unspAttr.SetSpecified(false);
            }
            return defattr;
        }
 
        // Creates an XmlEntityReference with the specified name.
        public virtual XmlEntityReference CreateEntityReference(String name)
        {
            return new XmlEntityReference(name, this);
        }
 
        // Creates a XmlProcessingInstruction with the specified name
        // and data strings.
        public virtual XmlProcessingInstruction CreateProcessingInstruction(String target, String data)
        {
            return new XmlProcessingInstruction(target, data, this);
        }
 
        // Creates a XmlDeclaration node with the specified values.
        public virtual XmlDeclaration CreateXmlDeclaration(String version, string encoding, string standalone)
        {
            return new XmlDeclaration(version, encoding, standalone, this);
        }
 
        // Creates an XmlText with the specified text.
        public virtual XmlText CreateTextNode(String text)
        {
            return new XmlText(text, this);
        }
 
        // Creates a XmlSignificantWhitespace node.
        public virtual XmlSignificantWhitespace CreateSignificantWhitespace(string text)
        {
            return new XmlSignificantWhitespace(text, this);
        }
 
        public override XPathNavigator CreateNavigator()
        {
            return CreateNavigator(this);
        }
 
        internal protected virtual XPathNavigator CreateNavigator(XmlNode node)
        {
            XmlNodeType nodeType = node.NodeType;
            XmlNode parent;
            XmlNodeType parentType;
 
            switch (nodeType)
            {
                case XmlNodeType.EntityReference:
                case XmlNodeType.Entity:
                case XmlNodeType.DocumentType:
                case XmlNodeType.Notation:
                case XmlNodeType.XmlDeclaration:
                    return null;
                case XmlNodeType.Text:
                case XmlNodeType.CDATA:
                case XmlNodeType.SignificantWhitespace:
                    parent = node.ParentNode;
                    if (parent != null)
                    {
                        do
                        {
                            parentType = parent.NodeType;
                            if (parentType == XmlNodeType.Attribute)
                            {
                                return null;
                            }
                            else if (parentType == XmlNodeType.EntityReference)
                            {
                                parent = parent.ParentNode;
                            }
                            else
                            {
                                break;
                            }
                        }
                        while (parent != null);
                    }
                    node = NormalizeText(node);
                    break;
                case XmlNodeType.Whitespace:
                    parent = node.ParentNode;
                    if (parent != null)
                    {
                        do
                        {
                            parentType = parent.NodeType;
                            if (parentType == XmlNodeType.Document
                                || parentType == XmlNodeType.Attribute)
                            {
                                return null;
                            }
                            else if (parentType == XmlNodeType.EntityReference)
                            {
                                parent = parent.ParentNode;
                            }
                            else
                            {
                                break;
                            }
                        }
                        while (parent != null);
                    }
                    node = NormalizeText(node);
                    break;
                default:
                    break;
            }
            return new DocumentXPathNavigator(this, node);
        }
 
        internal static bool IsTextNode(XmlNodeType nt)
        {
            switch (nt)
            {
                case XmlNodeType.Text:
                case XmlNodeType.CDATA:
                case XmlNodeType.Whitespace:
                case XmlNodeType.SignificantWhitespace:
                    return true;
                default:
                    return false;
            }
        }
 
        private XmlNode NormalizeText(XmlNode n)
        {
            XmlNode retnode = null;
            while (IsTextNode(n.NodeType))
            {
                retnode = n;
                n = n.PreviousSibling;
 
                if (n == null)
                {
                    XmlNode intnode = retnode;
                    while (true)
                    {
                        if (intnode.ParentNode != null && intnode.ParentNode.NodeType == XmlNodeType.EntityReference)
                        {
                            if (intnode.ParentNode.PreviousSibling != null)
                            {
                                n = intnode.ParentNode.PreviousSibling;
                                break;
                            }
                            else
                            {
                                intnode = intnode.ParentNode;
                                if (intnode == null)
                                    break;
                            }
                        }
                        else
                            break;
                    }
                }
 
                if (n == null)
                    break;
                while (n.NodeType == XmlNodeType.EntityReference)
                {
                    n = n.LastChild;
                }
            }
            return retnode;
        }
 
        // Creates a XmlWhitespace node.
        public virtual XmlWhitespace CreateWhitespace(string text)
        {
            return new XmlWhitespace(text, this);
        }
 
        // Returns an XmlNodeList containing
        // a list of all descendant elements that match the specified name.
        public virtual XmlNodeList GetElementsByTagName(String name)
        {
            return new XmlElementList(this, name);
        }
 
        // DOM Level 2
 
        // Creates an XmlAttribute with the specified LocalName
        // and NamespaceURI.
        public XmlAttribute CreateAttribute(String qualifiedName, String namespaceURI)
        {
            string prefix = String.Empty;
            string localName = String.Empty;
 
            SplitName(qualifiedName, out prefix, out localName);
            return CreateAttribute(prefix, localName, namespaceURI);
        }
 
        // Creates an XmlElement with the specified LocalName and
        // NamespaceURI.
        public XmlElement CreateElement(String qualifiedName, String namespaceURI)
        {
            string prefix = String.Empty;
            string localName = String.Empty;
            SplitName(qualifiedName, out prefix, out localName);
            return CreateElement(prefix, localName, namespaceURI);
        }
 
        // Returns a XmlNodeList containing
        // a list of all descendant elements that match the specified name.
        public virtual XmlNodeList GetElementsByTagName(String localName, String namespaceURI)
        {
            return new XmlElementList(this, localName, namespaceURI);
        }
 
        // Returns the XmlElement with the specified ID.
        public virtual XmlElement GetElementById(string elementId)
        {
            if (_htElementIdMap != null)
            {
                ArrayList elementList = (ArrayList)(_htElementIdMap[elementId]);
                if (elementList != null)
                {
                    foreach (WeakReference elemRef in elementList)
                    {
                        XmlElement elem = (XmlElement)elemRef.Target;
                        if (elem != null
                            && elem.IsConnected())
                            return elem;
                    }
                }
            }
            return null;
        }
 
        // Imports a node from another document to this document.
        public virtual XmlNode ImportNode(XmlNode node, bool deep)
        {
            return ImportNodeInternal(node, deep);
        }
 
        private XmlNode ImportNodeInternal(XmlNode node, bool deep)
        {
            XmlNode newNode = null;
 
            if (node == null)
            {
                throw new InvalidOperationException(ResXml.Xdom_Import_NullNode);
            }
            else
            {
                switch (node.NodeType)
                {
                    case XmlNodeType.Element:
                        newNode = CreateElement(node.Prefix, node.LocalName, node.NamespaceURI);
                        ImportAttributes(node, newNode);
                        if (deep)
                            ImportChildren(node, newNode, deep);
                        break;
 
                    case XmlNodeType.Attribute:
                        Debug.Assert(((XmlAttribute)node).Specified);
                        newNode = CreateAttribute(node.Prefix, node.LocalName, node.NamespaceURI);
                        ImportChildren(node, newNode, true);
                        break;
 
                    case XmlNodeType.Text:
                        newNode = CreateTextNode(node.Value);
                        break;
                    case XmlNodeType.Comment:
                        newNode = CreateComment(node.Value);
                        break;
                    case XmlNodeType.ProcessingInstruction:
                        newNode = CreateProcessingInstruction(node.Name, node.Value);
                        break;
                    case XmlNodeType.XmlDeclaration:
                        XmlDeclaration decl = (XmlDeclaration)node;
                        newNode = CreateXmlDeclaration(decl.Version, decl.Encoding, decl.Standalone);
                        break;
                    case XmlNodeType.CDATA:
                        newNode = CreateCDataSection(node.Value);
                        break;
                    case XmlNodeType.DocumentType:
                        XmlDocumentType docType = (XmlDocumentType)node;
                        newNode = CreateDocumentType(docType.Name, docType.PublicId, docType.SystemId, docType.InternalSubset);
                        break;
                    case XmlNodeType.DocumentFragment:
                        newNode = CreateDocumentFragment();
                        if (deep)
                            ImportChildren(node, newNode, deep);
                        break;
 
                    case XmlNodeType.EntityReference:
                        newNode = CreateEntityReference(node.Name);
                        // we don't import the children of entity reference because they might result in different
                        // children nodes given different namesapce context in the new document.
                        break;
 
                    case XmlNodeType.Whitespace:
                        newNode = CreateWhitespace(node.Value);
                        break;
 
                    case XmlNodeType.SignificantWhitespace:
                        newNode = CreateSignificantWhitespace(node.Value);
                        break;
 
                    default:
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, ResXml.Xdom_Import, node.NodeType.ToString()));
                }
            }
 
            return newNode;
        }
 
        private void ImportAttributes(XmlNode fromElem, XmlNode toElem)
        {
            int cAttr = fromElem.Attributes.Count;
            for (int iAttr = 0; iAttr < cAttr; iAttr++)
            {
                if (fromElem.Attributes[iAttr].Specified)
                    toElem.Attributes.SetNamedItem(ImportNodeInternal(fromElem.Attributes[iAttr], true));
            }
        }
 
        private void ImportChildren(XmlNode fromNode, XmlNode toNode, bool deep)
        {
            Debug.Assert(toNode.NodeType != XmlNodeType.EntityReference);
            for (XmlNode n = fromNode.FirstChild; n != null; n = n.NextSibling)
            {
                toNode.AppendChild(ImportNodeInternal(n, deep));
            }
        }
 
        // Microsoft extensions
 
        // Gets the XmlNameTable associated with this
        // implementation.
        public XmlNameTable NameTable
        {
            get { return _implementation.NameTable; }
        }
 
        // Creates a XmlAttribute with the specified Prefix, LocalName,
        // and NamespaceURI.
        public virtual XmlAttribute CreateAttribute(string prefix, string localName, string namespaceURI)
        {
            return new XmlAttribute(AddAttrXmlName(prefix, localName, namespaceURI, null), this);
        }
 
        protected internal virtual XmlAttribute CreateDefaultAttribute(string prefix, string localName, string namespaceURI)
        {
            return new XmlUnspecifiedAttribute(prefix, localName, namespaceURI, this);
        }
 
        public virtual XmlElement CreateElement(string prefix, string localName, string namespaceURI)
        {
            XmlElement elem = new XmlElement(AddXmlName(prefix, localName, namespaceURI, null), true, this);
            if (!IsLoading)
                AddDefaultAttributes(elem);
            return elem;
        }
 
        // Gets or sets a value indicating whether to preserve whitespace.
        public bool PreserveWhitespace
        {
            get { return _preserveWhitespace; }
            set { _preserveWhitespace = value; }
        }
 
        // Gets a value indicating whether the node is read-only.
        public override bool IsReadOnly
        {
            get { return false; }
        }
 
        internal XmlNamedNodeMap Entities
        {
            get
            {
                if (_entities == null)
                    _entities = new XmlNamedNodeMap(this);
                return _entities;
            }
            set { _entities = value; }
        }
 
        internal bool IsLoading
        {
            get { return _isLoading; }
            set { _isLoading = value; }
        }
 
        internal bool ActualLoadingStatus
        {
            get { return _actualLoadingStatus; }
            set { _actualLoadingStatus = value; }
        }
 
 
        // Creates a XmlNode with the specified XmlNodeType, Prefix, Name, and NamespaceURI.
        public virtual XmlNode CreateNode(XmlNodeType type, string prefix, string name, string namespaceURI)
        {
            switch (type)
            {
                case XmlNodeType.Element:
                    if (prefix != null)
                        return CreateElement(prefix, name, namespaceURI);
                    else
                        return CreateElement(name, namespaceURI);
 
                case XmlNodeType.Attribute:
                    if (prefix != null)
                        return CreateAttribute(prefix, name, namespaceURI);
                    else
                        return CreateAttribute(name, namespaceURI);
 
                case XmlNodeType.Text:
                    return CreateTextNode(string.Empty);
 
                case XmlNodeType.CDATA:
                    return CreateCDataSection(string.Empty);
 
                case XmlNodeType.EntityReference:
                    return CreateEntityReference(name);
 
                case XmlNodeType.ProcessingInstruction:
                    return CreateProcessingInstruction(name, string.Empty);
 
                case XmlNodeType.XmlDeclaration:
                    return CreateXmlDeclaration("1.0", null, null);
 
                case XmlNodeType.Comment:
                    return CreateComment(string.Empty);
 
                case XmlNodeType.DocumentFragment:
                    return CreateDocumentFragment();
 
                case XmlNodeType.DocumentType:
                    return CreateDocumentType(name, string.Empty, string.Empty, string.Empty);
 
                case XmlNodeType.Document:
                    return new XmlDocument();
 
                case XmlNodeType.SignificantWhitespace:
                    return CreateSignificantWhitespace(string.Empty);
 
                case XmlNodeType.Whitespace:
                    return CreateWhitespace(string.Empty);
 
                default:
                    throw new ArgumentException(string.Format(ResXml.Arg_CannotCreateNode, type));
            }
        }
 
        // Creates an XmlNode with the specified node type, Name, and
        // NamespaceURI.
        public virtual XmlNode CreateNode(string nodeTypeString, string name, string namespaceURI)
        {
            return CreateNode(ConvertToNodeType(nodeTypeString), name, namespaceURI);
        }
 
        // Creates an XmlNode with the specified XmlNodeType, Name, and
        // NamespaceURI.
        public virtual XmlNode CreateNode(XmlNodeType type, string name, string namespaceURI)
        {
            return CreateNode(type, null, name, namespaceURI);
        }
 
        // Creates an XmlNode object based on the information in the XmlReader.
        // The reader must be positioned on a node or attribute.
        // [PermissionSetAttribute( SecurityAction.InheritanceDemand, Name = "FullTrust" )]
        public virtual XmlNode ReadNode(XmlReader reader)
        {
            XmlNode node = null;
            try
            {
                IsLoading = true;
                XmlLoader loader = new XmlLoader();
                node = loader.ReadCurrentNode(this, reader);
            }
            finally
            {
                IsLoading = false;
            }
            return node;
        }
 
        internal XmlNodeType ConvertToNodeType(string nodeTypeString)
        {
            if (nodeTypeString == "element")
            {
                return XmlNodeType.Element;
            }
            else if (nodeTypeString == "attribute")
            {
                return XmlNodeType.Attribute;
            }
            else if (nodeTypeString == "text")
            {
                return XmlNodeType.Text;
            }
            else if (nodeTypeString == "cdatasection")
            {
                return XmlNodeType.CDATA;
            }
            else if (nodeTypeString == "entityreference")
            {
                return XmlNodeType.EntityReference;
            }
            else if (nodeTypeString == "entity")
            {
                return XmlNodeType.Entity;
            }
            else if (nodeTypeString == "processinginstruction")
            {
                return XmlNodeType.ProcessingInstruction;
            }
            else if (nodeTypeString == "comment")
            {
                return XmlNodeType.Comment;
            }
            else if (nodeTypeString == "document")
            {
                return XmlNodeType.Document;
            }
            else if (nodeTypeString == "documenttype")
            {
                return XmlNodeType.DocumentType;
            }
            else if (nodeTypeString == "documentfragment")
            {
                return XmlNodeType.DocumentFragment;
            }
            else if (nodeTypeString == "notation")
            {
                return XmlNodeType.Notation;
            }
            else if (nodeTypeString == "significantwhitespace")
            {
                return XmlNodeType.SignificantWhitespace;
            }
            else if (nodeTypeString == "whitespace")
            {
                return XmlNodeType.Whitespace;
            }
            throw new ArgumentException(string.Format(ResXml.Xdom_Invalid_NT_String, nodeTypeString));
        }
 
 
        private XmlTextReader SetupReader(XmlTextReader tr)
        {
            tr.XmlValidatingReaderCompatibilityMode = true;
            tr.EntityHandling = EntityHandling.ExpandCharEntities;
            if (this.HasSetResolver)
                tr.XmlResolver = GetResolver();
            return tr;
        }
 
        // Loads the XML document from the specified URL.
        // [ResourceConsumption(ResourceScope.Machine)]
        // [ResourceExposure(ResourceScope.Machine)]
        public virtual void Load(string filename)
        {
            XmlTextReader reader = SetupReader(new XmlTextReader(filename, NameTable));
            try
            {
                Load(reader);
            }
            finally
            {
                reader.Close();
            }
        }
 
        public virtual void Load(Stream inStream)
        {
            XmlTextReader reader = SetupReader(new XmlTextReader(inStream, NameTable));
            try
            {
                Load(reader);
            }
            finally
            {
                reader.Impl.Close(false);
            }
        }
 
        // Loads the XML document from the specified TextReader.
        public virtual void Load(TextReader txtReader)
        {
            XmlTextReader reader = SetupReader(new XmlTextReader(txtReader, NameTable));
            try
            {
                Load(reader);
            }
            finally
            {
                reader.Impl.Close(false);
            }
        }
 
        // Loads the XML document from the specified XmlReader.
        public virtual void Load(XmlReader reader)
        {
            try
            {
                IsLoading = true;
                _actualLoadingStatus = true;
                RemoveAll();
                fEntRefNodesPresent = false;
                fCDataNodesPresent = false;
                _reportValidity = true;
 
                XmlLoader loader = new XmlLoader();
                loader.Load(this, reader, _preserveWhitespace);
            }
            finally
            {
                IsLoading = false;
                _actualLoadingStatus = false;
 
                // Ensure the bit is still on after loading a dtd 
                _reportValidity = true;
            }
        }
 
        // Loads the XML document from the specified string.
        public virtual void LoadXml(string xml)
        {
            XmlTextReader reader = SetupReader(new XmlTextReader(new StringReader(xml), NameTable));
            try
            {
                Load(reader);
            }
            finally
            {
                reader.Close();
            }
        }
 
        //TextEncoding is the one from XmlDeclaration if there is any
        internal Encoding TextEncoding
        {
            get
            {
                if (Declaration != null)
                {
                    string value = Declaration.Encoding;
                    if (value.Length > 0)
                    {
                        return System.Text.Encoding.GetEncoding(value);
                    }
                }
                return null;
            }
        }
 
        public override string InnerText
        {
            set
            {
                throw new InvalidOperationException(ResXml.Xdom_Document_Innertext);
            }
        }
 
        public override string InnerXml
        {
            get
            {
                return base.InnerXml;
            }
            set
            {
                LoadXml(value);
            }
        }
 
        // Saves the XML document to the specified file.
        //Saves out the to the file with exact content in the XmlDocument.
        // [ResourceConsumption(ResourceScope.Machine)]
        // [ResourceExposure(ResourceScope.Machine)]
        public virtual void Save(string filename)
        {
            if (DocumentElement == null)
                throw new XmlException(ResXml.Xml_InvalidXmlDocument, ResXml.Xdom_NoRootEle);
            XmlDOMTextWriter xw = new XmlDOMTextWriter(filename, TextEncoding);
            try
            {
                if (_preserveWhitespace == false)
                    xw.Formatting = Formatting.Indented;
                WriteTo(xw);
                xw.Flush();
            }
            finally
            {
                xw.Close();
            }
        }
 
        //Saves out the to the file with exact content in the XmlDocument.
        public virtual void Save(Stream outStream)
        {
            XmlDOMTextWriter xw = new XmlDOMTextWriter(outStream, TextEncoding);
            if (_preserveWhitespace == false)
                xw.Formatting = Formatting.Indented;
            WriteTo(xw);
            xw.Flush();
        }
 
        // Saves the XML document to the specified TextWriter.
        //
        //Saves out the file with xmldeclaration which has encoding value equal to
        //that of textwriter's encoding
        public virtual void Save(TextWriter writer)
        {
            XmlDOMTextWriter xw = new XmlDOMTextWriter(writer);
            if (_preserveWhitespace == false)
                xw.Formatting = Formatting.Indented;
            Save(xw);
        }
 
        // Saves the XML document to the specified XmlWriter.
        // 
        //Saves out the file with xmldeclaration which has encoding value equal to
        //that of textwriter's encoding
        public virtual void Save(XmlWriter w)
        {
            XmlNode n = this.FirstChild;
            if (n == null)
                return;
            if (w.WriteState == WriteState.Start)
            {
                if (n is XmlDeclaration)
                {
                    if (Standalone.Length == 0)
                        w.WriteStartDocument();
                    else if (Standalone == "yes")
                        w.WriteStartDocument(true);
                    else if (Standalone == "no")
                        w.WriteStartDocument(false);
                    n = n.NextSibling;
                }
                else
                {
                    w.WriteStartDocument();
                }
            }
            while (n != null)
            {
                //Debug.Assert( n.NodeType != XmlNodeType.XmlDeclaration );
                n.WriteTo(w);
                n = n.NextSibling;
            }
            w.Flush();
        }
 
        // Saves the node to the specified XmlWriter.
        // 
        //Writes out the to the file with exact content in the XmlDocument.
        public override void WriteTo(XmlWriter w)
        {
            WriteContentTo(w);
        }
 
        // Saves all the children of the node to the specified XmlWriter.
        // 
        //Writes out the to the file with exact content in the XmlDocument.
        public override void WriteContentTo(XmlWriter xw)
        {
            foreach (XmlNode n in this)
            {
                n.WriteTo(xw);
            }
        }
 
        public void Validate(ValidationEventHandler validationEventHandler)
        {
            Validate(validationEventHandler, this);
        }
 
        public void Validate(ValidationEventHandler validationEventHandler, XmlNode nodeToValidate)
        {
            if (_schemas == null || _schemas.Count == 0)
            { //Should we error
                throw new InvalidOperationException(ResXml.XmlDocument_NoSchemaInfo);
            }
            XmlDocument parentDocument = nodeToValidate.Document;
            if (parentDocument != this)
            {
                throw new ArgumentException(string.Format(ResXml.XmlDocument_NodeNotFromDocument, "nodeToValidate"));
            }
            if (nodeToValidate == this)
            {
                _reportValidity = false;
            }
            DocumentSchemaValidator validator = new DocumentSchemaValidator(this, _schemas, validationEventHandler);
            validator.Validate(nodeToValidate);
            if (nodeToValidate == this)
            {
                _reportValidity = true;
            }
        }
 
        public event XmlNodeChangedEventHandler NodeInserting
        {
            add
            {
                _onNodeInsertingDelegate += value;
            }
            remove
            {
                _onNodeInsertingDelegate -= value;
            }
        }
 
        public event XmlNodeChangedEventHandler NodeInserted
        {
            add
            {
                _onNodeInsertedDelegate += value;
            }
            remove
            {
                _onNodeInsertedDelegate -= value;
            }
        }
 
        public event XmlNodeChangedEventHandler NodeRemoving
        {
            add
            {
                _onNodeRemovingDelegate += value;
            }
            remove
            {
                _onNodeRemovingDelegate -= value;
            }
        }
 
        public event XmlNodeChangedEventHandler NodeRemoved
        {
            add
            {
                _onNodeRemovedDelegate += value;
            }
            remove
            {
                _onNodeRemovedDelegate -= value;
            }
        }
 
        public event XmlNodeChangedEventHandler NodeChanging
        {
            add
            {
                _onNodeChangingDelegate += value;
            }
            remove
            {
                _onNodeChangingDelegate -= value;
            }
        }
 
        public event XmlNodeChangedEventHandler NodeChanged
        {
            add
            {
                _onNodeChangedDelegate += value;
            }
            remove
            {
                _onNodeChangedDelegate -= value;
            }
        }
 
        internal override XmlNodeChangedEventArgs GetEventArgs(XmlNode node, XmlNode oldParent, XmlNode newParent, string oldValue, string newValue, XmlNodeChangedAction action)
        {
            _reportValidity = false;
 
            switch (action)
            {
                case XmlNodeChangedAction.Insert:
                    if (_onNodeInsertingDelegate == null && _onNodeInsertedDelegate == null)
                    {
                        return null;
                    }
                    break;
                case XmlNodeChangedAction.Remove:
                    if (_onNodeRemovingDelegate == null && _onNodeRemovedDelegate == null)
                    {
                        return null;
                    }
                    break;
                case XmlNodeChangedAction.Change:
                    if (_onNodeChangingDelegate == null && _onNodeChangedDelegate == null)
                    {
                        return null;
                    }
                    break;
            }
            return new XmlNodeChangedEventArgs(node, oldParent, newParent, oldValue, newValue, action);
        }
 
        internal XmlNodeChangedEventArgs GetInsertEventArgsForLoad(XmlNode node, XmlNode newParent)
        {
            if (_onNodeInsertingDelegate == null && _onNodeInsertedDelegate == null)
            {
                return null;
            }
            string nodeValue = node.Value;
            return new XmlNodeChangedEventArgs(node, null, newParent, nodeValue, nodeValue, XmlNodeChangedAction.Insert);
        }
 
        internal override void BeforeEvent(XmlNodeChangedEventArgs args)
        {
            if (args != null)
            {
                switch (args.Action)
                {
                    case XmlNodeChangedAction.Insert:
                        if (_onNodeInsertingDelegate != null)
                            _onNodeInsertingDelegate(this, args);
                        break;
 
                    case XmlNodeChangedAction.Remove:
                        if (_onNodeRemovingDelegate != null)
                            _onNodeRemovingDelegate(this, args);
                        break;
 
                    case XmlNodeChangedAction.Change:
                        if (_onNodeChangingDelegate != null)
                            _onNodeChangingDelegate(this, args);
                        break;
                }
            }
        }
 
        internal override void AfterEvent(XmlNodeChangedEventArgs args)
        {
            if (args != null)
            {
                switch (args.Action)
                {
                    case XmlNodeChangedAction.Insert:
                        if (_onNodeInsertedDelegate != null)
                            _onNodeInsertedDelegate(this, args);
                        break;
 
                    case XmlNodeChangedAction.Remove:
                        if (_onNodeRemovedDelegate != null)
                            _onNodeRemovedDelegate(this, args);
                        break;
 
                    case XmlNodeChangedAction.Change:
                        if (_onNodeChangedDelegate != null)
                            _onNodeChangedDelegate(this, args);
                        break;
                }
            }
        }
 
        // The function such through schema info to find out if there exists a default attribute with passed in names in the passed in element
        // If so, return the newly created default attribute (with children tree);
        // Otherwise, return null.
 
        internal XmlAttribute GetDefaultAttribute(XmlElement elem, string attrPrefix, string attrLocalname, string attrNamespaceURI)
        {
            SchemaInfo schInfo = DtdSchemaInfo;
            SchemaElementDecl ed = GetSchemaElementDecl(elem);
            if (ed != null && ed.AttDefs != null)
            {
                IDictionaryEnumerator attrDefs = ed.AttDefs.GetEnumerator();
                while (attrDefs.MoveNext())
                {
                    SchemaAttDef attdef = (SchemaAttDef)attrDefs.Value;
                    if (attdef.Presence == SchemaDeclBase.Use.Default ||
                        attdef.Presence == SchemaDeclBase.Use.Fixed)
                    {
                        if (attdef.Name.Name == attrLocalname)
                        {
                            if ((schInfo.SchemaType == SchemaType.DTD && attdef.Name.Namespace == attrPrefix) ||
                                 (schInfo.SchemaType != SchemaType.DTD && attdef.Name.Namespace == attrNamespaceURI))
                            {
                                //find a def attribute with the same name, build a default attribute and return
                                XmlAttribute defattr = PrepareDefaultAttribute(attdef, attrPrefix, attrLocalname, attrNamespaceURI);
                                return defattr;
                            }
                        }
                    }
                }
            }
            return null;
        }
 
        internal String Version
        {
            get
            {
                XmlDeclaration decl = Declaration;
                if (decl != null)
                    return decl.Version;
                return null;
            }
        }
 
        internal String Encoding
        {
            get
            {
                XmlDeclaration decl = Declaration;
                if (decl != null)
                    return decl.Encoding;
                return null;
            }
        }
 
        internal String Standalone
        {
            get
            {
                XmlDeclaration decl = Declaration;
                if (decl != null)
                    return decl.Standalone;
                return null;
            }
        }
 
        internal XmlEntity GetEntityNode(String name)
        {
            if (DocumentType != null)
            {
                XmlNamedNodeMap entites = DocumentType.Entities;
                if (entites != null)
                    return (XmlEntity)(entites.GetNamedItem(name));
            }
            return null;
        }
 
        public override IXmlSchemaInfo SchemaInfo
        {
            get
            {
                if (_reportValidity)
                {
                    XmlElement documentElement = DocumentElement;
                    if (documentElement != null)
                    {
                        switch (documentElement.SchemaInfo.Validity)
                        {
                            case XmlSchemaValidity.Valid:
                                return ValidSchemaInfo;
                            case XmlSchemaValidity.Invalid:
                                return InvalidSchemaInfo;
                        }
                    }
                }
                return NotKnownSchemaInfo;
            }
        }
 
        public override String BaseURI
        {
            get { return baseURI; }
        }
 
        internal void SetBaseURI(String inBaseURI)
        {
            baseURI = inBaseURI;
        }
 
        internal override XmlNode AppendChildForLoad(XmlNode newChild, XmlDocument doc)
        {
            Debug.Assert(doc == this);
 
            if (!IsValidChildType(newChild.NodeType))
                throw new InvalidOperationException(ResXml.Xdom_Node_Insert_TypeConflict);
 
            if (!CanInsertAfter(newChild, LastChild))
                throw new InvalidOperationException(ResXml.Xdom_Node_Insert_Location);
 
            XmlNodeChangedEventArgs args = GetInsertEventArgsForLoad(newChild, this);
 
            if (args != null)
                BeforeEvent(args);
 
            XmlLinkedNode newNode = (XmlLinkedNode)newChild;
 
            if (_lastChild == null)
            {
                newNode.next = newNode;
            }
            else
            {
                newNode.next = _lastChild.next;
                _lastChild.next = newNode;
            }
 
            _lastChild = newNode;
            newNode.SetParentForLoad(this);
 
            if (args != null)
                AfterEvent(args);
 
            return newNode;
        }
 
        internal override XPathNodeType XPNodeType { get { return XPathNodeType.Root; } }
 
        internal bool HasEntityReferences
        {
            get
            {
                return fEntRefNodesPresent;
            }
        }
 
        internal XmlAttribute NamespaceXml
        {
            get
            {
                if (_namespaceXml == null)
                {
                    _namespaceXml = new XmlAttribute(AddAttrXmlName(strXmlns, strXml, strReservedXmlns, null), this);
                    _namespaceXml.Value = strReservedXml;
                }
                return _namespaceXml;
            }
        }
    }
}