[gxml] API change: most methods now returns owned values



commit b5f55ca777ee1cddfb68b99965653c7350af9b6c
Author: Daniel Espinosa <esodan gmail com>
Date:   Thu Feb 4 18:27:01 2016 -0600

    API change: most methods now returns owned values
    
    * Change required for GNode series implementation, due to
      use internal pointer managed by libmxl2, then objects
      are created when needed no reference is kept
    
    * All implementations ported to new API on GXml.Node*
    
    * TwDocument.write_document now support any GXml.Document
    
    * Added initial tests for HtmlDocument, actualy failing
      on search elements with given "id"

 gxml/Document.vala                  |    2 +-
 gxml/GXmlAttribute.vala             |    3 +-
 gxml/GXmlCDATA.vala                 |    8 +-
 gxml/GXmlComment.vala               |    8 +-
 gxml/GXmlDocument.vala              |  325 +++++------------------------------
 gxml/GXmlElement.vala               |    7 +-
 gxml/GXmlHashMapAttr.vala           |   24 ++-
 gxml/GXmlListChildren.vala          |   20 ++-
 gxml/GXmlListNamespaces.vala        |    4 +-
 gxml/GXmlNode.vala                  |   22 ++--
 gxml/GXmlProcessingInstruction.vala |    3 +-
 gxml/GXmlText.vala                  |    8 +-
 gxml/Node.vala                      |   16 ++-
 gxml/TwDocument.vala                |   51 ++++---
 gxml/libxml-ChildNodeList.vala      |    5 +-
 gxml/xlibxml.c                      |    6 +-
 gxml/xlibxml.h                      |    6 +-
 test/GXmlTest.vala                  |    1 +
 test/Makefile.am                    |    1 +
 19 files changed, 169 insertions(+), 351 deletions(-)
---
diff --git a/gxml/Document.vala b/gxml/Document.vala
index 2141b73..4d0d798 100644
--- a/gxml/Document.vala
+++ b/gxml/Document.vala
@@ -73,7 +73,7 @@ public interface GXml.Document : Object, GXml.Node
    * Is a matter of you to add as a child to any other
    * { link GXml.Node}.
    */
-  public abstract GXml.Node create_element (string name);
+  public abstract GXml.Node create_element (string name) throws GLib.Error;
   /**
    * Creates a new { link GXml.Text}.
    *
diff --git a/gxml/GXmlAttribute.vala b/gxml/GXmlAttribute.vala
index 5895e60..4963767 100644
--- a/gxml/GXmlAttribute.vala
+++ b/gxml/GXmlAttribute.vala
@@ -27,10 +27,11 @@ using Gee;
 public class GXml.GAttribute : GXml.GNode, GXml.Attribute
 {
   private Xml.Attr* _attr;
-  public GAttribute (Xml.Attr *node)
+  public GAttribute (GDocument doc, Xml.Attr *node)
   {
     _attr = node;
     _node = _attr->parent;
+    _doc = doc;
   }
   public Namespace @namespace {
     owned get {
diff --git a/gxml/GXmlCDATA.vala b/gxml/GXmlCDATA.vala
index 7d91061..61d357d 100644
--- a/gxml/GXmlCDATA.vala
+++ b/gxml/GXmlCDATA.vala
@@ -26,9 +26,15 @@ using Gee;
  */
 public class GXml.GCDATA : GXml.GNode, GXml.CDATA
 {
-  public GCDATA (Xml.Node *node)
+  public GCDATA (GDocument doc, Xml.Node *node)
   {
     _node = node;
+    _doc = doc;
+  }
+  public override string name {
+    owned get {
+      return "#cdata-section".dup ();
+    }
   }
   // GXml.CDATA
   public string str { owned get { return base.value; } }
diff --git a/gxml/GXmlComment.vala b/gxml/GXmlComment.vala
index 2927b6e..f3fe50f 100644
--- a/gxml/GXmlComment.vala
+++ b/gxml/GXmlComment.vala
@@ -26,9 +26,15 @@ using Gee;
  */
 public class GXml.GComment : GXml.GNode, GXml.Comment
 {
-  public GComment (Xml.Node *node)
+  public GComment (GDocument doc, Xml.Node *node)
   {
     _node = node;
+    _doc = doc;
+  }
+  public override string name {
+    owned get {
+      return "#comment".dup ();
+    }
   }
   // GXml.Comment
   public string str { owned get { return base.value; } }
diff --git a/gxml/GXmlDocument.vala b/gxml/GXmlDocument.vala
index 62c0892..110829d 100644
--- a/gxml/GXmlDocument.vala
+++ b/gxml/GXmlDocument.vala
@@ -52,15 +52,25 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
     this.from_string ((string) b.data, options);
   }
 
-  public GDocument.from_string (string str, int options = 0) {
+  public GDocument.from_string (string str, int options = 0) throws GLib.Error {
     Xmlx.reset_last_error ();
     doc = Xml.Parser.parse_memory (str, (int) str.length);
+    var e = Xmlx.get_last_error ();
+    if (e != null) {
+      var errmsg = "Parser Error for string";
+      string s = libxml2_error_to_string (e);
+      if (s != null)
+        errmsg = ".  ";
+      throw new GXml.Error.PARSER (errmsg);
+    }
     if (doc == null)
       doc = new Xml.Doc ();
   }
-  public GDocument.from_stream (GLib.InputStream istream) {
+  public GDocument.from_stream (GLib.InputStream istream) throws GLib.Error {
     var b = new MemoryOutputStream.resizable ();
     b.splice (istream, 0);
+    if (b.data == null)
+      throw new DocumentError.INVALID_DOCUMENT_ERROR ("stream doesn't provide data'");
     this.from_string ((string) b.data);
   }
   public GDocument.from_doc (Xml.Doc doc) { this.doc = doc; }
@@ -74,6 +84,10 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
     }
     return false;
   }
+  // GXml.Node
+  public override Gee.Map<string,GXml.Node> attrs { owned get { return new GHashMapAttr (this, _node); } }
+  public override Gee.BidirList<GXml.Node> children { owned get { return new GListChildren (this, _node); } }
+  public override Gee.List<GXml.Namespace> namespaces { owned get { return new GListNamespaces (this, 
_node); } }
   public override GXml.Document document { get { return this; } }
   // GXml.Document
   public bool indent { get; set; default = false; }
@@ -98,264 +112,42 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
           GLib.warning ("Document have more than one root GXmlElement. Using first found");
         }
       } 
