[gxml] Improved TwDocument Namespace handling



commit c872a9ce9603872b6c36ff65dbab671774153039
Author: Daniel Espinosa <esodan gmail com>
Date:   Wed May 13 11:02:14 2015 -0500

    Improved TwDocument Namespace handling
    
    * By default no prefix are added for default namespace
    * Added GXml.Document.prefix_default_ns to add default namespace's
      prefix
    * By setting a namespace to GXml.Document/TwDocument, first one
      is used as default for all document
    * Added GXml.Document.ns_top to add all namespaces declarations to
      root node (still fails to remove its declaration in children nodes)

 gxml/Document.vala                        |   16 +++
 gxml/Node.vala                            |    2 +-
 gxml/TwDocument.vala                      |   93 ++++++++++-----
 gxml/TwNamespace.vala                     |    2 +-
 gxml/TwNode.vala                          |    2 +-
 gxml/libxml-BackedNode.vala               |    4 +-
 gxml/libxml-Document.vala                 |    2 +
 gxml/libxml-Node.vala                     |    4 +-
 test/SerializableObjectModel-Tw-Test.vala |    4 +-
 test/TwElementTest.vala                   |  181 +++++++++++++++++++++++++++++
 test/TwProcessingInstructionTest.vala     |    1 -
 11 files changed, 272 insertions(+), 39 deletions(-)
---
diff --git a/gxml/Document.vala b/gxml/Document.vala
index 44b63f9..085ddae 100644
--- a/gxml/Document.vala
+++ b/gxml/Document.vala
@@ -39,6 +39,22 @@ public interface GXml.Document : Object, GXml.Node
    */
   public abstract bool indent { get; set; }
   /**
+   * Controls if writting this documentsshould use namespaces
+   * declaration at root { link GXml.Element}.
+   *
+   * This removes full declaration at childs nodes, because they
+   * are just prefixed if a prefix was defined for namespace apply.
+   */
+  public abstract bool ns_top { get; set; }
+  /**
+   * Controls if writting this document should use default namespace's prefix
+   * to prefix root's childs { link GXml.Element}.
+   *
+   * This removes prefix on childs using default namespace. Default namespace
+   * is the first one found in { link GXml.Node.namespaces} for this document.
+   */
+  public abstract bool prefix_default_ns { get; set; }
+  /**
    * XML document root node as a { link GXml.Element}.
    */
   public abstract GXml.Node root { get; }
diff --git a/gxml/Node.vala b/gxml/Node.vala
index dc366b9..95bd31e 100644
--- a/gxml/Node.vala
+++ b/gxml/Node.vala
@@ -68,7 +68,7 @@ public interface GXml.Node : Object
    * Search for existing document's namespaces and applies it if found or creates
    * a new one, appending to document's namespaces collection.
    */
