[gxml] Fixes on GAttribute adding Unit Tests



commit 675258b5970c9664db50113de30445c9ab4c8983
Author: Daniel Espinosa <esodan gmail com>
Date:   Mon Feb 8 17:13:18 2016 -0600

    Fixes on GAttribute adding Unit Tests

 NEWS                      |    2 +
 gxml/Element.vala         |   17 +++----
 gxml/GXmlAttribute.vala   |   22 ++++++++-
 gxml/GXmlElement.vala     |   31 ++++++++++-
 gxml/GXmlHashMapAttr.vala |   26 +++++++++-
 gxml/GXmlNode.vala        |   13 -----
 gxml/TwElement.vala       |    8 +++
 gxml/libxml-Element.vala  |    6 ++
 test/GAttributeTest.vala  |  120 +++++++++++++++++++++++++++++++++++++++++++++
 test/GXmlTest.vala        |    1 +
 test/Makefile.am          |    1 +
 11 files changed, 218 insertions(+), 29 deletions(-)
---
diff --git a/NEWS b/NEWS
index 6c88ee9..d7310b8 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ API/ABI break
 * New libxml2 implementation called GNode and derivatives, expected to replace
   old implementation. It is a creating objects on demand.
 * New HtmlDocument for HTML handling
+* Element interface removed finalize_attr (), due it is unsed
+* Element added new get_ns_attr() for namespaced attributes
 
 
 ===============
diff --git a/gxml/Element.vala b/gxml/Element.vala
index c688dcb..aa9432b 100644
--- a/gxml/Element.vala
+++ b/gxml/Element.vala
@@ -46,16 +46,13 @@ public interface GXml.Element : Object, GXml.Node
      * All attributes could be get using { link GXml.Node.attrs} property.
      */
     public abstract GXml.Node get_attr (string name);
-  /**
-   * This method should finalize a new created { link GXml.Attribute}.
-   *
-   * Once a { link GXml.Attribute} was created and setup, you should finalize it
-   * by calling this method. Is a good practice to call this function, even if
-   * current implemention doesn't requires it.
-   *
-   * This function is useful when using { link Xml.TextWriter} implementations.
-   */
-  public virtual void finalize_attr () { return; }
+    /**
+     * Serach for a { link GXml.Attribute} with a given name and namespace uri.
+     *
+     * To get a attibute from { link GXml.Node.attrs} with a given namespace
+     * prefix, use "prefix:name".
+     */
+    public abstract GXml.Node get_ns_attr (string name, string uri);
     /**
      * This should be just a different name for { link GXml.Node.name}.
      */
diff --git a/gxml/GXmlAttribute.vala b/gxml/GXmlAttribute.vala
index 49339d0..65d3ebe 100644
--- a/gxml/GXmlAttribute.vala
+++ b/gxml/GXmlAttribute.vala
@@ -34,10 +34,19 @@ public class GXml.GAttribute : GXml.GNode, GXml.Attribute
     _node = _attr->parent;
     _doc = doc;
   }
+  public override Gee.List<GXml.Namespace> namespaces {
+    owned get {
+      var l = new Gee.ArrayList<GXml.Namespace> ();
+      if (_attr->ns == null) return l;
+      l.add (new GNamespace (_attr->ns));
+      return l;
+    }
+  }
   public Namespace @namespace {
     owned get {
       if (_attr == null) return null;
       if (_attr->ns == null) return null;
+      Test.message ("Attr Namespace: "+_attr->name+" : "+_attr->ns->prefix);
       return new GNamespace (_attr->ns);
     }
     set {
@@ -51,10 +60,19 @@ public class GXml.GAttribute : GXml.GNode, GXml.Attribute
   }
   public override string value {
     owned get {
-      return _node->get_prop (_attr->name);
+      if (_node == null) return  null;
+      if (_attr->ns == null) {
+        return _node->get_no_ns_prop (_attr->name);
+      }
+      else
+        return _node->get_ns_prop (_attr->name, _attr->ns->href);
     }
     set {
-      _node->set_prop (_attr->name, value);
+      if (_node == null) return;
+      if (_attr->ns == null)
+        _node->set_prop (_attr->name, value);
+      else
+        _node->set_ns_prop (_attr->ns, _attr->name, value);
     }
   }
   public string prefix {
diff --git a/gxml/GXmlElement.vala b/gxml/GXmlElement.vala
index 96cad72..74155d7 100644
--- a/gxml/GXmlElement.vala
+++ b/gxml/GXmlElement.vala
@@ -50,14 +50,39 @@ public class GXml.GElement : GXml.GNode, GXml.Element
       }
       if (!found) return;
     }
