| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- //
- // Mono.Xml.XPath.XPathDocument2Editable
- //
- // Author:
- // Atsushi Enomoto <[email protected]>
- //
- // (C)2004 Novell Inc.
- //
- // Yet another implementation of XPathEditableNavigator.
- // (Even runnable under MS.NET 2.0)
- //
- //
- // 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 Driver
- {
- public static void Main ()
- {
- try {
- #if true
- XPathDocument2 doc = new XPathDocument2 ();
- XPathDocument2Editable pd = new XPathDocument2Editable (doc);
- XPathEditableNavigator nav = pd.CreateEditor ();
- IChangeTracking xp = pd;
- #else
- XPathDocument doc = new XPathDocument ();
- XPathEditableNavigator nav = doc.CreateEditor ();
- 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.DeleteCurrent (); // delete foo
- Console.WriteLine (nav.Name);
- nav.MoveToNext ();
- Console.WriteLine (nav.Name);
- Console.WriteLine (nav.MoveToFirstAttribute ());
- nav.DeleteCurrent (); // delete fuga
- doc.Save (Console.Out);
- } catch (Exception ex) {
- Console.WriteLine (ex);
- }
- }
- }
- */
- public class XPathDocument2Editable
- : IXPathNavigable, IXPathEditable,
- IRevertibleChangeTracking, IChangeTracking, IXmlSerializable
- {
- XPathDocument2 document;
- ArrayList changes = new ArrayList ();
- bool enableChangeTracking;
- public XPathDocument2Editable (XPathDocument2 doc)
- {
- document = doc;
- }
- #region Events
- public event NodeChangedEventHandler ChangeRejected;
- public event NodeChangedEventHandler ItemUpdated;
- public event NodeChangedEventHandler ItemUpdating;
- public event NodeChangedEventHandler ItemInserted;
- public event NodeChangedEventHandler ItemInserting;
- public event NodeChangedEventHandler ItemDeleted;
- public event NodeChangedEventHandler ItemDeleting;
- public event NodeChangedEventHandler RejectingChange;
- #endregion // Events
- public XmlNameTable NameTable {
- get { return document.NameTable; }
- }
- public XPathNavigator CreateNavigator ()
- {
- return document.CreateNavigator ();
- }
- public XPathEditableNavigator CreateEditor ()
- {
- return new XomEditableNavigator (this);
- }
- public XmlWriter CreateWriter ()
- {
- return CreateEditor ().AppendChild ();
- }
- public bool HasChanges ()
- {
- return IsChanged;
- }
- public bool EnableChangeTracking {
- get { return enableChangeTracking; }
- set { enableChangeTracking = value; }
- }
- #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--) {
- Insertion2 ins = changes [i] as Insertion2;
- if (ins != null) {
- ins.ParentNode.RemoveChild (ins.InsertedNode);
- continue;
- }
-
- Removal2 rem = changes [i] as Removal2;
- if (rem != null) {
- if (rem.RemovedNode.NodeType == XPathNodeType.Attribute) {
- XomElement el = (XomElement) rem.OwnerNode;
- el.UpdateAttribute ((XomAttribute) rem.RemovedNode);
- }
- else
- rem.OwnerNode.InsertBefore (rem.RemovedNode, rem.NextSibling);
- continue;
- }
- AttributeUpdate2 au = changes [i] as AttributeUpdate2;
- if (au != null) {
- if (au.OldAttribute != null)
- au.Element.UpdateAttribute (au.OldAttribute);
- else
- au.Element.RemoveAttribute (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 (XomNode node)
- {
- Removal2 rem = new Removal2 ();
- if (node.NodeType == XPathNodeType.Attribute) {
- XomAttribute attr = node as XomAttribute;
- rem.OwnerNode = attr.Parent;
- rem.RemovedNode = node;
- ((XomElement) attr.Parent).RemoveAttribute (attr);
- return false;
- } else {
- rem.OwnerNode = node.Parent;
- rem.NextSibling = node.NextSibling;
- rem.RemovedNode = node;
- node.Parent.RemoveChild (node);
- return rem.NextSibling != null;
- }
- }
- internal XmlWriter CreateInsertionWriter (XomNode owner, XomNode previousSibling)
- {
- return new XPathDocument2InsertionWriter (owner, previousSibling, this);
- }
- internal XmlWriter CreateAttributesWriter (XomNode owner)
- {
- return new XPathDocument2AttributeWriter (owner, this);
- }
- internal void AttributeUpdate2 (XomElement element, XomAttribute oldAttr, XomAttribute newAttr)
- {
- AttributeUpdate2 au = new AttributeUpdate2 ();
- au.Element = element;
- au.OldAttribute = oldAttr;
- au.NewAttribute = newAttr;
- changes.Add (au);
- }
-
- internal void AppendChild (XomParentNode parent, XomNode child)
- {
- Insertion2 ins = new Insertion2 ();
- ins.ParentNode = parent;
- ins.InsertedNode = child;
- changes.Add (ins);
- }
- }
- public class XPathDocument2InsertionWriter : XmlWriter
- {
- XomNode current;
- XomNode previousSibling;
- XPathDocument2Editable document;
- Stack nodeStack = new Stack ();
- public XPathDocument2InsertionWriter (XomNode owner, XomNode previousSibling, XPathDocument2Editable doc)
- {
- this.current = (XomNode) owner;
- if (current == null)
- throw new InvalidOperationException ();
- this.previousSibling = previousSibling;
- this.document = doc;
- state = WriteState.Content;
- }
- WriteState state;
- XomAttribute attribute;
- public override WriteState WriteState {
- get { return state; }
- }
- public override void Close ()
- {
- }
- public override void Flush ()
- {
- }
- public override string LookupPrefix (string ns)
- {
- return current.LookupPrefix (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 = new XomAttribute (prefix, name, ns, String.Empty);
- state = WriteState.Attribute;
- }
- public override void WriteProcessingInstruction (string name, string value)
- {
- XomParentNode p = current as XomParentNode;
- if (p == null)
- throw new InvalidOperationException ("Current writer node cannot have a child.");
- XomPI pi = new XomPI (name, value);
- p.AppendChild (pi);
- document.AppendChild (p, pi);
- }
- public override void WriteComment (string text)
- {
- XomParentNode p = current as XomParentNode;
- if (p == null)
- throw new InvalidOperationException ("Current writer node cannot have a child.");
- XomComment comment = new XomComment (text);
- p.AppendChild (comment);
- document.AppendChild (p, comment);
- }
- public override void WriteCData (string text)
- {
- if (attribute != null)
- throw new InvalidOperationException ("Current writer node is attribute. It cannot accept CDATA section.");
- /*
- XomParentNode p = current as XomParentNode;
- if (p == null)
- throw new InvalidOperationException ("Current writer node cannot have a child.");
- XomText cdata = new XomText (text);
- p.AppendChild (cdata);
- document.AppendChild (p, cdata);
- */
- WriteString (text);
- }
- public override void WriteStartElement (string prefix, string name, string ns)
- {
- XomParentNode p = current as XomParentNode;
- if (p == null)
- throw new InvalidOperationException ("Current writer node cannot have a child.");
- XomElement el = new XomElement (prefix, name, ns);
- p.AppendChild (el);
- document.AppendChild (p, el);
- nodeStack.Push (current);
- current = el;
- }
- public override void WriteEndElement ()
- {
- WriteFullEndElement ();
- XomElement el = current as XomElement;
- if (el != null && el.ChildCount == 0)
- el.SetIsEmpty (true);
- }
- public override void WriteFullEndElement ()
- {
- if (nodeStack.Count == 0)
- throw new InvalidOperationException ("No element is opened.");
- current = nodeStack.Pop () as XomNode;
- }
- 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)
- {
- throw new NotSupportedException ();
- }
- 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 {
- XomParentNode p = current as XomParentNode;
- if (p == null)
- throw new InvalidOperationException ("Current writer node cannot have a child.");
- XomText xt = new XomText (text);
- p.AppendChild (xt);
- document.AppendChild (p, xt);
- }
- }
- public override void WriteWhitespace (string text)
- {
- if (attribute != null)
- attribute.Value += text;
- else {
- XomParentNode p = current as XomParentNode;
- if (p == null)
- throw new InvalidOperationException ("Current writer node cannot have a child.");
- XomWhitespace ws = new XomWhitespace (text);
- p.AppendChild (ws);
- document.AppendChild (p, ws);
- }
- }
- public override void WriteEndAttribute ()
- {
- XomElement element = current as XomElement;
- if (state != WriteState.Attribute || element == null)
- throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
- XomAttribute old = element.GetAttribute (attribute.LocalName, attribute.Namespace);
- element.UpdateAttribute (attribute);
- document.AttributeUpdate2 (element, old, attribute);
- attribute = null;
- state = WriteState.Content;
- }
- }
- public class XPathDocument2AttributeWriter : XmlWriter
- {
- XomElement element;
- XPathDocument2Editable document;
- public XPathDocument2AttributeWriter (XomNode owner, XPathDocument2Editable doc)
- {
- element = owner as XomElement;
- if (element == null)
- throw new ArgumentException ("To write attributes, current node must be an element.");
- state = WriteState.Content;
- document = doc;
- }
- WriteState state;
- XomAttribute attribute;
- public override WriteState WriteState {
- get { return state; }
- }
- public override void Close ()
- {
- }
- public override void Flush ()
- {
- }
- public override string LookupPrefix (string ns)
- {
- return element.LookupPrefix (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 = new XomAttribute (prefix, name, ns, String.Empty);
- 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)
- {
- throw new NotSupportedException ();
- }
- 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.");
- else
- attribute.Value += text;
- }
- public override void WriteEndAttribute ()
- {
- if (state != WriteState.Attribute)
- throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
- XomAttribute old = element.GetAttribute (attribute.LocalName, attribute.Namespace);
- element.UpdateAttribute (attribute);
- document.AttributeUpdate2 (element, old, attribute);
- attribute = null;
- state = WriteState.Content;
- }
- }
- public class Insertion2
- {
- // AppendChild : last child / true
- // InsertBefore : current node / false
- // InsertAfter : current node / true
- // PrependChild : first child / false
- public XomParentNode ParentNode;
- public XomNode InsertedNode;
- public bool Afterward;
- }
- public class Removal2
- {
- public XomParentNode OwnerNode;
- public XomNode NextSibling;
- public XomNode RemovedNode;
- }
- public class AttributeUpdate2
- {
- public XomElement Element;
- public XomAttribute NewAttribute;
- public XomAttribute OldAttribute;
- }
- public class XomEditableNavigator : XPathEditableNavigator, IHasXomNode
- {
- XPathDocument2Editable document;
- XPathNavigator navigator;
- public XomEditableNavigator (XPathDocument2Editable doc)
- {
- document = doc;
- navigator = doc.CreateNavigator ();
- }
- public XomEditableNavigator (XomEditableNavigator 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 XomEditableNavigator (this);
- }
- public override XPathNavigator CreateNavigator ()
- {
- return navigator.Clone ();
- }
- public XomNode GetNode ()
- {
- return ((IHasXomNode) navigator).GetNode ();
- }
- public override bool IsSamePosition (XPathNavigator other)
- {
- XomEditableNavigator nav = other as XomEditableNavigator;
- if (nav != null)
- return navigator.IsSamePosition (nav.navigator);
- else
- return navigator.IsSamePosition (nav);
- }
- public override bool MoveTo (XPathNavigator other)
- {
- XomEditableNavigator nav = other as XomEditableNavigator;
- 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 void Validate (XmlSchemaSet schemas, ValidationEventHandler handler)
- {
- throw new NotImplementedException ();
- /*
- // FIXME: use handler
- XmlReaderSettings settings = new XmlReaderSettings ();
- settings.Schemas.Add (schemas);
- settings.NameTable = this.NameTable;
- settings.XsdValidate = true;
- settings.DtdValidate = false;
- XmlReader xvr = XmlReader.Create (new XPathNavigatorReader (this), settings);
- while (!xvr.EOF)
- xvr.Read ();
- */
- }
- public override XmlWriter AppendChild ()
- {
- XomNode n = ((IHasXomNode) navigator).GetNode ();
- if (n == null)
- throw new InvalidOperationException ("Should not happen.");
- return document.CreateInsertionWriter (n, null);
- }
- public override XmlWriter InsertBefore ()
- {
- XomNode n = ((IHasXomNode) navigator).GetNode ();
- return document.CreateInsertionWriter (n.Parent, n.PreviousSibling);
- }
- public override XmlWriter CreateAttributes ()
- {
- XomNode n = ((IHasXomNode) navigator).GetNode ();
- return document.CreateInsertionWriter (n, null);
- }
- public override bool DeleteCurrent ()
- {
- XomNode n = ((IHasXomNode) navigator).GetNode ();
- if (!navigator.MoveToNext ())
- navigator.MoveToParent ();
- return document.DeleteNode (n);
- }
- public override void SetValue (object value)
- {
- XomNode n = ((IHasXomNode) navigator).GetNode ();
- int count = n.ChildCount;
- for (int i = 0; i < count; i++)
- document.DeleteNode (n.GetChild (i));
- XmlWriter w = document.CreateInsertionWriter (n, null);
- // FIXME: Hmm, it does not look like using it.
- w.WriteFromObject (value);
- w.Close ();
- }
- }
- }
- #endif
|