-  public abstract bool set_namespace (string uri, string prefix);
+  public abstract bool set_namespace (string uri, string? prefix);
   /**
    * Node's defaults namespace's prefix.
    *
diff --git a/gxml/TwDocument.vala b/gxml/TwDocument.vala
index 0a42017..6c2119c 100644
--- a/gxml/TwDocument.vala
+++ b/gxml/TwDocument.vala
@@ -35,7 +35,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
     this.file = f;
   }
   // GXml.Node
-  public override bool set_namespace (string uri, string prefix)
+  public override bool set_namespace (string uri, string? prefix)
   {
     _namespaces.add (new TwNamespace (this, uri, prefix));
     return true;
@@ -43,6 +43,28 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
   public override GXml.Document document { get { return this; } }
   // GXml.Document
   public bool indent { get; set; default = false; }
+  public bool ns_top { get; set; default = false; }
+  public bool prefix_default_ns { get; set; default = false; }
+  public GLib.File file { get; set; }
+  public GXml.Node root {
+    get {
+      if (_root == null) {
+        int found = 0;
+        for (int i = 0; i < childs.size; i++) {
+          GXml.Node n = childs.get (i);
+          if (n is GXml.Element) {
+            found++;
+            if (found == 1)
+              _root = (GXml.Element) n;
+          }
+        }
+        if (found > 1) {
+          GLib.warning ("Document have more than one root GXmlElement. Using first found");
+        }
+      }
+      return _root;
+    }
+  }
   public GXml.Node create_comment (string text)
   {
     var c = new TwComment (this, text);
@@ -67,26 +89,6 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
     var t = new TwCDATA (this, text);
     return t;
   }
-  public GLib.File file { get; set; }
-  public GXml.Node root {
-    get {
-      if (_root == null) {
-        int found = 0;
-        for (int i = 0; i < childs.size; i++) {
-          GXml.Node n = childs.get (i);
-          if (n is GXml.Element) {
-            found++;
-            if (found == 1)
-              _root = (GXml.Element) n;
-          }
-        }
-        if (found > 1) {
-          GLib.warning ("Document have more than one GXmlElement. Using first found");
-        }
-      }
-      return _root;
-    }
-  }
   public bool save (GLib.Cancellable? cancellable = null)
     throws GLib.Error
   {
@@ -110,7 +112,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
 #if DEBUG
     GLib.message ("Starting writting Document Root node");
 #endif
-    start_node (tw, root);
+    start_node (tw, root, true);
 #if DEBUG
     GLib.message ("Ending writting Document Root node");
 #endif
@@ -121,7 +123,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
     tw.end_document ();
     tw.flush ();
   }
-  public virtual void start_node (Xml.TextWriter tw, GXml.Node node)
+  public virtual void start_node (Xml.TextWriter tw, GXml.Node node, bool root)
   {
     int size = 0;
 #if DEBUG
@@ -133,16 +135,47 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
     GLib.message (@"Element Document is Null... '$((node.document == null).to_string ())'");
     GLib.message (@"Namespaces in Element... '$(node.namespaces.size)'");
 #endif
-      if (node.namespaces.size > 0) {
+      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);
+          else {
+            // Write default namespace no prefix
+            tw.start_element (node.name);
+            if (dns.prefix == null)
+              tw.write_attribute ("xmlns",dns.uri);
+            else
+              tw.write_attribute ("xmlns:"+dns.prefix,dns.uri);
+          }
+          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);
+              tw.write_attribute ("xmlns:"+ns.prefix, ns.uri);
+            }
+          }
+        }
+        else
+          tw.start_element (node.name);
+      }
+      else {
+        if (node.namespaces.size > 0) {
 #if DEBUG
-    GLib.message ("Starting Element: start with NS");
+      GLib.message ("Starting Element: start with NS");
 #endif
-        tw.start_element_ns (node.ns_prefix (), node.name, node.ns_uri ());
-      } else {
+          if (node.document.namespaces.first ().uri == node.ns_uri () && !node.document.prefix_default_ns) {
+            // Don't prefix. Using default namespace and prefix_default_ns = false
+            tw.start_element (node.name);
+          }
+          else
+            tw.start_element_ns (node.ns_prefix (), node.name, node.ns_uri ());
+        } else {
 #if DEBUG
-    GLib.message ("Starting Element: start no NS");
+      GLib.message ("Starting Element: start no NS");
 #endif
-        tw.start_element (node.name);
+          tw.start_element (node.name);
+        }
       }
 #if DEBUG
     GLib.message ("Starting Element: writting attributes");
@@ -174,7 +207,7 @@ public class GXml.TwDocument : GXml.TwNode, GXml.Document
 #if DEBUG
     GLib.message (@"Starting Child Element: writting Node '$(n.name)'");
 #endif
-          start_node (tw, n);
+          start_node (tw, n, false);
           size += tw.end_element ();
           if (size > 1500)
             tw.flush ();
diff --git a/gxml/TwNamespace.vala b/gxml/TwNamespace.vala
index cc987e0..705632c 100644
--- a/gxml/TwNamespace.vala
+++ b/gxml/TwNamespace.vala
@@ -25,7 +25,7 @@ public class GXml.TwNamespace : GXml.TwNode, GXml.Namespace
 {
   private string _uri = null;
   private string _prefix = null;
-  public TwNamespace (GXml.Document d, string uri, string prefix)
+  public TwNamespace (GXml.Document d, string uri, string? prefix)
     requires (d is TwDocument)
   {
     _doc = d;
diff --git a/gxml/TwNode.vala b/gxml/TwNode.vala
index 7677a2b..c3c98dd 100644
--- a/gxml/TwNode.vala
+++ b/gxml/TwNode.vala
@@ -32,7 +32,7 @@ public abstract class GXml.TwNode : Object, GXml.Node
   internal Xml.TextWriter *tw;
 
   // GXml.Node
-  public virtual bool set_namespace (string uri, string prefix)
+  public virtual bool set_namespace (string uri, string? prefix)
   {
     bool found = false;
     foreach (GXml.Namespace ns in document.namespaces) {
diff --git a/gxml/libxml-BackedNode.vala b/gxml/libxml-BackedNode.vala
index e17d1dd..67eeb84 100644
--- a/gxml/libxml-BackedNode.vala
+++ b/gxml/libxml-BackedNode.vala
@@ -89,7 +89,7 @@ namespace GXml {
                /**
                 * { inheritDoc}
                 */