-      return new GElement (r);
+      return new GElement (this, r);
     }
   }
   public GXml.Node create_comment (string text)
   {
     var c = doc->new_comment (text);
-    return new GComment (c);
+    return new GComment (this, c);
   }
   public GXml.Node create_pi (string target, string data)
   {
     var pi = doc->new_pi (target, data);
-    return new GProcessingInstruction (pi);
+    return new GProcessingInstruction (this, pi);
   }
-  public GXml.Node create_element (string name)
+  public GXml.Node create_element (string name) throws GLib.Error
   {
-    var e = doc->new_raw_node (null, name, null);
-    return new GElement (e);
+    Xmlx.reset_last_error ();
+    var el = doc->new_raw_node (null, name, null);
+    var e = Xmlx.get_last_error ();
+    if (e != null) {
+      var errmsg = "Parser Error for string";
+      string s = libxml2_error_to_string (e);
+      if (s != null)
+        errmsg = ".  ";
+      throw new GXml.Error.PARSER (errmsg);
+    }
+    return new GElement (this, el);
   }
   public GXml.Node create_text (string text)
   {
     var t = doc->new_text (text);
-    return new GText (t);
+    return new GText (this, t);
   }
   public GXml.Node create_cdata (string text)
   {
     var cd = doc->new_cdata_block (text, text.length);
-    return new GCDATA (cd);
-  }
-  public bool save (GLib.Cancellable? cancellable = null)
-    throws GLib.Error
-    requires (file != null)
-  {
-    return save_as (file, cancellable);
-  }
-  public bool save_as (GLib.File f, GLib.Cancellable? cancellable = null)
-  {
-    var buf = new Xml.Buffer ();
-    var tw = Xmlx.new_text_writer_memory (buf, 0);
-    GLib.Test.message ("Writing down to buffer");
-    write_document (tw);
-    GLib.Test.message ("Writing down to file");
-    GLib.Test.message ("TextWriter buffer:\n"+buf.content ());
-    var s = new GLib.StringBuilder ();
-    s.append (buf.content ());
-    try {
-      GLib.Test.message ("Writing down to file: Creating input stream");
-      var b = new GLib.MemoryInputStream.from_data (s.data, null);
-      GLib.Test.message ("Writing down to file: Replacing with backup");
-      var ostream = f.replace (null, backup, GLib.FileCreateFlags.NONE, cancellable);
-      ostream.splice (b, GLib.OutputStreamSpliceFlags.NONE);
-      ostream.close ();
-    } catch (GLib.Error e) {
-      GLib.warning ("Error on Save to file: "+e.message);
-      return false;
-    }
-    return true;
-  }
-  public virtual void write_document (Xml.TextWriter tw)
-  {
-    tw.start_document ();
-    tw.set_indent (indent);
-    // Root
-    if (root == null) {
-      tw.end_document ();
-    }
-    var dns = new ArrayList<string> ();
-#if DEBUG
-    GLib.message ("Starting writting Document Root node");
-#endif
-    start_node (tw, root, true, ref dns);
-#if DEBUG
-    GLib.message ("Ending writting Document Root node");
-#endif
-    tw.end_element ();
-#if DEBUG
-    GLib.message ("Ending Document");
-#endif
-    tw.end_document ();
-    tw.flush ();
-  }
-  public virtual void start_node (Xml.TextWriter tw, GXml.Node node, bool root, ref Gee.ArrayList<string> 
declared_ns)
-  {
-    int size = 0;
-#if DEBUG
-    GLib.message (@"Starting Node: start Node: '$(node.name)'");
-#endif
-    if (node is GXml.Element) {
-#if DEBUG
-    GLib.message (@"Starting Element... '$(node.name)'");
-    GLib.message (@"Element Document is Null... '$((node.document == null).to_string ())'");
-    GLib.message (@"Namespaces in Element... '$(node.namespaces.size)'");
-#endif
-      if (root) {
-        if (node.document.namespaces.size > 0) {
-          var dns = node.document.namespaces.get (0);
-          assert (dns != null);
-          if (prefix_default_ns) {
-            tw.start_element_ns (dns.prefix, node.name, dns.uri);
-            declared_ns.add (dns.uri);
-#if DEBUG
-              GLib.message (@"Declared NS: '$(dns.uri)' Total declared = $(declared_ns.size.to_string ())");
-#endif
-          }
-          else {
-            tw.start_element (node.name);
-            if (dns.prefix == null)
-              tw.write_attribute ("xmlns",dns.uri);// Write default namespace no prefix
-            else
-              tw.write_attribute ("xmlns:"+dns.prefix,dns.uri);
-            // Add to declared namespaces
-            declared_ns.add (dns.uri);
-#if DEBUG
-              GLib.message (@"Declared NS: $(dns.uri) Total declared = $(declared_ns.size.to_string ())");
-#endif
-          }
-          if (node.document.namespaces.size > 1 && node.document.ns_top) {
-            for (int i = 1; i < node.document.namespaces.size; i++) {
-              GXml.Namespace ns = node.document.namespaces.get (i);
-              if (ns.prefix == null) continue;
-              tw.write_attribute ("xmlns:"+ns.prefix, ns.uri);
-              declared_ns.add (ns.uri);
-#if DEBUG
-              GLib.message (@"Declared NS: '$(ns.uri)' Total declared = $(declared_ns.size.to_string ())");
-#endif
-            }
-          }
-        }
-        else
-          tw.start_element (node.name);
-      }
-      else {
-        if (node.namespaces.size > 0) {
-#if DEBUG
-      GLib.message (@"Starting Element: '$(node.name)' start with NS");
-#endif
-          if (node.document.ns_uri () == node.ns_uri ()) {
-#if DEBUG
-      GLib.message (@"Node '$(node.name)' Have Default NS");
-#endif
-            if (node.document.prefix_default_ns)  // Default NS at root element
-              tw.start_element_ns (node.ns_prefix (), node.name, null);
-            else // Don't prefix. Using default namespace and prefix_default_ns = false
-              tw.start_element (node.name);
-          }
-          else {
-#if DEBUG
-      GLib.message (@"No default NS in use for Node '$(node.name)'. Ns = '$(node.ns_uri ())'");
-#endif
-            if (node.ns_prefix () == null && !declared_ns.contains (node.ns_uri ())) {// Its a default ns 
for children
-              tw.start_element_ns (node.ns_prefix (), node.name, node.ns_uri ());
-              declared_ns.add (node.ns_uri ());
-#if DEBUG
-              GLib.message (@"Declared NS: '$(node.ns_uri ())' Total declared = $(declared_ns.size.to_string 
())");
-#endif
-            }
-            else {
-              if (node.document.ns_top || declared_ns.contains (node.ns_uri ()))
-                tw.start_element_ns (node.ns_prefix (), node.name, null);
-              else {
-                tw.start_element_ns (node.ns_prefix (), node.name, node.ns_uri ());
-                declared_ns.add (node.ns_uri ());
-#if DEBUG
-              GLib.message (@"Declared NS: $(node.ns_uri ()) Total declared = $(declared_ns.size.to_string 
())");
-#endif
-              }
-            }
-          }
-        } else {
-#if DEBUG
-      GLib.message (@"Starting Element: '$(node.name)' : start no NS: Check for default prefix_default_ns 
enabled");
-#endif
-          if (node.document.prefix_default_ns)
-            tw.start_element_ns (node.document.ns_prefix (), node.name, null);
-          else
-            tw.start_element (node.name);
-        }
-      }
-#if DEBUG
-    GLib.message (@"Starting Element '$(node.name)': writting attributes");
-#endif
-      foreach (GXml.Node attr in node.attrs.values) {
-        if (attr.namespaces.size > 0) {
-#if DEBUG
-    GLib.message (@"Starting Element '$(node.name)': write attribute '$(attr.name)' with NS");
-#endif
-          if (!declared_ns.contains (attr.ns_uri ())) {
-            size += tw.write_attribute_ns (attr.ns_prefix (), attr.name, attr.ns_uri (), attr.value);
-            declared_ns.add (attr.ns_uri ());
-#if DEBUG
-              GLib.message (@"Declared NS: $(attr.ns_uri ()) Total declared = $(declared_ns.size.to_string 
())");
-#endif
-          }
-          else
-            size += tw.write_attribute_ns (attr.ns_prefix (), attr.name, null, attr.value);
-        }
-        else {
-#if DEBUG
-    GLib.message (@"Starting Element '$(node.name)': write attribute '$(attr.name)' no NS");
-#endif
-          size += tw.write_attribute (attr.name, attr.value);
-        }
-        if (size > 1500)
-          tw.flush ();
-      }
-#if DEBUG
-    GLib.message (@"Starting Element: writting Node '$(node.name)' childs");
-#endif
-      foreach (GXml.Node n in node.childs) {
-#if DEBUG
-    GLib.message (@"Child Node is: $(n.get_type ().name ())");
-#endif
-        if (n is GXml.Element) {
-#if DEBUG
-    GLib.message (@"Starting Child Element: writting Node '$(n.name)'");
-#endif
-          if (node.namespaces.size > 0) {
-            if (node.document.namespaces.size > 0)
-              if (node.ns_uri () != node.document.ns_uri ())
-                if (n.namespaces.size == 0 && node.ns_prefix == null) // Apply parent ns
-                  n.set_namespace (node.ns_uri (), node.ns_prefix ());
-          }
-          start_node (tw, n, false, ref declared_ns);
-          size += tw.end_element ();
-          if (size > 1500)
-            tw.flush ();
-        }
-        if (n is GXml.Text) {
-          //GLib.message ("Writting Element's contents");
-          size += tw.write_string (node.value);
-          if (size > 1500)
-            tw.flush ();
-        }
-        if (n is GXml.Comment) {
-#if DEBUG
-    GLib.message (@"Starting Child Element: writting Comment '$(n.value)'");
-#endif
-          size += tw.write_comment (n.value);
-          if (size > 1500)
-            tw.flush ();
-        }
-        if (n is GXml.CDATA) {
-#if DEBUG
-    GLib.message (@"Starting Child Element: writting CDATA '$(n.value)'");
-#endif
-          size += Xmlx.text_writer_write_cdata (tw, n.value);
-          if (size > 1500)
-            tw.flush ();
-        }
-        if (n is GXml.ProcessingInstruction) {
-#if DEBUG
-    GLib.message (@"Starting Child Element: writting ProcessingInstruction '$(n.value)'");
-#endif
-          size += Xmlx.text_writer_write_pi (tw, ((ProcessingInstruction) n).target, 
((ProcessingInstruction) n).data);
-          if (size > 1500)
-            tw.flush ();
-        }
-      }
-    }
+    return new GCDATA (this, cd);
   }
   public override string to_string ()
   {
@@ -364,49 +156,20 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
 #endif
     Xml.Doc doc = new Xml.Doc ();
     Xml.TextWriter tw = Xmlx.new_text_writer_doc (ref doc);
-    write_document (tw);
+    TwDocument.write_document (this, tw);
     string str;
     int size;
     doc.dump_memory (out str, out size);
     return str;
   }
-  // HTML methods
-               public static int default_options {
-                       get {
-                               return Html.ParserOption.NONET | Html.ParserOption.NOWARNING | 
Html.ParserOption.NOERROR | Html.ParserOption.NOBLANKS;
-                       }
-               }
-               /**
-                * Search all { link GXml.Element} with a property called "class" and with a
-                * value as a class apply to a node.
-                */
-               public Gee.List<GXml.Node> get_elements_by_class_name (string klass) {
-                       var rl = new Gee.ArrayList<GXml.Node> ();
-                       var l = root.get_elements_by_property_value ("class", klass);
-                       foreach (GXml.Node n in l) {
-                               var p = n.attrs.get ("class");
-                               if (p == null) continue;
-                               if (" " in p.value) {
-                                       foreach (string ks in p.value.split (" ")) {
-                                               if (ks == klass)
-                                                       rl.add (n);
-                                       }
-                               } else if (klass == p.value) {
-                                       rl.add (n);
-                               }
-                       }
-                       return rl;
-               }
-               /**
-                * Get first node where 'id' attribute has given value.
-                */
-               public GXml.Node? get_element_by_id (string id) {
-                       var l = root.get_elements_by_property_value ("id", id);
-                       foreach (GXml.Node n in l) {
-                               var p = n.attrs.get ("id");
-                               if (p == null) continue;
-                               if (p.value == id) return n;
-                       }
-                       return null;
-               }
+  public virtual bool save (GLib.Cancellable? cancellable = null)
+    throws GLib.Error
+  {
+    return save_as (file, cancellable);
+  }
+  public virtual bool save_as (GLib.File f, GLib.Cancellable? cancellable = null)
+    throws GLib.Error
+  {
+    return TwDocument.tw_save_as (this, f, cancellable);
+  }
 }
