[librest] xml-node: API for manually constructing and outputting XML



commit db9aefd94e376fb5a984bd59f860adb0abae532d
Author: Tomas Frydrych <tf linux intel com>
Date:   Mon Jan 31 15:15:36 2011 +0000

    xml-node: API for manually constructing and outputting XML
    
    Split out RestXmlNode into separate source files and added simple API for
    manually constructing tree of RextXmlNodes and converting such a tree to a
    string:
    
     * xml_node_add_child()
     * xml_node_add_attribute()
     * xml_node_set_content()
     * xml_node_print()
    
    Includes xml test for make check

 rest/Makefile.am       |    2 +
 rest/rest-private.h    |    7 +
 rest/rest-xml-node.c   |  399 ++++++++++++++++++++++++++++++++++++++++++++++++
 rest/rest-xml-node.h   |   75 +++++++++
 rest/rest-xml-parser.c |  215 +-------------------------
 rest/rest-xml-parser.h |   36 +-----
 tests/Makefile.am      |    3 +-
 tests/xml.c            |   85 ++++++++++
 8 files changed, 574 insertions(+), 248 deletions(-)
---
diff --git a/rest/Makefile.am b/rest/Makefile.am
index 09acd12..f3f8517 100644
--- a/rest/Makefile.am
+++ b/rest/Makefile.am
@@ -8,6 +8,7 @@ lib_sources = \
 	rest-proxy.c 			\
 	rest-proxy-call.c		\
 	rest-proxy-call-private.h	\
+	rest-xml-node.c			\
 	rest-xml-parser.c		\
 	rest-main.c			\
 	rest-private.h			\
@@ -28,6 +29,7 @@ lib_headers = \
 	oauth-proxy-call.h	\
 	oauth2-proxy.h		\
 	oauth2-proxy-call.h	\
+	rest-xml-node.h		\
 	rest-xml-parser.h
 
 lib_LTLIBRARIES = librest- API_VERSION@.la
diff --git a/rest/rest-private.h b/rest/rest-private.h
index 400ead2..b0f1fe4 100644
--- a/rest/rest-private.h
+++ b/rest/rest-private.h
@@ -26,6 +26,7 @@
 #include <glib.h>
 #include <rest/rest-proxy.h>
 #include <rest/rest-proxy-call.h>
+#include <rest/rest-xml-node.h>
 #include <libsoup/soup.h>
 
 G_BEGIN_DECLS
@@ -58,5 +59,11 @@ void _rest_proxy_cancel_message (RestProxy   *proxy,
                                  SoupMessage *message);
 guint _rest_proxy_send_message (RestProxy   *proxy,
                                 SoupMessage *message);
+
+RestXmlNode *_rest_xml_node_new (void);
+void         _rest_xml_node_reverse_children_siblings (RestXmlNode *node);
+RestXmlNode *_rest_xml_node_prepend (RestXmlNode *cur_node,
+                                     RestXmlNode *new_node);
+
 G_END_DECLS
 #endif /* _REST_PRIVATE */
