--- /dev/null
+//\r
+// SubtreeXmlReader.cs - reads descendant nodes in XmlReader\r
+//\r
+// Author:\r
+// Atsushi Enomoto <atsushi@ximian.com>\r
+//\r
+// Copyright (c) 2004 Novell Inc. All rights reserved\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+#if NET_2_0\r
+\r
+using System;\r
+using System.Collections;\r
+using System.Xml;\r
+\r
+namespace Mono.Xml\r
+{\r
+ public class SubtreeXmlReader : XmlReader, IXmlLineInfo, IXmlNamespaceResolver\r
+ {\r
+ int startDepth;\r
+ bool eof;\r
+ bool initial;\r
+ bool read;\r
+ XmlReader Reader;\r
+ IXmlLineInfo li;\r
+ IXmlNamespaceResolver nsResolver;\r
+\r
+ public SubtreeXmlReader (XmlReader reader)\r
+ {\r
+ this.Reader = reader;\r
+ li = reader as IXmlLineInfo;\r
+ nsResolver = reader as IXmlNamespaceResolver;\r
+ initial = true;\r
+ startDepth = reader.Depth;\r
+ if (reader.ReadState == ReadState.Initial)\r
+ startDepth = -1; // end == the reader's end\r
+ }\r
+\r
+ public override int AttributeCount {\r
+ get { return initial ? 0 : Reader.AttributeCount; }\r
+ }\r
+\r
+ public override int Depth {\r
+ get { return Reader.Depth - startDepth; }\r
+ }\r
+\r
+ public override string BaseURI {\r
+ get { return Reader.BaseURI; }\r
+ }\r
+\r
+ public override bool EOF {\r
+ get { return eof || Reader.EOF; }\r
+ }\r
+\r
+ public int LineNumber {\r
+ get { return initial ? 0 : li != null ? li.LineNumber : 0; }\r
+ }\r
+\r
+ public int LinePosition {\r
+ get { return initial ? 0 : li != null ? li.LinePosition : 0; }\r
+ }\r
+\r
+ public override bool HasValue {\r
+ get { return initial ? false : Reader.HasValue; }\r
+ }\r
+\r
+ public override string LocalName {\r
+ get { return initial ? String.Empty : Reader.LocalName; }\r
+ }\r
+\r
+ public override string Name {\r
+ get { return initial ? String.Empty : Reader.Name; }\r
+ }\r
+\r
+ public override XmlNameTable NameTable {\r
+ get { return Reader.NameTable; }\r
+ }\r
+\r
+ public override string NamespaceURI {\r
+ get { return initial ? String.Empty : Reader.NamespaceURI; }\r
+ }\r
+\r
+ public override XmlNodeType NodeType {\r
+ get { return initial ? XmlNodeType.None : Reader.NodeType; }\r
+ }\r
+\r
+ public override string Prefix {\r
+ get { return initial ? String.Empty : Reader.Prefix; }\r
+ }\r
+\r
+ public override ReadState ReadState {\r
+ get { return initial ? ReadState.Initial : eof ? ReadState.EndOfFile : Reader.ReadState ; }\r
+ }\r
+\r
+ public override XmlReaderSettings Settings {\r
+ get { return Reader.Settings; }\r
+ }\r
+\r
+ public override string Value {\r
+ get { return initial ? String.Empty : Reader.Value; }\r
+ }\r
+\r
+ public override void Close ()\r
+ {\r
+ // do nothing\r
+ }\r
+\r
+ public override string GetAttribute (int i)\r
+ {\r
+ return initial ? null : Reader.GetAttribute (i);\r
+ }\r
+\r
+ public override string GetAttribute (string name)\r
+ {\r
+ return initial ? null : Reader.GetAttribute (name);\r
+ }\r
+\r
+ public override string GetAttribute (string local, string ns)\r
+ {\r
+ return initial ? null : Reader.GetAttribute (local, ns);\r
+ }\r
+\r
+ IDictionary IXmlNamespaceResolver.GetNamespacesInScope (XmlNamespaceScope scope)\r
+ {\r
+ return nsResolver != null ? nsResolver.GetNamespacesInScope (scope) : new Hashtable ();\r
+ }\r
+\r
+ public bool HasLineInfo ()\r
+ {\r
+ return li != null ? li.HasLineInfo () : false;\r
+ }\r
+\r
+ public override string LookupNamespace (string prefix)\r
+ {\r
+ return Reader.LookupNamespace (prefix);\r
+ }\r
+\r
+ string IXmlNamespaceResolver.LookupPrefix (string ns)\r
+ {\r
+ return nsResolver != null ? nsResolver.LookupPrefix (ns) : String.Empty;\r
+ }\r
+\r
+ string IXmlNamespaceResolver.LookupPrefix (string ns, bool atomizedNames)\r
+ {\r
+ return nsResolver != null ? nsResolver.LookupPrefix (ns, atomizedNames) : String.Empty;\r
+ }\r
+\r
+ public override bool MoveToFirstAttribute ()\r
+ {\r
+ return initial ? false : Reader.MoveToFirstAttribute ();\r
+ }\r
+\r
+ public override bool MoveToNextAttribute ()\r
+ {\r
+ return initial ? false : Reader.MoveToNextAttribute ();\r
+ }\r
+\r
+ public override void MoveToAttribute (int i)\r
+ {\r
+ if (!initial)\r
+ Reader.MoveToAttribute (i);\r
+ }\r
+\r
+ public override bool MoveToAttribute (string name)\r
+ {\r
+ return initial ? false : Reader.MoveToAttribute (name);\r
+ }\r
+\r
+ public override bool MoveToAttribute (string local, string ns)\r
+ {\r
+ return initial ? false : Reader.MoveToAttribute (local, ns);\r
+ }\r
+\r
+ public override bool MoveToElement ()\r
+ {\r
+ return initial ? false : Reader.MoveToElement ();\r
+ }\r
+\r
+ public override bool Read ()\r
+ {\r
+ if (initial) {\r
+ initial = false;\r
+ return true;\r
+ }\r
+ if (!read) {\r
+ read = true;\r
+ return !Reader.IsEmptyElement && Reader.Read ();\r
+ }\r
+ if (Reader.Depth > startDepth)\r
+ if (Reader.Read ())\r
+ return true;\r
+ eof = true;\r
+ return false;\r
+ }\r
+\r
+ public override bool ReadAttributeValue ()\r
+ {\r
+ if (initial || eof)\r
+ return false;\r
+ return Reader.ReadAttributeValue ();\r
+ }\r
+\r
+ public override void ResolveEntity ()\r
+ {\r
+ if (initial || eof)\r
+ return;\r
+ Reader.ResolveEntity ();\r
+ }\r
+ }\r
+}\r
+\r
+#endif\r
--- /dev/null
+//
+// XmlCachingResolver.cs
+//
+// Author:
+// Ben Maurer (bmaurer@users.sourceforge.net)
+//
+// (C) 2003 Ben Maurer
+//
+
+using System;
+using System.Xml;
+using System.Net;
+using System.IO;
+
+namespace Mono.Xml {
+ public class XmlCachingResolver : XmlUrlResolver {
+ static string tmpFolder;
+
+ static XmlCachingResolver ()
+ {
+ tmpFolder = Path.Combine (Path.GetTempPath (), "XmlCachingResolver_Cache");
+ Directory.CreateDirectory (tmpFolder);
+ }
+ #region XmlResolver impl
+ ICredentials credentials;
+ public override ICredentials Credentials
+ {
+ set { credentials = value; }
+ }
+
+ public override object GetEntity (Uri absoluteUri, string role, Type ofObjectToReturn)
+ {
+ if (ofObjectToReturn == null || ofObjectToReturn == typeof (Stream))
+ return GetStream (absoluteUri);
+ else
+ throw new XmlException ("Unsupported class type: " + ofObjectToReturn);
+ }
+
+ Stream GetStream (Uri uri)
+ {
+ // We can handle file:// without all the excess System.Net stuff
+ if (uri.Scheme == "file")
+ return File.OpenRead (uri.LocalPath);
+
+ else {
+ WebRequest req = WebRequest.Create (uri);
+ if (credentials != null)
+ req.Credentials = credentials;
+
+ if (req is HttpWebRequest) {
+ string url = uri.ToString ();
+
+ if (File.Exists (GetCachedPath (url))) {
+ // The file is in the cache, lets make sure it is up to date
+ HttpWebRequest hreq = req as HttpWebRequest;\r
+ // MS has a bug in their .net that makes 3xx errors (such as NotModified, 304)\r
+ // throw when this is *TRUE* even though their docs say it will throw when *FALSE*\r
+ hreq.AllowAutoRedirect = false;
+ hreq.IfModifiedSince = File.GetLastWriteTime (GetCachedPath (url));
+ HttpWebResponse hresp = hreq.GetResponse () as HttpWebResponse;
+
+ if (hresp.StatusCode != HttpStatusCode.NotModified)\r
+ using (Stream s = hresp.GetResponseStream ())
+ AddToCache (url, s);
+
+ return GetFromCache (url);
+
+ } else {
+ // The file has not been cached yet, so lets just get it
+ // and add it there.
+ using (Stream s = req.GetResponse ().GetResponseStream ())\r
+ AddToCache (url, s);
+ return GetFromCache (url);
+ }
+ } else // Ok, its not a http request, we dont know how to cache this
+ return req.GetResponse ().GetResponseStream ();
+ }
+ }
+ #endregion
+
+ #region Caching
+
+ static void AddToCache (string url, Stream data)
+ {
+ const int cbBuff = 8192;
+ int cb = 0;
+ byte [] buff = new byte [cbBuff];
+
+ using (FileStream fs = File.Create (GetCachedPath (url))) {
+ do {
+ cb = data.Read (buff, 0, cbBuff);
+ fs.Write (buff, 0, cb);
+ } while (cb > 0) ;
+ }
+ }
+
+ static string GetCachedPath (string url)
+ {
+ // EncodeLocalName will take out all things that would
+ // be bad to have in the file system
+ return Path.Combine (tmpFolder, XmlConvert.EncodeLocalName (url));
+ }
+
+ static Stream GetFromCache (string url)
+ {
+ return File.OpenRead (GetCachedPath (url));
+ }
+
+ #endregion
+
+ // utility method to make reading from this easier.
+ public XmlReader GetXmlReader (string url)
+ {
+ Uri uri = ResolveUri (null, url);
+ Stream stream = (Stream)GetEntity (uri, null, typeof (Stream));
+ XmlTextReader ret = new XmlTextReader (url, stream);
+ ret.XmlResolver = this;
+ return ret;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+//
+// Mono.Xml.XmlNodeWriter
+//
+// Author:
+// Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
+//
+// (C)2003 Atsushi Enomoto
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Xml;
+
+namespace Mono.Xml
+{
+ public class XmlNodeWriter : XmlWriter
+ {
+ public XmlNodeWriter () : this (true)
+ {
+ }
+
+ // It should be public after some tests are done :-)
+ public XmlNodeWriter (bool isDocumentEntity)
+ {
+ doc = new XmlDocument ();
+ state = XmlNodeType.None;
+ this.isDocumentEntity = isDocumentEntity;
+ if (!isDocumentEntity)
+ current = fragment = doc.CreateDocumentFragment ();
+ }
+
+ XmlDocument doc;
+ bool isClosed;
+ // If it is not null, then we are now inside the element.
+ XmlNode current;
+ // If it is not null, then we are now inside the attribute.
+ XmlAttribute attribute;
+ // If it is false, then allow to contain multiple document elements.
+ bool isDocumentEntity;
+ XmlDocumentFragment fragment;
+
+ // None: started or closed.
+ // XmlDeclaration: after xmldecl. Never allow xmldecl.
+ // DocumentType: after doctype. Never allow xmldecl and doctype.
+ // Element: inside document element.
+ //
+ XmlNodeType state;
+
+ // Properties
+ public XmlNode Document {
+ get { return isDocumentEntity ? (XmlNode)doc : (XmlNode)fragment; }
+ }
+
+ public override WriteState WriteState {
+ get {
+ if (isClosed)
+ return WriteState.Closed;
+ if (attribute != null)
+ return WriteState.Attribute;
+
+ switch (state) {
+ case XmlNodeType.None:
+ return WriteState.Start;
+ case XmlNodeType.XmlDeclaration:
+ return WriteState.Prolog;
+ case XmlNodeType.DocumentType:
+ return WriteState.Element;
+ default:
+ return WriteState.Content;
+ }
+ }
+ }
+
+ public override string XmlLang {
+ get {
+ for (XmlElement n = current as XmlElement; n != null; n = n.ParentNode as XmlElement)
+ if (n.HasAttribute ("xml:lang"))
+ return n.GetAttribute ("xml:lang");
+ return String.Empty;
+ }
+ }
+
+ public override XmlSpace XmlSpace {
+ get {
+ for (XmlElement n = current as XmlElement; n != null; n = n.ParentNode as XmlElement) {
+ string xs = n.GetAttribute ("xml:space");
+ switch (xs) {
+ case "preserve":
+ return XmlSpace.Preserve;
+ case "default":
+ return XmlSpace.Default;
+ case "":
+ continue;
+ default:
+ throw new InvalidOperationException (String.Format ("Invalid xml:space {0}.", xs));
+ }
+ }
+ return XmlSpace.None;
+ }
+ }
+
+ // Private Methods
+
+ private void CheckState ()
+ {
+ if (isClosed)
+ throw new InvalidOperationException ();
+
+ }
+
+ private void WritePossiblyTopLevelNode (XmlNode n, bool possiblyAttribute)
+ {
+ CheckState ();
+ if (!possiblyAttribute && attribute != null)
+ throw new InvalidOperationException (String.Format ("Current state is not acceptable for {0}.", n.NodeType));
+
+ if (state != XmlNodeType.Element)
+ Document.AppendChild (n);
+ else if (attribute != null)
+ attribute.AppendChild (n);
+ else
+ current.AppendChild (n);
+ if (state == XmlNodeType.None)
+ state = XmlNodeType.XmlDeclaration;
+ }
+
+ // Public Methods
+
+ public override void Close ()
+ {
+ CheckState ();
+ isClosed = true;
+ }
+
+ public override void Flush ()
+ {
+ }
+
+ public override string LookupPrefix (string ns)
+ {
+ CheckState ();
+ if (current == null)
+ throw new InvalidOperationException ();
+ return current.GetPrefixOfNamespace (ns);
+ }
+
+ // StartDocument
+
+ public override void WriteStartDocument ()
+ {
+ WriteStartDocument (null);
+ }
+
+ public override void WriteStartDocument (bool standalone)
+ {
+ WriteStartDocument (standalone ? "yes" : "no");
+ }
+
+ private void WriteStartDocument (string sddecl)
+ {
+ CheckState ();
+ if (state != XmlNodeType.None)
+ throw new InvalidOperationException ("Current state is not acceptable for xmldecl.");
+
+ doc.AppendChild (doc.CreateXmlDeclaration ("1.0", null, sddecl));
+ state = XmlNodeType.XmlDeclaration;
+ }
+
+ // EndDocument
+
+ public override void WriteEndDocument ()
+ {
+ CheckState ();
+
+ isClosed = true;
+ }
+
+ // DocumentType
+ public override void WriteDocType (string name, string publicId, string systemId, string internalSubset)
+ {
+ CheckState ();
+ switch (state) {
+ case XmlNodeType.None:
+ case XmlNodeType.XmlDeclaration:
+ doc.AppendChild (doc.CreateDocumentType (name, publicId, systemId, internalSubset));
+ state = XmlNodeType.DocumentType;
+ break;
+ default:
+ throw new InvalidOperationException ("Current state is not acceptable for doctype.");
+ }
+ }
+
+ // StartElement
+
+ public override void WriteStartElement (string prefix, string name, string ns)
+ {
+ CheckState ();
+ if (isDocumentEntity && state == XmlNodeType.EndElement && doc.DocumentElement != null)
+ throw new InvalidOperationException ("Current state is not acceptable for startElement.");
+
+ XmlElement el = doc.CreateElement (prefix, name, ns);
+ if (current == null) {
+ Document.AppendChild (el);
+ state = XmlNodeType.Element;
+ } else {
+ current.AppendChild (el);
+ state = XmlNodeType.Element;
+ }
+
+ current = el;
+ }
+
+ // EndElement
+
+ public override void WriteEndElement ()
+ {
+ WriteEndElementInternal (false);
+ }
+
+ public override void WriteFullEndElement ()
+ {
+ WriteEndElementInternal (true);
+ }
+
+ private void WriteEndElementInternal (bool forceFull)
+ {
+ CheckState ();
+ if (current == null)
+ throw new InvalidOperationException ("Current state is not acceptable for endElement.");
+
+ if (!forceFull && current.FirstChild == null)
+ ((XmlElement) current).IsEmpty = true;
+
+ if (isDocumentEntity && current.ParentNode == doc)
+ state = XmlNodeType.EndElement;
+ else
+ current = current.ParentNode;
+ }
+
+ // StartAttribute
+
+ public override void WriteStartAttribute (string prefix, string name, string ns)
+ {
+ CheckState ();
+ if (attribute != null)
+ throw new InvalidOperationException ("There is an open attribute.");
+ if (!(current is XmlElement))
+ throw new InvalidOperationException ("Current state is not acceptable for startAttribute.");
+
+ attribute = doc.CreateAttribute (prefix, name, ns);
+ ((XmlElement)current).SetAttributeNode (attribute);
+ }
+
+ public override void WriteEndAttribute ()
+ {
+ CheckState ();
+ if (attribute == null)
+ throw new InvalidOperationException ("Current state is not acceptable for startAttribute.");
+
+ attribute = null;
+ }
+
+ public override void WriteCData (string data)
+ {
+ CheckState ();
+ if (current == null)
+ throw new InvalidOperationException ("Current state is not acceptable for CDATAsection.");
+
+ current.AppendChild (doc.CreateCDataSection (data));
+ }
+
+ public override void WriteComment (string comment)
+ {
+ WritePossiblyTopLevelNode (doc.CreateComment (comment), false);
+ }
+
+ public override void WriteProcessingInstruction (string name, string value)
+ {
+ WritePossiblyTopLevelNode (
+ doc.CreateProcessingInstruction (name, value), false);
+ }
+
+ public override void WriteEntityRef (string name)
+ {
+ WritePossiblyTopLevelNode (doc.CreateEntityReference (name), true);
+ }
+
+ public override void WriteCharEntity (char c)
+ {
+ WritePossiblyTopLevelNode (doc.CreateTextNode (new string (new char [] {c}, 0, 1)), true);
+ }
+
+ public override void WriteWhitespace (string ws)
+ {
+ WritePossiblyTopLevelNode (doc.CreateWhitespace (ws), true);
+ }
+
+ public override void WriteString (string data)
+ {
+ CheckState ();
+ if (current == null)
+ throw new InvalidOperationException ("Current state is not acceptable for Text.");
+
+ if (attribute != null)
+ attribute.AppendChild (doc.CreateTextNode (data));
+ else {
+ XmlText last = current.LastChild as XmlText;
+ if (last == null)
+ current.AppendChild(doc.CreateTextNode(data));
+ else
+ last.AppendData(data);
+ }
+ }
+
+ public override void WriteName (string name)
+ {
+ WriteString (name);
+ }
+
+ public override void WriteNmToken (string nmtoken)
+ {
+ WriteString (nmtoken);
+ }
+
+ public override void WriteQualifiedName (string name, string ns)
+ {
+ string prefix = LookupPrefix (ns);
+ if (prefix == null)
+ throw new ArgumentException (String.Format ("Invalid namespace {0}", ns));
+ if (prefix != String.Empty)
+ WriteString (name);
+ else
+ WriteString (prefix + ":" + name);
+ }
+
+ public override void WriteChars (char [] chars, int start, int len)
+ {
+ WriteString (new string (chars, start, len));
+ }
+
+ public override void WriteRaw (string data)
+ {
+ // It never supports raw string.
+ WriteString (data);
+ }
+
+ public override void WriteRaw (char [] chars, int start, int len)
+ {
+ // It never supports raw string.
+ WriteChars (chars, start, len);
+ }
+
+ public override void WriteBase64 (byte [] data, int start, int len)
+ {
+ // It never supports raw string.
+ WriteString (Convert.ToBase64String (data, start, len));
+ }
+
+ public override void WriteBinHex (byte [] data, int start, int len)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void WriteSurrogateCharEntity (char c1, char c2)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}