diff options
author | Tomas Frydrych <tf@linux.intel.com> | 2011-01-31 15:15:36 +0000 |
---|---|---|
committer | Tomas Frydrych <tf@linux.intel.com> | 2011-02-10 12:12:34 +0000 |
commit | db9aefd94e376fb5a984bd59f860adb0abae532d (patch) | |
tree | cc36de9293294812aa0ecd9f3f6a1c8af315f855 | |
parent | 880049882106f92ab8db7befa3d6d66ab30d4c37 (diff) |
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
-rw-r--r-- | rest/Makefile.am | 2 | ||||
-rw-r--r-- | rest/rest-private.h | 7 | ||||
-rw-r--r-- | rest/rest-xml-node.c | 399 | ||||
-rw-r--r-- | rest/rest-xml-node.h | 75 | ||||
-rw-r--r-- | rest/rest-xml-parser.c | 215 | ||||
-rw-r--r-- | rest/rest-xml-parser.h | 36 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | 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; +} |