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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlLoader.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.IO;
  18.     using System.Collections;
  19.     using System.Diagnostics;
  20.     using System.Text;
  21.     using System.Xml.Schema;
  22.     using System.Globalization;
  23.    
  24.     internal class XmlLoader
  25.     {
  26.         XmlDocument doc;
  27.         XmlReader reader;
  28.         bool preserveWhitespace;
  29.        
  30.        
  31.         public XmlLoader()
  32.         {
  33.         }
  34.        
  35.         internal void Load(XmlDocument doc, XmlReader reader, bool preserveWhitespace)
  36.         {
  37.             this.doc = doc;
  38.             // perf: unwrap XmlTextReader if no one derived from it
  39.             if (reader.GetType() == typeof(System.Xml.XmlTextReader)) {
  40.                 this.reader = ((XmlTextReader)reader).Impl;
  41.             }
  42.             else {
  43.                 this.reader = reader;
  44.             }
  45.             this.preserveWhitespace = preserveWhitespace;
  46.             if (doc == null)
  47.                 throw new ArgumentException(Res.GetString(Res.Xdom_Load_NoDocument));
  48.             if (reader == null)
  49.                 throw new ArgumentException(Res.GetString(Res.Xdom_Load_NoReader));
  50.             doc.SetBaseURI(reader.BaseURI);
  51.             if (reader.Settings != null && reader.Settings.ValidationType == ValidationType.Schema) {
  52.                 doc.Schemas = reader.Settings.Schemas;
  53.             }
  54.             if (this.reader.ReadState != ReadState.Interactive) {
  55.                 if (!this.reader.Read())
  56.                     return;
  57.             }
  58.             LoadDocSequence(doc);
  59.         }
  60.        
  61.         //The function will start loading the document from where current XmlReader is pointing at.
  62.         private void LoadDocSequence(XmlDocument parentDoc)
  63.         {
  64.             Debug.Assert(this.reader != null);
  65.             Debug.Assert(parentDoc != null);
  66.             XmlNode node = null;
  67.             while ((node = LoadNode(true)) != null) {
  68.                 parentDoc.AppendChildForLoad(node, parentDoc);
  69.                 if (!this.reader.Read())
  70.                     return;
  71.             }
  72.         }
  73.        
  74.         internal XmlNode ReadCurrentNode(XmlDocument doc, XmlReader reader)
  75.         {
  76.             this.doc = doc;
  77.             this.reader = reader;
  78.             // WS are optional only for loading (see XmlDocument.PreserveWhitespace)
  79.             this.preserveWhitespace = true;
  80.             if (doc == null)
  81.                 throw new ArgumentException(Res.GetString(Res.Xdom_Load_NoDocument));
  82.             if (reader == null)
  83.                 throw new ArgumentException(Res.GetString(Res.Xdom_Load_NoReader));
  84.            
  85.             if (reader.ReadState == ReadState.Initial) {
  86.                 reader.Read();
  87.             }
  88.             if (reader.ReadState == ReadState.Interactive) {
  89.                 XmlNode n = LoadNode(true);
  90.                
  91.                 // Move to the next node
  92.                 if (n.NodeType != XmlNodeType.Attribute)
  93.                     reader.Read();
  94.                
  95.                 return n;
  96.             }
  97.             return null;
  98.         }
  99.        
  100.         private XmlNode LoadNode(bool skipOverWhitespace)
  101.         {
  102.             XmlReader r = this.reader;
  103.             XmlNode parent = null;
  104.             XmlElement element;
  105.             IXmlSchemaInfo schemaInfo;
  106.             do {
  107.                 XmlNode node = null;
  108.                 switch (r.NodeType) {
  109.                     case XmlNodeType.Element:
  110.                         bool fEmptyElement = r.IsEmptyElement;
  111.                         element = doc.CreateElement(r.Prefix, r.LocalName, r.NamespaceURI);
  112.                         element.IsEmpty = fEmptyElement;
  113.                        
  114.                         if (r.MoveToFirstAttribute()) {
  115.                             XmlAttributeCollection attributes = element.Attributes;
  116.                             do {
  117.                                 XmlAttribute attr = LoadAttributeNode();
  118.                                 attributes.Append(attr);
  119.                                 // special case for load
  120.                             }
  121.                             while (r.MoveToNextAttribute());
  122.                             r.MoveToElement();
  123.                         }
  124.                        
  125.                         // recursively load all children.
  126.                         if (!fEmptyElement) {
  127.                             if (parent != null) {
  128.                                 parent.AppendChildForLoad(element, doc);
  129.                             }
  130.                             parent = element;
  131.                             continue;
  132.                         }
  133.                         else {
  134.                             schemaInfo = r.SchemaInfo;
  135.                             if (schemaInfo != null) {
  136.                                 element.XmlName = doc.AddXmlName(element.Prefix, element.LocalName, element.NamespaceURI, schemaInfo);
  137.                             }
  138.                             node = element;
  139.                             break;
  140.                         }
  141.                         break;
  142.                     case XmlNodeType.EndElement:
  143.                        
  144.                         if (parent == null) {
  145.                             return null;
  146.                         }
  147.                         Debug.Assert(parent.NodeType == XmlNodeType.Element);
  148.                         schemaInfo = r.SchemaInfo;
  149.                         if (schemaInfo != null) {
  150.                             element = parent as XmlElement;
  151.                             if (element != null) {
  152.                                 element.XmlName = doc.AddXmlName(element.Prefix, element.LocalName, element.NamespaceURI, schemaInfo);
  153.                             }
  154.                         }
  155.                         if (parent.ParentNode == null) {
  156.                             return parent;
  157.                         }
  158.                         parent = parent.ParentNode;
  159.                         continue;
  160.                     case XmlNodeType.EntityReference:
  161.                        
  162.                         node = LoadEntityReferenceNode(false);
  163.                         break;
  164.                     case XmlNodeType.EndEntity:
  165.                        
  166.                         Debug.Assert(parent == null);
  167.                         return null;
  168.                     case XmlNodeType.Attribute:
  169.                        
  170.                         node = LoadAttributeNode();
  171.                         break;
  172.                     case XmlNodeType.Text:
  173.                        
  174.                         node = doc.CreateTextNode(r.Value);
  175.                         break;
  176.                     case XmlNodeType.SignificantWhitespace:
  177.                        
  178.                         node = doc.CreateSignificantWhitespace(r.Value);
  179.                         break;
  180.                     case XmlNodeType.Whitespace:
  181.                        
  182.                         if (preserveWhitespace) {
  183.                             node = doc.CreateWhitespace(r.Value);
  184.                             break;
  185.                         }
  186.                         else if (parent == null && !skipOverWhitespace) {
  187.                             // if called from LoadEntityReferenceNode, just return null
  188.                             return null;
  189.                         }
  190.                         else {
  191.                             continue;
  192.                         }
  193.                         break;
  194.                     case XmlNodeType.CDATA:
  195.                         node = doc.CreateCDataSection(r.Value);
  196.                         break;
  197.                     case XmlNodeType.XmlDeclaration:
  198.                        
  199.                        
  200.                         node = LoadDeclarationNode();
  201.                         break;
  202.                     case XmlNodeType.ProcessingInstruction:
  203.                        
  204.                         node = doc.CreateProcessingInstruction(r.Name, r.Value);
  205.                         break;
  206.                     case XmlNodeType.Comment:
  207.                        
  208.                         node = doc.CreateComment(r.Value);
  209.                         break;
  210.                     case XmlNodeType.DocumentType:
  211.                        
  212.                         node = LoadDocumentTypeNode();
  213.                         break;
  214.                     default:
  215.                        
  216.                         throw UnexpectedNodeType(r.NodeType);
  217.                         break;
  218.                 }
  219.                
  220.                 Debug.Assert(node != null);
  221.                 if (parent != null) {
  222.                     parent.AppendChildForLoad(node, doc);
  223.                 }
  224.                 else {
  225.                     return node;
  226.                 }
  227.             }
  228.             while (r.Read());
  229.            
  230.             return null;
  231.         }
  232.        
  233.         private XmlAttribute LoadAttributeNode()
  234.         {
  235.             Debug.Assert(reader.NodeType == XmlNodeType.Attribute);
  236.            
  237.             XmlReader r = reader;
  238.             if (r.IsDefault) {
  239.                 return LoadDefaultAttribute();
  240.             }
  241.            
  242.             XmlAttribute attr = doc.CreateAttribute(r.Prefix, r.LocalName, r.NamespaceURI);
  243.             IXmlSchemaInfo schemaInfo = r.SchemaInfo;
  244.             if (schemaInfo != null) {
  245.                 attr.XmlName = doc.AddAttrXmlName(attr.Prefix, attr.LocalName, attr.NamespaceURI, schemaInfo);
  246.             }
  247.             while (r.ReadAttributeValue()) {
  248.                 XmlNode node;
  249.                 switch (r.NodeType) {
  250.                     case XmlNodeType.Text:
  251.                         node = doc.CreateTextNode(r.Value);
  252.                         break;
  253.                     case XmlNodeType.EntityReference:
  254.                         node = doc.CreateEntityReference(r.LocalName);
  255.                         if (r.CanResolveEntity) {
  256.                             r.ResolveEntity();
  257.                             LoadAttributeValue(node, false);
  258.                             // Code internally relies on the fact that an EntRef nodes has at least one child (even an empty text node). Ensure that this holds true,
  259.                             // if the reader does not present any children for the ent-ref
  260.                             if (node.FirstChild == null) {
  261.                                 node.AppendChildForLoad(doc.CreateTextNode(""), doc);
  262.                             }
  263.                         }
  264.                         break;
  265.                     default:
  266.                         throw UnexpectedNodeType(r.NodeType);
  267.                         break;
  268.                 }
  269.                 Debug.Assert(node != null);
  270.                 attr.AppendChildForLoad(node, doc);
  271.             }
  272.            
  273.             return attr;
  274.         }
  275.        
  276.         private XmlAttribute LoadDefaultAttribute()
  277.         {
  278.             Debug.Assert(reader.IsDefault);
  279.            
  280.             XmlReader r = reader;
  281.             XmlAttribute attr = doc.CreateDefaultAttribute(r.Prefix, r.LocalName, r.NamespaceURI);
  282.             IXmlSchemaInfo schemaInfo = r.SchemaInfo;
  283.             if (schemaInfo != null) {
  284.                 attr.XmlName = doc.AddAttrXmlName(attr.Prefix, attr.LocalName, attr.NamespaceURI, schemaInfo);
  285.             }
  286.            
  287.             LoadAttributeValue(attr, false);
  288.            
  289.             XmlUnspecifiedAttribute defAttr = attr as XmlUnspecifiedAttribute;
  290.             // If user overrides CreateDefaultAttribute, then attr will NOT be a XmlUnspecifiedAttribute instance.
  291.             if (defAttr != null)
  292.                 defAttr.SetSpecified(false);
  293.            
  294.             return attr;
  295.         }
  296.        
  297.         private void LoadAttributeValue(XmlNode parent, bool direct)
  298.         {
  299.             XmlReader r = reader;
  300.             while (r.ReadAttributeValue()) {
  301.                 XmlNode node;
  302.                 switch (r.NodeType) {
  303.                     case XmlNodeType.Text:
  304.                         node = direct ? new XmlText(r.Value, doc) : doc.CreateTextNode(r.Value);
  305.                         break;
  306.                     case XmlNodeType.EndEntity:
  307.                         return;
  308.                     case XmlNodeType.EntityReference:
  309.                         node = direct ? new XmlEntityReference(reader.LocalName, doc) : doc.CreateEntityReference(reader.LocalName);
  310.                         if (r.CanResolveEntity) {
  311.                             r.ResolveEntity();
  312.                             LoadAttributeValue(node, direct);
  313.                             // Code internally relies on the fact that an EntRef nodes has at least one child (even an empty text node). Ensure that this holds true,
  314.                             // if the reader does not present any children for the ent-ref
  315.                             if (node.FirstChild == null) {
  316.                                 node.AppendChildForLoad(direct ? new XmlText("") : doc.CreateTextNode(""), doc);
  317.                             }
  318.                         }
  319.                         break;
  320.                     default:
  321.                         throw UnexpectedNodeType(r.NodeType);
  322.                         break;
  323.                 }
  324.                 Debug.Assert(node != null);
  325.                 parent.AppendChildForLoad(node, doc);
  326.             }
  327.             return;
  328.         }
  329.        
  330.         private XmlEntityReference LoadEntityReferenceNode(bool direct)
  331.         {
  332.             Debug.Assert(reader.NodeType == XmlNodeType.EntityReference);
  333.             XmlEntityReference eref = direct ? new XmlEntityReference(reader.Name, this.doc) : doc.CreateEntityReference(reader.Name);
  334.             if (reader.CanResolveEntity) {
  335.                 reader.ResolveEntity();
  336.                 while (reader.Read() && reader.NodeType != XmlNodeType.EndEntity) {
  337.                     XmlNode node = direct ? LoadNodeDirect() : LoadNode(false);
  338.                     if (node != null) {
  339.                         eref.AppendChildForLoad(node, doc);
  340.                     }
  341.                 }
  342.                 // Code internally relies on the fact that an EntRef nodes has at least one child (even an empty text node). Ensure that this holds true,
  343.                 // if the reader does not present any children for the ent-ref
  344.                 if (eref.LastChild == null)
  345.                     eref.AppendChildForLoad(doc.CreateTextNode(""), doc);
  346.             }
  347.             return eref;
  348.         }
  349.        
  350.         private XmlDeclaration LoadDeclarationNode()
  351.         {
  352.             Debug.Assert(reader.NodeType == XmlNodeType.XmlDeclaration);
  353.            
  354.             //parse data
  355.             string version = null;
  356.             string encoding = null;
  357.             string standalone = null;
  358.            
  359.             // Try first to use the reader to get the xml decl "attributes". Since not all readers are required to support this, it is possible to have
  360.             // implementations that do nothing
  361.             while (reader.MoveToNextAttribute()) {
  362.                 switch (reader.Name) {
  363.                     case "version":
  364.                         version = reader.Value;
  365.                         break;
  366.                     case "encoding":
  367.                         encoding = reader.Value;
  368.                         break;
  369.                     case "standalone":
  370.                         standalone = reader.Value;
  371.                         break;
  372.                     default:
  373.                         Debug.Assert(false);
  374.                         break;
  375.                 }
  376.             }
  377.            
  378.             // For readers that do not break xml decl into attributes, we must parse the xml decl ourselfs. We use version attr, b/c xml decl MUST contain
  379.             // at least version attr, so if the reader implements them as attr, then version must be present
  380.             if (version == null)
  381.                 ParseXmlDeclarationValue(reader.Value, out version, out encoding, out standalone);
  382.            
  383.             return doc.CreateXmlDeclaration(version, encoding, standalone);
  384.         }
  385.        
  386.         private XmlDocumentType LoadDocumentTypeNode()
  387.         {
  388.             Debug.Assert(reader.NodeType == XmlNodeType.DocumentType);
  389.            
  390.             string publicId = null;
  391.             string systemId = null;
  392.             string internalSubset = reader.Value;
  393.             string localName = reader.LocalName;
  394.             while (reader.MoveToNextAttribute()) {
  395.                 switch (reader.Name) {
  396.                     case "PUBLIC":
  397.                         publicId = reader.Value;
  398.                         break;
  399.                     case "SYSTEM":
  400.                         systemId = reader.Value;
  401.                         break;
  402.                 }
  403.             }
  404.            
  405.             XmlDocumentType dtNode = doc.CreateDocumentType(localName, publicId, systemId, internalSubset);
  406.            
  407.             SchemaInfo schemaInfo = XmlReader.GetDtdSchemaInfo(reader);
  408.             if (schemaInfo != null)
  409.                 LoadDocumentType(schemaInfo, dtNode);
  410.             else {
  411.                 //construct our own XmlValidatingReader to parse the DocumentType node so we could get Entities and notations information
  412.                 ParseDocumentType(dtNode);
  413.             }
  414.            
  415.             return dtNode;
  416.         }
  417.        
  418.         // LoadNodeDirect does not use creator functions on XmlDocument. It is used loading nodes that are children of entity nodes,
  419.         // becaouse we do not want to let users extend these (if we would allow this, XmlDataDocument would have a problem, becaouse
  420.         // they do not know that those nodes should not be mapped). It can be also used for an optimized load path when if the
  421.         // XmlDocument is not extended if XmlDocumentType and XmlDeclaration handling is added.
  422.         private XmlNode LoadNodeDirect()
  423.         {
  424.             XmlReader r = this.reader;
  425.             XmlNode parent = null;
  426.             do {
  427.                 XmlNode node = null;
  428.                 switch (r.NodeType) {
  429.                     case XmlNodeType.Element:
  430.                         bool fEmptyElement = reader.IsEmptyElement;
  431.                         XmlElement element = new XmlElement(reader.Prefix, reader.LocalName, reader.NamespaceURI, this.doc);
  432.                         element.IsEmpty = fEmptyElement;
  433.                        
  434.                         if (reader.MoveToFirstAttribute()) {
  435.                             XmlAttributeCollection attributes = element.Attributes;
  436.                             do {
  437.                                 XmlAttribute attr = LoadAttributeNodeDirect();
  438.                                 attributes.Append(attr);
  439.                                 // special case for load
  440.                             }
  441.                             while (r.MoveToNextAttribute());
  442.                         }
  443.                        
  444.                         // recursively load all children.
  445.                         if (!fEmptyElement) {
  446.                             parent.AppendChildForLoad(element, doc);
  447.                             parent = element;
  448.                             continue;
  449.                         }
  450.                         else {
  451.                             node = element;
  452.                             break;
  453.                         }
  454.                         break;
  455.                     case XmlNodeType.EndElement:
  456.                        
  457.                         Debug.Assert(parent.NodeType == XmlNodeType.Element);
  458.                         if (parent.ParentNode == null) {
  459.                             return parent;
  460.                         }
  461.                         parent = parent.ParentNode;
  462.                         continue;
  463.                     case XmlNodeType.EntityReference:
  464.                        
  465.                         node = LoadEntityReferenceNode(true);
  466.                         break;
  467.                     case XmlNodeType.EndEntity:
  468.                        
  469.                         continue;
  470.                     case XmlNodeType.Attribute:
  471.                        
  472.                         node = LoadAttributeNodeDirect();
  473.                         break;
  474.                     case XmlNodeType.SignificantWhitespace:
  475.                        
  476.                         node = new XmlSignificantWhitespace(reader.Value, this.doc);
  477.                         break;
  478.                     case XmlNodeType.Whitespace:
  479.                        
  480.                         if (preserveWhitespace) {
  481.                             node = new XmlWhitespace(reader.Value, this.doc);
  482.                         }
  483.                         else {
  484.                             continue;
  485.                         }
  486.                         break;
  487.                     case XmlNodeType.Text:
  488.                        
  489.                         node = new XmlText(reader.Value, this.doc);
  490.                         break;
  491.                     case XmlNodeType.CDATA:
  492.                        
  493.                         node = new XmlCDataSection(reader.Value, this.doc);
  494.                         break;
  495.                     case XmlNodeType.ProcessingInstruction:
  496.                        
  497.                         node = new XmlProcessingInstruction(reader.Name, reader.Value, this.doc);
  498.                         break;
  499.                     case XmlNodeType.Comment:
  500.                        
  501.                         node = new XmlComment(reader.Value, this.doc);
  502.                         break;
  503.                     default:
  504.                        
  505.                         throw UnexpectedNodeType(reader.NodeType);
  506.                         break;
  507.                 }
  508.                
  509.                 Debug.Assert(node != null);
  510.                 if (parent != null) {
  511.                     parent.AppendChildForLoad(node, doc);
  512.                 }
  513.                 else {
  514.                     return node;
  515.                 }
  516.             }
  517.             while (r.Read());
  518.            
  519.             return null;
  520.         }
  521.        
  522.         private XmlAttribute LoadAttributeNodeDirect()
  523.         {
  524.             XmlReader r = reader;
  525.             XmlAttribute attr;
  526.             if (r.IsDefault) {
  527.                 XmlUnspecifiedAttribute defattr = new XmlUnspecifiedAttribute(r.Prefix, r.LocalName, r.NamespaceURI, this.doc);
  528.                 LoadAttributeValue(defattr, true);
  529.                 defattr.SetSpecified(false);
  530.                 return defattr;
  531.             }
  532.             else {
  533.                 attr = new XmlAttribute(r.Prefix, r.LocalName, r.NamespaceURI, this.doc);
  534.                 LoadAttributeValue(attr, true);
  535.                 return attr;
  536.             }
  537.         }
  538.        
  539.         internal void ParseDocumentType(XmlDocumentType dtNode)
  540.         {
  541.             XmlDocument doc = dtNode.OwnerDocument;
  542.             //if xmlresolver is set on doc, use that one, otherwise use the default one being created by xmlvalidatingreader
  543.             if (doc.HasSetResolver)
  544.                 ParseDocumentType(dtNode, true, doc.GetResolver());
  545.             else
  546.                 ParseDocumentType(dtNode, false, null);
  547.         }
  548.        
  549.         private void ParseDocumentType(XmlDocumentType dtNode, bool bUseResolver, XmlResolver resolver)
  550.         {
  551.             this.doc = dtNode.OwnerDocument;
  552.             XmlNameTable nt = this.doc.NameTable;
  553.             XmlNamespaceManager mgr = new XmlNamespaceManager(nt);
  554.             SchemaInfo schemaInfo = DtdParser.Parse(nt, mgr, dtNode.ParseWithNamespaces, this.doc.BaseURI, dtNode.Name, dtNode.PublicId, dtNode.SystemId, dtNode.InternalSubset, bUseResolver, resolver
  555.             );
  556.             LoadDocumentType(schemaInfo, dtNode);
  557.         }
  558.        
  559.         private void LoadDocumentType(SchemaInfo schInfo, XmlDocumentType dtNode)
  560.         {
  561.             dtNode.DtdSchemaInfo = schInfo;
  562.             if (schInfo != null) {
  563.                 //set the schema information into the document
  564.                 doc.DtdSchemaInfo = schInfo;
  565.                
  566.                 // Notation hashtable
  567.                 if (schInfo.Notations != null) {
  568.                     foreach (SchemaNotation scNot in schInfo.Notations.Values) {
  569.                         dtNode.Notations.SetNamedItem(new XmlNotation(scNot.Name.Name, scNot.Pubid, scNot.SystemLiteral, doc));
  570.                     }
  571.                 }
  572.                
  573.                 // Entity hashtables
  574.                 if (schInfo.GeneralEntities != null) {
  575.                     foreach (SchemaEntity scEnt in schInfo.GeneralEntities.Values) {
  576.                         XmlEntity ent = new XmlEntity(scEnt.Name.Name, scEnt.Text, scEnt.Pubid, scEnt.Url, scEnt.NData.IsEmpty ? null : scEnt.NData.Name, doc);
  577.                         ent.SetBaseURI(scEnt.DeclaredURI);
  578.                         dtNode.Entities.SetNamedItem(ent);
  579.                     }
  580.                 }
  581.                
  582.                 if (schInfo.ParameterEntities != null) {
  583.                     foreach (SchemaEntity scEnt in schInfo.ParameterEntities.Values) {
  584.                         XmlEntity ent = new XmlEntity(scEnt.Name.Name, scEnt.Text, scEnt.Pubid, scEnt.Url, scEnt.NData.IsEmpty ? null : scEnt.NData.Name, doc);
  585.                         ent.SetBaseURI(scEnt.DeclaredURI);
  586.                         dtNode.Entities.SetNamedItem(ent);
  587.                     }
  588.                 }
  589.                 doc.Entities = dtNode.Entities;
  590.                
  591.                 //extract the elements which has attribute defined as ID from the element declarations
  592.                 IDictionaryEnumerator elementDecls = schInfo.ElementDecls.GetEnumerator();
  593.                 if (elementDecls != null) {
  594.                     elementDecls.Reset();
  595.                     while (elementDecls.MoveNext()) {
  596.                         SchemaElementDecl elementDecl = (SchemaElementDecl)elementDecls.Value;
  597.                         if (elementDecl.AttDefs != null) {
  598.                             IDictionaryEnumerator attDefs = elementDecl.AttDefs.GetEnumerator();
  599.                             while (attDefs.MoveNext()) {
  600.                                 SchemaAttDef attdef = (SchemaAttDef)attDefs.Value;
  601.                                 if (attdef.Datatype.TokenizedType == XmlTokenizedType.ID) {
  602.                                     //we only register the XmlElement based on their Prefix/LocalName and skip the namespace
  603.                                     doc.AddIdInfo(doc.AddXmlName(elementDecl.Prefix, elementDecl.Name.Name, string.Empty, null), doc.AddAttrXmlName(attdef.Prefix, attdef.Name.Name, string.Empty, null));
  604.                                     break;
  605.                                 }
  606.                             }
  607.                         }
  608.                     }
  609.                 }
  610.             }
  611.         }
  612.         #pragma warning restore 618
  613.        
  614.         private XmlParserContext GetContext(XmlNode node)
  615.         {
  616.             string lang = null;
  617.             XmlSpace spaceMode = XmlSpace.None;
  618.             XmlDocumentType docType = this.doc.DocumentType;
  619.             string baseURI = this.doc.BaseURI;
  620.             //constructing xmlnamespace
  621.             Hashtable prefixes = new Hashtable();
  622.             XmlNameTable nt = this.doc.NameTable;
  623.             XmlNamespaceManager mgr = new XmlNamespaceManager(nt);
  624.             bool bHasDefXmlnsAttr = false;
  625.            
  626.             // Process all xmlns, xmlns:prefix, xml:space and xml:lang attributes
  627.             while (node != null && node != doc) {
  628.                 if (node is XmlElement && ((XmlElement)node).HasAttributes) {
  629.                     mgr.PushScope();
  630.                     foreach (XmlAttribute attr in ((XmlElement)node).Attributes) {
  631.                         if (attr.Prefix == doc.strXmlns && prefixes.Contains(attr.LocalName) == false) {
  632.                             // Make sure the next time we will not add this prefix
  633.                             prefixes.Add(attr.LocalName, attr.LocalName);
  634.                             mgr.AddNamespace(attr.LocalName, attr.Value);
  635.                         }
  636.                         else if (!bHasDefXmlnsAttr && attr.Prefix.Length == 0 && attr.LocalName == doc.strXmlns) {
  637.                             // Save the case xmlns="..." where xmlns is the LocalName
  638.                             mgr.AddNamespace(String.Empty, attr.Value);
  639.                             bHasDefXmlnsAttr = true;
  640.                         }
  641.                         else if (spaceMode == XmlSpace.None && attr.Prefix == doc.strXml && attr.LocalName == doc.strSpace) {
  642.                             // Save xml:space context
  643.                             if (attr.Value == "default")
  644.                                 spaceMode = XmlSpace.Default;
  645.                             else if (attr.Value == "preserve")
  646.                                 spaceMode = XmlSpace.Preserve;
  647.                         }
  648.                         else if (lang == null && attr.Prefix == doc.strXml && attr.LocalName == doc.strLang) {
  649.                             // Save xml:lag context
  650.                             lang = attr.Value;
  651.                         }
  652.                     }
  653.                 }
  654.                 node = node.ParentNode;
  655.             }
  656.             return new XmlParserContext(nt, mgr, (docType == null) ? null : docType.Name, (docType == null) ? null : docType.PublicId, (docType == null) ? null : docType.SystemId, (docType == null) ? null : docType.InternalSubset, baseURI, lang, spaceMode);
  657.         }
  658.        
  659.        
  660.        
  661.         internal XmlNamespaceManager ParsePartialContent(XmlNode parentNode, string innerxmltext, XmlNodeType nt)
  662.         {
  663.             //the function shouldn't be used to set innerxml for XmlDocument node
  664.             Debug.Assert(parentNode.NodeType != XmlNodeType.Document);
  665.             this.doc = parentNode.OwnerDocument;
  666.             Debug.Assert(this.doc != null);
  667.             XmlParserContext pc = GetContext(parentNode);
  668.             this.reader = CreateInnerXmlReader(innerxmltext, nt, pc, this.doc);
  669.             try {
  670.                 this.preserveWhitespace = true;
  671.                 bool bOrigLoading = doc.IsLoading;
  672.                 doc.IsLoading = true;
  673.                
  674.                 if (nt == XmlNodeType.Entity) {
  675.                     XmlNode node = null;
  676.                     while (reader.Read() && (node = LoadNodeDirect()) != null) {
  677.                         parentNode.AppendChildForLoad(node, doc);
  678.                     }
  679.                 }
  680.                 else {
  681.                     XmlNode node = null;
  682.                     while (reader.Read() && (node = LoadNode(true)) != null) {
  683.                         parentNode.AppendChildForLoad(node, doc);
  684.                     }
  685.                 }
  686.                 doc.IsLoading = bOrigLoading;
  687.             }
  688.             finally {
  689.                 this.reader.Close();
  690.             }
  691.             return pc.NamespaceManager;
  692.         }
  693.        
  694.         internal void LoadInnerXmlElement(XmlElement node, string innerxmltext)
  695.         {
  696.             //construct a tree underneth the node
  697.             XmlNamespaceManager mgr = ParsePartialContent(node, innerxmltext, XmlNodeType.Element);
  698.             //remove the duplicate namesapce
  699.             if (node.ChildNodes.Count > 0)
  700.                 RemoveDuplicateNamespace((XmlElement)node, mgr, false);
  701.         }
  702.        
  703.         internal void LoadInnerXmlAttribute(XmlAttribute node, string innerxmltext)
  704.         {
  705.             ParsePartialContent(node, innerxmltext, XmlNodeType.Attribute);
  706.         }
  707.        
  708.        
  709.         private void RemoveDuplicateNamespace(XmlElement elem, XmlNamespaceManager mgr, bool fCheckElemAttrs)
  710.         {
  711.             //remove the duplicate attributes on current node first
  712.             mgr.PushScope();
  713.             XmlAttributeCollection attrs = elem.Attributes;
  714.             int cAttrs = attrs.Count;
  715.             if (fCheckElemAttrs && cAttrs > 0) {
  716.                 for (int i = cAttrs - 1; i >= 0; --i) {
  717.                     XmlAttribute attr = attrs[i];
  718.                     if (attr.Prefix == doc.strXmlns) {
  719.                         string nsUri = mgr.LookupNamespace(attr.LocalName);
  720.                         if (nsUri != null) {
  721.                             if (attr.Value == nsUri)
  722.                                 elem.Attributes.RemoveNodeAt(i);
  723.                         }
  724.                         else {
  725.                             // Add this namespace, so it we will behave corectly when setting "<bar xmlns:p="BAR"><foo2 xmlns:p="FOO"/></bar>" as
  726.                             // InnerXml on this foo elem where foo is like this "<foo xmlns:p="FOO"></foo>"
  727.                             // If do not do this, then we will remove the inner p prefix definition and will let the 1st p to be in scope for
  728.                             // the subsequent InnerXml_set or setting an EntRef inside.
  729.                             mgr.AddNamespace(attr.LocalName, attr.Value);
  730.                         }
  731.                     }
  732.                     else if (attr.Prefix.Length == 0 && attr.LocalName == doc.strXmlns) {
  733.                         string nsUri = mgr.DefaultNamespace;
  734.                         if (nsUri != null) {
  735.                             if (attr.Value == nsUri)
  736.                                 elem.Attributes.RemoveNodeAt(i);
  737.                         }
  738.                         else {
  739.                             // Add this namespace, so it we will behave corectly when setting "<bar xmlns:p="BAR"><foo2 xmlns:p="FOO"/></bar>" as
  740.                             // InnerXml on this foo elem where foo is like this "<foo xmlns:p="FOO"></foo>"
  741.                             // If do not do this, then we will remove the inner p prefix definition and will let the 1st p to be in scope for
  742.                             // the subsequent InnerXml_set or setting an EntRef inside.
  743.                             mgr.AddNamespace(attr.LocalName, attr.Value);
  744.                         }
  745.                     }
  746.                 }
  747.             }
  748.             //now recursively remove the duplicate attributes on the children
  749.             XmlNode child = elem.FirstChild;
  750.             while (child != null) {
  751.                 XmlElement childElem = child as XmlElement;
  752.                 if (childElem != null)
  753.                     RemoveDuplicateNamespace(childElem, mgr, true);
  754.                 child = child.NextSibling;
  755.             }
  756.             mgr.PopScope();
  757.         }
  758.        
  759.         private string EntitizeName(string name)
  760.         {
  761.             return "&" + name + ";";
  762.         }
  763.        
  764.         //The function is called when expanding the entity when its children being asked
  765.         internal void ExpandEntity(XmlEntity ent)
  766.         {
  767.             ParsePartialContent(ent, EntitizeName(ent.Name), XmlNodeType.Entity);
  768.         }
  769.        
  770.         //The function is called when expanding the entity ref. ( inside XmlEntityReference.SetParent )
  771.         internal void ExpandEntityReference(XmlEntityReference eref)
  772.         {
  773.             //when the ent ref is not associated w/ an entity, append an empty string text node as child
  774.             this.doc = eref.OwnerDocument;
  775.             bool bOrigLoadingState = doc.IsLoading;
  776.             doc.IsLoading = true;
  777.             switch (eref.Name) {
  778.                 case "lt":
  779.                     eref.AppendChildForLoad(doc.CreateTextNode("<"), doc);
  780.                     doc.IsLoading = bOrigLoadingState;
  781.                     return;
  782.                 case "gt":
  783.                     eref.AppendChildForLoad(doc.CreateTextNode(">"), doc);
  784.                     doc.IsLoading = bOrigLoadingState;
  785.                     return;
  786.                 case "amp":
  787.                     eref.AppendChildForLoad(doc.CreateTextNode("&"), doc);
  788.                     doc.IsLoading = bOrigLoadingState;
  789.                     return;
  790.                 case "apos":
  791.                     eref.AppendChildForLoad(doc.CreateTextNode("'"), doc);
  792.                     doc.IsLoading = bOrigLoadingState;
  793.                     return;
  794.                 case "quot":
  795.                     eref.AppendChildForLoad(doc.CreateTextNode("\""), doc);
  796.                     doc.IsLoading = bOrigLoadingState;
  797.                     return;
  798.             }
  799.            
  800.             XmlNamedNodeMap entities = doc.Entities;
  801.             foreach (XmlEntity ent in entities) {
  802.                 if (Ref.Equal(ent.Name, eref.Name)) {
  803.                     ParsePartialContent(eref, EntitizeName(eref.Name), XmlNodeType.EntityReference);
  804.                     return;
  805.                 }
  806.             }
  807.             //no fit so far
  808.             if (!(doc.ActualLoadingStatus)) {
  809.                 eref.AppendChildForLoad(doc.CreateTextNode(""), doc);
  810.                 doc.IsLoading = bOrigLoadingState;
  811.             }
  812.             else {
  813.                 doc.IsLoading = bOrigLoadingState;
  814.                 throw new XmlException(Res.Xml_UndeclaredParEntity, eref.Name);
  815.             }
  816.         }
  817.        
  818.         #pragma warning disable 618
  819.         // Creates a XmlValidatingReader suitable for parsing InnerXml strings
  820.         private XmlReader CreateInnerXmlReader(string xmlFragment, XmlNodeType nt, XmlParserContext context, XmlDocument doc)
  821.         {
  822.             XmlNodeType contentNT = nt;
  823.             if (contentNT == XmlNodeType.Entity || contentNT == XmlNodeType.EntityReference)
  824.                 contentNT = XmlNodeType.Element;
  825.            
  826.             XmlTextReaderImpl tr = new XmlTextReaderImpl(xmlFragment, contentNT, context);
  827.             tr.XmlValidatingReaderCompatibilityMode = true;
  828.             if (doc.HasSetResolver) {
  829.                 tr.XmlResolver = doc.GetResolver();
  830.             }
  831.             if (!(doc.ActualLoadingStatus)) {
  832.                 tr.DisableUndeclaredEntityCheck = true;
  833.             }
  834.             Debug.Assert(tr.EntityHandling == EntityHandling.ExpandCharEntities);
  835.            
  836.             XmlDocumentType dtdNode = doc.DocumentType;
  837.             if (dtdNode != null) {
  838.                 tr.Namespaces = dtdNode.ParseWithNamespaces;
  839.                 if (dtdNode.DtdSchemaInfo != null) {
  840.                     tr.DtdSchemaInfo = dtdNode.DtdSchemaInfo;
  841.                 }
  842.                 else {
  843.                     SchemaInfo schemaInfo = DtdParser.Parse(tr, context.BaseURI, context.DocTypeName, context.PublicId, context.SystemId, context.InternalSubset);
  844.                     dtdNode.DtdSchemaInfo = schemaInfo;
  845.                     tr.DtdSchemaInfo = schemaInfo;
  846.                 }
  847.             }
  848.            
  849.             if (nt == XmlNodeType.Entity || nt == XmlNodeType.EntityReference) {
  850.                 tr.Read();
  851.                 //this will skip the first element "wrapper"
  852.                 tr.ResolveEntity();
  853.             }
  854.             return tr;
  855.         }
  856.         #pragma warning restore 618
  857.        
  858.         static internal void ParseXmlDeclarationValue(string strValue, out string version, out string encoding, out string standalone)
  859.         {
  860.             version = null;
  861.             encoding = null;
  862.             standalone = null;
  863.             XmlTextReaderImpl tempreader = new XmlTextReaderImpl(strValue, (XmlParserContext)null);
  864.             try {
  865.                 tempreader.Read();
  866.                 //get version info.
  867.                 if (tempreader.MoveToAttribute("version"))
  868.                     version = tempreader.Value;
  869.                 //get encoding info
  870.                 if (tempreader.MoveToAttribute("encoding"))
  871.                     encoding = tempreader.Value;
  872.                 //get standalone info
  873.                 if (tempreader.MoveToAttribute("standalone"))
  874.                     standalone = tempreader.Value;
  875.             }
  876.             finally {
  877.                 tempreader.Close();
  878.             }
  879.         }
  880.        
  881.         static internal Exception UnexpectedNodeType(XmlNodeType nodetype)
  882.         {
  883.             return new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Res.GetString(Res.Xml_UnexpectedNodeType), nodetype.ToString()));
  884.         }
  885.     }
  886. }

Developer Fusion