Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/XPathEditableDocument.cs')
-rwxr-xr-xmcs/class/Mono.Xml.Ext/Mono.Xml.XPath/XPathEditableDocument.cs765
1 files changed, 765 insertions, 0 deletions
diff --git a/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/XPathEditableDocument.cs b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/XPathEditableDocument.cs
new file mode 100755
index 00000000000..828a0414f05
--- /dev/null
+++ b/mcs/class/Mono.Xml.Ext/Mono.Xml.XPath/XPathEditableDocument.cs
@@ -0,0 +1,765 @@
+//
+// Mono.Xml.XPath.XPathEditableDocument
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// (C)2004 Novell Inc.
+//
+// Yet another implementation of editable XPathNavigator.
+// (Even runnable under MS.NET 2.0)
+//
+// By rewriting XPathEditableDocument.CreateNavigator() as just to
+// create XmlDocumentNavigator, XmlDocumentEditableNavigator could be used
+// as to implement XmlDocument.CreateNavigator().
+//
+
+//
+// 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.
+//
+#if NET_2_0
+
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using System.Xml.XPath;
+using System.Xml.Serialization;
+
+namespace Mono.Xml.XPath
+{
+ public class XPathEditableDocument : IXPathNavigable
+ {
+ /*
+ public static void Main ()
+ {
+ try {
+#if true
+ XmlDocument doc = new XmlDocument ();
+ XPathEditableDocument pd = new XPathEditableDocument (doc);
+ XPathNavigator nav = pd.CreateNavigator ();
+ IChangeTracking xp = pd;
+#else
+ XPathDocument doc = new XPathDocument ();
+ XPathNavigator nav = doc.CreateNavigator ();
+ IChangeTracking xp = doc;
+#endif
+ doc.LoadXml ("<root/>");
+ nav.MoveToFirstChild (); // root
+ XmlWriter w = nav.AppendChild ();
+ Console.WriteLine (((IChangeTracking) xp).IsChanged);
+ w.WriteElementString ("foo", "foo_text");
+ w.WriteElementString ("bar", "bar_text");
+ w.WriteStartElement ("hoge");
+ w.WriteAttributeString ("fuga", "fugafuga");
+ w.WriteAttributeString ("unya", "unyaunya");
+ w.WriteFullEndElement ();
+ w.Close ();
+
+ w = nav.CreateAttributes ();
+ w.WriteStartAttribute ("namara");
+ w.WriteString ("mokera");
+ w.WriteEndAttribute ();
+ w.WriteAttributeString ("beccho", "giccho");
+ w.Close ();
+
+ nav.MoveToRoot ();
+ nav.MoveToFirstChild ();
+ nav.MoveToFirstChild ();
+ nav.DeleteSelf (); // delete foo
+ Console.WriteLine (nav.Name);
+ nav.MoveToNext ();
+ Console.WriteLine (nav.Name);
+ Console.WriteLine (nav.MoveToFirstAttribute ());
+ nav.DeleteSelf (); // delete fuga
+
+ doc.Save (Console.Out);
+ } catch (Exception ex) {
+ Console.WriteLine (ex);
+ }
+ }
+ */
+
+ XmlDocument document;
+
+ ArrayList changes = new ArrayList ();
+
+ public XPathEditableDocument (XmlDocument doc)
+ {
+ document = doc;
+ }
+
+ public XPathNavigator CreateNavigator ()
+ {
+ return document.CreateNavigator ();
+ }
+
+ public XmlWriter CreateWriter ()
+ {
+ return CreateNavigator ().AppendChild ();
+ }
+
+ public bool HasChanges ()
+ {
+ return IsChanged;
+ }
+
+ #region IRevertibleChangeTracking/IChangeTracking
+ public bool IsChanged {
+ get { return changes.Count != 0; }
+ }
+
+ public void AcceptChanges ()
+ {
+ changes.Clear ();
+ }
+
+ public void RejectChanges ()
+ {
+ for (int i = changes.Count - 1; i >= 0; i--) {
+ Insertion ins = changes [i] as Insertion;
+ if (ins != null) {
+ ins.ParentNode.RemoveChild (ins.InsertedNode);
+ continue;
+ }
+
+ Removal rem = changes [i] as Removal;
+ if (rem != null) {
+ if (rem.RemovedNode.NodeType == XmlNodeType.Attribute) {
+ XmlElement el = (XmlElement) rem.OwnerNode;
+ el.SetAttributeNode ((XmlAttribute) rem.RemovedNode);
+ }
+ else
+ rem.OwnerNode.InsertBefore (rem.RemovedNode, rem.NextSibling);
+ continue;
+ }
+ AttributeUpdate au = changes [i] as AttributeUpdate;
+ if (au != null) {
+ if (au.OldAttribute != null)
+ au.Element.SetAttributeNode (au.OldAttribute);
+ else
+ au.Element.RemoveAttributeNode (au.NewAttribute);
+ continue;
+ }
+ }
+ changes.Clear ();
+ }
+ #endregion
+
+ #region IXmlSerializable
+ public void WriteXml (XmlWriter writer)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void ReadXml (XmlReader reader)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public XmlSchema GetSchema ()
+ {
+ throw new NotImplementedException ();
+ }
+ #endregion
+
+ internal bool DeleteNode (XmlNode node)
+ {
+ Removal rem = new Removal ();
+ if (node.NodeType == XmlNodeType.Attribute) {
+ XmlAttribute attr = node as XmlAttribute;
+ rem.OwnerNode = attr.OwnerElement;
+ rem.RemovedNode = node;
+ attr.OwnerElement.RemoveAttributeNode (attr);
+ return false;
+ } else {
+ rem.OwnerNode = node.ParentNode;
+ rem.NextSibling = node.NextSibling;
+ rem.RemovedNode = node;
+ node.ParentNode.RemoveChild (node);
+ return rem.NextSibling != null;
+ }
+ }
+
+ internal XmlWriter CreateInsertionWriter (XmlNode owner, XmlNode previousSibling)
+ {
+ return new XmlDocumentInsertionWriter (owner, previousSibling, this);
+ }
+
+ internal XmlWriter CreateAttributesWriter (XmlNode owner)
+ {
+ return new XmlDocumentAttributeWriter (owner, this);
+ }
+
+ internal void AttributeUpdate (XmlElement element, XmlAttribute oldAttr, XmlAttribute newAttr)
+ {
+ AttributeUpdate au = new AttributeUpdate ();
+ au.Element = element;
+ au.OldAttribute = oldAttr;
+ au.NewAttribute = newAttr;
+ changes.Add (au);
+ }
+
+ internal void AppendChild (XmlNode parent, XmlNode child)
+ {
+ Insertion ins = new Insertion ();
+ ins.ParentNode = parent;
+ ins.InsertedNode = child;
+ changes.Add (ins);
+ }
+ }
+
+ public class XmlDocumentInsertionWriter : XmlWriter
+ {
+ XmlNode current;
+ XmlNode previousSibling;
+ XPathEditableDocument document;
+ Stack nodeStack = new Stack ();
+
+ public XmlDocumentInsertionWriter (XmlNode owner, XmlNode previousSibling, XPathEditableDocument doc)
+ {
+ this.current = (XmlNode) owner;
+ if (current == null)
+ throw new InvalidOperationException ();
+ this.previousSibling = previousSibling;
+ this.document = doc;
+ state = WriteState.Content;
+ }
+
+ WriteState state;
+ XmlAttribute attribute;
+
+ public override WriteState WriteState {
+ get { return state; }
+ }
+
+ public override void Close ()
+ {
+ }
+
+ public override void Flush ()
+ {
+ }
+
+ public override string LookupPrefix (string ns)
+ {
+ return current.GetPrefixOfNamespace (ns);
+ }
+
+ public override void WriteStartAttribute (string prefix, string name, string ns)
+ {
+ if (state != WriteState.Content)
+ throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
+ attribute = current.OwnerDocument.CreateAttribute (prefix, name, ns);
+ state = WriteState.Attribute;
+ }
+
+ public override void WriteProcessingInstruction (string name, string value)
+ {
+ XmlProcessingInstruction pi = current.OwnerDocument.CreateProcessingInstruction (name, value);
+ current.AppendChild (pi);
+ document.AppendChild (current, pi);
+ }
+
+ public override void WriteComment (string text)
+ {
+ XmlComment comment = current.OwnerDocument.CreateComment (text);
+ current.AppendChild (comment);
+ document.AppendChild (current, comment);
+ }
+
+ public override void WriteCData (string text)
+ {
+ XmlCDataSection cdata = current.OwnerDocument.CreateCDataSection (text);
+ current.AppendChild (cdata);
+ document.AppendChild (current, cdata);
+ }
+
+ public override void WriteStartElement (string prefix, string name, string ns)
+ {
+ if (current.OwnerDocument == null)
+ throw new Exception ("Should not happen.");
+ XmlElement el = current.OwnerDocument.CreateElement (prefix, name, ns);
+ current.AppendChild (el);
+ document.AppendChild (current, el);
+ nodeStack.Push (current);
+ current = el;
+ }
+
+ public override void WriteEndElement ()
+ {
+ if (nodeStack.Count == 0)
+ throw new InvalidOperationException ("No element is opened.");
+ current = nodeStack.Pop () as XmlNode;
+ }
+
+ public override void WriteFullEndElement ()
+ {
+ WriteEndElement ();
+ XmlElement el = current as XmlElement;
+ if (el != null)
+ el.IsEmpty = false;
+ }
+
+ public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteStartDocument ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteStartDocument (bool standalone)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteEndDocument ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteBase64 (byte [] data, int start, int length)
+ {
+ WriteString (Convert.ToBase64String (data, start, length));
+ }
+
+ public override void WriteRaw (char [] raw, int start, int length)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteRaw (string raw)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteSurrogateCharEntity (char msb, char lsb)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteCharEntity (char c)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteEntityRef (string entname)
+ {
+ if (state != WriteState.Attribute)
+ throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
+ attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
+ }
+
+ public override void WriteChars (char [] data, int start, int length)
+ {
+ WriteString (new string (data, start, length));
+ }
+
+ public override void WriteString (string text)
+ {
+ if (attribute != null)
+ attribute.Value += text;
+ else {
+ XmlText t = current.OwnerDocument.CreateTextNode (text);
+ current.AppendChild (t);
+ document.AppendChild (current, t);
+ }
+ }
+
+ public override void WriteWhitespace (string text)
+ {
+ if (state != WriteState.Attribute)
+ current.AppendChild (current.OwnerDocument.CreateTextNode (text));
+ else if (attribute.ChildNodes.Count == 0)
+ attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
+ else
+ attribute.Value += text;
+ }
+
+ public override void WriteEndAttribute ()
+ {
+ XmlElement element = current as XmlElement;
+ if (state != WriteState.Attribute || element == null)
+ throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
+ document.AttributeUpdate (element, element.SetAttributeNode (attribute), attribute);
+ attribute = null;
+ state = WriteState.Content;
+ }
+ }
+
+ public class XmlDocumentAttributeWriter : XmlWriter
+ {
+ XmlElement element;
+ XPathEditableDocument document;
+
+ public XmlDocumentAttributeWriter (XmlNode owner, XPathEditableDocument doc)
+ {
+ element = owner as XmlElement;
+ if (element == null)
+ throw new ArgumentException ("To write attributes, current node must be an element.");
+ state = WriteState.Content;
+ document = doc;
+ }
+
+ WriteState state;
+ XmlAttribute attribute;
+
+ public override WriteState WriteState {
+ get { return state; }
+ }
+
+ public override void Close ()
+ {
+ }
+
+ public override void Flush ()
+ {
+ }
+
+ public override string LookupPrefix (string ns)
+ {
+ return element.GetPrefixOfNamespace (ns);
+ }
+
+ public override void WriteStartAttribute (string prefix, string name, string ns)
+ {
+ if (state != WriteState.Content)
+ throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
+ attribute = element.OwnerDocument.CreateAttribute (prefix, name, ns);
+ state = WriteState.Attribute;
+ }
+
+ public override void WriteProcessingInstruction (string name, string value)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteComment (string text)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteCData (string text)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteStartElement (string prefix, string name, string ns)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteEndElement ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteFullEndElement ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteStartDocument ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteStartDocument (bool standalone)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteEndDocument ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteBase64 (byte [] data, int start, int length)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteRaw (char [] raw, int start, int length)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteRaw (string raw)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteSurrogateCharEntity (char msb, char lsb)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteCharEntity (char c)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void WriteEntityRef (string entname)
+ {
+ if (state != WriteState.Attribute)
+ throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
+ attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
+ }
+
+ public override void WriteChars (char [] data, int start, int length)
+ {
+ WriteString (new string (data, start, length));
+ }
+
+ public override void WriteString (string text)
+ {
+ if (state != WriteState.Attribute)
+ throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
+ attribute.Value += text;
+ }
+
+ public override void WriteWhitespace (string text)
+ {
+ if (state != WriteState.Attribute)
+ throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
+ if (attribute.ChildNodes.Count == 0)
+ attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
+ else
+ attribute.Value += text;
+ }
+
+ public override void WriteEndAttribute ()
+ {
+ if (state != WriteState.Attribute)
+ throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
+ document.AttributeUpdate (element, element.SetAttributeNode (attribute), attribute);
+ attribute = null;
+ state = WriteState.Content;
+ }
+ }
+
+ public class Insertion
+ {
+ // AppendChild : last child / true
+ // InsertBefore : current node / false
+ // InsertAfter : current node / true
+ // PrependChild : first child / false
+ public XmlNode ParentNode;
+ public XmlNode InsertedNode;
+ public bool Afterward;
+ }
+
+ public class Removal
+ {
+ public XmlNode OwnerNode;
+ public XmlNode NextSibling;
+ public XmlNode RemovedNode;
+ }
+
+ public class AttributeUpdate
+ {
+ public XmlElement Element;
+ public XmlAttribute NewAttribute;
+ public XmlAttribute OldAttribute;
+ }
+
+ public class XmlDocumentEditableNavigator : XPathNavigator, IHasXmlNode
+ {
+ XPathEditableDocument document;
+ XPathNavigator navigator;
+
+ public XmlDocumentEditableNavigator (XPathEditableDocument doc)
+ {
+ document = doc;
+ navigator = doc.CreateNavigator ();
+ }
+
+ public XmlDocumentEditableNavigator (XmlDocumentEditableNavigator nav)
+ {
+ document = nav.document;
+ navigator = nav.navigator.Clone ();
+ }
+
+ public override string BaseURI {
+ get { return navigator.BaseURI; }
+ }
+
+ public override bool IsEmptyElement {
+ get { return navigator.IsEmptyElement; }
+ }
+
+ public override string LocalName {
+ get { return navigator.LocalName; }
+ }
+
+ public override XmlNameTable NameTable {
+ get { return navigator.NameTable; }
+ }
+
+ public override string Name {
+ get { return navigator.Name; }
+ }
+
+ public override string NamespaceURI {
+ get { return navigator.NamespaceURI; }
+ }
+
+ public override XPathNodeType NodeType {
+ get { return navigator.NodeType; }
+ }
+
+ public override string Prefix {
+ get { return navigator.Prefix; }
+ }
+
+ public override string Value {
+ get { return navigator.Value; }
+ }
+
+ public override XPathNavigator Clone ()
+ {
+ return new XmlDocumentEditableNavigator (this);
+ }
+
+ public override XPathNavigator CreateNavigator ()
+ {
+ return navigator.Clone ();
+ }
+
+ public XmlNode GetNode ()
+ {
+ return ((IHasXmlNode) navigator).GetNode ();
+ }
+
+ public override bool IsSamePosition (XPathNavigator other)
+ {
+ XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
+ if (nav != null)
+ return navigator.IsSamePosition (nav.navigator);
+ else
+ return navigator.IsSamePosition (nav);
+ }
+
+ public override bool MoveTo (XPathNavigator other)
+ {
+ XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
+ if (nav != null)
+ return navigator.MoveTo (nav.navigator);
+ else
+ return navigator.MoveTo (nav);
+ }
+
+ public override bool MoveToFirstAttribute ()
+ {
+ return navigator.MoveToFirstAttribute ();
+ }
+
+ public override bool MoveToFirstChild ()
+ {
+ return navigator.MoveToFirstChild ();
+ }
+
+ public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
+ {
+ return navigator.MoveToFirstNamespace (scope);
+ }
+
+ public override bool MoveToId (string id)
+ {
+ return navigator.MoveToId (id);
+ }
+
+ public override bool MoveToNext ()
+ {
+ return navigator.MoveToNext ();
+ }
+
+ public override bool MoveToNextAttribute ()
+ {
+ return navigator.MoveToNextAttribute ();
+ }
+
+ public override bool MoveToNextNamespace (XPathNamespaceScope scope)
+ {
+ return navigator.MoveToNextNamespace (scope);
+ }
+
+ public override bool MoveToParent ()
+ {
+ return navigator.MoveToParent ();
+ }
+
+ public override bool MoveToPrevious ()
+ {
+ return navigator.MoveToPrevious ();
+ }
+
+ public override XmlWriter AppendChild ()
+ {
+ XmlNode n = ((IHasXmlNode) navigator).GetNode ();
+ if (n == null)
+ throw new InvalidOperationException ("Should not happen.");
+ return document.CreateInsertionWriter (n, null);
+ }
+
+ public override XmlWriter InsertBefore ()
+ {
+ XmlNode n = ((IHasXmlNode) navigator).GetNode ();
+ return document.CreateInsertionWriter (n.ParentNode, n.PreviousSibling);
+ }
+
+ public override XmlWriter CreateAttributes ()
+ {
+ XmlNode n = ((IHasXmlNode) navigator).GetNode ();
+ return document.CreateInsertionWriter (n, null);
+ }
+
+ public override bool DeleteSelf ()
+ {
+ XmlNode n = ((IHasXmlNode) navigator).GetNode ();
+ if (!navigator.MoveToNext ())
+ navigator.MoveToParent ();
+ return document.DeleteNode (n);
+ }
+
+ public override void SetValue (string value)
+ {
+ XmlNode n = ((IHasXmlNode) navigator).GetNode ();
+ foreach (XmlNode c in n.ChildNodes)
+ document.DeleteNode (c);
+ XmlWriter w = document.CreateInsertionWriter (n, null);
+ // FIXME: Hmm, it does not look like using it.
+ w.WriteValue (value);
+ w.Close ();
+ }
+ }
+}
+
+#endif