[gxml: 7/7] GomElement: Implemented read unparsed children



commit 90266e7a93ea076942300c5585ddbcf562ce2066
Author: Daniel Espinosa <esodan gmail com>
Date:   Sat Apr 8 22:24:10 2017 -0500

    GomElement: Implemented read unparsed children
    
    If GomObject.parse_children is false, all children
    are stored as string in GomObject.unparsed, without
    parsing them, so no childs are added to current node.
    
    GomObject.read_unparsed() will parse all children
    stored in GomObject.unparsed, appending them to current
    node as child. Once children have been parsed,
    GomObject.unparsed is set to null to release resources.

 gxml/GomElement.vala     |    6 +++++
 gxml/GomObject.vala      |    8 +-----
 gxml/XParser.vala        |   47 +++++++++++++++++++++++++++++----------------
 test/GomElementTest.vala |   24 +++++++++++++++++++++++
 4 files changed, 62 insertions(+), 23 deletions(-)
---
diff --git a/gxml/GomElement.vala b/gxml/GomElement.vala
index f9a1404..af60b17 100644
--- a/gxml/GomElement.vala
+++ b/gxml/GomElement.vala
@@ -635,6 +635,12 @@ public class GXml.GomElement : GomNode,
   // GomObject
   public bool parse_children { get; set; default = true; }
   public string unparsed { get; set; }
+  public void read_unparsed () throws GLib.Error {
+    if (unparsed == null) return;
+    var parser = new XParser (this);
+    parser.read_child_nodes_string (unparsed, null);
+    unparsed = null;
+  }
 }
 
 
diff --git a/gxml/GomObject.vala b/gxml/GomObject.vala
index 4658a6b..e53a852 100644
--- a/gxml/GomObject.vala
+++ b/gxml/GomObject.vala
@@ -49,13 +49,9 @@ public interface GXml.GomObject : GLib.Object,
   /**
    * Reads all children stored in {@link unparsed} string.
    *
-   * After this method is called, {@link unparsed} is freed.
+   * After this method is called, {@link unparsed} is freed and set to null.
    */
-  public virtual void read_children () throws GLib.Error {
-    if (unparsed != null);
-    (this as GomElement).read_from_string (unparsed);
-    unparsed = null;
-  }
+  public abstract void read_unparsed () throws GLib.Error;
   /**
    * Returns a list with all properties' nick with "::" prefix. Nick name,
    * with "::" prefix will be used on serialization to an attribute's name.
diff --git a/gxml/XParser.vala b/gxml/XParser.vala
index 189ba90..2a0fc4f 100644
--- a/gxml/XParser.vala
+++ b/gxml/XParser.vala
@@ -105,6 +105,22 @@ public class GXml.XParser : Object, GXml.Parser {
     read_node (_node);
     tr = null;
   }
+
+  public void read_child_nodes_stream (GLib.InputStream istream,
+                          GLib.Cancellable? cancellable = null) throws GLib.Error {
+    var b = new MemoryOutputStream.resizable ();
+    b.splice (istream, 0);
+    tr = new TextReader.for_memory ((char[]) b.data, (int) b.get_data_size (), "/gxml_memory");
+    read_child_nodes (_node);
+    tr = null;
+  }
+
+  public void read_child_nodes_string (string str, GLib.Cancellable? cancellable) throws GLib.Error {
+    if (str == "")
+      throw new ParserError.INVALID_DATA_ERROR (_("Invalid document string, it is empty or is not allowed"));
+    var stream = new GLib.MemoryInputStream.from_data (str.data);
+    read_child_nodes_stream (stream, cancellable);
+  }
   /**
    * Reads a node using current parser.
    */
@@ -114,17 +130,9 @@ public class GXml.XParser : Object, GXml.Parser {
     move_next_node ();
     if (node is DomElement) {
       while (true) {
-#if DEBUG
-        GLib.message ("Node's name: "+(node as DomElement).local_name.down ());
-        GLib.message ("Current Node's name: "+current_node_name ().down ());
-        GLib.message ("Current Node is Element: "+current_is_element ().to_string ());
-#endif
         if (current_is_element ()
             &&
             (current_node_name ().down () == (node as DomElement).local_name.down ())) {
-#if DEBUG
-          GLib.message ("Found Element node: "+current_node_name ());
-#endif
           break;
         }
         if (!current_is_document ()) {
@@ -134,17 +142,28 @@ public class GXml.XParser : Object, GXml.Parser {
       }
       read_element (node as DomElement);
     }
-#if DEBUG
-        GLib.message ("Parsing child nodes of: "+node.node_name);
-#endif
     if (current_is_element () && (node is DomDocument))
       read_child_element (node);
     else {
       if ((node as GomObject).parse_children)
         read_child_nodes (node);
+      else {
+        (node as GomObject).unparsed = read_unparsed ();
+        //warning ("Unparsed text: "+(node as GomObject).unparsed);
+        move_next_node ();
+      }
     }
   }
   /**
+   * Reads all child nodes as string
+   */
+  public string read_unparsed () throws GLib.Error {
+    if (tr == null)
+      throw new ParserError.INVALID_DATA_ERROR (_("Internal Error: No TextReader was set"));
+    string s = tr.read_inner_xml ();
+    return s;
+  }
+  /**
    * Use parser to go to next parsed node.
    */
   public bool move_next_node () throws GLib.Error {
@@ -299,13 +318,7 @@ public class GXml.XParser : Object, GXml.Parser {
       throw new ParserError.INVALID_DATA_ERROR (_("Internal Error: No TextReader was set"));
     bool cont = true;
     while (cont) {
-#if DEBUG
-      GLib.message ("Parent: "+parent.node_name+" Current node: "+current_node_name ());
-#endif
       if (!move_next_node ()) return;
-#if DEBUG
-      GLib.message ("Parent: "+parent.node_name+" Next Current child node: "+current_node_name ());
-#endif
       if (current_is_element ())
         cont = read_child_element (parent);
       else
diff --git a/test/GomElementTest.vala b/test/GomElementTest.vala
index 64ff3cf..e017882 100644
--- a/test/GomElementTest.vala
+++ b/test/GomElementTest.vala
@@ -23,6 +23,13 @@
 using GXml;
 
 class GomElementTest : GXmlTest  {
+       public class ParsedDelayed : GomElement {
+               construct {
+                       try { initialize ("root"); }
+                       catch (GLib.Error e) { warning ("Error: "+e.message); }
+                       parse_children = false;
+               }
+       }
        public static void add_tests () {
        Test.add_func ("/gxml/gom-element/read/namespace_uri", () => {
                        DomDocument doc = null;
@@ -197,5 +204,22 @@ class GomElementTest : GXmlTest  {
                    assert_not_reached ();
                  }
                });
+               Test.add_func ("/gxml/gom-element/parsed-delayed", () => {
+                       try {
+                               var n = new ParsedDelayed ();
+                               n.read_from_string ("<root><child p1=\"Value1\" 
p2=\"Value2\"><child2/></child></root>");
+                               assert (n.unparsed != null);
+                               assert (n.unparsed == "<child p1=\"Value1\" p2=\"Value2\"><child2/></child>");
+                               assert (!n.has_child_nodes ());
+                               assert (n.child_nodes.length == 0);
+                               (n as GomObject).read_unparsed ();
+                               assert (n.has_child_nodes ());
+                               assert (n.child_nodes.length == 1);
+                               assert (n.unparsed == null);
+                       } catch (GLib.Error e) {
+                   GLib.message ("Error: "+e.message);
+                   assert_not_reached ();
+                 }
+               });
        }
 }


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