-               public override NamespaceAttr? add_namespace_attr (string uri, string namespace_prefix)
+               public override NamespaceAttr? add_namespace_attr (string uri, string? namespace_prefix)
                {
                        //stdout.printf ("BackedNode: Before add new Namespace\n");
                        var ns = this.node->new_ns (uri, namespace_prefix);
@@ -101,7 +101,7 @@ namespace GXml {
                /**
                 * { inheritDoc}
                 */
-               public override bool set_namespace (string uri, string namespace_prefix)
+               public override bool set_namespace (string uri, string? namespace_prefix)
                {
 #if DEBUG
                        GLib.message ("Setting a new Namespace...");
diff --git a/gxml/libxml-Document.vala b/gxml/libxml-Document.vala
index abda0c7..660f584 100644
--- a/gxml/libxml-Document.vala
+++ b/gxml/libxml-Document.vala
@@ -1015,6 +1015,8 @@ namespace GXml {
                }
                // GXml.Document interface
                public bool indent { get; set; default = false; }
+               public bool ns_top { get; set; default = false; }
+               public bool prefix_default_ns { get; set; default = false; }
                public GLib.File file { get; set; }
                public virtual GXml.Node root { get { return document_element; } }
                public GXml.Node create_text (string str) { return (GXml.Node) this.create_text_node (str); }
diff --git a/gxml/libxml-Node.vala b/gxml/libxml-Node.vala
index f816e1e..63cb3a3 100644
--- a/gxml/libxml-Node.vala
+++ b/gxml/libxml-Node.vala
@@ -114,7 +114,7 @@ namespace GXml {
                /**
                 * Add a new namespace to this { link GXml.xNode}
                 */
-               public virtual NamespaceAttr? add_namespace_attr (string uri, string namespace_prefix)
+               public virtual NamespaceAttr? add_namespace_attr (string uri, string? namespace_prefix)
                {
                        return null;
                }
@@ -124,7 +124,7 @@ namespace GXml {
                 *
                 * Returns: { link true} if namespace exists.
                 */
-               public virtual bool set_namespace (string uri, string namespace_prefix)
+               public virtual bool set_namespace (string uri, string? namespace_prefix)
                {
                        return false;
                }
diff --git a/test/SerializableObjectModel-Tw-Test.vala b/test/SerializableObjectModel-Tw-Test.vala
index 735a0ee..fd1aee0 100644
--- a/test/SerializableObjectModel-Tw-Test.vala
+++ b/test/SerializableObjectModel-Tw-Test.vala
@@ -288,7 +288,9 @@ class SerializableObjectModelTwTest : GXmlTest
         var doc = new TwDocument ();
         ns.serialize (doc);
         string str = doc.to_string ();
-        assert ("<gxml:namespace xmlns:gxml=\"http://www.gnome.org/GXml\"/>" in str);
+#if DEBUG
+        GLib.message (@"$doc");
+        assert ("<namespace xmlns:gxml=\"http://www.gnome.org/GXml\"/>" in str);
       } catch (GLib.Error e) {
 #if DEBUG
         GLib.message ("ERROR: "+e.message);
diff --git a/test/TwElementTest.vala b/test/TwElementTest.vala
index c333eed..4cf4c86 100644
--- a/test/TwElementTest.vala
+++ b/test/TwElementTest.vala
@@ -95,5 +95,186 @@ class TwElementTest : GXmlTest {
                        e.content = null;
                        assert (e.childs.size == 1);
                });
+               Test.add_func ("/gxml/tw-element/namespaces/default", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       // Set default namespace
+                       d.set_namespace ("http://www.gnome.org/gxml";, null);
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (d.namespaces.size == 1);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert ("<root xmlns=\"http://www.gnome.org/gxml\";>" in str);
+               });
+               Test.add_func ("/gxml/tw-element/namespaces/default-prefix", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       // Set default namespace
+                       d.set_namespace ("http://www.gnome.org/gxml";, "gxml");
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (d.namespaces.size == 1);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert ("<root xmlns:gxml=\"http://www.gnome.org/gxml\";>" in str);
+               });
+               Test.add_func ("/gxml/tw-element/namespaces/default-prefix-null", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       // Set default namespace
+                       d.set_namespace ("http://www.gnome.org/gxml";, null);
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (d.namespaces.size == 1);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert ("<root xmlns=\"http://www.gnome.org/gxml\";>" in str);
+               });
+               Test.add_func ("/gxml/tw-element/namespaces/default/enable-prefix_default_ns", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       // Set default namespace
+                       d.set_namespace ("http://www.gnome.org/gxml";, "gxml");
+                       d.prefix_default_ns = true;
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (d.namespaces.size == 1);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert ("<gxml:root xmlns:gxml=\"http://www.gnome.org/gxml\";>" in str);
+               });
+               Test.add_func ("/gxml/tw-element/multiple-namespaces", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       r.set_namespace ("http://git.gnome.org/browse/gxml";, "gxml");
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (r.namespaces.size == 1);
+                       assert (d.namespaces.size == 1);
+                       e.set_namespace ("http://developer.gnome.org/";, "dg");
+                       assert (e.namespaces.size == 1);
+                       assert (r.namespaces.size == 1);
+                       assert (d.namespaces.size == 2);
+                       var e2 = d.create_element ("nons");
+                       e.childs.add (e2);
+                       e2.set_namespace ("http://www.gnome.org/";, null);
+                       assert (e.namespaces.size == 1);
+                       assert (r.namespaces.size == 1);
+                       assert (e2.namespaces.size == 1);
+                       assert (d.namespaces.size == 3);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert ("<root xmlns:gxml=\"http://git.gnome.org/browse/gxml\";>" in str);
+                       assert ("</root>" in str);
+                       assert ("<dg:child xmlns:dg=\"http://developer.gnome.org/\";>" in str);
+                       assert ("<nons xmlns=\"http://www.gnome.org/\"/>" in str);
+               });
+               Test.add_func ("/gxml/tw-element/multiple-namespaces/default", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       // Default NS
+                       d.set_namespace ("http://git.gnome.org/browse/gxml";, null);
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (d.namespaces.size == 1);
+                       e.set_namespace ("http://developer.gnome.org/";, "dg");
+                       assert (e.namespaces.size == 1);
+                       assert (d.namespaces.size == 2);
+                       var e2 = d.create_element ("children");
+                       e.childs.add (e2);
+                       assert (e.namespaces.size == 1);
+                       assert (e2.namespaces.size == 0);
+                       assert (d.namespaces.size == 2);
+                       var e3 = d.create_element ("nons");
+                       e.childs.add (e3);
+                       e3.set_namespace ("http://www.gnome.org/";, "ns");
+                       assert (e.namespaces.size == 1);
+                       assert (e2.namespaces.size == 0);
+                       assert (e3.namespaces.size == 1);
+                       assert (d.namespaces.size == 3);
+                       var e4 = d.create_element ("childrenons");
+                       e3.childs.add (e4);
+                       assert (e.namespaces.size == 1);
+                       assert (e2.namespaces.size == 0);
+                       assert (e3.namespaces.size == 1);
+                       assert (e4.namespaces.size == 0);
+                       assert (d.namespaces.size == 3);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert ("<root xmlns=\"http://git.gnome.org/browse/gxml\";>" in str);
+                       assert ("</root>" in str);
+                       assert ("<dg:child xmlns:dg=\"http://developer.gnome.org/\";>" in str);
+                       assert ("<children/>" in str);
+                       assert ("<ns:nons xmlns:ns=\"http://www.gnome.org/\";>" in str);
+                       assert ("<childrenons/>" in str);
+                       assert ("</ns:nons>" in str);
+                       assert ("</dg:child>" in str);
+               });/*
+               Test.add_func ("/gxml/tw-element/multiple-namespaces/default/enable-ns_top", () => {
+                       var d = new TwDocument ();
+                       var r = d.create_element ("root");
+                       d.childs.add (r);
+                       // Default NS
+                       d.set_namespace ("http://git.gnome.org/browse/gxml";, null);
+                       // All namespaces declaration should be on root node
+                       d.ns_top = true;
+                       var e = d.create_element ("child");
+                       r.childs.add (e);
+                       assert (d.namespaces.size == 1);
+                       e.set_namespace ("http://developer.gnome.org/";, "dg");
+                       assert (e.namespaces.size == 1);
+                       assert (d.namespaces.size == 2);
+                       var e2 = d.create_element ("children");
+                       e.childs.add (e2);
+                       assert (e.namespaces.size == 1);
+                       assert (e2.namespaces.size == 0);
+                       assert (d.namespaces.size == 2);
+                       var e3 = d.create_element ("nons");
+                       e.childs.add (e3);
+                       e3.set_namespace ("http://www.gnome.org/";, "ns");
+                       assert (e.namespaces.size == 1);
+                       assert (e2.namespaces.size == 0);
+                       assert (e3.namespaces.size == 1);
+                       assert (d.namespaces.size == 3);
+                       var e4 = d.create_element ("childrenons");
+                       e3.childs.add (e4);
+                       assert (e.namespaces.size == 1);
+                       assert (e2.namespaces.size == 0);
+                       assert (e3.namespaces.size == 1);
+                       assert (e4.namespaces.size == 0);
+                       assert (d.namespaces.size == 3);
+                       string str = d.to_string ();
+#if DEBUG
+                       GLib.message (@"$d");
+#endif
+                       assert_not_reached ();
+                       assert ("<root xmlns=\"http://git.gnome.org/browse/gxml\"; 
xmlns:dg=\"http://developer.gnome.org/\"; xmlns:ns=\"http://www.gnome.org/\";>" in str);
+                       assert ("</root>" in str);
+                       assert ("<dg:child>" in str);
+                       assert ("<children/>" in str);
+                       assert ("<ns:nons >" in str);
+                       assert ("<childrenons/>" in str);
+                       assert ("</ns:nons>" in str);
+                       assert ("</dg:child>" in str);
+               });*/
        }
 }
diff --git a/test/TwProcessingInstructionTest.vala b/test/TwProcessingInstructionTest.vala
index e9eb7ec..c154f47 100644
--- a/test/TwProcessingInstructionTest.vala
+++ b/test/TwProcessingInstructionTest.vala
@@ -34,7 +34,6 @@ class TwProcessingInstructionTest : GXmlTest {
                                assert (pi.value == "transform");
                                d.root.childs.add (pi);
                                assert (d.root.childs.size == 1);
-                               GLib.message (@"Document created: $d");
                                string str = d.to_string ();
                                assert ("<root><?xslt transform?></root>" in str);
 #if DEBUG


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