-    var a = _node->set_prop (aname, avalue);
+    _node->set_prop (aname, avalue);
   }
   public GXml.Node get_attr (string name)
   {
     if (_node == null) return null;
-    var a = _node->has_prop (name);
+    string prefix = "";
+    string n = name;
+    if (":" in name) {
+      string[] pp = name.split (":");
+      if (pp.length != 2) return null;
+      Test.message ("Checking for namespaced attribute: "+name);
+      prefix = pp[0];
+      n = pp[1];
+    }
+    var ps = _node->properties;
+    Test.message ("Name= "+n+" Prefix= "+prefix);
+    while (ps != null) {
+      Test.message ("At Attribute: "+ps->name);
+      if (ps->name == n) {
+        if (ps->ns == null && prefix == "") return new GAttribute (_doc, ps);
+        if (ps->ns == null) continue;
+        if (ps->ns->prefix == prefix)
+          return new GAttribute (_doc, ps);
+      }
+      ps = ps->next;
+    }
+    return null;
+  }
+  public GXml.Node get_ns_attr (string name, string uri) {
+    if (_node == null) return null;
+    var a = _node->has_ns_prop (name, uri);
     if (a == null) return null;
-    Test.message ("Element Prop: "+a->name);
+    Test.message ("Element NS Prop: "+a->name);
     return new GAttribute (_doc, a);
   }
   public void normalize () {}
diff --git a/gxml/GXmlHashMapAttr.vala b/gxml/GXmlHashMapAttr.vala
index c0301aa..d0a2cfa 100644
--- a/gxml/GXmlHashMapAttr.vala
+++ b/gxml/GXmlHashMapAttr.vala
@@ -58,8 +58,32 @@ public class GXml.GHashMapAttr : Gee.AbstractMap<string,GXml.Node>
   }
   public override GXml.Node @get (string key) {
     if (_node == null) return null;
+    if (":" in key) {
+      string[] pp = key.split (":");
+      if (pp.length != 2) return null;
+      Test.message ("Checking for namespaced attribute: "+key);
+      var ps = _node->properties;
+      var prefix = pp[0];
+      var n = pp[1];
+      Test.message ("Name= "+n+" Prefix= "+prefix);
+      while (ps != null) {
+        Test.message ("At Attribute: "+ps->name);
+        if (ps->name == n) {
+          if (ps->ns == null) continue;
+          if (ps->ns->prefix == prefix)
+            return new GAttribute (_doc, ps);
+        }
+        ps = ps->next;
+      }
+    }
     var p = _node->has_prop (key);
-    if (p == null) return  null;
+    if (p == null) return null;
+    // Check property found has Ns, then try to find one without it to return instead
+    if (p->ns != null) {
+      var npns = _node->has_ns_prop (key, null);
+      if (npns != null)
+        return new GAttribute (_doc, npns);
+    }
     return new GAttribute (_doc, p);
   }
   public override bool has (string key, GXml.Node value) { return has_key (key); }
diff --git a/gxml/GXmlNode.vala b/gxml/GXmlNode.vala
index f5370cc..3a2fdec 100644
--- a/gxml/GXmlNode.vala
+++ b/gxml/GXmlNode.vala
@@ -29,7 +29,6 @@ public abstract class GXml.GNode : Object, GXml.Node
 {
   protected GXml.GDocument _doc;
   protected Xml.Node *_node;
-  internal Xml.TextWriter *tw;
 
   construct { Init.init (); }
 
@@ -74,40 +73,28 @@ public abstract class GXml.GNode : Object, GXml.Node
     switch (t) {
       case GXml.NodeType.ELEMENT:
         return new GElement (doc, node);
-        break;
       case GXml.NodeType.ATTRIBUTE:
         return new GAttribute (doc, (Xml.Attr*) node);
-        break;
       case GXml.NodeType.TEXT:
         return new GText (doc, node);
-        break;
       case GXml.NodeType.CDATA_SECTION:
         return new GCDATA (doc, node);
-        break;
       case GXml.NodeType.ENTITY_REFERENCE:
         return null;
-        break;
       case GXml.NodeType.ENTITY:
         return null;
-        break;
       case GXml.NodeType.PROCESSING_INSTRUCTION:
         return new GProcessingInstruction (doc, node);
-        break;
       case GXml.NodeType.COMMENT:
         return new GComment (doc, node);
-        break;
       case GXml.NodeType.DOCUMENT:
         return new GDocument.from_doc (node->doc);
-        break;
       case GXml.NodeType.DOCUMENT_TYPE:
         return null;
-        break;
       case GXml.NodeType.DOCUMENT_FRAGMENT:
         return null;
-        break;
       case GXml.NodeType.NOTATION:
         return null;
-        break;
     }
     return null;
   }
