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

xml/soap/webservice

开发平台:

Visual C++

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Xml;
  5. using System.IO;
  6. namespace XmlNotepad {
  7.     /// <summary>
  8.     /// XmlIncludeReader automatically expands XInclude elements and returns
  9.     /// the expanded nodes making the XInclude 
  10.     /// </summary>
  11.     public class XmlIncludeReader : XmlReader, IXmlLineInfo {
  12.         XmlReaderSettings settings;
  13.         XmlReader reader; // current reader 
  14.         Stack<XmlReader> stack = new Stack<XmlReader>();
  15.         Stack<Uri> baseUris = new Stack<Uri>();
  16.         Uri baseUri;
  17.         public const string XIncludeNamespaceUri = "http://www.w3.org/2001/XInclude";
  18.         public static XmlIncludeReader CreateIncludeReader(string url, XmlReaderSettings settings) {
  19.             XmlIncludeReader r = new XmlIncludeReader();
  20.             r.reader = XmlReader.Create(url, settings);
  21.             r.settings = settings;
  22.             return r;
  23.         }
  24.         // [cjl] dead code removal
  25.         //public static XmlIncludeReader CreateIncludeReader(Stream stream, XmlReaderSettings settings, string baseUri) {
  26.         //    XmlIncludeReader r = new XmlIncludeReader();
  27.         //    r.reader = XmlReader.Create(stream, settings, baseUri);
  28.         //    r.settings = settings;
  29.         //    r.baseUri = new Uri(baseUri);
  30.         //    return r;
  31.         //}
  32.         //public static XmlIncludeReader CreateIncludeReader(TextReader reader, XmlReaderSettings settings, string baseUri) {
  33.         //    XmlIncludeReader r = new XmlIncludeReader();
  34.         //    r.reader = XmlReader.Create(reader, settings, baseUri);
  35.         //    r.settings = settings;
  36.         //    r.baseUri = new Uri(baseUri);
  37.         //    return r;
  38.         //}
  39.         //public static XmlIncludeReader CreateIncludeReader(TextReader reader, XmlReaderSettings settings, XmlParserContext context) {
  40.         //    XmlIncludeReader r = new XmlIncludeReader();
  41.         //    r.reader = XmlReader.Create(reader, settings, context);
  42.         //    r.settings = settings;
  43.         //    return r;
  44.         //}
  45.         public static XmlIncludeReader CreateIncludeReader(XmlDocument doc, XmlReaderSettings settings, string baseUri) {
  46.             XmlIncludeReader r = new XmlIncludeReader();
  47.             r.reader = new XmlNodeReader(doc);
  48.             r.settings = settings;
  49.             r.baseUri = new Uri(baseUri);
  50.             return r;
  51.         }
  52.         public override XmlNodeType NodeType {
  53.             get { return reader.NodeType;  }
  54.         }
  55.         public override string LocalName {
  56.             get { return reader.LocalName; }
  57.         }
  58.         public override string NamespaceURI {
  59.             get { return reader.NamespaceURI; }
  60.         }
  61.         public override string Prefix {
  62.             get { return reader.Prefix; }
  63.         }
  64.         public override bool HasValue {
  65.             get { return reader.HasValue; }
  66.         }
  67.         public override string Value {
  68.             get { return reader.Value; }
  69.         }
  70.         public override string BaseURI {
  71.             get {
  72.                 Uri uri = GetBaseUri();
  73.                 if (uri.IsFile) return uri.LocalPath;
  74.                 return uri.AbsoluteUri;
  75.             }
  76.         }
  77.         public Uri GetBaseUri() {
  78.             string s = reader.BaseURI;
  79.             if (string.IsNullOrEmpty(s)) {
  80.                 if (baseUris.Count > 0) {
  81.                     Uri curi = baseUris.Peek();
  82.                     if (curi != null) return curi;
  83.                 }
  84.                 return this.baseUri;
  85.             } else {
  86.                 return new Uri(s);
  87.             }
  88.         }
  89.         public override bool IsEmptyElement {
  90.             get { return reader.IsEmptyElement; }
  91.         }
  92.         public override int AttributeCount {
  93.             get { return reader.AttributeCount; }
  94.         }
  95.         public override string GetAttribute(int i) {
  96.             return reader.GetAttribute(i);
  97.         }
  98.         public override string GetAttribute(string name) {
  99.             return reader.GetAttribute(name);
  100.         }
  101.         public override string GetAttribute(string name, string namespaceURI) {
  102.             return reader.GetAttribute(name, namespaceURI);
  103.         }
  104.         public override bool MoveToAttribute(string name) {
  105.             return reader.MoveToAttribute(name);
  106.         }
  107.         public override bool MoveToAttribute(string name, string ns) {
  108.             return reader.MoveToAttribute(name, ns);
  109.         }
  110.         public override bool MoveToFirstAttribute() {
  111.             return reader.MoveToFirstAttribute();
  112.         }
  113.         public override bool MoveToNextAttribute() {
  114.             return reader.MoveToNextAttribute();
  115.         }
  116.         public override bool ReadAttributeValue() {
  117.             return reader.ReadAttributeValue();
  118.         }
  119.         public override bool EOF {
  120.             get { return reader.EOF; }
  121.         }
  122.         public override void Close() {
  123.             reader.Close();
  124.             while (stack.Count > 0) {
  125.                 reader = stack.Pop();
  126.                 reader.Close();
  127.             }
  128.         }
  129.         public override ReadState ReadState {
  130.             get { return reader.ReadState; }
  131.         }
  132.         public override XmlNameTable NameTable {
  133.             get { return reader.NameTable; }
  134.         }
  135.         public override string LookupNamespace(string prefix) {
  136.             return reader.LookupNamespace(prefix);
  137.         }
  138.         public override void ResolveEntity() {
  139.             reader.ResolveEntity();
  140.         }
  141.         public override int Depth {
  142.             get { return reader.Depth; }
  143.         }
  144.         public override bool MoveToElement() {
  145.             return reader.MoveToElement();
  146.         }
  147.         /// <summary>
  148.         /// This is the real meat of this class where we automatically expand the 
  149.         /// XInclude elements following their href attributes, returning the expanded
  150.         /// nodes.
  151.         /// </summary>
  152.         /// <returns>Returns false when all includes have been expanded and 
  153.         /// we have reached the end of the top level document.</returns>
  154.         public override bool Read() {
  155.             bool rc = reader.Read();
  156.         pop:
  157.             while (!rc && stack.Count > 0) {
  158.                 reader.Close();
  159.                 reader = stack.Pop();
  160.                 rc = reader.Read();
  161.             }
  162.             if (!rc) return rc; // we're done!
  163.             // Now check if we're on an XInclude element and expand it if we are.
  164.             while (reader.NamespaceURI == XIncludeNamespaceUri) {
  165.                 if (reader.LocalName == "fallback" && reader.NodeType == XmlNodeType.EndElement) {
  166.                     rc = reader.Read();
  167.                 } else if (reader.LocalName == "include") {
  168.                     rc = ExpandInclude();
  169.                 } else {
  170.                     rc = reader.Read();
  171.                 }
  172.                 if (!rc) goto pop;
  173.             }
  174.             return rc;
  175.         }
  176.         bool ExpandInclude() {
  177.             string href = reader.GetAttribute("href");
  178.             string parse = reader.GetAttribute("parse");
  179.             string xpointer = reader.GetAttribute("xpointer");
  180.             string encoding = reader.GetAttribute("encoding");
  181.             string accept = reader.GetAttribute("accept");
  182.             string acceptLanguage = reader.GetAttribute("accept-language");
  183.             // todo: support for parse, xpointer, etc.
  184.             if (string.IsNullOrEmpty(href)) {
  185.                 throw new ApplicationException(SR.IncludeHRefRequired);
  186.             }
  187.             XmlElement fallback = ReadFallback();
  188.             try {
  189.                 Uri baseUri = this.GetBaseUri();
  190.                 Uri resolved = new Uri(baseUri, href);
  191.                 // HTTP has a limit of 2 requests per client on a given server, so we
  192.                 // have to cache the entire include to avoid a deadlock.
  193.                 using (XmlReader ir = XmlReader.Create(resolved.AbsoluteUri, settings)) {
  194.                     XmlDocument include = new XmlDocument(reader.NameTable);
  195.                     include.Load(ir);
  196.                     if (include.FirstChild.NodeType == XmlNodeType.XmlDeclaration) {
  197.                         // strip XML declarations.
  198.                         include.RemoveChild(include.FirstChild);
  199.                     }
  200.                     stack.Push(reader);
  201.                     baseUris.Push(resolved);
  202.                     reader = new XmlNodeReader(include);
  203.                     return reader.Read(); // initialize reader to first node in document.
  204.                 }
  205.             } catch (Exception) {
  206.                 // return fall back element.
  207.                 if (fallback != null) {
  208.                     baseUris.Push(this.GetBaseUri());
  209.                     stack.Push(reader);
  210.                     reader = new XmlNodeReader(fallback);
  211.                     reader.Read(); // initialize reader
  212.                     return reader.Read(); // consume fallback start tag.
  213.                 } else {
  214.                     throw;
  215.                 }
  216.             }
  217.         }
  218.         XmlElement ReadFallback() {
  219.             XmlDocument fallback = new XmlDocument(reader.NameTable);
  220.             if (reader.IsEmptyElement) {
  221.                 return null;
  222.             } else {
  223.                 reader.Read();
  224.             }
  225.             while (reader.NodeType != XmlNodeType.EndElement) {
  226.                 if (reader.NamespaceURI == XIncludeNamespaceUri &&
  227.                     reader.LocalName == "fallback") {
  228.                     fallback.AppendChild(fallback.ReadNode(reader));
  229.                 } else {
  230.                     reader.Skip();
  231.                 }
  232.             }
  233.             return fallback.DocumentElement;
  234.         }
  235.         #region IXmlLineInfo Members
  236.         public bool HasLineInfo() {
  237.             IXmlLineInfo xi = reader as IXmlLineInfo;
  238.             return xi != null ? xi.HasLineInfo() : false;
  239.         }
  240.         public int LineNumber {
  241.             get {
  242.                 IXmlLineInfo xi = reader as IXmlLineInfo;
  243.                 if (xi != null) return xi.LineNumber;
  244.                 return 0;
  245.             }
  246.         }
  247.         public int LinePosition {
  248.             get {
  249.                 IXmlLineInfo xi = reader as IXmlLineInfo;
  250.                 if (xi != null) return xi.LinePosition;
  251.                 return 0;
  252.             }
  253.         }
  254.         #endregion
  255.     }
  256. }