diff --git a/rest/rest-xml-node.c b/rest/rest-xml-node.c
new file mode 100644
index 0000000..a691754
--- /dev/null
+++ b/rest/rest-xml-node.c
@@ -0,0 +1,399 @@
+/*
+ * librest - RESTful web services access
+ * Copyright (c) 2008, 2009, 2011, Intel Corporation.
+ *
+ * Authors: Rob Bradford <rob linux intel com>
+ *          Ross Burton <ross linux intel com>
+ *          Tomas Frydrych <tf linux intel com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "rest-xml-node.h"
+
+#define G(x) (gchar *)x
+
+static RestXmlNode *
+rest_xml_node_reverse_siblings (RestXmlNode *current)
+{
+  RestXmlNode *next;
+  RestXmlNode *prev = NULL;
+
+  while (current)
+  {
+    next = current->next;
+    current->next = prev;
+
+    prev = current;
+    current = next;
+  }
+
+  return prev;
+}
+
+void
+_rest_xml_node_reverse_children_siblings (RestXmlNode *node)
+{
+  GList *l, *children;
+  RestXmlNode *new_node;
+
+  children = g_hash_table_get_values (node->children);
+
+  for (l = children; l; l = l->next)
+  {
+    new_node = rest_xml_node_reverse_siblings ((RestXmlNode *)l->data);
+    g_hash_table_insert (node->children, new_node->name, new_node);
+  }
+
+  if (children)
+    g_list_free (children);
+}
+
+/*
+ * _rest_xml_node_prepend:
+ * @cur_node: a sibling #RestXmlNode to prepend the new before
+ * @new_node: new #RestXmlNode to prepend to the siblings list
+ *
+ * Prepends new_node to the list of siblings starting at cur_node.
+ *
+ * Return value: (transfer none): returns new start of the sibling list
+ */
+RestXmlNode *
+_rest_xml_node_prepend (RestXmlNode *cur_node, RestXmlNode *new_node)
+{
+  g_assert (new_node->next == NULL);
+  new_node->next = cur_node;
+
+  return new_node;
+}
+
+/*
+ * rest_xml_node_append_end:
+ * @cur_node: a member of the sibling #RestXmlNode list
+ * @new_node: new #RestXmlNode to append to the siblings list
+ *
+ * Appends new_node to end of the list of siblings containing cur_node.
+ */
+static void
+rest_xml_node_append_end (RestXmlNode *cur_node, RestXmlNode *new_node)
+{
+  RestXmlNode *tmp = cur_node;
+
+  g_return_if_fail (cur_node);
+
+  while (tmp->next)
+    tmp = tmp->next;
+
+  tmp->next = new_node;
+}
+
+GType
+rest_xml_node_get_type (void)
+{
+  static GType type = 0;
+  if (G_UNLIKELY (type == 0)) {
+    type = g_boxed_type_register_static ("RestXmlNode",
+                                         (GBoxedCopyFunc)rest_xml_node_ref,
+                                         (GBoxedFreeFunc)rest_xml_node_unref);
+  }
+  return type;
+}
+
+/*
+ * _rest_xml_node_new:
+ *
+ * Creates a new instance of #RestXmlNode.
+ *
+ * Return value: (transfer full): newly allocated #RestXmlNode.
+ */
+RestXmlNode *
+_rest_xml_node_new ()
+{
+  RestXmlNode *node;
+
+  node = g_slice_new0 (RestXmlNode);
+  node->ref_count = 1;
+  node->children = g_hash_table_new (NULL, NULL);
+  node->attrs = g_hash_table_new_full (g_str_hash,
+                                       g_str_equal,
+                                       g_free,
+                                       g_free);
+
+  return node;
+}
+
+/**
+ * rest_xml_node_ref:
+ * @node: a #RestXmlNode
+ *
+ * Increases the reference count of @node.
+ *
+ * Returns: the same @node.
+ */
+RestXmlNode *
+rest_xml_node_ref (RestXmlNode *node)
+{
+  g_return_val_if_fail (node, NULL);
+  g_return_val_if_fail (node->ref_count > 0, NULL);
+
+  g_atomic_int_inc (&node->ref_count);
+
+  return node;
+}
+
+/**
+ * rest_xml_node_unref:
+ * @node: a #RestXmlNode
+ *
+ * Decreases the reference count of @node. When its reference count drops to 0,
+ * the node is finalized (i.e. its memory is freed).
+ */
+void
+rest_xml_node_unref (RestXmlNode *node)
+{
+  GList *l;
+  RestXmlNode *next = NULL;
+  g_return_if_fail (node);
+  g_return_if_fail (node->ref_count > 0);
+
+  /* Try and unref the chain, this is equivalent to being tail recursively
+   * unreffing the next pointer
+   */
+  while (node && g_atomic_int_dec_and_test (&node->ref_count))
+  {
+      /*
+       * Save this pointer now since we are going to free the structure it
+       * contains soon.
+       */
+    next = node->next;
+
+    l = g_hash_table_get_values (node->children);
+    while (l)
+    {
+      rest_xml_node_unref ((RestXmlNode *)l->data);
+      l = g_list_delete_link (l, l);
+    }
+
+    g_hash_table_unref (node->children);
+    g_hash_table_unref (node->attrs);
+    g_free (node->content);
+    g_slice_free (RestXmlNode, node);
+
+    /*
+     * Free the next in the chain by updating node. If we're at the end or
+     * there are no siblings then the next = NULL definition deals with this
+     * case
+     */
+    node = next;
+  }
+}
+
+G_GNUC_DEPRECATED void
+rest_xml_node_free (RestXmlNode *node)
+{
+  rest_xml_node_unref (node);
+}
+
+/**
+ * rest_xml_node_get_attr:
+ * @node: a #RestXmlNode
+ * @attr_name: the name of an attribute
+ *
+ * Get the value of the attribute named @attr_name, or %NULL if it doesn't
+ * exist.
+ *
+ * Returns: the attribute value. This string is owned by #RestXmlNode and should
+ * not be freed.
+ */
+const gchar *
+rest_xml_node_get_attr (RestXmlNode *node,
+                        const gchar *attr_name)
+{
+  return g_hash_table_lookup (node->attrs, attr_name);
+}
+
+/**
+ * rest_xml_node_find:
+ * @start: a #RestXmlNode
+ * @tag: the name of a node
+ *
+ * Searches for the first child node of @start named @tag.
+ *
+ * Returns: the first child node, or %NULL if it doesn't exist.
+ */
+RestXmlNode *
+rest_xml_node_find (RestXmlNode *start,
+                    const gchar *tag)
+{
+  RestXmlNode *node;
+  RestXmlNode *tmp;
+  GQueue stack = G_QUEUE_INIT;
+  GList *children, *l;
+  const char *tag_interned;
+
+  g_return_val_if_fail (start, NULL);
+  g_return_val_if_fail (start->ref_count > 0, NULL);
+
+  tag_interned = g_intern_string (tag);
+
+  g_queue_push_head (&stack, start);
+
+  while ((node = g_queue_pop_head (&stack)) != NULL)
+  {
+    if ((tmp = g_hash_table_lookup (node->children, tag_interned)) != NULL)
+    {
+      g_queue_clear (&stack);
+      return tmp;
+    }
+
+    children = g_hash_table_get_values (node->children);
+    for (l = children; l; l = l->next)
+    {
+      g_queue_push_head (&stack, l->data);
+    }
+    g_list_free (children);
+  }
+
+  g_queue_clear (&stack);
+  return NULL;
+}
+
+/**
+ * rest_xml_node_print_node:
+ * @node: #RestXmlNode
+ *
+ * Recursively outputs given node and it's children.
+ *
+ * Return value: (transfer: full): xml string representing the node.
+ */
+char *
+rest_xml_node_print (RestXmlNode *node)
+{
+  GHashTableIter iter;
+  gpointer       key, value;
+  char          *xml = g_strconcat ("<", node->name, NULL);
+  RestXmlNode   *n;
+
+  g_hash_table_iter_init (&iter, node->attrs);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    xml = g_strconcat (xml, " ", key, "=\'", value, "\'", NULL);
+
+  xml = g_strconcat (xml, ">", NULL);
+
+  g_hash_table_iter_init (&iter, node->children);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      char *child = rest_xml_node_print ((RestXmlNode *) value);
+
+      xml = g_strconcat (xml, child, NULL);
+      g_free (child);
+    }
+
+  if (node->content)
+    xml = g_strconcat (xml, node->content, "</", node->name, ">", NULL);
+  else
+    xml = g_strconcat (xml, "</", node->name, ">", NULL);
+
+  for (n = node->next; n; n = n->next)
+    {
+      char *sibling = rest_xml_node_print (n);
+
+      xml = g_strconcat (xml, sibling, NULL);
+      g_free (sibling);
+    }
+
+  return xml;
+}
+
+/**
+ * rest_xml_node_add_child:
+ * @parent: parent #RestXmlNode, or %NULL for the top-level node
+ * @tag: name of the child node
+ *
+ * Adds a new node to the given parent node; to create the top-level node,
+ * parent should be %NULL.
+ *
+ * Return value: (transfer none): the newly added #RestXmlNode; the node object
+ * is owned by, and valid for the life time of, the #RestXmlCreator.
+ */
+RestXmlNode *
+rest_xml_node_add_child (RestXmlNode *parent, const char *tag)
+{
+  RestXmlNode *node;
+  char        *escaped;
+
+  g_return_val_if_fail (tag && *tag, NULL);
+
+  escaped = g_markup_escape_text (tag, -1);
+
+  node = _rest_xml_node_new ();
+  node->name = (char *) g_intern_string (escaped);
+
+  if (parent)
+    {
+      RestXmlNode *tmp_node;
+
+      tmp_node = g_hash_table_lookup (parent->children, node->name);
+
+      if (tmp_node)
+        {
+          rest_xml_node_append_end (tmp_node, node);
+        }
+      else
+        {
+          g_hash_table_insert (parent->children, G(node->name), node);
+        }
+    }
+
+  g_free (escaped);
+
+  return node;
+}
+
+/**
+ * rest_xml_node_add_attr:
+ * @node: #RestXmlNode to add attribute to
+ * @attribute: name of the attribute
+ * @value: value to set attribute to
+ *
+ * Adds attribute to the given node.
+ */
+void
+rest_xml_node_add_attr (RestXmlNode *node,
+                        const char  *attribute,
+                        const char  *value)
+{
+  g_return_if_fail (node && attribute && *attribute);
+
+  g_hash_table_insert (node->attrs,
+                       g_markup_escape_text (attribute, -1),
+                       g_markup_escape_text (value, -1));
+}
+
+/**
+ * rest_xml_node_set_content:
+ * @node: #RestXmlNode to set content
+ * @value: the content
+ *
+ * Sets content for the given node.
+ */
+void
+rest_xml_node_set_content (RestXmlNode *node, const char *value)
+{
+  g_return_if_fail (node && value && *value);
+
+  g_free (node->content);
+  node->content = g_markup_escape_text (value, -1);
+}
diff --git a/rest/rest-xml-node.h b/rest/rest-xml-node.h
new file mode 100644
index 0000000..6d34f7e
--- /dev/null
+++ b/rest/rest-xml-node.h
@@ -0,0 +1,75 @@
+/*
+ * librest - RESTful web services access
+ * Copyright (c) 2008, 2009, 2011 Intel Corporation.
+ *
+ * Authors: Rob Bradford <rob linux intel com>
+ *          Ross Burton <ross linux intel com>
+ *          Tomas Frydrych <tf linux intel com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _REST_XML_NODE
+#define _REST_XML_NODE
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define REST_TYPE_XML_NODE rest_xml_node_get_type ()
+
+/**
+ * RestXmlNode:
+ * @name: the name of the element
+ * @content: the textual content of the element
+ * @children: a #GHashTable of string name to #RestXmlNode for the children of
+ * the element.
+ * @attrs: a #GHashTable of string name to string values for the attributes of
+ * the element.
+ * @next: the sibling #RestXmlNode with the same name
+ */
+typedef struct _RestXmlNode RestXmlNode;
+struct _RestXmlNode {
+  /*< private >*/
+  volatile int ref_count;
+  /*< public >*/
+  gchar *name;
+  gchar *content;
+  GHashTable *children;
+  GHashTable *attrs;
+  RestXmlNode *next;
+};
+
+GType rest_xml_node_get_type (void);
+
+RestXmlNode *rest_xml_node_ref (RestXmlNode *node);
+void         rest_xml_node_unref (RestXmlNode *node);
+const gchar *rest_xml_node_get_attr (RestXmlNode *node,
+                                     const gchar *attr_name);
+RestXmlNode *rest_xml_node_find (RestXmlNode *start,
+                                 const gchar *tag);
+
+RestXmlNode *rest_xml_node_add_child (RestXmlNode *parent, const char *tag);
+char        *rest_xml_node_print (RestXmlNode *node);
+void         rest_xml_node_add_attr (RestXmlNode *node,
+                                     const char  *attribute,
+                                     const char  *value);
+void         rest_xml_node_set_content (RestXmlNode *node, const char *value);
+
+G_GNUC_DEPRECATED void rest_xml_node_free (RestXmlNode *node);
+
+G_END_DECLS
+
+#endif /* _REST_XML_NODE */
diff --git a/rest/rest-xml-parser.c b/rest/rest-xml-parser.c
index 0d78273..690d757 100644
--- a/rest/rest-xml-parser.c
+++ b/rest/rest-xml-parser.c
@@ -39,215 +39,6 @@ rest_xml_parser_init (RestXmlParser *self)
 {
 }
 
