[sgen] Restore hazard pointers in suspend signal handler. Fixes #15695.
[mono.git] / mcs / class / System.XML / Mono.Xml.XPath / XPathEditableDocument.cs
index 79bce7a1851f73d0de27489ee77a792edef211ba..1c21cae56243233a0ac587c61787e25b13519841 100644 (file)
@@ -74,7 +74,8 @@ namespace Mono.Xml.XPath
                XmlNode parent;
                XmlNode current;
                XmlNode nextSibling;
-               Stack nodeStack = new Stack ();
+               WriteState state;
+               XmlAttribute attribute;
 
                public XmlDocumentInsertionWriter (XmlNode owner, XmlNode nextSibling)
                {
@@ -96,20 +97,15 @@ namespace Mono.Xml.XPath
                        state = WriteState.Content;
                }
 
-               WriteState state;
-               XmlAttribute attribute;
-
                public override WriteState WriteState {
                        get { return state; }
                }
 
                public override void Close ()
                {
-                       while (nodeStack.Count > 0) {
-                               XmlNode n = nodeStack.Pop () as XmlNode;
-                               n.AppendChild (current);
-                               current = n;
-                       }
+                       while (current.ParentNode != null)
+                               current = current.ParentNode;
+
                        parent.InsertBefore ((XmlDocumentFragment) current, nextSibling);
                        if (Closed != null)
                                Closed (this);
@@ -117,8 +113,6 @@ namespace Mono.Xml.XPath
 
                internal event XmlWriterClosedEventHandler Closed;
 
-               internal XmlNode AppendedFirstChild;
-
                public override void Flush ()
                {
                }
@@ -132,6 +126,8 @@ namespace Mono.Xml.XPath
                {
                        if (state != WriteState.Content)
                                throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
+                       if (prefix == null && ns != null && ns.Length > 0)
+                               prefix = LookupPrefix (ns);
                        attribute = current.OwnerDocument.CreateAttribute (prefix, name, ns);
                        state = WriteState.Attribute;
                }
@@ -156,17 +152,18 @@ namespace Mono.Xml.XPath
 
                public override void WriteStartElement (string prefix, string name, string ns)
                {
+                       if (prefix == null && ns != null && ns.Length > 0)
+                               prefix = LookupPrefix (ns);
                        XmlElement el = current.OwnerDocument.CreateElement (prefix, name, ns);
                        current.AppendChild (el);
-                       nodeStack.Push (current);
                        current = el;
                }
 
                public override void WriteEndElement ()
                {
-                       if (nodeStack.Count == 0)
+                       current = current.ParentNode;
+                       if (current == null)
                                throw new InvalidOperationException ("No element is opened.");
-                       current = nodeStack.Pop () as XmlNode;
                }
 
                public override void WriteFullEndElement ()
@@ -209,7 +206,20 @@ namespace Mono.Xml.XPath
 
                public override void WriteRaw (string raw)
                {
-                       throw new NotSupportedException ();
+                       XmlReader reader = new XmlTextReader(new System.IO.StringReader(raw));
+                       WriteRaw(reader);
+               }
+
+               private void WriteRaw(XmlReader reader)
+               {
+                       if (reader != null && reader.NodeType == XmlNodeType.Element)
+                       {
+                               WriteStartElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
+                               WriteAttributes (reader, true);
+                               WriteRaw (reader.ReadSubtree ());
+                               WriteEndElement ();
+
+                       }
                }
 
                public override void WriteSurrogateCharEntity (char msb, char lsb)
@@ -256,7 +266,10 @@ namespace Mono.Xml.XPath
 
                public override void WriteEndAttribute ()
                {
-                       XmlElement element = current as XmlElement;
+                       // when the writer is for AppendChild() and the root 
+                       // node is element, it allows to write attributes
+                       // (IMHO incorrectly: isn't it append "child" ???)
+                       XmlElement element = (current as XmlElement) ?? (nextSibling == null ? parent as XmlElement : null);
                        if (state != WriteState.Attribute || element == null)
                                throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
                        element.SetAttributeNode (attribute);
@@ -268,6 +281,8 @@ namespace Mono.Xml.XPath
        internal class XmlDocumentAttributeWriter : XmlWriter
        {
                XmlElement element;
+               WriteState state;
+               XmlAttribute attribute;
 
                public XmlDocumentAttributeWriter (XmlNode owner)
                {
@@ -277,9 +292,6 @@ namespace Mono.Xml.XPath
                        state = WriteState.Content;
                }
 
-               WriteState state;
-               XmlAttribute attribute;
-
                public override WriteState WriteState {
                        get { return state; }
                }
@@ -301,6 +313,8 @@ namespace Mono.Xml.XPath
                {
                        if (state != WriteState.Content)
                                throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
+                       if (prefix == null && ns != null && ns.Length > 0)
+                               prefix = LookupPrefix (ns);
                        attribute = element.OwnerDocument.CreateAttribute (prefix, name, ns);
                        state = WriteState.Attribute;
                }
@@ -452,6 +466,10 @@ namespace Mono.Xml.XPath
                        get { return navigator.BaseURI; }
                }
 
+               public override bool CanEdit {
+                       get { return true; }
+               }
+
                public override bool IsEmptyElement {
                        get { return navigator.IsEmptyElement; }
                }
@@ -492,6 +510,18 @@ namespace Mono.Xml.XPath
                        get { return navigator.Value; }
                }
 
+               public override string XmlLang {
+                       get { return navigator.XmlLang; }
+               }
+
+               public override bool HasChildren {
+                       get { return navigator.HasChildren; }
+               }
+
+               public override bool HasAttributes {
+                       get { return navigator.HasAttributes; }
+               }
+
                public override XPathNavigator Clone ()
                {
                        return new XmlDocumentEditableNavigator (this);
@@ -499,7 +529,7 @@ namespace Mono.Xml.XPath
 
                public override XPathNavigator CreateNavigator ()
                {
-                       return navigator.Clone ();
+                       return Clone ();
                }
 
                public XmlNode GetNode ()
@@ -662,11 +692,18 @@ namespace Mono.Xml.XPath
                public override void DeleteSelf ()
                {
                        XmlNode n = ((IHasXmlNode) navigator).GetNode ();
-                       if (!navigator.MoveToNext ())
+                       XmlAttribute a = n as XmlAttribute;
+                       if (a != null) {
+                               if (a.OwnerElement == null)
+                                       throw new InvalidOperationException ("This attribute node cannot be removed since it has no owner element.");
                                navigator.MoveToParent ();
-                       if (n.ParentNode == null)
-                               throw new InvalidOperationException ("This node cannot be removed since it has no parent.");
-                       n.ParentNode.RemoveChild (n);
+                               a.OwnerElement.RemoveAttributeNode (a);
+                       } else {
+                               if (n.ParentNode == null)
+                                       throw new InvalidOperationException ("This node cannot be removed since it has no parent.");
+                               navigator.MoveToParent ();
+                               n.ParentNode.RemoveChild (n);
+                       }
                }
 
                public override void ReplaceSelf (XmlReader reader)
@@ -716,6 +753,54 @@ namespace Mono.Xml.XPath
                                n.RemoveChild (n.FirstChild);
                        n.InnerText = value;
                }
+
+               public override void MoveToRoot ()
+               {
+                       navigator.MoveToRoot ();
+               }
+
+               public override bool MoveToNamespace (string name)
+               {
+                       return navigator.MoveToNamespace (name);
+               }
+
+               public override bool MoveToFirst ()
+               {
+                       return navigator.MoveToFirst ();
+               }
+
+               public override bool MoveToAttribute (string localName, string namespaceURI)
+               {
+                       return navigator.MoveToAttribute (localName, namespaceURI);
+               }
+
+               public override bool IsDescendant (XPathNavigator nav)
+               {
+                       XmlDocumentEditableNavigator e = nav as XmlDocumentEditableNavigator;
+                       if (e != null)
+                               return navigator.IsDescendant (e.navigator);
+                       else
+                               return navigator.IsDescendant (nav);
+               }
+
+               public override string GetNamespace (string name)
+               {
+                       return navigator.GetNamespace (name);
+               }
+
+               public override string GetAttribute (string localName, string namespaceURI)
+               {
+                       return navigator.GetAttribute (localName, namespaceURI);
+               }
+
+               public override XmlNodeOrder ComparePosition (XPathNavigator nav)
+               {
+                       XmlDocumentEditableNavigator e = nav as XmlDocumentEditableNavigator;
+                       if (e != null)
+                               return navigator.ComparePosition (e.navigator);
+                       else
+                               return navigator.ComparePosition (nav);
+               }
        }
 }