DomLoader.cs
上传用户:hbhltzc
上传日期:2022-06-04
资源大小:1925k
文件大小:12k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Xml;
  5. using System.Xml.Schema;
  6. using System.Diagnostics;
  7. using System.Reflection;
  8. namespace XmlNotepad {
  9.     /// <summary>
  10.     /// This class keeps track of DOM node line locations so you can do error reporting.
  11.     /// </summary>
  12.     class DomLoader {
  13.         Dictionary<XmlNode, LineInfo> lineTable = new Dictionary<XmlNode, LineInfo>();
  14.         XmlDocument doc;
  15.         XmlReader reader;
  16.         IServiceProvider site;
  17.         const string xsiUri = "http://www.w3.org/2001/XMLSchema-instance";
  18.         
  19.         public DomLoader(IServiceProvider site) {
  20.             this.site = site;
  21.         }
  22.         void AddToTable(XmlNode node) {
  23.             lineTable[node] = new LineInfo(reader);
  24.         }
  25.         public LineInfo GetLineInfo(XmlNode node) {
  26.             if (node != null && lineTable.ContainsKey(node)) {
  27.                 return lineTable[node];
  28.             }
  29.             return null;
  30.         }
  31.         public XmlDocument Load(XmlReader r) {
  32.             this.lineTable = new Dictionary<XmlNode, LineInfo>();
  33.             this.doc = new XmlDocument();
  34.             this.doc.XmlResolver = new XmlProxyResolver(this.site);
  35.             this.doc.Schemas.XmlResolver = new XmlProxyResolver(this.site);
  36.             SetLoading(this.doc, true);
  37.             try {
  38.                 this.reader = r;
  39.                 AddToTable(this.doc);
  40.                 LoadDocument();
  41.             } finally {
  42.                 SetLoading(this.doc, false);
  43.             }
  44.             return doc;
  45.         }
  46.         void SetLoading(XmlDocument doc, bool flag) {
  47.             FieldInfo fi = this.doc.GetType().GetField("isLoading", BindingFlags.Instance | BindingFlags.NonPublic);
  48.             if (fi != null) {
  49.                 fi.SetValue(doc, flag);
  50.             }
  51.         }
  52.         private void LoadDocument() {
  53.             bool preserveWhitespace = false;
  54.             XmlReader r = this.reader;
  55.             XmlNode parent = this.doc;
  56.             XmlElement element;
  57.             while (r.Read()) {
  58.                 XmlNode node = null;                
  59.                 switch (r.NodeType) {
  60.                     case XmlNodeType.Element:
  61.                         bool fEmptyElement = r.IsEmptyElement;
  62.                         element = doc.CreateElement(r.Prefix, r.LocalName, r.NamespaceURI);
  63.                         
  64.                         AddToTable(element);
  65.                         element.IsEmpty = fEmptyElement;
  66.                         ReadAttributes(r, element);
  67.                         if (!fEmptyElement) {
  68.                             parent.AppendChild(element);
  69.                             parent = element; 
  70.                             continue;
  71.                         } 
  72.                         node = element;
  73.                         break;
  74.                     case XmlNodeType.EndElement:
  75.                         if (parent.ParentNode == null) {
  76.                             // syntax error in document.
  77.                             IXmlLineInfo li = (IXmlLineInfo)r;
  78.                             throw new XmlException(string.Format(SR.UnexpectedToken,
  79.                                 "</"+r.LocalName+">", li.LineNumber, li.LinePosition), null, li.LineNumber, li.LinePosition);
  80.                         }
  81.                         parent = parent.ParentNode;
  82.                         continue;
  83.                     case XmlNodeType.EntityReference:
  84.                         if (r.CanResolveEntity) {
  85.                             r.ResolveEntity();
  86.                         }
  87.                         continue;
  88.                     case XmlNodeType.EndEntity:
  89.                         continue;
  90.                     case XmlNodeType.Attribute:
  91.                         node = LoadAttributeNode();
  92.                         break;
  93.                     case XmlNodeType.Text:
  94.                         node = doc.CreateTextNode(r.Value);
  95.                         AddToTable(node);
  96.                         break;
  97.                     case XmlNodeType.SignificantWhitespace:
  98.                         node = doc.CreateSignificantWhitespace(r.Value);
  99.                         AddToTable(node);
  100.                         break;
  101.                     case XmlNodeType.Whitespace:
  102.                         if (preserveWhitespace) {
  103.                             node = doc.CreateWhitespace(r.Value);
  104.                             AddToTable(node);
  105.                             break;
  106.                         } else {
  107.                             continue;
  108.                         }
  109.                     case XmlNodeType.CDATA:
  110.                         node = doc.CreateCDataSection(r.Value);
  111.                         AddToTable(node);
  112.                         break;
  113.                     case XmlNodeType.XmlDeclaration:
  114.                         node = LoadDeclarationNode();
  115.                         break;
  116.                     case XmlNodeType.ProcessingInstruction:
  117.                         node = doc.CreateProcessingInstruction(r.Name, r.Value);
  118.                         AddToTable(node);
  119.                         if (string.IsNullOrEmpty(this.xsltFileName) && r.Name == "xml-stylesheet") {
  120.                             string href = ParseXsltArgs(((XmlProcessingInstruction)node).Data);
  121.                             if (!string.IsNullOrEmpty(href)) this.xsltFileName = href;
  122.                         }
  123.                         break;
  124.                     case XmlNodeType.Comment:
  125.                         node = doc.CreateComment(r.Value);
  126.                         AddToTable(node);
  127.                         break;
  128.                     case XmlNodeType.DocumentType: {
  129.                             string pubid = r.GetAttribute("PUBLIC");
  130.                             string sysid = r.GetAttribute("SYSTEM");
  131.                             node = doc.CreateDocumentType(r.Name, pubid, sysid, r.Value);
  132.                             break;
  133.                         }
  134.                     default:
  135.                         UnexpectedNodeType(r.NodeType);
  136.                         break;
  137.                 }
  138.                 
  139.                 Debug.Assert(node != null);
  140.                 Debug.Assert(parent != null);
  141.                 if (parent != null) {
  142.                     parent.AppendChild(node);
  143.                 }
  144.             }        
  145.         }
  146.         public static string ParseXsltArgs(string data) {
  147.             try {
  148.                 XmlDocument doc = new XmlDocument();
  149.                 doc.LoadXml("<xsl " + data + "/>");
  150.                 XmlElement root = doc.DocumentElement;
  151.                 if (root.GetAttribute("type") == "text/xsl") {
  152.                     return root.GetAttribute("href");
  153.                 }
  154.             } catch (Exception){
  155.             }
  156.             return null;
  157.         }
  158.         private void ReadAttributes(XmlReader r, XmlElement element) {
  159.             if (r.MoveToFirstAttribute()) {
  160.                 XmlAttributeCollection attributes = element.Attributes;
  161.                 do {
  162.                     XmlAttribute attr = LoadAttributeNode();
  163.                     attributes.Append(attr); // special case for load
  164.                 }
  165.                 while (r.MoveToNextAttribute());
  166.                 r.MoveToElement();
  167.             }
  168.         }
  169.         string xsltFileName=null;
  170.         public string XsltFileName {
  171.             get { return this.xsltFileName; }
  172.         }
  173.         private XmlAttribute LoadAttributeNode() {
  174.             Debug.Assert(reader.NodeType == XmlNodeType.Attribute);
  175.             XmlReader r = reader;
  176.             XmlAttribute attr = doc.CreateAttribute(r.Prefix, r.LocalName, r.NamespaceURI);
  177.             AddToTable(attr);
  178.             XmlNode parent = attr;
  179.             
  180.             while (r.ReadAttributeValue()) {
  181.                 XmlNode node = null;
  182.                 switch (r.NodeType) {
  183.                     case XmlNodeType.Text:
  184.                         node = doc.CreateTextNode(r.Value);
  185.                         AddToTable(node);
  186.                         break;
  187.                     case XmlNodeType.EntityReference:
  188.                         if (r.CanResolveEntity) {
  189.                             r.ResolveEntity();                      
  190.                         }
  191.                         continue;
  192.                     case XmlNodeType.EndEntity:
  193.                         continue;
  194.                     default:
  195.                         UnexpectedNodeType(r.NodeType); 
  196.                         break;
  197.                 }
  198.                 Debug.Assert(node != null);
  199.                 parent.AppendChild(node);
  200.             }
  201.             if (attr.NamespaceURI == xsiUri) {
  202.                 HandleXsiAttribute(attr);
  203.             }
  204.             return attr;
  205.         }
  206.         void HandleXsiAttribute(XmlAttribute a) {
  207.             switch (a.LocalName) {
  208.                 case "schemaLocation":
  209.                     LoadSchemaLocations(a.Value);
  210.                     break;
  211.                 case "noNamespaceSchemaLocation":
  212.                     LoadSchema(a.Value);
  213.                     break;
  214.             }
  215.         }
  216.         void LoadSchemaLocations(string pairs) {
  217.             string[] words = pairs.Split(new char[] { ' ', 'r', 'n', 't' }, StringSplitOptions.RemoveEmptyEntries);
  218.             for (int i = 0, n = words.Length; i < n; i++) {                
  219.                 if (i + 1 < n) {
  220.                     i++;
  221.                     string url = words[i];
  222.                     LoadSchema(url);
  223.                 }
  224.             }
  225.         }
  226.         void LoadSchema(string fname) {
  227.             try {
  228.                 Uri resolved = new Uri(new Uri(reader.BaseURI), fname);                
  229.                 this.doc.Schemas.Add(null, resolved.AbsoluteUri);
  230.             } catch (Exception) {
  231.             }
  232.         }
  233.         private XmlDeclaration LoadDeclarationNode() {
  234.             Debug.Assert(reader.NodeType == XmlNodeType.XmlDeclaration);
  235.             //parse data
  236.             XmlDeclaration decl = doc.CreateXmlDeclaration("1.0",null,null);
  237.             AddToTable(decl);
  238.             // 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
  239.             // implementations that do nothing
  240.             while (reader.MoveToNextAttribute()) {
  241.                 switch (reader.Name) {
  242.                     case "version":                        
  243.                         break;
  244.                     case "encoding":
  245.                         decl.Encoding = reader.Value;
  246.                         break;
  247.                     case "standalone":
  248.                         decl.Standalone = reader.Value;
  249.                         break;
  250.                     default:
  251.                         Debug.Assert(false);
  252.                         break;
  253.                 }
  254.             }
  255.             return decl;
  256.         }        
  257.         void UnexpectedNodeType(XmlNodeType type) {
  258.             IXmlLineInfo li = (IXmlLineInfo)reader;
  259.             throw new XmlException(string.Format(SR.UnexpectedNodeType, type.ToString()), null,
  260.                 li.LineNumber, li.LinePosition);
  261.         }
  262.         
  263.     }
  264.     public class LineInfo : IXmlLineInfo {
  265.         int line, col;
  266.         string baseUri;
  267.         IXmlSchemaInfo info;
  268.         internal LineInfo(int line, int col) {
  269.             this.line = line;
  270.             this.col = col;
  271.         }
  272.         internal LineInfo(XmlReader reader) {
  273.             IXmlLineInfo li = reader as IXmlLineInfo;
  274.             if (li != null) {
  275.                 this.line = li.LineNumber;
  276.                 this.col = li.LinePosition;
  277.                 this.baseUri = reader.BaseURI;
  278.                 this.info = reader.SchemaInfo;
  279.             }
  280.         }
  281.         public bool HasLineInfo() {
  282.             return true;
  283.         }
  284.         public int LineNumber {
  285.             get { return this.line; }
  286.         }
  287.         public int LinePosition {
  288.             get { return this.col; }
  289.         }
  290.         public string BaseUri {
  291.             get { return this.baseUri; }
  292.         }
  293.         public IXmlSchemaInfo SchemaInfo {
  294.             get { return this.info; }
  295.         }
  296.     }
  297. }