-static RestXmlNode *
-rest_xml_node_reverse_siblings (RestXmlNode *current)
-{
-  RestXmlNode *next;
-  RestXmlNode *prev = NULL;
-
-  while (current)
-  {
-    next = current->next;
-    current->next = prev;
-
-    prev = current;
-    current = next;
-  }
-
-  return prev;
-}
-
-static void
-rest_xml_node_reverse_children_siblings (RestXmlNode *node)
-{
-  GList *l, *children;
-  RestXmlNode *new_node;
-
-  children = g_hash_table_get_values (node->children);
-
-  for (l = children; l; l = l->next)
-  {
-    new_node = rest_xml_node_reverse_siblings ((RestXmlNode *)l->data);
-    g_hash_table_insert (node->children, new_node->name, new_node);
-  }
-
-  if (children)
-    g_list_free (children);
-}
-
-static RestXmlNode *
-rest_xml_node_prepend (RestXmlNode *cur_node, RestXmlNode *new_node)
-{
-  g_assert (new_node->next == NULL);
-  new_node->next = cur_node;
-
-  return new_node;
-}
-
-GType
-rest_xml_node_get_type (void)
-{
-  static GType type = 0;
-  if (G_UNLIKELY (type == 0)) {
-    type = g_boxed_type_register_static ("RestXmlNode",
-                                         (GBoxedCopyFunc)rest_xml_node_ref,
-                                         (GBoxedFreeFunc)rest_xml_node_unref);
-  }
-  return type;
-}
-
-static RestXmlNode *
-rest_xml_node_new ()
-{
-  RestXmlNode *node;
-
-  node = g_slice_new0 (RestXmlNode);
-  node->ref_count = 1;
-  node->children = g_hash_table_new (NULL, NULL);
-  node->attrs = g_hash_table_new_full (g_str_hash,
-                                       g_str_equal,
-                                       g_free,
-                                       g_free);
-
-  return node;
-}
-
-/**
- * rest_xml_node_ref:
- * @node: a #RestXmlNode
- *
- * Increases the reference count of @node.
- *
- * Returns: the same @node.
- */
-RestXmlNode *
-rest_xml_node_ref (RestXmlNode *node)
-{
-  g_return_val_if_fail (node, NULL);
-  g_return_val_if_fail (node->ref_count > 0, NULL);
-
-  g_atomic_int_inc (&node->ref_count);
-
-  return node;
-}
-
-/**
- * rest_xml_node_unref:
- * @node: a #RestXmlNode
- *
- * Decreases the reference count of @node. When its reference count drops to 0,
- * the node is finalized (i.e. its memory is freed).
- */
-void
-rest_xml_node_unref (RestXmlNode *node)
-{
-  GList *l;
-  RestXmlNode *next = NULL;
-  g_return_if_fail (node);
-  g_return_if_fail (node->ref_count > 0);
-
-  /* Try and unref the chain, this is equivalent to being tail recursively
-   * unreffing the next pointer
-   */
-  while (node && g_atomic_int_dec_and_test (&node->ref_count))
-  {
-      /*
-       * Save this pointer now since we are going to free the structure it
-       * contains soon.
-       */
-    next = node->next;
-
-    l = g_hash_table_get_values (node->children);
-    while (l)
-    {
-      rest_xml_node_unref ((RestXmlNode *)l->data);
-      l = g_list_delete_link (l, l);
-    }
-
-    g_hash_table_unref (node->children);
-    g_hash_table_unref (node->attrs);
-    g_free (node->content);
-    g_slice_free (RestXmlNode, node);
-
-    /*
-     * Free the next in the chain by updating node. If we're at the end or
-     * there are no siblings then the next = NULL definition deals with this
-     * case
-     */
-    node = next;
-  }
-}
-
-G_GNUC_DEPRECATED void
-rest_xml_node_free (RestXmlNode *node)
-{
-  rest_xml_node_unref (node);
-}
-
-/**
- * rest_xml_node_get_attr:
- * @node: a #RestXmlNode
- * @attr_name: the name of an attribute
- *
- * Get the value of the attribute named @attr_name, or %NULL if it doesn't
- * exist.
- *
- * Returns: the attribute value. This string is owned by #RestXmlNode and should
- * not be freed.
- */
-const gchar *
-rest_xml_node_get_attr (RestXmlNode *node, 
-                        const gchar *attr_name)
-{
-  return g_hash_table_lookup (node->attrs, attr_name);
-}
-
-/**
- * rest_xml_node_find:
- * @start: a #RestXmlNode
- * @tag: the name of a node
- *
- * Searches for the first child node of @start named @tag.
- *
- * Returns: the first child node, or %NULL if it doesn't exist.
- */
-RestXmlNode *
-rest_xml_node_find (RestXmlNode *start,
-                    const gchar *tag)
-{
-  RestXmlNode *node;
-  RestXmlNode *tmp;
-  GQueue stack = G_QUEUE_INIT;
-  GList *children, *l;
-  const char *tag_interned;
-
-  g_return_val_if_fail (start, NULL);
-  g_return_val_if_fail (start->ref_count > 0, NULL);
-
-  tag_interned = g_intern_string (tag);
-
-  g_queue_push_head (&stack, start);
-
-  while ((node = g_queue_pop_head (&stack)) != NULL)
-  {
-    if ((tmp = g_hash_table_lookup (node->children, tag_interned)) != NULL)
-    {
-      g_queue_clear (&stack);
-      return tmp;
-    }
-
-    children = g_hash_table_get_values (node->children);
-    for (l = children; l; l = l->next)
-    {
-      g_queue_push_head (&stack, l->data);
-    }
-    g_list_free (children);
-  }
-
-  g_queue_clear (&stack);
-  return NULL;
-}
-
 /**
  * rest_xml_parser_new:
  *
@@ -310,7 +101,7 @@ rest_xml_parser_parse_from_data (RestXmlParser *parser,
 
         /* Create our new node for this tag */
 