diff --git a/gxml/GXmlElement.vala b/gxml/GXmlElement.vala
index 7c3d2e6..0b4ef49 100644
--- a/gxml/GXmlElement.vala
+++ b/gxml/GXmlElement.vala
@@ -26,7 +26,10 @@ using Gee;
  */
 public class GXml.GElement : GXml.GNode, GXml.Element
 {
-  public GElement (Xml.Node *node) { _node = node; }
+  public GElement (GDocument doc, Xml.Node *node) {
+    _node = node;
+    _doc = doc;
+  }
   // GXml.Node
   public override string value
   {
@@ -42,7 +45,7 @@ public class GXml.GElement : GXml.GNode, GXml.Element
   }
   public GXml.Node get_attr (string name)
   {
-    return new GAttribute (_node->get_prop (name));
+    return new GAttribute (_doc, _node->get_prop (name));
   }
   public void normalize () {}
   public string content {
diff --git a/gxml/GXmlHashMapAttr.vala b/gxml/GXmlHashMapAttr.vala
index 13db1ce..4dc7d8c 100644
--- a/gxml/GXmlHashMapAttr.vala
+++ b/gxml/GXmlHashMapAttr.vala
@@ -24,17 +24,21 @@ using Gee;
 
 public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
 {
+  private GDocument _doc;
   private Xml.Node *_node;
-  public GHashMapAttr (Xml.Node *node) {
+  public GHashMapAttr (GDocument doc, Xml.Node *node) {
     _node = node;
+    _doc = doc;
   }
   
   public class Entry : Gee.Map.Entry<string,GXml.Node> {
+    private GXml.GDocument _doc;
     private Xml.Attr *_attr;
     private GAttribute oattr;
-    public Entry (Xml.Attr *attr) {
+    public Entry (GDocument doc, Xml.Attr *attr) {
       _attr = attr;
-      oattr = new GAttribute (_attr);
+      _doc = doc;
+      oattr = new GAttribute (_doc, _attr);
     }
     public override string key { get { return _attr->name; } }
     public override bool read_only { get { return true; } }
@@ -55,7 +59,7 @@ public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
   public override GXml.Node @get (string key) {
     if (_node == null) return null;
     var p = _node->get_prop (key);
-    return new GAttribute (p);
+    return new GAttribute (_doc, p);
   }
   public override bool has (string key, GXml.Node value) { return has_key (key); }
   public override bool has_key (string key) {
@@ -66,7 +70,7 @@ public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
     }
     return false;
   }
-  public override Gee.MapIterator<string,GXml.Node> map_iterator () { return new Iterator (_node); }
+  public override Gee.MapIterator<string,GXml.Node> map_iterator () { return new Iterator (_doc, _node); }
   public override void @set (string key, GXml.Node value) {
     if (_node == null) return;
     _node->new_prop (key, value  value);
@@ -82,7 +86,7 @@ public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
       if (_node == null) return l;
       var p = _node->properties;
       while (p != null) {
-        var e = new Entry (p);
+        var e = new Entry (_doc, p);
         l.add (e);
         p = p->next;
       }
@@ -117,19 +121,21 @@ public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
       var l = new ArrayList<GXml.Node> ();
       var p = _node->properties;
       while (p != null) {
-        l.add (new GAttribute (p));
+        l.add (new GAttribute (_doc, p));
         p = p->next;
       }
       return l;
     }
   }
   public class Iterator : Object, MapIterator<string,GXml.Node> {
+    private GXml.GDocument _doc;
     private Xml.Node *_node;
     private Xml.Attr *_current;
 
-    public Iterator (Xml.Node *node) {
+    public Iterator (GXml.GDocument doc, Xml.Node *node) {
       _node = node;
       _current = null;
+      _doc = doc;
     }
 
     public string get_key () {
@@ -137,7 +143,7 @@ public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
       return null;
     }
     public GXml.Node get_value () {
-      return new GAttribute (_current);
+      return new GAttribute (_doc, _current);
     }
     public bool has_next () {
       if (_node->properties == null) return false;
diff --git a/gxml/GXmlListChildren.vala b/gxml/GXmlListChildren.vala
index c10460f..e062404 100644
--- a/gxml/GXmlListChildren.vala
+++ b/gxml/GXmlListChildren.vala
@@ -24,13 +24,15 @@ using Gee;
 
 public class GXml.GListChildren : AbstractBidirList<GXml.Node>
 {
+  private GXml.GDocument _doc;
   private Xml.Node *_node;
   private bool _read_only = false;
-  public GListChildren (Xml.Node* node) {
+  public GListChildren (GDocument doc, Xml.Node* node) {
     _node = node;
+    _doc = doc;
   }
   public new override Gee.BidirListIterator<GXml.Node> bidir_list_iterator () {
-    return new Iterator (_node);
+    return new Iterator (_doc, _node);
   }
   // List
   public override GXml.Node @get (int index) {
@@ -40,7 +42,7 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
     while (n != null) {
       var t = (GXml.NodeType) n->type;
       if (i == index) {
-        return GNode.to_gnode (n);
+        return GNode.to_gnode (_doc, n);
       }
       i++;
       n = n->next;
@@ -63,7 +65,7 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
    * This method is ignored by default.
    */
   public override void insert (int index, GXml.Node item) {}
-  public override  Gee.ListIterator<GXml.Node> list_iterator () { return new Iterator (_node); }
+  public override  Gee.ListIterator<GXml.Node> list_iterator () { return new Iterator (_doc, _node); }
   /**
    * This method is ignored by default.
    */
@@ -79,7 +81,7 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
     int i = 0;
     while (n != null) {
       if (i >= start && i <= stop) {
-        l.add (GNode.to_gnode (n));
+        l.add (GNode.to_gnode (_doc, n));
       }
       n = n->next;
       i++;
@@ -110,7 +112,7 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
     }
     return false;
   }
-  public override Gee.Iterator<GXml.Node> iterator () { return new Iterator (_node); }
+  public override Gee.Iterator<GXml.Node> iterator () { return new Iterator (_doc, _node); }
   public override bool remove (GXml.Node item) {
     if (_node == null) return false;
     if (!(item is GXml.GNode)) return false;
@@ -144,12 +146,14 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
                           Gee.BidirIterator<GXml.Node>,
                           Gee.ListIterator<GXml.Node>,
                           BidirListIterator<GXml.Node> {
+    private GDocument _doc;
     private Xml.Node *_node;
     private Xml.Node *_current;
     private int i = 0;
-    public Iterator (Xml.Node *node) {
+    public Iterator (GDocument doc, Xml.Node *node) {
       _node = node;
       _current = _node->children;
+      _doc = doc;
     }
     /**
      * This method is ignored by default.
@@ -166,7 +170,7 @@ public class GXml.GListChildren : AbstractBidirList<GXml.Node>
      */
     public new void @set (GXml.Node item) {}
     // Iterator
-    public new GXml.Node @get () { return GNode.to_gnode (_node); }
+    public new GXml.Node @get () { return GNode.to_gnode (_doc, _node); }
     public bool has_next () {
       if (_node == null) return false;
       if (_node->children == null) return false;
diff --git a/gxml/GXmlListNamespaces.vala b/gxml/GXmlListNamespaces.vala
index 43f8c5e..2484fd1 100644
--- a/gxml/GXmlListNamespaces.vala
+++ b/gxml/GXmlListNamespaces.vala
@@ -24,10 +24,12 @@ using Gee;
 
 public class GXml.GListNamespaces : Gee.AbstractList<GXml.Node>
 {
+  private GDocument _doc;
   private Xml.Node *_node;
   private bool _read_only = false;
-  public GListNamespaces (Xml.Node *node) {
+  public GListNamespaces (GDocument doc, Xml.Node *node) {
     _node = node;
+    _doc = doc;
   }
   // List
   public override new GXml.Node @get (int index) {
diff --git a/gxml/GXmlNode.vala b/gxml/GXmlNode.vala
index 3b1eff3..f5370cc 100644
--- a/gxml/GXmlNode.vala
+++ b/gxml/GXmlNode.vala
@@ -31,7 +31,7 @@ public abstract class GXml.GNode : Object, GXml.Node
   protected Xml.Node *_node;
   internal Xml.TextWriter *tw;
 
-       construct { Init.init (); }
+  construct { Init.init (); }
 
   // GXml.Node
   public virtual bool set_namespace (string uri, string? prefix)
@@ -39,9 +39,9 @@ public abstract class GXml.GNode : Object, GXml.Node
     if (_node == null) return false;
     return ((_node->new_ns (uri, prefix)) != null);
   }
-  public virtual Gee.Map<string,GXml.Node> attrs { owned get { return new GHashMapAttr (_node); } }
-  public virtual Gee.BidirList<GXml.Node> children { owned get { return new GListChildren (_node); } }
-  public virtual Gee.List<GXml.Namespace> namespaces { owned get { return new GListNamespaces (_node); } }
+  public virtual Gee.Map<string,GXml.Node> attrs { owned get { return new GHashMapAttr (_doc, _node); } }
+  public virtual Gee.BidirList<GXml.Node> children { owned get { return new GListChildren (_doc, _node); } }
+  public virtual Gee.List<GXml.Namespace> namespaces { owned get { return new GListNamespaces (_doc, _node); 
} }
   public virtual GXml.Document document { get { return _doc; } }
   public virtual GXml.NodeType type_node {
     get {
@@ -69,20 +69,20 @@ public abstract class GXml.GNode : Object, GXml.Node
   public virtual string to_string () { return get_type ().name (); }
   public Xml.Node* get_internal_node () { return _node; }
   // Static
-  public static GXml.Node to_gnode (Xml.Node *node) {
+  public static GXml.Node to_gnode (GXml.GDocument doc, Xml.Node *node) {
     var t = (GXml.NodeType) node->type;
     switch (t) {
       case GXml.NodeType.ELEMENT:
-        return new GElement (node);
+        return new GElement (doc, node);
         break;
       case GXml.NodeType.ATTRIBUTE:
-        return new GAttribute ((Xml.Attr*) node);
+        return new GAttribute (doc, (Xml.Attr*) node);
         break;
       case GXml.NodeType.TEXT:
-        return new GText (node);
+        return new GText (doc, node);
         break;
       case GXml.NodeType.CDATA_SECTION:
-        return new GCDATA (node);
+        return new GCDATA (doc, node);
         break;
       case GXml.NodeType.ENTITY_REFERENCE:
         return null;
@@ -91,10 +91,10 @@ public abstract class GXml.GNode : Object, GXml.Node
         return null;
         break;
       case GXml.NodeType.PROCESSING_INSTRUCTION:
-        return new GProcessingInstruction (node);
+        return new GProcessingInstruction (doc, node);
         break;
       case GXml.NodeType.COMMENT:
-        return new GComment (node);
+        return new GComment (doc, node);
         break;
       case GXml.NodeType.DOCUMENT:
         return new GDocument.from_doc (node->doc);
diff --git a/gxml/GXmlProcessingInstruction.vala b/gxml/GXmlProcessingInstruction.vala
index c7a8711..54e5665 100644
--- a/gxml/GXmlProcessingInstruction.vala
+++ b/gxml/GXmlProcessingInstruction.vala
@@ -26,9 +26,10 @@ using Gee;
  */
 public class GXml.GProcessingInstruction : GXml.GNode, GXml.ProcessingInstruction
 {
-  public GProcessingInstruction (Xml.Node *node)
+  public GProcessingInstruction (GDocument doc, Xml.Node *node)
   {
     _node = node;
+    _doc = doc;
   }
   // GXml.ProcessingInstruction
   public string target { owned get { return name; } }
diff --git a/gxml/GXmlText.vala b/gxml/GXmlText.vala
index 4c02115..2dc07ab 100644
--- a/gxml/GXmlText.vala
+++ b/gxml/GXmlText.vala
@@ -26,9 +26,15 @@ using Gee;
  */
 public class GXml.GText : GXml.GNode, GXml.Text
 {
-  public GText (Xml.Node *node)
+  public GText (GDocument doc, Xml.Node *node)
   {
     _node = node;
+    _doc = doc;
+  }
+  public override string name {
+    owned get {
+      return "#text".dup ();
+    }
   }
   // GXml.Text
   public string str { owned get { return base.value; } }
diff --git a/gxml/Node.vala b/gxml/Node.vala
index ca62760..da0a433 100644
--- a/gxml/Node.vala
+++ b/gxml/Node.vala
@@ -83,12 +83,20 @@ public interface GXml.Node : Object
    get_elements_by_property_value (string property, string value)
   {
     var list = new Gee.ArrayList<GXml.Node>();
-    foreach (var child in childs) {
+    if (!(this is GXml.Element)) return list;
+    foreach (var child in children) {
+      Test.message ("At node: "+child.name);
       list.add_all (child.get_elements_by_property_value (property, value));
       if (child is GXml.Element) {
-        var cls = (child as GXml.Element).attrs.get (property);
-        if (cls == null) continue;
-        if (value in ((GXml.Element) child).content)
+        Test.message ("Node is Element: "+child.name);
+        if (child.attrs == null) continue;
+        Test.message ("Searching property: "+property+" in node: "+child.name);
+        var cls = child.attrs.get (property);
+        if (cls == null) {
+          Test.message ("No property :"+ property+" found");
+          continue;
+        }
+        if (value in ((GXml.Element) cls).value)
             list.add (child);
       }
     }
diff --git a/gxml/TwDocument.vala b/gxml/TwDocument.vala
index aca7887..78b8287 100644
--- a/gxml/TwDocument.vala
+++ b/gxml/TwDocument.vala
@@ -97,8 +97,10 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
     var pi = new TwProcessingInstruction (this, target, data);
     return pi;
   }
-  public GXml.Node create_element (string name)
+  public GXml.Node create_element (string name) throws GLib.Error
   {
+    if (Xmlx.validate_name (name, 1) != 0)
+      throw new GXml.Error.PARSER (_("Invalid element name"));
     return new TwElement (this, name);
   }
   public GXml.Node create_text (string text)
@@ -119,45 +121,49 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
   }
   [Deprecated (since="0.8.1", replacement="save_as")]
   public bool save_to (GLib.File f, GLib.Cancellable? cancellable = null)
+    throws GLib.Error
   {
     return save_as (f, cancellable);
   }
   public bool save_as (GLib.File f, GLib.Cancellable? cancellable = null)
+    throws GLib.Error
+  {
+    return tw_save_as (this, f, cancellable);
+  }
+  public static bool tw_save_as (GXml.Document doc, GLib.File f,
+                                GLib.Cancellable? cancellable = null)
+    throws GLib.Error
   {
     var buf = new Xml.Buffer ();
     var tw = Xmlx.new_text_writer_memory (buf, 0);
     GLib.Test.message ("Writing down to buffer");
-    write_document (tw);
+    write_document (doc, tw);
     GLib.Test.message ("Writing down to file");
     GLib.Test.message ("TextWriter buffer:\n"+buf.content ());
     var s = new GLib.StringBuilder ();
     s.append (buf.content ());
-    try {
-      GLib.Test.message ("Writing down to file: Creating input stream");
-      var b = new GLib.MemoryInputStream.from_data (s.data, null);
-      GLib.Test.message ("Writing down to file: Replacing with backup");
-      var ostream = f.replace (null, backup, GLib.FileCreateFlags.NONE, cancellable);
-      ostream.splice (b, GLib.OutputStreamSpliceFlags.NONE);
-      ostream.close ();
-    } catch (GLib.Error e) {
-      GLib.warning ("Error on Save to file: "+e.message);
-      return false;
-    }
+    GLib.Test.message ("Writing down to file: Creating input stream");
+    var b = new GLib.MemoryInputStream.from_data (s.data, null);
+    GLib.Test.message ("Writing down to file: Replacing with backup");
+    var ostream = f.replace (null, doc.backup, GLib.FileCreateFlags.NONE, cancellable);
+    ostream.splice (b, GLib.OutputStreamSpliceFlags.NONE);
+    ostream.close ();
     return true;
   }
-  public virtual void write_document (Xml.TextWriter tw)
+  public static void write_document (GXml.Document doc, Xml.TextWriter tw)
+    throws GLib.Error
   {
     tw.start_document ();
-    tw.set_indent (indent);
+    tw.set_indent (doc.indent);
     // Root
-    if (root == null) {
+    if (doc.root == null) {
       tw.end_document ();
     }
     var dns = new ArrayList<string> ();
 #if DEBUG
     GLib.message ("Starting writting Document Root node");
 #endif
-    start_node (tw, root, true, ref dns);
+    start_node (doc, tw, doc.root, true, ref dns);
 #if DEBUG
     GLib.message ("Ending writting Document Root node");
 #endif
@@ -168,7 +174,10 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
     tw.end_document ();
     tw.flush ();
   }
-  public virtual void start_node (Xml.TextWriter tw, GXml.Node node, bool root, ref Gee.ArrayList<string> 
declared_ns)
+  public static void start_node (GXml.Document doc, Xml.TextWriter tw,
+                                GXml.Node node, bool root,
+                                ref Gee.ArrayList<string> declared_ns)
+    throws GLib.Error
   {
     int size = 0;
 #if DEBUG
@@ -184,7 +193,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
         if (node.document.namespaces.size > 0) {
           var dns = node.document.namespaces.get (0);
           assert (dns != null);
-          if (prefix_default_ns) {
+          if (doc.prefix_default_ns) {
             tw.start_element_ns (dns.prefix, node.name, dns.uri);
             declared_ns.add (dns.uri);
 #if DEBUG
@@ -309,7 +318,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
                 if (n.namespaces.size == 0 && node.ns_prefix == null) // Apply parent ns
                   n.set_namespace (node.ns_uri (), node.ns_prefix ());
           }
-          start_node (tw, n, false, ref declared_ns);
+          start_node (doc, tw, n, false, ref declared_ns);
           size += tw.end_element ();
           if (size > 1500)
             tw.flush ();
@@ -354,7 +363,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
 #endif
     Xml.Doc doc = new Xml.Doc ();
     Xml.TextWriter tw = Xmlx.new_text_writer_doc (ref doc);
-    write_document (tw);
+    write_document (this, tw);
     string str;
     int size;
     doc.dump_memory (out str, out size);
diff --git a/gxml/libxml-ChildNodeList.vala b/gxml/libxml-ChildNodeList.vala
index cb3a8d4..1f4bb94 100644
--- a/gxml/libxml-ChildNodeList.vala
+++ b/gxml/libxml-ChildNodeList.vala
@@ -82,11 +82,12 @@ internal abstract class GXml.ChildNodeList : AbstractBidirList<xNode>, NodeList
         {
             Xml.Node *cur = head;
             int i = 0;
-            while (cur->next != null && i != n) {
+            while (cur != null) {
+              if (i == n) return this.owner.lookup_node (cur);
                 cur = cur->next;
                 i++;
             }
-                       return this.owner.lookup_node (cur);
+                       return null;
                }
                public override int index_of (xNode item)
       requires (item is BackedNode)
diff --git a/gxml/xlibxml.c b/gxml/xlibxml.c
index eac9868..2f57eaa 100644
--- a/gxml/xlibxml.c
+++ b/gxml/xlibxml.c
@@ -27,7 +27,7 @@ void* gxml_doc_get_intsubset_entities (xmlDoc *doc)
   return doc->intSubset->entities;
 }
 
-int gxml_validate_name (xmlChar* name, int space)
+gint gxml_validate_name (xmlChar* name, int space)
 {
   g_return_if_fail (name != NULL);
   return xmlValidateName (name, space);
@@ -82,14 +82,14 @@ xmlTextWriterPtr gxml_new_text_writer_memory (xmlBufferPtr buffer, gint compress
   return xmlNewTextWriterMemory (buffer, compression);
 }
 
-int gxml_text_writer_write_cdata (xmlTextWriterPtr tw, const xmlChar* text)
+gint gxml_text_writer_write_cdata (xmlTextWriterPtr tw, const xmlChar* text)
 {
   g_return_if_fail (tw != NULL);
   g_return_if_fail (text != NULL);
   return xmlTextWriterWriteCDATA (tw, text);
 }
 
-int gxml_text_writer_write_pi (xmlTextWriterPtr tw, const xmlChar* target, const xmlChar* data)
+gint gxml_text_writer_write_pi (xmlTextWriterPtr tw, const xmlChar* target, const xmlChar* data)
 {
   g_return_if_fail (tw != NULL);
   g_return_if_fail (target != NULL);
diff --git a/gxml/xlibxml.h b/gxml/xlibxml.h
index a1431fe..09c5280 100644
--- a/gxml/xlibxml.h
+++ b/gxml/xlibxml.h
@@ -27,7 +27,7 @@
 #include <glib.h>
 
 void*       gxml_doc_get_intsubset_entities    (xmlDoc *doc);
-int         gxml_validate_name                 (xmlChar* name, int space);
+gint         gxml_validate_name                 (xmlChar* name, int space);
 xmlErrorPtr gxml_parser_context_get_last_error (void* ctx);
 xmlErrorPtr gxml_context_get_last_error        (void* ctx);
 void        gxml_context_reset_last_error      (void* ctx);
@@ -36,7 +36,7 @@ void        gxml_reset_last_error              ();
 xmlNsPtr*   gxml_doc_get_ns_list               (xmlDoc* doc, xmlNode* node);
 xmlTextWriterPtr gxml_new_text_writer_doc      (xmlDoc** doc);
 xmlTextWriterPtr gxml_new_text_writer_memory   (xmlBufferPtr buffer, gint compression);
-int         gxml_text_writer_write_cdata       (xmlTextWriter* tw, const xmlChar* text);
-int         gxml_text_writer_write_pi          (xmlTextWriter* tw, const xmlChar* target, const xmlChar* 
data);
+gint         gxml_text_writer_write_cdata       (xmlTextWriter* tw, const xmlChar* text);
+gint         gxml_text_writer_write_pi          (xmlTextWriter* tw, const xmlChar* target, const xmlChar* 
data);
 
 #endif
diff --git a/test/GXmlTest.vala b/test/GXmlTest.vala
index fe1aa52..7815542 100644
--- a/test/GXmlTest.vala
+++ b/test/GXmlTest.vala
@@ -83,6 +83,7 @@ class GXmlTest {
                SerializablePropertyValueListTest.add_tests ();
                SerializablePropertyEnumTest.add_tests ();
                GDocumentTest.add_tests ();
+               HtmlDocumentTest.add_tests ();
 
                Test.run ();
 
diff --git a/test/Makefile.am b/test/Makefile.am
index b82343e..341ee24 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -61,6 +61,7 @@ sources = \
        TwCommentTest.vala \
        TwProcessingInstructionTest.vala \
        GDocumentTest.vala \
+       HtmlDocumentTest.vala \
        $(NULL)
 
 gxml_test.vala.stamp: $(sources)



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