diff --git a/gxml/TwElement.vala b/gxml/TwElement.vala
index 8077378..eec7427 100644
--- a/gxml/TwElement.vala
+++ b/gxml/TwElement.vala
@@ -49,6 +49,14 @@ public class GXml.TwElement : GXml.TwNode, GXml.Element
     attrs.set (name, att);
   }
   public GXml.Node get_attr (string name) { return attrs.get (name); }
+  public GXml.Node get_ns_attr (string name, string uri) {
+    foreach (GXml.Node a in attrs.values) {
+      if (a.name == name)
+        if (((Attribute) a).namespace != null)
+          if (((Attribute) a).namespace.uri == uri) return (GXml.Node) a;
+    }
+    return null;
+  }
   public void normalize () {}
   public string content {
     owned get {
diff --git a/gxml/libxml-Element.vala b/gxml/libxml-Element.vala
index 3bc4c15..380b7f8 100644
--- a/gxml/libxml-Element.vala
+++ b/gxml/libxml-Element.vala
@@ -478,5 +478,11 @@ namespace GXml {
                // GXml.Element interface
     public void set_attr (string name, string value) { set_attribute (name, value); }
     public GXml.Node get_attr (string name) { return (GXml.Node) get_attribute_node (name); }
+    public GXml.Node get_ns_attr (string name, string uri) {
+      var p = get_attr (name) as Attribute;
+      if (p.namespace == null) return null;
+      if (p.namespace.uri == uri) return (GXml.Node) p;
+      return null;
+    }
        }
 }
diff --git a/test/GAttributeTest.vala b/test/GAttributeTest.vala
new file mode 100644
index 0000000..58b98b6
--- /dev/null
+++ b/test/GAttributeTest.vala
@@ -0,0 +1,120 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
+/* Notation.vala
+ *
+ * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+
+using GXml;
+
+/* TODO: add tests for g_warnings being set; apparently you can trap g_criticals and test error messages 
with gtester */
+class GAttributeTest : GXmlTest {
+       public static void add_tests () {
+               Test.add_func ("/gxml/gattribute/value", () => {
+                       try {
+                               GDocument doc = new GDocument.from_string ("<Wands 
xmlns:wands=\"http://mom.co.uk/wands\";><Wand price=\"43.56\" wands:core=\"dragon heart cord\" 
wands:shell=\"oak\"/></Wands>");
+                               GAttribute attr = (GAttribute) doc.root.children[0].attrs.get ("price");
+                               assert (attr != null);
+                               assert (attr.name == "price");
+                               assert (attr.value == "43.56");
+                               attr.value = "56.1";
+                               assert (doc.root.children[0].to_string () == "<Wand price=\"56.1\" 
wands:core=\"dragon heart cord\" wands:shell=\"oak\"/>");
+                               // shell property is Namespaced, but no other property exists with same name 
then this should work
+                               GAttribute shell = (GAttribute) doc.root.children[0].attrs.get ("shell");
+                               assert (shell != null);
+                               assert (shell.name == "shell");
+                               assert (shell.value == "oak");
+                               shell.value = "Bad!?";
+                               Test.message (doc.root.children[0].to_string ());
+                               assert (doc.root.children[0].to_string () == "<Wand price=\"56.1\" 
wands:core=\"dragon heart cord\" wands:shell=\"Bad!?\"/>");
+                       } catch (GLib.Error e) {
+                               Test.message ("ERROR: "+e.message);
+                               assert_not_reached ();
+                       }
+               });
+               Test.add_func ("/gxml/gattribute/namespace", () => {
+                       try {
+                               GDocument doc = new GDocument.from_string ("<Wands 
xmlns:wands=\"http://mom.co.uk/wands\";><Wand price=\"43.56\" wands:core=\"dragon heart cord\" 
wands:shell=\"oak\"/></Wands>");
+                               assert (doc.root != null);
+                               GXml.GNode root = (GXml.GNode) doc.root;
+                               GElement node = (GElement)root.children[0];
+
+                               GAttribute core = (GAttribute) node.attrs.get ("core");
+                               assert (core != null);
+                               assert (core.name == "core");
+                               assert (core.namespace.prefix == "wands");
+                               assert (core.namespace.uri == "http://mom.co.uk/wands";);
+                               assert (core.namespaces != null);
+                               assert (core.namespaces.size == 1);
+                               assert (core.namespaces[0].uri == "http://mom.co.uk/wands";);
+                               assert (core.prefix == "wands");
+                               GAttribute shell = (GAttribute) node.attrs.get ("shell");
+                               assert (shell != null);
+                               assert (shell.name == "shell");
+                               assert (shell.namespaces != null);
+                               assert (shell.namespaces.size == 1);
+                               assert (shell.namespaces[0].uri == "http://mom.co.uk/wands";);
+                               assert (shell.prefix == "wands");
+                               GAttribute price = (GAttribute) node.attrs.get ("price");
+                               assert (price != null);
+                               assert (price.name == "price");
+                               assert (price.namespaces != null);
+                               assert (price.namespaces.size == 0);
+                       } catch (GLib.Error e) {
+                               Test.message ("ERROR: "+e.message);
+                               assert_not_reached ();
+                       }
+               });
+               Test.add_func ("/gxml/gattribute/namespace_value", () => {
+                       try {
+                               GDocument doc = new GDocument.from_string ("<Wands 
xmlns:wands=\"http://mom.co.uk/wands\";><Wand price=\"43.56\" wands:core=\"dragon heart cord\" 
wands:shell=\"oak\" shell=\"NoNs\"/></Wands>");
+                               // User namespace prefix to find namespaced attribute
+                               var nspshell = ((GElement) doc.root.children[0]).get_attr ("wands:shell") as 
GAttribute;
+                               assert (nspshell != null);
+                               assert (nspshell.name == "shell");
+                               assert (nspshell.namespace != null);
+                               assert (nspshell.namespace.prefix == "wands");
+                               assert (nspshell.namespace.uri == "http://mom.co.uk/wands";);
+                               assert (nspshell.value == "oak");
+                               // User namespace prefix to find namespaced attribute from Node.attrs
+                               var nspshell2 = doc.root.children[0].attrs.get ("wands:shell") as GAttribute;
+                               assert (nspshell2 != null);
+                               assert (nspshell2.name == "shell");
+                               assert (nspshell2.namespace != null);
+                               assert (nspshell2.namespace.prefix == "wands");
+                               assert (nspshell2.namespace.uri == "http://mom.co.uk/wands";);
+                               assert (nspshell2.value == "oak");
+                               // User no namespaced attribute
+                               var shell = ((GElement) doc.root.children[0]).get_attr ("shell") as 
GAttribute;
+                               assert (shell != null);
+                               assert (shell.name == "shell");
+                               assert (shell.namespace == null);
+                               assert (shell.value == "NoNs");
+                               // User no namespaced from Node.attrs
+                               var shell2 = doc.root.children[0].attrs.get ("shell") as GAttribute;
+                               assert (shell2 != null);
+                               assert (shell2.name == "shell");
+                               assert (shell2.namespace == null);
+                               assert (shell2.value == "NoNs");
+                       } catch (GLib.Error e) {
+                               Test.message ("ERROR: "+e.message);
+                               assert_not_reached ();
+                       }
+               });
+       }
+}
diff --git a/test/GXmlTest.vala b/test/GXmlTest.vala
index 005c3de..78e405c 100644
--- a/test/GXmlTest.vala
+++ b/test/GXmlTest.vala
@@ -84,6 +84,7 @@ class GXmlTest {
                SerializablePropertyEnumTest.add_tests ();
                GDocumentTest.add_tests ();
                GElementTest.add_tests ();
+               GAttributeTest.add_tests ();
                HtmlDocumentTest.add_tests ();
 
                Test.run ();
diff --git a/test/Makefile.am b/test/Makefile.am
index f650314..6d20e1e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -62,6 +62,7 @@ sources = \
        TwProcessingInstructionTest.vala \
        GDocumentTest.vala \
        GElementTest.vala \
+       GAttributeTest.vala \
        HtmlDocumentTest.vala \
        $(NULL)
 


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