The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlDocument

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlDocument.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Diagnostics;
  20.     using System.IO;
  21.     using System.Text;
  22.     using System.Xml.Schema;
  23.     using System.Xml.XPath;
  24.     using System.Security;
  25.     using System.Security.Permissions;
  26.     using System.Globalization;
  27.    
  28.     // Represents an entire document. An XmlDocument contains XML data.
  29.     public class XmlDocument : XmlNode
  30.     {
  31.         private XmlImplementation implementation;
  32.         private DomNameTable domNameTable;
  33.         // hash table of XmlName
  34.         private XmlLinkedNode lastChild;
  35.         private XmlNamedNodeMap entities;
  36.         private Hashtable htElementIdMap;
  37.         private Hashtable htElementIDAttrDecl;
  38.         //key: id; object: the ArrayList of the elements that have the same id (connected or disconnected)
  39.         private SchemaInfo schemaInfo;
  40.         private XmlSchemaSet schemas;
  41.         // schemas associated with the cache
  42.         private bool reportValidity;
  43.         //This variable represents the actual loading status. Since, IsLoading will
  44.         //be manipulated soemtimes for adding content to EntityReference this variable
  45.         //has been added which would always represent the loading status of document.
  46.         private bool actualLoadingStatus;
  47.        
  48.         private XmlNodeChangedEventHandler onNodeInsertingDelegate;
  49.         private XmlNodeChangedEventHandler onNodeInsertedDelegate;
  50.         private XmlNodeChangedEventHandler onNodeRemovingDelegate;
  51.         private XmlNodeChangedEventHandler onNodeRemovedDelegate;
  52.         private XmlNodeChangedEventHandler onNodeChangingDelegate;
  53.         private XmlNodeChangedEventHandler onNodeChangedDelegate;
  54.        
  55.         // 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)
  56.         internal bool fEntRefNodesPresent;
  57.         internal bool fCDataNodesPresent;
  58.        
  59.         private bool preserveWhitespace;
  60.         private bool isLoading;
  61.        
  62.         // special name strings for
  63.         internal string strDocumentName;
  64.         internal string strDocumentFragmentName;
  65.         internal string strCommentName;
  66.         internal string strTextName;
  67.         internal string strCDataSectionName;
  68.         internal string strEntityName;
  69.         internal string strID;
  70.         internal string strXmlns;
  71.         internal string strXml;
  72.         internal string strSpace;
  73.         internal string strLang;
  74.         internal string strEmpty;
  75.        
  76.         internal string strNonSignificantWhitespaceName;
  77.         internal string strSignificantWhitespaceName;
  78.         internal string strReservedXmlns;
  79.         internal string strReservedXml;
  80.        
  81.         internal string baseURI;
  82.        
  83.         private XmlResolver resolver;
  84.         internal bool bSetResolver;
  85.         internal object objLock;
  86.        
  87.         private XmlAttribute namespaceXml;
  88.        
  89.         static internal EmptyEnumerator EmptyEnumerator = new EmptyEnumerator();
  90.         static internal IXmlSchemaInfo NotKnownSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.NotKnown);
  91.         static internal IXmlSchemaInfo ValidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Valid);
  92.         static internal IXmlSchemaInfo InvalidSchemaInfo = new XmlSchemaInfo(XmlSchemaValidity.Invalid);
  93.        
  94.         // Initializes a new instance of the XmlDocument class.
  95.         public XmlDocument() : this(new XmlImplementation())
  96.         {
  97.         }
  98.        
  99.         // Initializes a new instance
  100.         // of the XmlDocument class with the specified XmlNameTable.
  101.         public XmlDocument(XmlNameTable nt) : this(new XmlImplementation(nt))
  102.         {
  103.         }
  104.        
  105.         protected internal XmlDocument(XmlImplementation imp) : base()
  106.         {
  107.            
  108.             implementation = imp;
  109.             domNameTable = new DomNameTable(this);
  110.            
  111.             // force the following string instances to be default in the nametable
  112.             XmlNameTable nt = this.NameTable;
  113.             nt.Add(string.Empty);
  114.             strDocumentName = nt.Add("#document");
  115.             strDocumentFragmentName = nt.Add("#document-fragment");
  116.             strCommentName = nt.Add("#comment");
  117.             strTextName = nt.Add("#text");
  118.             strCDataSectionName = nt.Add("#cdata-section");
  119.             strEntityName = nt.Add("#entity");
  120.             strID = nt.Add("id");
  121.             strNonSignificantWhitespaceName = nt.Add("#whitespace");
  122.             strSignificantWhitespaceName = nt.Add("#significant-whitespace");
  123.             strXmlns = nt.Add("xmlns");
  124.             strXml = nt.Add("xml");
  125.             strSpace = nt.Add("space");
  126.             strLang = nt.Add("lang");
  127.             strReservedXmlns = nt.Add("http://www.w3.org/2000/xmlns/");
  128.             strReservedXml = nt.Add("http://www.w3.org/XML/1998/namespace");
  129.             strEmpty = nt.Add(String.Empty);
  130.             baseURI = String.Empty;
  131.            
  132.             objLock = new object();
  133.         }
  134.        
  135.         internal SchemaInfo DtdSchemaInfo {
  136.             get { return schemaInfo; }
  137.             set { schemaInfo = value; }
  138.         }
  139.        
  140.         static internal void CheckName(string name)
  141.         {
  142.             XmlCharType xmlCharType = XmlCharType.Instance;
  143.             for (int i = 0; i < name.Length; i++) {
  144.                 if (!xmlCharType.IsNCNameChar(name[i]))
  145.                     throw new XmlException(Res.Xml_BadNameChar, XmlException.BuildCharExceptionStr(name[i]));
  146.             }
  147.         }
  148.        
  149.         internal XmlName AddXmlName(string prefix, string localName, string namespaceURI, IXmlSchemaInfo schemaInfo)
  150.         {
  151.             XmlName n = domNameTable.AddName(prefix, localName, namespaceURI, schemaInfo);
  152.             Debug.Assert((prefix == null) ? (n.Prefix.Length == 0) : (prefix == n.Prefix));
  153.             Debug.Assert(n.LocalName == localName);
  154.             Debug.Assert((namespaceURI == null) ? (n.NamespaceURI.Length == 0) : (n.NamespaceURI == namespaceURI));
  155.             return n;
  156.         }
  157.        
  158.         internal XmlName GetXmlName(string prefix, string localName, string namespaceURI, IXmlSchemaInfo schemaInfo)
  159.         {
  160.             XmlName n = domNameTable.GetName(prefix, localName, namespaceURI, schemaInfo);
  161.             Debug.Assert(n == null || ((prefix == null) ? (n.Prefix.Length == 0) : (prefix == n.Prefix)));
  162.             Debug.Assert(n == null || n.LocalName == localName);
  163.             Debug.Assert(n == null || ((namespaceURI == null) ? (n.NamespaceURI.Length == 0) : (n.NamespaceURI == namespaceURI)));
  164.             return n;
  165.         }
  166.        
  167.         internal XmlName AddAttrXmlName(string prefix, string localName, string namespaceURI, IXmlSchemaInfo schemaInfo)
  168.         {
  169.             XmlName xmlName = AddXmlName(prefix, localName, namespaceURI, schemaInfo);
  170.             Debug.Assert((prefix == null) ? (xmlName.Prefix.Length == 0) : (prefix == xmlName.Prefix));
  171.             Debug.Assert(xmlName.LocalName == localName);
  172.             Debug.Assert((namespaceURI == null) ? (xmlName.NamespaceURI.Length == 0) : (xmlName.NamespaceURI == namespaceURI));
  173.            
  174.             if (!this.IsLoading) {
  175.                 // Use atomized versions instead of prefix, localName and nsURI
  176.                 object oPrefix = xmlName.Prefix;
  177.                 object oNamespaceURI = xmlName.NamespaceURI;
  178.                 object oLocalName = xmlName.LocalName;
  179.                 if ((oPrefix == (object)strXmlns || (oPrefix == (object)strEmpty && oLocalName == (object)strXmlns)) ^ (oNamespaceURI == (object)strReservedXmlns))
  180.                     throw new ArgumentException(Res.GetString(Res.Xdom_Attr_Reserved_XmlNS, namespaceURI));
  181.             }
  182.             return xmlName;
  183.         }
  184.        
  185.         internal bool AddIdInfo(XmlName eleName, XmlName attrName)
  186.         {
  187.             //when XmlLoader call XmlDocument.AddInfo, the element.XmlName and attr.XmlName
  188.             //have already been replaced with the ones that don't have namespace values (or just
  189.             //string.Empty) because in DTD, the namespace is not supported
  190.             if (htElementIDAttrDecl == null || htElementIDAttrDecl[eleName] == null) {
  191.                 if (htElementIDAttrDecl == null)
  192.                     htElementIDAttrDecl = new Hashtable();
  193.                 htElementIDAttrDecl.Add(eleName, attrName);
  194.                 return true;
  195.             }
  196.             return false;
  197.         }
  198.        
  199.         private XmlName GetIDInfoByElement_(XmlName eleName)
  200.         {
  201.             //When XmlDocument is getting the IDAttribute for a given element,
  202.             //we need only compare the prefix and localname of element.XmlName with
  203.             //the registered htElementIDAttrDecl.
  204.             XmlName newName = GetXmlName(eleName.Prefix, eleName.LocalName, string.Empty, null);
  205.             if (newName != null) {
  206.                 return (XmlName)(htElementIDAttrDecl[newName]);
  207.             }
  208.             return null;
  209.         }
  210.        
  211.         internal XmlName GetIDInfoByElement(XmlName eleName)
  212.         {
  213.             if (htElementIDAttrDecl == null)
  214.                 return null;
  215.             else
  216.                 return GetIDInfoByElement_(eleName);
  217.         }
  218.        
  219.         private WeakReference GetElement(ArrayList elementList, XmlElement elem)
  220.         {
  221.             ArrayList gcElemRefs = new ArrayList();
  222.             foreach (WeakReference elemRef in elementList) {
  223.                 if (!elemRef.IsAlive)
  224.                     gcElemRefs.Add(elemRef);
  225.                 //take notes on the garbage collected nodes
  226.                 else {
  227.                     if ((XmlElement)(elemRef.Target) == elem)
  228.                         return elemRef;
  229.                 }
  230.             }
  231.             //Clear out the gced elements
  232.             foreach (WeakReference elemRef in gcElemRefs)
  233.                 elementList.Remove(elemRef);
  234.             return null;
  235.         }
  236.        
  237.         internal void AddElementWithId(string id, XmlElement elem)
  238.         {
  239.             if (htElementIdMap == null || !htElementIdMap.Contains(id)) {
  240.                 if (htElementIdMap == null)
  241.                     htElementIdMap = new Hashtable();
  242.                 ArrayList elementList = new ArrayList();
  243.                 elementList.Add(new WeakReference(elem));
  244.                 htElementIdMap.Add(id, elementList);
  245.             }
  246.             else {
  247.                 // there are other element(s) that has the same id
  248.                 ArrayList elementList = (ArrayList)(htElementIdMap[id]);
  249.                 if (GetElement(elementList, elem) == null)
  250.                     elementList.Add(new WeakReference(elem));
  251.             }
  252.         }
  253.        
  254.         internal void RemoveElementWithId(string id, XmlElement elem)
  255.         {
  256.             if (htElementIdMap != null && htElementIdMap.Contains(id)) {
  257.                 ArrayList elementList = (ArrayList)(htElementIdMap[id]);
  258.                 WeakReference elemRef = GetElement(elementList, elem);
  259.                 if (elemRef != null) {
  260.                     elementList.Remove(elemRef);
  261.                     if (elementList.Count == 0)
  262.                         htElementIdMap.Remove(id);
  263.                 }
  264.             }
  265.         }
  266.        
  267.        
  268.         // Creates a duplicate of this node.
  269.         public override XmlNode CloneNode(bool deep)
  270.         {
  271.             XmlDocument clone = Implementation.CreateDocument();
  272.             clone.SetBaseURI(this.baseURI);
  273.             if (deep)
  274.                 clone.ImportChildren(this, clone, deep);
  275.            
  276.             return clone;
  277.         }
  278.        
  279.         // Gets the type of the current node.
  280.         public override XmlNodeType NodeType {
  281.             get { return XmlNodeType.Document; }
  282.         }
  283.        
  284.         public override XmlNode ParentNode {
  285.             get { return null; }
  286.         }
  287.        
  288.         // Gets the node for the DOCTYPE declaration.
  289.         public virtual XmlDocumentType DocumentType {
  290.             get { return (XmlDocumentType)FindChild(XmlNodeType.DocumentType); }
  291.         }
  292.        
  293.         internal virtual XmlDeclaration Declaration {
  294.             get {
  295.                 if (HasChildNodes) {
  296.                     XmlDeclaration dec = FirstChild as XmlDeclaration;
  297.                     return dec;
  298.                 }
  299.                 return null;
  300.             }
  301.         }
  302.        
  303.         // Gets the XmlImplementation object for this document.
  304.         public XmlImplementation Implementation {
  305.             get { return this.implementation; }
  306.         }
  307.        
  308.         // Gets the name of the node.
  309.         public override string Name {
  310.             get { return strDocumentName; }
  311.         }
  312.        
  313.         // Gets the name of the current node without the namespace prefix.
  314.         public override string LocalName {
  315.             get { return strDocumentName; }
  316.         }
  317.        
  318.         // Gets the root XmlElement for the document.
  319.         public XmlElement DocumentElement {
  320.             get { return (XmlElement)FindChild(XmlNodeType.Element); }
  321.         }
  322.        
  323.         internal override bool IsContainer {
  324.             get { return true; }
  325.         }
  326.        
  327.         internal override XmlLinkedNode LastNode {
  328.             get { return lastChild; }
  329.             set { lastChild = value; }
  330.         }
  331.        
  332.         // Gets the XmlDocument that contains this node.
  333.         public override XmlDocument OwnerDocument {
  334.             get { return null; }
  335.         }
  336.        
  337.         public XmlSchemaSet Schemas {
  338.             get {
  339.                 if (schemas == null) {
  340.                     schemas = new XmlSchemaSet(NameTable);
  341.                 }
  342.                 return schemas;
  343.             }
  344.            
  345.             set { schemas = value; }
  346.         }
  347.        
  348.         internal bool CanReportValidity {
  349.             get { return reportValidity; }
  350.         }
  351.        
  352.         internal bool HasSetResolver {
  353.             get { return bSetResolver; }
  354.         }
  355.        
  356.         internal XmlResolver GetResolver()
  357.         {
  358.             return resolver;
  359.         }
  360.        
  361.         public virtual XmlResolver XmlResolver {
  362.             set {
  363.                 if (value != null) {
  364.                     try {
  365.                         new NamedPermissionSet("FullTrust").Demand();
  366.                     }
  367.                     catch (SecurityException e) {
  368.                         throw new SecurityException(Res.GetString(Res.Xml_UntrustedCodeSettingResolver), e);
  369.                     }
  370.                 }
  371.                
  372.                 resolver = value;
  373.                 if (!bSetResolver)
  374.                     bSetResolver = true;
  375.                
  376.                 XmlDocumentType dtd = this.DocumentType;
  377.                 if (dtd != null) {
  378.                     dtd.DtdSchemaInfo = null;
  379.                 }
  380.             }
  381.         }
  382.         internal override bool IsValidChildType(XmlNodeType type)
  383.         {
  384.             switch (type) {
  385.                 case XmlNodeType.ProcessingInstruction:
  386.                 case XmlNodeType.Comment:
  387.                 case XmlNodeType.Whitespace:
  388.                 case XmlNodeType.SignificantWhitespace:
  389.                     return true;
  390.                 case XmlNodeType.DocumentType:
  391.                    
  392.                     if (DocumentType != null)
  393.                         throw new InvalidOperationException(Res.GetString(Res.Xdom_DualDocumentTypeNode));
  394.                     return true;
  395.                 case XmlNodeType.Element:
  396.                    
  397.                     if (DocumentElement != null)
  398.                         throw new InvalidOperationException(Res.GetString(Res.Xdom_DualDocumentElementNode));
  399.                     return true;
  400.                 case XmlNodeType.XmlDeclaration:
  401.                    
  402.                     if (Declaration != null)
  403.                         throw new InvalidOperationException(Res.GetString(Res.Xdom_DualDeclarationNode));
  404.                     return true;
  405.                 default:
  406.                    
  407.                     return false;
  408.             }
  409.         }
  410.         // the function examines all the siblings before the refNode
  411.         // if any of the nodes has type equals to "nt", return true; otherwise, return false;
  412.         private bool HasNodeTypeInPrevSiblings(XmlNodeType nt, XmlNode refNode)
  413.         {
  414.             if (refNode == null)
  415.                 return false;
  416.            
  417.             XmlNode node = null;
  418.             if (refNode.ParentNode != null)
  419.                 node = refNode.ParentNode.FirstChild;
  420.             while (node != null) {
  421.                 if (node.NodeType == nt)
  422.                     return true;
  423.                 if (node == refNode)
  424.                     break;
  425.                 node = node.NextSibling;
  426.             }
  427.             return false;
  428.         }
  429.        
  430.         // the function examines all the siblings after the refNode
  431.         // if any of the nodes has the type equals to "nt", return true; otherwise, return false;
  432.         private bool HasNodeTypeInNextSiblings(XmlNodeType nt, XmlNode refNode)
  433.         {
  434.             XmlNode node = refNode;
  435.             while (node != null) {
  436.                 if (node.NodeType == nt)
  437.                     return true;
  438.                 node = node.NextSibling;
  439.             }
  440.             return false;
  441.         }
  442.        
  443.         internal override bool CanInsertBefore(XmlNode newChild, XmlNode refChild)
  444.         {
  445.             if (refChild == null)
  446.                 refChild = FirstChild;
  447.            
  448.             if (refChild == null)
  449.                 return true;
  450.            
  451.             switch (newChild.NodeType) {
  452.                 case XmlNodeType.XmlDeclaration:
  453.                     return (refChild == FirstChild);
  454.                 case XmlNodeType.ProcessingInstruction:
  455.                 case XmlNodeType.Comment:
  456.                    
  457.                     return refChild.NodeType != XmlNodeType.XmlDeclaration;
  458.                 case XmlNodeType.DocumentType:
  459.                    
  460.                    
  461.                     {
  462.                         if (refChild.NodeType != XmlNodeType.XmlDeclaration) {
  463.                             //if refChild is not the XmlDeclaration node, only need to go through the sibling before and including refChild to
  464.                             // make sure no Element ( rootElem node ) before the current position
  465.                             return !HasNodeTypeInPrevSiblings(XmlNodeType.Element, refChild.PreviousSibling);
  466.                         }
  467.                     }
  468.                     break;
  469.                 case XmlNodeType.Element:
  470.                    
  471.                    
  472.                     {
  473.                         if (refChild.NodeType != XmlNodeType.XmlDeclaration) {
  474.                             //if refChild is not the XmlDeclaration node, only need to go through the siblings after and including the refChild to
  475.                             // make sure no DocType node and XmlDeclaration node after the current posistion.
  476.                             return !HasNodeTypeInNextSiblings(XmlNodeType.DocumentType, refChild);
  477.                         }
  478.                     }
  479.                     break;
  480.             }
  481.            
  482.             return false;
  483.         }
  484.        
  485.         internal override bool CanInsertAfter(XmlNode newChild, XmlNode refChild)
  486.         {
  487.             if (refChild == null)
  488.                 refChild = LastChild;
  489.            
  490.             if (refChild == null)
  491.                 return true;
  492.            
  493.             switch (newChild.NodeType) {
  494.                 case XmlNodeType.ProcessingInstruction:
  495.                 case XmlNodeType.Comment:
  496.                 case XmlNodeType.Whitespace:
  497.                 case XmlNodeType.SignificantWhitespace:
  498.                     return true;
  499.                 case XmlNodeType.DocumentType:
  500.                    
  501.                    
  502.                     {
  503.                         //we will have to go through all the siblings before the refChild just to make sure no Element node ( rootElem )
  504.                         // before the current position
  505.                         return !HasNodeTypeInPrevSiblings(XmlNodeType.Element, refChild);
  506.                     }
  507.                     break;
  508.                 case XmlNodeType.Element:
  509.                    
  510.                    
  511.                     {
  512.                         return !HasNodeTypeInNextSiblings(XmlNodeType.DocumentType, refChild.NextSibling);
  513.                     }
  514.                     break;
  515.                
  516.             }
  517.            
  518.             return false;
  519.         }
  520.        
  521.         // Creates an XmlAttribute with the specified name.
  522.         public XmlAttribute CreateAttribute(string name)
  523.         {
  524.             string prefix = String.Empty;
  525.             string localName = String.Empty;
  526.             string namespaceURI = String.Empty;
  527.            
  528.             SplitName(name, out prefix, out localName);
  529.            
  530.             SetDefaultNamespace(prefix, localName, ref namespaceURI);
  531.            
  532.             return CreateAttribute(prefix, localName, namespaceURI);
  533.         }
  534.        
  535.         internal void SetDefaultNamespace(string prefix, string localName, ref string namespaceURI)
  536.         {
  537.             if (prefix == strXmlns || (prefix.Length == 0 && localName == strXmlns)) {
  538.                 namespaceURI = strReservedXmlns;
  539.             }
  540.             else if (prefix == strXml) {
  541.                 namespaceURI = strReservedXml;
  542.             }
  543.         }
  544.        
  545.         // Creates a XmlCDataSection containing the specified data.
  546.         public virtual XmlCDataSection CreateCDataSection(string data)
  547.         {
  548.             fCDataNodesPresent = true;
  549.             return new XmlCDataSection(data, this);
  550.         }
  551.        
  552.         // Creates an XmlComment containing the specified data.
  553.         public virtual XmlComment CreateComment(string data)
  554.         {
  555.             return new XmlComment(data, this);
  556.         }
  557.        
  558.         // Returns a new XmlDocumentType object.
  559.         [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
  560.         public virtual XmlDocumentType CreateDocumentType(string name, string publicId, string systemId, string internalSubset)
  561.         {
  562.             return new XmlDocumentType(name, publicId, systemId, internalSubset, this);
  563.         }
  564.        
  565.         // Creates an XmlDocumentFragment.
  566.         public virtual XmlDocumentFragment CreateDocumentFragment()
  567.         {
  568.             return new XmlDocumentFragment(this);
  569.         }
  570.        
  571.         // Creates an element with the specified name.
  572.         public XmlElement CreateElement(string name)
  573.         {
  574.             string prefix = String.Empty;
  575.             string localName = String.Empty;
  576.             SplitName(name, out prefix, out localName);
  577.             return CreateElement(prefix, localName, string.Empty);
  578.         }
  579.        
  580.        
  581.         internal void AddDefaultAttributes(XmlElement elem)
  582.         {
  583.             SchemaInfo schInfo = DtdSchemaInfo;
  584.             SchemaElementDecl ed = GetSchemaElementDecl(elem);
  585.             if (ed != null && ed.AttDefs != null) {
  586.                 IDictionaryEnumerator attrDefs = ed.AttDefs.GetEnumerator();
  587.                 while (attrDefs.MoveNext()) {
  588.                     SchemaAttDef attdef = (SchemaAttDef)attrDefs.Value;
  589.                     if (attdef.Presence == SchemaDeclBase.Use.Default || attdef.Presence == SchemaDeclBase.Use.Fixed) {
  590.                         //build a default attribute and return
  591.                         string attrPrefix = string.Empty;
  592.                         string attrLocalname = attdef.Name.Name;
  593.                         string attrNamespaceURI = string.Empty;
  594.                         if (schInfo.SchemaType == SchemaType.DTD)
  595.                             attrPrefix = attdef.Name.Namespace;
  596.                         else {
  597.                             attrPrefix = attdef.Prefix;
  598.                             attrNamespaceURI = attdef.Name.Namespace;
  599.                         }
  600.                         XmlAttribute defattr = PrepareDefaultAttribute(attdef, attrPrefix, attrLocalname, attrNamespaceURI);
  601.                         elem.SetAttributeNode(defattr);
  602.                     }
  603.                 }
  604.             }
  605.         }
  606.        
  607.         private SchemaElementDecl GetSchemaElementDecl(XmlElement elem)
  608.         {
  609.             SchemaInfo schInfo = DtdSchemaInfo;
  610.             if (schInfo != null) {
  611.                 //build XmlQualifiedName used to identify the element schema declaration
  612.                 XmlQualifiedName qname = new XmlQualifiedName(elem.LocalName, schInfo.SchemaType == SchemaType.DTD ? elem.Prefix : elem.NamespaceURI);
  613.                 //get the schema info for the element
  614.                 return ((SchemaElementDecl)schInfo.ElementDecls[qname]);
  615.             }
  616.             return null;
  617.         }
  618.        
  619.         //Will be used by AddDeafulatAttributes() and GetDefaultAttribute() methods
  620.         private XmlAttribute PrepareDefaultAttribute(SchemaAttDef attdef, string attrPrefix, string attrLocalname, string attrNamespaceURI)
  621.         {
  622.             SetDefaultNamespace(attrPrefix, attrLocalname, ref attrNamespaceURI);
  623.             XmlAttribute defattr = CreateDefaultAttribute(attrPrefix, attrLocalname, attrNamespaceURI);
  624.             //parsing the default value for the default attribute
  625.             defattr.InnerXml = attdef.DefaultValueRaw;
  626.             //during the expansion of the tree, the flag could be set to true, we need to set it back.
  627.             XmlUnspecifiedAttribute unspAttr = defattr as XmlUnspecifiedAttribute;
  628.             if (unspAttr != null) {
  629.                 unspAttr.SetSpecified(false);
  630.             }
  631.             return defattr;
  632.         }
  633.        
  634.         // Creates an XmlEntityReference with the specified name.
  635.         public virtual XmlEntityReference CreateEntityReference(string name)
  636.         {
  637.             return new XmlEntityReference(name, this);
  638.         }
  639.        
  640.         // Creates a XmlProcessingInstruction with the specified name
  641.         // and data strings.
  642.         public virtual XmlProcessingInstruction CreateProcessingInstruction(string target, string data)
  643.         {
  644.             return new XmlProcessingInstruction(target, data, this);
  645.         }
  646.        
  647.         // Creates a XmlDeclaration node with the specified values.
  648.         public virtual XmlDeclaration CreateXmlDeclaration(string version, string encoding, string standalone)
  649.         {
  650.             return new XmlDeclaration(version, encoding, standalone, this);
  651.         }
  652.        
  653.         // Creates an XmlText with the specified text.
  654.         public virtual XmlText CreateTextNode(string text)
  655.         {
  656.             return new XmlText(text, this);
  657.         }
  658.        
  659.         // Creates a XmlSignificantWhitespace node.
  660.         public virtual XmlSignificantWhitespace CreateSignificantWhitespace(string text)
  661.         {
  662.             return new XmlSignificantWhitespace(text, this);
  663.         }
  664.        
  665.         public override XPathNavigator CreateNavigator()
  666.         {
  667.             return CreateNavigator(this);
  668.         }
  669.        
  670.         protected internal virtual XPathNavigator CreateNavigator(XmlNode node)
  671.         {
  672.             XmlNodeType nodeType = node.NodeType;
  673.             XmlNode parent;
  674.             XmlNodeType parentType;
  675.            
  676.             switch (nodeType) {
  677.                 case XmlNodeType.EntityReference:
  678.                 case XmlNodeType.Entity:
  679.                 case XmlNodeType.DocumentType:
  680.                 case XmlNodeType.Notation:
  681.                 case XmlNodeType.XmlDeclaration:
  682.                     return null;
  683.                 case XmlNodeType.Text:
  684.                 case XmlNodeType.CDATA:
  685.                 case XmlNodeType.SignificantWhitespace:
  686.                     parent = node.ParentNode;
  687.                     if (parent != null) {
  688.                         do {
  689.                             parentType = parent.NodeType;
  690.                             if (parentType == XmlNodeType.Attribute) {
  691.                                 return null;
  692.                             }
  693.                             else if (parentType == XmlNodeType.EntityReference) {
  694.                                 parent = parent.ParentNode;
  695.                             }
  696.                             else {
  697.                                 break;
  698.                             }
  699.                         }
  700.                         while (parent != null);
  701.                     }
  702.                     node = NormalizeText(node);
  703.                     break;
  704.                 case XmlNodeType.Whitespace:
  705.                     parent = node.ParentNode;
  706.                     if (parent != null) {
  707.                         do {
  708.                             parentType = parent.NodeType;
  709.                             if (parentType == XmlNodeType.Document || parentType == XmlNodeType.Attribute) {
  710.                                 return null;
  711.                             }
  712.                             else if (parentType == XmlNodeType.EntityReference) {
  713.                                 parent = parent.ParentNode;
  714.                             }
  715.                             else {
  716.                                 break;
  717.                             }
  718.                         }
  719.                         while (parent != null);
  720.                     }
  721.                     node = NormalizeText(node);
  722.                     break;
  723.                 default:
  724.                     break;
  725.             }
  726.             return new DocumentXPathNavigator(this, node);
  727.         }
  728.        
  729.         static internal bool IsTextNode(XmlNodeType nt)
  730.         {
  731.             switch (nt) {
  732.                 case XmlNodeType.Text:
  733.                 case XmlNodeType.CDATA:
  734.                 case XmlNodeType.Whitespace:
  735.                 case XmlNodeType.SignificantWhitespace:
  736.                     return true;
  737.                 default:
  738.                     return false;
  739.             }
  740.         }
  741.        
  742.         private XmlNode NormalizeText(XmlNode n)
  743.         {
  744.             XmlNode retnode = null;
  745.             while (IsTextNode(n.NodeType)) {
  746.                 retnode = n;
  747.                 n = n.PreviousSibling;
  748.                
  749.                 if (n == null) {
  750.                     XmlNode intnode = retnode;
  751.                     while (true) {
  752.                         if (intnode.ParentNode != null && intnode.ParentNode.NodeType == XmlNodeType.EntityReference) {
  753.                             if (intnode.ParentNode.PreviousSibling != null) {
  754.                                 n = intnode.ParentNode.PreviousSibling;
  755.                                 break;
  756.                             }
  757.                             else {
  758.                                 intnode = intnode.ParentNode;
  759.                                 if (intnode == null)
  760.                                     break;
  761.                             }
  762.                         }
  763.                         else
  764.                             break;
  765.                     }
  766.                 }
  767.                
  768.                 if (n == null)
  769.                     break;
  770.                 while (n.NodeType == XmlNodeType.EntityReference) {
  771.                     n = n.LastChild;
  772.                 }
  773.             }
  774.             return retnode;
  775.         }
  776.        
  777.         // Creates a XmlWhitespace node.
  778.         public virtual XmlWhitespace CreateWhitespace(string text)
  779.         {
  780.             return new XmlWhitespace(text, this);
  781.         }
  782.        
  783.         // Returns an XmlNodeList containing
  784.         // a list of all descendant elements that match the specified name.
  785.         public virtual XmlNodeList GetElementsByTagName(string name)
  786.         {
  787.             return new XmlElementList(this, name);
  788.         }
  789.        
  790.         // DOM Level 2
  791.        
  792.         // Creates an XmlAttribute with the specified LocalName
  793.         // and NamespaceURI.
  794.         public XmlAttribute CreateAttribute(string qualifiedName, string namespaceURI)
  795.         {
  796.             string prefix = String.Empty;
  797.             string localName = String.Empty;
  798.            
  799.             SplitName(qualifiedName, out prefix, out localName);
  800.             return CreateAttribute(prefix, localName, namespaceURI);
  801.         }
  802.        
  803.         // Creates an XmlElement with the specified LocalName and
  804.         // NamespaceURI.
  805.         public XmlElement CreateElement(string qualifiedName, string namespaceURI)
  806.         {
  807.             string prefix = String.Empty;
  808.             string localName = String.Empty;
  809.            
  810.             SplitName(qualifiedName, out prefix, out localName);
  811.             return CreateElement(prefix, localName, namespaceURI);
  812.         }
  813.        
  814.         // Returns a XmlNodeList containing
  815.         // a list of all descendant elements that match the specified name.
  816.         public virtual XmlNodeList GetElementsByTagName(string localName, string namespaceURI)
  817.         {
  818.             return new XmlElementList(this, localName, namespaceURI);
  819.         }
  820.        
  821.         // Returns the XmlElement with the specified ID.
  822.         public virtual XmlElement GetElementById(string elementId)
  823.         {
  824.             if (htElementIdMap != null) {
  825.                 ArrayList elementList = (ArrayList)(htElementIdMap[elementId]);
  826.                 if (elementList != null) {
  827.                     foreach (WeakReference elemRef in elementList) {
  828.                         XmlElement elem = (XmlElement)elemRef.Target;
  829.                         if (elem != null && elem.IsConnected())
  830.                             return elem;
  831.                     }
  832.                 }
  833.             }
  834.             return null;
  835.         }
  836.        
  837.         // Imports a node from another document to this document.
  838.         public virtual XmlNode ImportNode(XmlNode node, bool deep)
  839.         {
  840.             return ImportNodeInternal(node, deep);
  841.         }
  842.        
  843.         private XmlNode ImportNodeInternal(XmlNode node, bool deep)
  844.         {
  845.             XmlNode newNode = null;
  846.            
  847.             if (node == null) {
  848.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Import_NullNode));
  849.             }
  850.             else {
  851.                 switch (node.NodeType) {
  852.                     case XmlNodeType.Element:
  853.                         newNode = CreateElement(node.Prefix, node.LocalName, node.NamespaceURI);
  854.                         ImportAttributes(node, newNode);
  855.                         if (deep)
  856.                             ImportChildren(node, newNode, deep);
  857.                         break;
  858.                     case XmlNodeType.Attribute:
  859.                        
  860.                         Debug.Assert(((XmlAttribute)node).Specified);
  861.                         newNode = CreateAttribute(node.Prefix, node.LocalName, node.NamespaceURI);
  862.                         ImportChildren(node, newNode, true);
  863.                         break;
  864.                     case XmlNodeType.Text:
  865.                        
  866.                         newNode = CreateTextNode(node.Value);
  867.                         break;
  868.                     case XmlNodeType.Comment:
  869.                         newNode = CreateComment(node.Value);
  870.                         break;
  871.                     case XmlNodeType.ProcessingInstruction:
  872.                         newNode = CreateProcessingInstruction(node.Name, node.Value);
  873.                         break;
  874.                     case XmlNodeType.XmlDeclaration:
  875.                         XmlDeclaration decl = (XmlDeclaration)node;
  876.                         newNode = CreateXmlDeclaration(decl.Version, decl.Encoding, decl.Standalone);
  877.                         break;
  878.                     case XmlNodeType.CDATA:
  879.                         newNode = CreateCDataSection(node.Value);
  880.                         break;
  881.                     case XmlNodeType.DocumentType:
  882.                         XmlDocumentType docType = (XmlDocumentType)node;
  883.                         newNode = CreateDocumentType(docType.Name, docType.PublicId, docType.SystemId, docType.InternalSubset);
  884.                         break;
  885.                     case XmlNodeType.DocumentFragment:
  886.                         newNode = CreateDocumentFragment();
  887.                         if (deep)
  888.                             ImportChildren(node, newNode, deep);
  889.                         break;
  890.                     case XmlNodeType.EntityReference:
  891.                        
  892.                         newNode = CreateEntityReference(node.Name);
  893.                         // we don't import the children of entity reference because they might result in different
  894.                         // children nodes given different namesapce context in the new document.
  895.                         break;
  896.                     case XmlNodeType.Whitespace:
  897.                        
  898.                         newNode = CreateWhitespace(node.Value);
  899.                         break;
  900.                     case XmlNodeType.SignificantWhitespace:
  901.                        
  902.                         newNode = CreateSignificantWhitespace(node.Value);
  903.                         break;
  904.                     default:
  905.                        
  906.                         throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, Res.GetString(Res.Xdom_Import), node.NodeType.ToString()));
  907.                         break;
  908.                 }
  909.             }
  910.            
  911.             return newNode;
  912.         }
  913.        
  914.         private void ImportAttributes(XmlNode fromElem, XmlNode toElem)
  915.         {
  916.             int cAttr = fromElem.Attributes.Count;
  917.             for (int iAttr = 0; iAttr < cAttr; iAttr++) {
  918.                 if (fromElem.Attributes[iAttr].Specified)
  919.                     toElem.Attributes.SetNamedItem(ImportNodeInternal(fromElem.Attributes[iAttr], true));
  920.             }
  921.         }
  922.        
  923.         private void ImportChildren(XmlNode fromNode, XmlNode toNode, bool deep)
  924.         {
  925.             Debug.Assert(toNode.NodeType != XmlNodeType.EntityReference);
  926.             for (XmlNode n = fromNode.FirstChild; n != null; n = n.NextSibling) {
  927.                 toNode.AppendChild(ImportNodeInternal(n, deep));
  928.             }
  929.         }
  930.        
  931.         // Microsoft extensions
  932.        
  933.         // Gets the XmlNameTable associated with this
  934.         // implementation.
  935.         public XmlNameTable NameTable {
  936.             get { return implementation.NameTable; }
  937.         }
  938.        
  939.         // Creates a XmlAttribute with the specified Prefix, LocalName,
  940.         // and NamespaceURI.
  941.         public virtual XmlAttribute CreateAttribute(string prefix, string localName, string namespaceURI)
  942.         {
  943.             return new XmlAttribute(AddAttrXmlName(prefix, localName, namespaceURI, null), this);
  944.         }
  945.        
  946.         protected internal virtual XmlAttribute CreateDefaultAttribute(string prefix, string localName, string namespaceURI)
  947.         {
  948.             return new XmlUnspecifiedAttribute(prefix, localName, namespaceURI, this);
  949.         }
  950.        
  951.         public virtual XmlElement CreateElement(string prefix, string localName, string namespaceURI)
  952.         {
  953.             XmlElement elem = new XmlElement(AddXmlName(prefix, localName, namespaceURI, null), true, this);
  954.             if (!IsLoading)
  955.                 AddDefaultAttributes(elem);
  956.             return elem;
  957.         }
  958.        
  959.         // Gets or sets a value indicating whether to preserve whitespace.
  960.         public bool PreserveWhitespace {
  961.             get { return preserveWhitespace; }
  962.             set { preserveWhitespace = value; }
  963.         }
  964.        
  965.         // Gets a value indicating whether the node is read-only.
  966.         public override bool IsReadOnly {
  967.             get { return false; }
  968.         }
  969.        
  970.         internal XmlNamedNodeMap Entities {
  971.             get {
  972.                 if (entities == null)
  973.                     entities = new XmlNamedNodeMap(this);
  974.                 return entities;
  975.             }
  976.             set { entities = value; }
  977.         }
  978.        
  979.         internal bool IsLoading {
  980.             get { return isLoading; }
  981.             set { isLoading = value; }
  982.         }
  983.        
  984.         internal bool ActualLoadingStatus {
  985.             get { return actualLoadingStatus; }
  986.             set { actualLoadingStatus = value; }
  987.         }
  988.        
  989.        
  990.         // Creates a XmlNode with the specified XmlNodeType, Prefix, Name, and NamespaceURI.
  991.         public virtual XmlNode CreateNode(XmlNodeType type, string prefix, string name, string namespaceURI)
  992.         {
  993.             switch (type) {
  994.                 case XmlNodeType.Element:
  995.                     if (prefix != null)
  996.                         return CreateElement(prefix, name, namespaceURI);
  997.                     else
  998.                         return CreateElement(name, namespaceURI);
  999.                     break;
  1000.                 case XmlNodeType.Attribute:
  1001.                    
  1002.                     if (prefix != null)
  1003.                         return CreateAttribute(prefix, name, namespaceURI);
  1004.                     else
  1005.                         return CreateAttribute(name, namespaceURI);
  1006.                     break;
  1007.                 case XmlNodeType.Text:
  1008.                    
  1009.                     return CreateTextNode(string.Empty);
  1010.                 case XmlNodeType.CDATA:
  1011.                    
  1012.                     return CreateCDataSection(string.Empty);
  1013.                 case XmlNodeType.EntityReference:
  1014.                    
  1015.                     return CreateEntityReference(name);
  1016.                 case XmlNodeType.ProcessingInstruction:
  1017.                    
  1018.                     return CreateProcessingInstruction(name, string.Empty);
  1019.                 case XmlNodeType.XmlDeclaration:
  1020.                    
  1021.                     return CreateXmlDeclaration("1.0", null, null);
  1022.                 case XmlNodeType.Comment:
  1023.                    
  1024.                     return CreateComment(string.Empty);
  1025.                 case XmlNodeType.DocumentFragment:
  1026.                    
  1027.                     return CreateDocumentFragment();
  1028.                 case XmlNodeType.DocumentType:
  1029.                    
  1030.                     return CreateDocumentType(name, string.Empty, string.Empty, string.Empty);
  1031.                 case XmlNodeType.Document:
  1032.                    
  1033.                     return new XmlDocument();
  1034.                 case XmlNodeType.SignificantWhitespace:
  1035.                    
  1036.                     return CreateSignificantWhitespace(string.Empty);
  1037.                 case XmlNodeType.Whitespace:
  1038.                    
  1039.                     return CreateWhitespace(string.Empty);
  1040.                 default:
  1041.                    
  1042.                     throw new ArgumentException(Res.GetString(Res.Arg_CannotCreateNode, type));
  1043.                     break;
  1044.             }
  1045.         }
  1046.        
  1047.         // Creates an XmlNode with the specified node type, Name, and
  1048.         // NamespaceURI.
  1049.         public virtual XmlNode CreateNode(string nodeTypeString, string name, string namespaceURI)
  1050.         {
  1051.             return CreateNode(ConvertToNodeType(nodeTypeString), name, namespaceURI);
  1052.         }
  1053.        
  1054.         // Creates an XmlNode with the specified XmlNodeType, Name, and
  1055.         // NamespaceURI.
  1056.         public virtual XmlNode CreateNode(XmlNodeType type, string name, string namespaceURI)
  1057.         {
  1058.             return CreateNode(type, null, name, namespaceURI);
  1059.         }
  1060.        
  1061.         // Creates an XmlNode object based on the information in the XmlReader.
  1062.         // The reader must be positioned on a node or attribute.
  1063.         [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
  1064.         public virtual XmlNode ReadNode(XmlReader reader)
  1065.         {
  1066.             XmlNode node = null;
  1067.             try {
  1068.                 IsLoading = true;
  1069.                 XmlLoader loader = new XmlLoader();
  1070.                 node = loader.ReadCurrentNode(this, reader);
  1071.             }
  1072.             finally {
  1073.                 IsLoading = false;
  1074.             }
  1075.             return node;
  1076.         }
  1077.        
  1078.         internal XmlNodeType ConvertToNodeType(string nodeTypeString)
  1079.         {
  1080.             if (nodeTypeString == "element") {
  1081.                 return XmlNodeType.Element;
  1082.             }
  1083.             else if (nodeTypeString == "attribute") {
  1084.                 return XmlNodeType.Attribute;
  1085.             }
  1086.             else if (nodeTypeString == "text") {
  1087.                 return XmlNodeType.Text;
  1088.             }
  1089.             else if (nodeTypeString == "cdatasection") {
  1090.                 return XmlNodeType.CDATA;
  1091.             }
  1092.             else if (nodeTypeString == "entityreference") {
  1093.                 return XmlNodeType.EntityReference;
  1094.             }
  1095.             else if (nodeTypeString == "entity") {
  1096.                 return XmlNodeType.Entity;
  1097.             }
  1098.             else if (nodeTypeString == "processinginstruction") {
  1099.                 return XmlNodeType.ProcessingInstruction;
  1100.             }
  1101.             else if (nodeTypeString == "comment") {
  1102.                 return XmlNodeType.Comment;
  1103.             }
  1104.             else if (nodeTypeString == "document") {
  1105.                 return XmlNodeType.Document;
  1106.             }
  1107.             else if (nodeTypeString == "documenttype") {
  1108.                 return XmlNodeType.DocumentType;
  1109.             }
  1110.             else if (nodeTypeString == "documentfragment") {
  1111.                 return XmlNodeType.DocumentFragment;
  1112.             }
  1113.             else if (nodeTypeString == "notation") {
  1114.                 return XmlNodeType.Notation;
  1115.             }
  1116.             else if (nodeTypeString == "significantwhitespace") {
  1117.                 return XmlNodeType.SignificantWhitespace;
  1118.             }
  1119.             else if (nodeTypeString == "whitespace") {
  1120.                 return XmlNodeType.Whitespace;
  1121.             }
  1122.             throw new ArgumentException(Res.GetString(Res.Xdom_Invalid_NT_String, nodeTypeString));
  1123.         }
  1124.        
  1125.        
  1126.         private XmlTextReader SetupReader(XmlTextReader tr)
  1127.         {
  1128.             tr.XmlValidatingReaderCompatibilityMode = true;
  1129.             tr.EntityHandling = EntityHandling.ExpandCharEntities;
  1130.             if (this.HasSetResolver)
  1131.                 tr.XmlResolver = GetResolver();
  1132.             return tr;
  1133.         }
  1134.        
  1135.         // Loads the XML document from the specified URL.
  1136.         public virtual void Load(string filename)
  1137.         {
  1138.             XmlTextReader reader = SetupReader(new XmlTextReader(filename, NameTable));
  1139.             try {
  1140.                 Load(reader);
  1141.             }
  1142.             finally {
  1143.                 reader.Close();
  1144.             }
  1145.         }
  1146.        
  1147.         public virtual void Load(Stream inStream)
  1148.         {
  1149.             XmlTextReader reader = SetupReader(new XmlTextReader(inStream, NameTable));
  1150.             try {
  1151.                 Load(reader);
  1152.             }
  1153.             finally {
  1154.                 reader.Impl.Close(false);
  1155.             }
  1156.         }
  1157.        
  1158.         // Loads the XML document from the specified TextReader.
  1159.         public virtual void Load(TextReader txtReader)
  1160.         {
  1161.             XmlTextReader reader = SetupReader(new XmlTextReader(txtReader, NameTable));
  1162.             try {
  1163.                 Load(reader);
  1164.             }
  1165.             finally {
  1166.                 reader.Impl.Close(false);
  1167.             }
  1168.         }
  1169.        
  1170.         // Loads the XML document from the specified XmlReader.
  1171.         public virtual void Load(XmlReader reader)
  1172.         {
  1173.             try {
  1174.                 IsLoading = true;
  1175.                 actualLoadingStatus = true;
  1176.                 RemoveAll();
  1177.                 fEntRefNodesPresent = false;
  1178.                 fCDataNodesPresent = false;
  1179.                 reportValidity = true;
  1180.                
  1181.                 XmlLoader loader = new XmlLoader();
  1182.                 loader.Load(this, reader, preserveWhitespace);
  1183.             }
  1184.             finally {
  1185.                 IsLoading = false;
  1186.                 actualLoadingStatus = false;
  1187.                
  1188.                 // Ensure the bit is still on after loading a dtd
  1189.                 reportValidity = true;
  1190.             }
  1191.         }
  1192.        
  1193.         // Loads the XML document from the specified string.
  1194.         public virtual void LoadXml(string xml)
  1195.         {
  1196.             XmlTextReader reader = SetupReader(new XmlTextReader(new StringReader(xml), NameTable));
  1197.             try {
  1198.                 Load(reader);
  1199.             }
  1200.             finally {
  1201.                 reader.Close();
  1202.             }
  1203.         }
  1204.        
  1205.         //TextEncoding is the one from XmlDeclaration if there is any
  1206.         internal Encoding TextEncoding {
  1207.             get {
  1208.                 if (Declaration != null) {
  1209.                     string value = Declaration.Encoding;
  1210.                     if (value.Length > 0) {
  1211.                         return System.Text.Encoding.GetEncoding(value);
  1212.                     }
  1213.                 }
  1214.                 return null;
  1215.             }
  1216.         }
  1217.        
  1218.         public override string InnerXml {
  1219.             get { return base.InnerXml; }
  1220.             set { LoadXml(value); }
  1221.         }
  1222.        
  1223.         // Saves the XML document to the specified file.
  1224.         //Saves out the to the file with exact content in the XmlDocument.
  1225.         public virtual void Save(string filename)
  1226.         {
  1227.             if (DocumentElement == null)
  1228.                 throw new XmlException(Res.Xml_InvalidXmlDocument, Res.GetString(Res.Xdom_NoRootEle));
  1229.             XmlDOMTextWriter xw = new XmlDOMTextWriter(filename, TextEncoding);
  1230.             try {
  1231.                 if (preserveWhitespace == false)
  1232.                     xw.Formatting = Formatting.Indented;
  1233.                 WriteTo(xw);
  1234.             }
  1235.             finally {
  1236.                 xw.Flush();
  1237.                 xw.Close();
  1238.             }
  1239.         }
  1240.        
  1241.         //Saves out the to the file with exact content in the XmlDocument.
  1242.         public virtual void Save(Stream outStream)
  1243.         {
  1244.             XmlDOMTextWriter xw = new XmlDOMTextWriter(outStream, TextEncoding);
  1245.             if (preserveWhitespace == false)
  1246.                 xw.Formatting = Formatting.Indented;
  1247.             WriteTo(xw);
  1248.             xw.Flush();
  1249.         }
  1250.        
  1251.         // Saves the XML document to the specified TextWriter.
  1252.         //
  1253.         //Saves out the file with xmldeclaration which has encoding value equal to
  1254.         //that of textwriter's encoding
  1255.         public virtual void Save(TextWriter writer)
  1256.         {
  1257.             XmlDOMTextWriter xw = new XmlDOMTextWriter(writer);
  1258.             if (preserveWhitespace == false)
  1259.                 xw.Formatting = Formatting.Indented;
  1260.             Save(xw);
  1261.         }
  1262.        
  1263.         // Saves the XML document to the specified XmlWriter.
  1264.         //
  1265.         //Saves out the file with xmldeclaration which has encoding value equal to
  1266.         //that of textwriter's encoding
  1267.         public virtual void Save(XmlWriter w)
  1268.         {
  1269.             XmlNode n = this.FirstChild;
  1270.             if (n == null)
  1271.                 return;
  1272.             if (w.WriteState == WriteState.Start) {
  1273.                 if (n is XmlDeclaration) {
  1274.                     if (Standalone.Length == 0)
  1275.                         w.WriteStartDocument();
  1276.                     else if (Standalone == "yes")
  1277.                         w.WriteStartDocument(true);
  1278.                     else if (Standalone == "no")
  1279.                         w.WriteStartDocument(false);
  1280.                     n = n.NextSibling;
  1281.                 }
  1282.                 else {
  1283.                     w.WriteStartDocument();
  1284.                 }
  1285.             }
  1286.             while (n != null) {
  1287.                 //Debug.Assert( n.NodeType != XmlNodeType.XmlDeclaration );
  1288.                 n.WriteTo(w);
  1289.                 n = n.NextSibling;
  1290.             }
  1291.             w.Flush();
  1292.         }
  1293.        
  1294.         // Saves the node to the specified XmlWriter.
  1295.         //
  1296.         //Writes out the to the file with exact content in the XmlDocument.
  1297.         public override void WriteTo(XmlWriter w)
  1298.         {
  1299.             WriteContentTo(w);
  1300.         }
  1301.        
  1302.         // Saves all the children of the node to the specified XmlWriter.
  1303.         //
  1304.         //Writes out the to the file with exact content in the XmlDocument.
  1305.         public override void WriteContentTo(XmlWriter xw)
  1306.         {
  1307.             foreach (XmlNode n in this) {
  1308.                 n.WriteTo(xw);
  1309.             }
  1310.         }
  1311.        
  1312.         public void Validate(ValidationEventHandler validationEventHandler)
  1313.         {
  1314.             Validate(validationEventHandler, this);
  1315.         }
  1316.        
  1317.         public void Validate(ValidationEventHandler validationEventHandler, XmlNode nodeToValidate)
  1318.         {
  1319.             if (this.schemas == null || this.schemas.Count == 0) {
  1320.                 //Should we error
  1321.                 throw new InvalidOperationException(Res.GetString(Res.XmlDocument_NoSchemaInfo));
  1322.             }
  1323.             XmlDocument parentDocument = nodeToValidate.Document;
  1324.             if (parentDocument != this) {
  1325.                 throw new ArgumentException(Res.GetString(Res.XmlDocument_NodeNotFromDocument, "nodeToValidate"));
  1326.             }
  1327.             if (nodeToValidate == this) {
  1328.                 reportValidity = false;
  1329.             }
  1330.             DocumentSchemaValidator validator = new DocumentSchemaValidator(this, schemas, validationEventHandler);
  1331.             validator.Validate(nodeToValidate);
  1332.             if (nodeToValidate == this) {
  1333.                 reportValidity = true;
  1334.             }
  1335.         }
  1336.        
  1337.         public event XmlNodeChangedEventHandler NodeInserting {
  1338.             add { onNodeInsertingDelegate += value; }
  1339.             remove { onNodeInsertingDelegate -= value; }
  1340.         }
  1341.        
  1342.         public event XmlNodeChangedEventHandler NodeInserted {
  1343.             add { onNodeInsertedDelegate += value; }
  1344.             remove { onNodeInsertedDelegate -= value; }
  1345.         }
  1346.        
  1347.         public event XmlNodeChangedEventHandler NodeRemoving {
  1348.             add { onNodeRemovingDelegate += value; }
  1349.             remove { onNodeRemovingDelegate -= value; }
  1350.         }
  1351.        
  1352.         public event XmlNodeChangedEventHandler NodeRemoved {
  1353.             add { onNodeRemovedDelegate += value; }
  1354.             remove { onNodeRemovedDelegate -= value; }
  1355.         }
  1356.        
  1357.         public event XmlNodeChangedEventHandler NodeChanging {
  1358.             add { onNodeChangingDelegate += value; }
  1359.             remove { onNodeChangingDelegate -= value; }
  1360.         }
  1361.        
  1362.         public event XmlNodeChangedEventHandler NodeChanged {
  1363.             add { onNodeChangedDelegate += value; }
  1364.             remove { onNodeChangedDelegate -= value; }
  1365.         }
  1366.        
  1367.         internal override XmlNodeChangedEventArgs GetEventArgs(XmlNode node, XmlNode oldParent, XmlNode newParent, string oldValue, string newValue, XmlNodeChangedAction action)
  1368.         {
  1369.             reportValidity = false;
  1370.            
  1371.             switch (action) {
  1372.                 case XmlNodeChangedAction.Insert:
  1373.                     if (onNodeInsertingDelegate == null && onNodeInsertedDelegate == null) {
  1374.                         return null;
  1375.                     }
  1376.                     break;
  1377.                 case XmlNodeChangedAction.Remove:
  1378.                     if (onNodeRemovingDelegate == null && onNodeRemovedDelegate == null) {
  1379.                         return null;
  1380.                     }
  1381.                     break;
  1382.                 case XmlNodeChangedAction.Change:
  1383.                     if (onNodeChangingDelegate == null && onNodeChangedDelegate == null) {
  1384.                         return null;
  1385.                     }
  1386.                     break;
  1387.             }
  1388.             return new XmlNodeChangedEventArgs(node, oldParent, newParent, oldValue, newValue, action);
  1389.         }
  1390.        
  1391.         internal XmlNodeChangedEventArgs GetInsertEventArgsForLoad(XmlNode node, XmlNode newParent)
  1392.         {
  1393.             if (onNodeInsertingDelegate == null && onNodeInsertedDelegate == null) {
  1394.                 return null;
  1395.             }
  1396.             string nodeValue = node.Value;
  1397.             return new XmlNodeChangedEventArgs(node, null, newParent, nodeValue, nodeValue, XmlNodeChangedAction.Insert);
  1398.         }
  1399.        
  1400.         internal override void BeforeEvent(XmlNodeChangedEventArgs args)
  1401.         {
  1402.             if (args != null) {
  1403.                 switch (args.Action) {
  1404.                     case XmlNodeChangedAction.Insert:
  1405.                         if (onNodeInsertingDelegate != null)
  1406.                             onNodeInsertingDelegate(this, args);
  1407.                         break;
  1408.                     case XmlNodeChangedAction.Remove:
  1409.                        
  1410.                         if (onNodeRemovingDelegate != null)
  1411.                             onNodeRemovingDelegate(this, args);
  1412.                         break;
  1413.                     case XmlNodeChangedAction.Change:
  1414.                        
  1415.                         if (onNodeChangingDelegate != null)
  1416.                             onNodeChangingDelegate(this, args);
  1417.                         break;
  1418.                 }
  1419.             }
  1420.         }
  1421.        
  1422.         internal override void AfterEvent(XmlNodeChangedEventArgs args)
  1423.         {
  1424.             if (args != null) {
  1425.                 switch (args.Action) {
  1426.                     case XmlNodeChangedAction.Insert:
  1427.                         if (onNodeInsertedDelegate != null)
  1428.                             onNodeInsertedDelegate(this, args);
  1429.                         break;
  1430.                     case XmlNodeChangedAction.Remove:
  1431.                        
  1432.                         if (onNodeRemovedDelegate != null)
  1433.                             onNodeRemovedDelegate(this, args);
  1434.                         break;
  1435.                     case XmlNodeChangedAction.Change:
  1436.                        
  1437.                         if (onNodeChangedDelegate != null)
  1438.                             onNodeChangedDelegate(this, args);
  1439.                         break;
  1440.                 }
  1441.             }
  1442.         }
  1443.        
  1444.         // The function such through schema info to find out if there exists a default attribute with passed in names in the passed in element
  1445.         // If so, return the newly created default attribute (with children tree);
  1446.         // Otherwise, return null.
  1447.        
  1448.         internal XmlAttribute GetDefaultAttribute(XmlElement elem, string attrPrefix, string attrLocalname, string attrNamespaceURI)
  1449.         {
  1450.             SchemaInfo schInfo = DtdSchemaInfo;
  1451.             SchemaElementDecl ed = GetSchemaElementDecl(elem);
  1452.             if (ed != null && ed.AttDefs != null) {
  1453.                 IDictionaryEnumerator attrDefs = ed.AttDefs.GetEnumerator();
  1454.                 while (attrDefs.MoveNext()) {
  1455.                     SchemaAttDef attdef = (SchemaAttDef)attrDefs.Value;
  1456.                     if (attdef.Presence == SchemaDeclBase.Use.Default || attdef.Presence == SchemaDeclBase.Use.Fixed) {
  1457.                         if (attdef.Name.Name == attrLocalname) {
  1458.                             if ((schInfo.SchemaType == SchemaType.DTD && attdef.Name.Namespace == attrPrefix) || (schInfo.SchemaType != SchemaType.DTD && attdef.Name.Namespace == attrNamespaceURI)) {
  1459.                                 //find a def attribute with the same name, build a default attribute and return
  1460.                                 XmlAttribute defattr = PrepareDefaultAttribute(attdef, attrPrefix, attrLocalname, attrNamespaceURI);
  1461.                                 return defattr;
  1462.                             }
  1463.                         }
  1464.                     }
  1465.                 }
  1466.             }
  1467.             return null;
  1468.         }
  1469.        
  1470.         internal string Version {
  1471.             get {
  1472.                 XmlDeclaration decl = Declaration;
  1473.                 if (decl != null)
  1474.                     return decl.Version;
  1475.                 return null;
  1476.             }
  1477.         }
  1478.        
  1479.         internal string Encoding {
  1480.             get {
  1481.                 XmlDeclaration decl = Declaration;
  1482.                 if (decl != null)
  1483.                     return decl.Encoding;
  1484.                 return null;
  1485.             }
  1486.         }
  1487.        
  1488.         internal string Standalone {
  1489.             get {
  1490.                 XmlDeclaration decl = Declaration;
  1491.                 if (decl != null)
  1492.                     return decl.Standalone;
  1493.                 return null;
  1494.             }
  1495.         }
  1496.        
  1497.         internal XmlEntity GetEntityNode(string name)
  1498.         {
  1499.             if (DocumentType != null) {
  1500.                 XmlNamedNodeMap entites = DocumentType.Entities;
  1501.                 if (entites != null)
  1502.                     return (XmlEntity)(entites.GetNamedItem(name));
  1503.             }
  1504.             return null;
  1505.         }
  1506.        
  1507.         public override IXmlSchemaInfo SchemaInfo {
  1508.             get {
  1509.                 if (reportValidity) {
  1510.                     XmlElement documentElement = DocumentElement;
  1511.                     if (documentElement != null) {
  1512.                         switch (documentElement.SchemaInfo.Validity) {
  1513.                             case XmlSchemaValidity.Valid:
  1514.                                 return ValidSchemaInfo;
  1515.                             case XmlSchemaValidity.Invalid:
  1516.                                 return InvalidSchemaInfo;
  1517.                         }
  1518.                     }
  1519.                 }
  1520.                 return NotKnownSchemaInfo;
  1521.             }
  1522.         }
  1523.        
  1524.         public override string BaseURI {
  1525.             get { return baseURI; }
  1526.         }
  1527.        
  1528.         internal void SetBaseURI(string inBaseURI)
  1529.         {
  1530.             baseURI = inBaseURI;
  1531.         }
  1532.        
  1533.         internal override XmlNode AppendChildForLoad(XmlNode newChild, XmlDocument doc)
  1534.         {
  1535.             Debug.Assert(doc == this);
  1536.            
  1537.             if (!IsValidChildType(newChild.NodeType))
  1538.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_TypeConflict));
  1539.            
  1540.             if (!CanInsertAfter(newChild, LastChild))
  1541.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Location));
  1542.            
  1543.             XmlNodeChangedEventArgs args = GetInsertEventArgsForLoad(newChild, this);
  1544.            
  1545.             if (args != null)
  1546.                 BeforeEvent(args);
  1547.            
  1548.             XmlLinkedNode newNode = (XmlLinkedNode)newChild;
  1549.            
  1550.             if (lastChild == null) {
  1551.                 newNode.next = newNode;
  1552.             }
  1553.             else {
  1554.                 newNode.next = lastChild.next;
  1555.                 lastChild.next = newNode;
  1556.             }
  1557.            
  1558.             lastChild = newNode;
  1559.             newNode.SetParentForLoad(this);
  1560.            
  1561.             if (args != null)
  1562.                 AfterEvent(args);
  1563.            
  1564.             return newNode;
  1565.         }
  1566.        
  1567.         internal override XPathNodeType XPNodeType {
  1568.             get { return XPathNodeType.Root; }
  1569.         }
  1570.        
  1571.         internal bool HasEntityReferences {
  1572.             get { return fEntRefNodesPresent; }
  1573.         }
  1574.        
  1575.         internal XmlAttribute NamespaceXml {
  1576.             get {
  1577.                 if (namespaceXml == null) {
  1578.                     namespaceXml = new XmlAttribute(AddAttrXmlName(strXmlns, strXml, strReservedXmlns, null), this);
  1579.                     namespaceXml.Value = strReservedXml;
  1580.                 }
  1581.                 return namespaceXml;
  1582.             }
  1583.         }
  1584.     }
  1585. }

Developer Fusion