-        new_node = rest_xml_node_new ();
+        new_node = _rest_xml_node_new ();
         new_node->name = G (g_intern_string (name));
 
         if (!root_node)
@@ -332,7 +123,7 @@ rest_xml_parser_parse_from_data (RestXmlParser *parser,
                               "Prepending to the list.");
             g_hash_table_insert (cur_node->children, 
                                  G(tmp_node->name),
-                                 rest_xml_node_prepend (tmp_node, new_node));
+                                 _rest_xml_node_prepend (tmp_node, new_node));
           } else {
             REST_DEBUG (XML_PARSER, "Unseen name. Adding to the children table.");
             g_hash_table_insert (cur_node->children,
@@ -386,7 +177,7 @@ rest_xml_parser_parse_from_data (RestXmlParser *parser,
 
         /* For those children that have siblings, reverse the siblings */
         node = (RestXmlNode *)g_queue_pop_head (&nodes);
-        rest_xml_node_reverse_children_siblings (node);
+        _rest_xml_node_reverse_children_siblings (node);
 
         /* Update the current node to the new top of the stack */
         cur_node = (RestXmlNode *)g_queue_peek_head (&nodes);
diff --git a/rest/rest-xml-parser.h b/rest/rest-xml-parser.h
index 967c2cf..a8f51ee 100644
--- a/rest/rest-xml-parser.h
+++ b/rest/rest-xml-parser.h
@@ -24,6 +24,7 @@
 #define _REST_XML_PARSER
 
 #include <glib-object.h>
+#include <rest/rest-xml-node.h>
 
 G_BEGIN_DECLS
 
@@ -44,8 +45,6 @@ G_BEGIN_DECLS
 #define REST_XML_PARSER_GET_CLASS(obj) \
   (G_TYPE_INSTANCE_GET_CLASS ((obj), REST_TYPE_XML_PARSER, RestXmlParserClass))
 
-#define REST_TYPE_XML_NODE rest_xml_node_get_type ()
-
 typedef struct {
   GObject parent;
 } RestXmlParser;
@@ -54,28 +53,6 @@ typedef struct {
   GObjectClass parent_class;
 } RestXmlParserClass;
 
-/**
- * RestXmlNode:
- * @name: the name of the element
- * @content: the textual content of the element
- * @children: a #GHashTable of string name to #RestXmlNode for the children of
- * the element.
- * @attrs: a #GHashTable of string name to string values for the attributes of
- * the element.
- * @next: the sibling #RestXmlNode with the same name
- */
-typedef struct _RestXmlNode RestXmlNode;
-struct _RestXmlNode {
-  /*< private >*/
-  volatile int ref_count;
-  /*< public >*/
-  gchar *name;
-  gchar *content;
-  GHashTable *children;
-  GHashTable *attrs;
-  RestXmlNode *next;
-};
-
 GType rest_xml_parser_get_type (void);
 
 RestXmlParser *rest_xml_parser_new (void);
@@ -83,17 +60,6 @@ RestXmlNode *rest_xml_parser_parse_from_data (RestXmlParser *parser,
                                               const gchar   *data,
                                               goffset        len);
 
-GType rest_xml_node_get_type (void);
-
-RestXmlNode * rest_xml_node_ref (RestXmlNode *node);
-void rest_xml_node_unref (RestXmlNode *node);
-G_GNUC_DEPRECATED void rest_xml_node_free (RestXmlNode *node);
-
-const gchar *rest_xml_node_get_attr (RestXmlNode *node,
-                                     const gchar *attr_name);
-RestXmlNode *rest_xml_node_find (RestXmlNode *start,
-                                 const gchar *tag);
-
 G_END_DECLS
 
 #endif /* _REST_XML_PARSER */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 77d39c9..f159d14 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
-TESTS = proxy proxy-continuous threaded oauth oauth-async oauth2 flickr lastfm
+TESTS = proxy proxy-continuous threaded oauth oauth-async oauth2 flickr lastfm xml
 
 AM_CPPFLAGS = $(SOUP_CFLAGS) -I$(top_srcdir) $(GCOV_CFLAGS)
 AM_LDFLAGS = $(SOUP_LIBS) $(GCOV_LDFLAGS) \
@@ -14,3 +14,4 @@ oauth_async_SOURCES = oauth-async.c
 oauth2_SOURCES = oauth2.c
 flickr_SOURCES = flickr.c
 lastfm_SOURCES = lastfm.c
+xml_SOURCES = xml.c
diff --git a/tests/xml.c b/tests/xml.c
new file mode 100644
index 0000000..4a5f2c0
--- /dev/null
+++ b/tests/xml.c
@@ -0,0 +1,85 @@
+/*
+ * librest - RESTful web services access
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * Author: Tomas Frydrych <tf linux intel com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <rest/rest-xml-parser.h>
+
+#include <string.h>
+
+#define TEST_XML "<node0 a00=\'v00\' a01=\'v01\'><node1 a10=\'v10\'></node1><node1 a10=\'v10\'></node1>Cont0</node0>"
+
+int
+main (int argc, char **argv)
+{
+  GError *error = NULL;
+  RestXmlParser *parser;
+  RestXmlNode *root, *node;
+  char *xml;
+
+  g_thread_init (NULL);
+  g_type_init ();
+
+  parser = rest_xml_parser_new ();
+
+  root = rest_xml_parser_parse_from_data (parser, TEST_XML, strlen (TEST_XML));
+  g_assert (root);
+
+  xml = rest_xml_node_print (root);
+
+  g_assert (xml);
+
+  if (strcmp (TEST_XML, xml))
+    {
+      g_error ("Generated output for parsed XML does not match:\n"
+               "in:  %s\n"
+               "out: %s\n",
+               TEST_XML, xml);
+    }
+
+  rest_xml_node_unref (root);
+
+  root = rest_xml_node_add_child (NULL, "node0");
+  rest_xml_node_add_attr (root, "a00", "v00");
+  rest_xml_node_add_attr (root, "a01", "v01");
+
+  node = rest_xml_node_add_child (root, "node1");
+  rest_xml_node_add_attr (node, "a10", "v10");
+
+  node = rest_xml_node_add_child (root, "node1");
+  rest_xml_node_add_attr (node, "a10", "v10");
+
+  rest_xml_node_set_content (root, "Cont0");
+
+  xml = rest_xml_node_print (root);
+
+  g_assert (xml);
+
+  if (strcmp (TEST_XML, xml))
+    {
+      g_error ("Generated output for constructed XML does not match:\n"
+               "in:  %s\n"
+               "out: %s\n",
+               TEST_XML, xml);
+    }
+
+  rest_xml_node_unref (root);
+
+  return 0;
+}



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