[gxml] DOM4: Step 1: Implement DomNode by GNode



commit 5a720864171bbdfa05958b4d774c6310bc996a1f
Author: Daniel Espinosa <esodan gmail com>
Date:   Fri May 6 22:20:19 2016 -0500

    DOM4: Step 1: Implement DomNode by GNode
    
    * DomNode API addaptions for node_type() and compare_document_position()
    * Implementing DomNode by GNode
    * Implementing GListChildren.insert() and .remove_at() to implement
      DomNode.insert_before() and others

 gxml/DomNode.vala          |   29 ++++---
 gxml/GXmlListChildren.vala |   22 ++++-
 gxml/GXmlNode.vala         |  182 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 215 insertions(+), 18 deletions(-)
---
diff --git a/gxml/DomNode.vala b/gxml/DomNode.vala
index b11a79c..c012582 100644
--- a/gxml/DomNode.vala
+++ b/gxml/DomNode.vala
@@ -33,12 +33,12 @@ public interface GXml.DomNode : GLib.Object, GXml.DomEventTarget {
   public const ushort DOCUMENT_TYPE_NODE = 10;
   public const ushort DOCUMENT_FRAGMENT_NODE = 11;
   public const ushort NOTATION_NODE = 12; // historical
-  public abstract ushort node_type { get; }
+  public abstract GXml.NodeType node_type { get; }
   public abstract string node_name { get; }
 
-  public abstract string? baseURI { get; }
+  public abstract string? base_uri { get; }
 
-  public abstract Document? owner_document { get; }
+  public abstract DomDocument? owner_document { get; }
   public abstract DomNode? parent_node { get; }
   public abstract DomElement? parent_element { get; }
   public abstract DomNodeList child_nodes { get; }
@@ -56,23 +56,26 @@ public interface GXml.DomNode : GLib.Object, GXml.DomEventTarget {
   public abstract DomNode clone_node (bool deep = false);
   public abstract bool is_equal_node (DomNode? node);
 
-  public const ushort DOCUMENT_POSITION_DISCONNECTED = 0x01;
-  public const ushort DOCUMENT_POSITION_PRECEDING = 0x02;
-  public const ushort DOCUMENT_POSITION_FOLLOWING = 0x04;
-  public const ushort DOCUMENT_POSITION_CONTAINS = 0x08;
-  public const ushort DOCUMENT_POSITION_CONTAINED_BY = 0x10;
-  public const ushort DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
-  public abstract ushort compare_document_position (DomNode other);
+  [Flags]
+  public enum DocumenPosition {
+    DISCONNECTED,
+    PRECEDING,
+    FOLLOWING,
+    CONTAINS,
+    CONTAINED_BY,
+    IMPLEMENTATION_SPECIFIC
+  }
+  public abstract DocumenPosition compare_document_position (DomNode other);
   public abstract bool contains (DomNode? other);
 
-  public abstract string? lookup_prefix(string? namespace);
+  public abstract string? lookup_prefix (string? nspace);
   public abstract string? lookup_namespace_uri (string? prefix);
-  public abstract bool is_default_namespace(string? namespace);
+  public abstract bool is_default_namespace (string? nspace);
 
   public abstract DomNode insert_before (DomNode node, DomNode? child);
   public abstract DomNode append_child (DomNode node);
   public abstract DomNode replace_child (DomNode node, DomNode child);
-  public abstract DomNode remove_child(DomNode child);
+  public abstract DomNode remove_child (DomNode child);
 }
 
 public errordomain GXml.DomError {
diff --git a/gxml/GXmlListChildren.vala b/gxml/GXmlListChildren.vala
index 072b879..c864cad 100644
--- a/gxml/GXmlListChildren.vala
+++ b/gxml/GXmlListChildren.vala
@@ -25,7 +25,7 @@ using Gee;
 /**
  * A {@link Gee.AbstractBidirList} implementation to access {@link Xml.Node} collection
  */
-public class GXml.GListChildren : AbstractBidirList<GXml.Node>
+public class GXml.GListChildren : AbstractBidirList<GXml.Node>, DomNodeList
 {
   private GXml.GDocument _doc;
   private Xml.Node *_node;
@@ -65,14 +65,23 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
     return -1;
   }
   /**
-   * This method is ignored by default.
+   * Insert @item before @index
    */
-  public override void insert (int index, GXml.Node item) {}
+  public override void insert (int index, GXml.Node item) {
+    var n = @get (index);
+    if (n == null) return;
+    n.get_internal_node ()->add_prev_sibling (item.get_internal_node ());
+  }
   public override  Gee.ListIterator<GXml.Node> list_iterator () { return new Iterator (_doc, _node); }
   /**
-   * This method is ignored by default.
+   * Removes a node at @index
    */
-  public override GXml.Node remove_at (int index) { return null; }
+  public override GXml.Node remove_at (int index) {
+    var n = @get (index);
+    if (n == null) return null;
+    n.get_internal_node ()->unlink_node ();
+    return n;
+  }
   /**
    * This method is ignored by default.
    */
@@ -240,5 +249,8 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
       return true;
     }
   }
+  // DomNodeList implementation
+  public DomNode? item (ulong index) { return (DomNode) @get ((int) index); }
+  public ulong length { get { return (ulong) size; } }
 }
 
diff --git a/gxml/GXmlNode.vala b/gxml/GXmlNode.vala
index c219553..e7ed183 100644
--- a/gxml/GXmlNode.vala
+++ b/gxml/GXmlNode.vala
@@ -104,5 +104,187 @@ public abstract class GXml.GNode : Object, GXml.Node
     }
     return null;
   }
+  // DomNode Implementation
+  public string node_name { get { return name; } }
+
+  protected string _base_uri = null;
+  public string? base_uri { get { return _base_uri; } }
+
+  public DomDocument? owner_document { get { return document; } }
+  public DomNode? parent_node { get { return parent; } }
+  public DomElement? parent_element {
+    get {
+      if (parent is DomElement) return parent;
+      return null;
+    }
+  }
+  public DomNodeList child_nodes { get { return children; } }
+  public DomNode? first_child { get { return children.itirator ().first (); } }
+  public DomNode? last_child { get { return children.itirator ().last (); } }
+  public DomNode? previous_sibling {
+    get {
+      if (_node == null) return null;
+      if (_node->prev == null) return null;
+      return GNode.to_gnode (_doc, _node->prev);
+    }
+  }
+  public DomNode? next_sibling {
+    get {
+      if (_node == null) return null;
+      if (_node->next == null) return null;
+      return GNode.to_gnode (_doc, _node->next);
+    }
+  }
+
+       public string? node_value { get { return @value; } set { this.@value = value; } }
+       public string? text_content {
+         get {
+           string t = null;
+           if (this is GXml.Text) return this.@value;
+           if (this is GXml.ProcessingInstruction) return this.@value;
+           if (this is GXml.Comment) return this.@value;
+           if (this is GXml.Document || this is GXml.Element) {
+             foreach (GXml.Node n in children) {
+          if (n is GXml.Text) {
+            if (t == null) t = n.value;
+            else t += n.value;
+          }
+             }
+           }
+           return t;
+         }
+         set {
+      if (this is GXml.Document || this is GXml.Element) {
+        var t = this.document.create_text (value);
+        this.document.add (t);
+      }
+      if (!(this is GXml.Text || this is GXml.Comment || this is GXml.ProcessingInstruction)) return;
+      this.@value = value;
+         }
+       }
+
+  public bool has_child_nodes () { return (children.size > 0); }
+  public void normalize () {
+    GXml.Text t = null;
+    int[] r = {};
+    for (int i = 0; i < children.size; i++) {
+      var n = children.get (i);
+      if (n is GXml.DomText) {
+        if ((t as GXml.DomText).length == 0) {
+          r += i;
+          continue;
+        }
+        if (t == null) {
+          t = n;
+          continue;
+        } else {
+          t.@value += n.value;
+        }
+      }
+    }
+    foreach (int j in r) {
+      children.remove_at (j);
+    }
+  }
+
+  public DomNode clone_node (bool deep = false) {
+    Xml.Node *n = null;
+    if (deep)
+      n = _node->copy_node (2);
+    else
+      n = _node->copy_prop_list (_node->properties);
+    if (n == null) return null;
+    return Node.to_gnode (_doc, n);
+  }
+  public bool is_equal_node (DomNode? node) {
+    if (node == null) return false;
+    if (this.children.size != node.children.size) return false;
+    foreach (Attribute a in attrs.values) {
+      if (!node.attrs.has_key (a.name)) return false;
+      if (a.value != node.attrs.get (a.name).value) return false;
+    }
+    for (int i=0; i < children.size; i++) {
+      if (!children[i].is_equal_node (node.children[i])) return false;
+    }
+  }
+
+  public DocumenPosition compare_document_position (DomNode other) {
+    if (this == other) return (DocumenPosition) 0;
+    if (this.document != (other as GXml.Node).document)
+      return DocumenPosition.DISCONNECTED & DocumenPosition.IMPLEMENTATION_SPECIFIC
+              & (this > other) ? DocumentPosition.PRECEDING : DocumentPosition.FOLLOWING;
+    if (other.parent == this)
+      return DocumenPosition.CONTAINS & DocumenPosition.PRECEDING;
+    if (this.parent == other)
+      return DocumenPosition.CONTAINED_BY & DocumenPosition.FOLLOWING;
+    if (other < this) return DocumenPosition.PRECEDING;
+    return DocumenPosition.FOLLOWING;
+  }
+  public bool contains (DomNode? other) {
+    if (other == null) return false;
+    if (other == this) return true;
+    if (other.parent == this) return true;
+    return false;
+  }
+
+  public string? lookup_prefix (string? nspace) {
+    if (parent == null) return null;
+    if (this is GXml.DocumentType || this is GXml.DocumentFragment) return null;
+    if (this is GXml.Document)
+      if ((this as GXml.Document).root != null)
+        return (document.root as DomNode).lookup_prefix (nspace);
+      else
+        return null;
+    if (this is GXml.Element) {
+      if (namespaces.size > 0) {
+        var ns = namespaces[0];
+        if (ns.prefix == nspace) return ns.uri;
+        else return null;
+      }
+    }
+    return this.parent.lookup_prefix (nspace);
+  }
+  public string? lookup_namespace_uri (string? prefix) {
+    if (prefix == null) return null;
+    if (this is GXml.DocumentType || this is GXml.DocumentFragment) return null;
+    if (this is GXml.Document)
+      if ((this as GXml.Document).root != null)
+        return (document.root as DomNode).lookup_namespace_uri (prefix);
+      else
+        return null;
+    if (this is GXml.Element) {
+      if (namespaces.size > 0) {
+        var ns = namespaces[0];
+        if (ns.prefix == nspace) return ns.uri;
+        else return null;
+      }
+    }
+    return this.parent.lookup_namespace_uri (prefix);
+  }
+  public bool is_default_namespace (string? nspace) {
+    if (nspace == null) return false;
+    var ns = lookup_namespace_uri (null);
+    if (ns == nspace) return true;
+    return false;
+  }
+
+  public DomNode insert_before (DomNode node, DomNode? child) {
+    int i = children.index_of (child);
+    children.insert (i, node);
+    return node;
+  }
+  public DomNode append_child (DomNode node) {
+    children.add (node);
+    return node;
+  }
+  public DomNode replace_child (DomNode node, DomNode child) {
+    int i = children.index_of (child);
+    children.remove_at (i);
+    children.insert (node, i);
+  }
+  public DomNode remove_child (DomNode child) {
+    int i = children.index_of (child);
+    return children.remove_at (i);
+  }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]