new method to find a "real" (ie, not comment or whitespace) xml node
authorDan Winship <danw@src.gnome.org>
Mon, 6 Nov 2006 20:35:28 +0000 (20:35 +0000)
committerDan Winship <danw@src.gnome.org>
Mon, 6 Nov 2006 20:35:28 +0000 (20:35 +0000)
* libsoup/soup-misc.c (soup_xml_real_node): new method to find a
"real" (ie, not comment or whitespace) xml node

* libsoup/soup-soap-response.c (parse_parameters)
(soup_soap_response_from_string)
(soup_soap_parameter_get_first_child)
(soup_soap_parameter_get_next_child): Use soup_xml_real_node.
Based on a patch from Andrew W. Nosenko.

* libsoup/soup-xmlrpc-message.c (soup_xmlrpc_message_from_string):
don't call xmlKeepBlanksDefault, which changes libxml's behavior
globally! Instead, use soup_xml_real_node() when traversing the
xml tree.

* libsoup/soup-xmlrpc-response.c
(soup_xmlrpc_response_from_string): don't call
xmlKeepBlanksDefault.
(exactly_one_child): rewrite in terms of soup_xml_real_node()
(which means it handles comments now as well)
(soup_xmlrpc_value_get_struct)
(soup_xmlrpc_value_array_get_iterator)
(soup_xmlrpc_value_array_iterator_prev)
(soup_xmlrpc_value_array_iterator_next): Use soup_xml_real_node.

ChangeLog
libsoup/soup-misc.c
libsoup/soup-misc.h
libsoup/soup-soap-response.c
libsoup/soup-xmlrpc-message.c
libsoup/soup-xmlrpc-response.c

index 273b470..e3c70b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2006-11-06  Dan Winship  <danw@novell.com>
+
+       * libsoup/soup-misc.c (soup_xml_real_node): new method to find a
+       "real" (ie, not comment or whitespace) xml node
+
+       * libsoup/soup-soap-response.c (parse_parameters) 
+       (soup_soap_response_from_string) 
+       (soup_soap_parameter_get_first_child) 
+       (soup_soap_parameter_get_next_child): Use soup_xml_real_node.
+       Based on a patch from Andrew W. Nosenko.
+
+       * libsoup/soup-xmlrpc-message.c (soup_xmlrpc_message_from_string):
+       don't call xmlKeepBlanksDefault, which changes libxml's behavior
+       globally! Instead, use soup_xml_real_node() when traversing the
+       xml tree.
+
+       * libsoup/soup-xmlrpc-response.c
+       (soup_xmlrpc_response_from_string): don't call
+       xmlKeepBlanksDefault.
+       (exactly_one_child): rewrite in terms of soup_xml_real_node()
+       (which means it handles comments now as well)
+       (soup_xmlrpc_value_get_struct)
+       (soup_xmlrpc_value_array_get_iterator)
+       (soup_xmlrpc_value_array_iterator_prev)
+       (soup_xmlrpc_value_array_iterator_next): Use soup_xml_real_node.
+
 2006-11-05  Dan Winship  <danw@novell.com>
 
        * libsoup/soup-headers.c (soup_headers_parse_request): document
index f3d194b..d98ff4a 100644 (file)
@@ -471,3 +471,20 @@ soup_add_timeout (GMainContext *async_context,
        return source;
 }
 
+/**
+ * soup_xml_real_node:
+ * @node: an %xmlNodePtr
+ *
+ * Finds the first "real" node (ie, not a comment or whitespace) at or
+ * after @node at its level in the tree.
+ *
+ * Return: a node, or %NULL
+ **/
+xmlNode *
+soup_xml_real_node (xmlNode *node)
+{
+       while (node && (node->type == XML_COMMENT_NODE ||
+                       xmlIsBlankNode (node)))
+               node = node->next;
+       return node;
+}
index 0398abe..2d739e3 100644 (file)
@@ -7,6 +7,7 @@
 #define SOUP_MISC_H 1
 
 #include <glib-object.h>
+#include <libxml/tree.h>
 
 /* Base64 encoding/decoding */
 
@@ -61,6 +62,8 @@ guint              soup_str_case_hash        (gconstpointer key);
 gboolean           soup_str_case_equal       (gconstpointer v1,
                                              gconstpointer v2);
 
+xmlNode           *soup_xml_real_node        (xmlNode      *node);
+
 /**
  * soup_ssl_supported:
  *
index 261b5cf..65b77aa 100644 (file)
@@ -104,7 +104,9 @@ parse_parameters (SoupSoapResponsePrivate *priv, xmlNodePtr xml_method)
 {
        xmlNodePtr tmp;
 
-       for (tmp = xml_method->xmlChildrenNode; tmp != NULL; tmp = tmp->next) {
+       for (tmp = soup_xml_real_node (xml_method->children);
+            tmp != NULL;
+            tmp = soup_xml_real_node (tmp->next)) {
                if (!strcmp ((const char *)tmp->name, "Fault")) {
                        priv->soap_fault = tmp;
                        continue;
@@ -130,7 +132,7 @@ soup_soap_response_from_string (SoupSoapResponse *response, const char *xmlstr)
 {
        SoupSoapResponsePrivate *priv;
        xmlDocPtr old_doc = NULL;
-       xmlNodePtr xml_root, xml_body = NULL, xml_method = NULL;
+       xmlNodePtr xml_root, xml_body, xml_method = NULL;
 
        g_return_val_if_fail (SOUP_IS_SOAP_RESPONSE (response), FALSE);
        priv = SOUP_SOAP_RESPONSE_GET_PRIVATE (response);
@@ -160,17 +162,17 @@ soup_soap_response_from_string (SoupSoapResponse *response, const char *xmlstr)
                return FALSE;
        }
 
-       if (xml_root->xmlChildrenNode != NULL) {
-               xml_body = xml_root->xmlChildrenNode;
+       xml_body = soup_xml_real_node (xml_root->children);
+       if (xml_body != NULL) {
                if (strcmp ((const char *)xml_body->name, "Header") == 0)
-                       xml_body = xml_root->xmlChildrenNode->next;
+                       xml_body = soup_xml_real_node (xml_body->next);
                if (strcmp ((const char *)xml_body->name, "Body") != 0) {
                        xmlFreeDoc (priv->xmldoc);
                        priv->xmldoc = old_doc;
                        return FALSE;
                }
 
-               xml_method = xml_body->xmlChildrenNode;
+               xml_method = soup_xml_real_node (xml_body->children);
 
                /* read all parameters */
                if (xml_method)
@@ -306,7 +308,7 @@ soup_soap_parameter_get_first_child (SoupSoapParameter *param)
 {
        g_return_val_if_fail (param != NULL, NULL);
 
-       return param->xmlChildrenNode ? param->xmlChildrenNode : NULL;
+       return soup_xml_real_node (param->children);
 }
 
 /**
@@ -356,7 +358,7 @@ soup_soap_parameter_get_next_child (SoupSoapParameter *param)
 {
        g_return_val_if_fail (param != NULL, NULL);
 
-       return param->next;
+       return soup_xml_real_node (param->next);
 }
 
 /**
index d623424..05100ef 100644 (file)
@@ -55,8 +55,6 @@ soup_xmlrpc_message_init (SoupXmlrpcMessage *msg)
 {
        SoupXmlrpcMessagePrivate *priv = SOUP_XMLRPC_MESSAGE_GET_PRIVATE (msg);
 
-       xmlKeepBlanksDefault (0);
-
        priv->doc = xmlNewDoc ((const xmlChar *)"1.0");
        priv->doc->standalone = FALSE;
        priv->doc->encoding = xmlCharStrdup ("UTF-8");
@@ -338,7 +336,6 @@ soup_xmlrpc_message_from_string (SoupXmlrpcMessage *message, const char *xmlstr)
        priv = SOUP_XMLRPC_MESSAGE_GET_PRIVATE (message);
        g_return_val_if_fail (xmlstr != NULL, FALSE);
 
-       xmlKeepBlanksDefault (0);
        newdoc = xmlParseMemory (xmlstr, strlen (xmlstr));
        if (!newdoc)
                return FALSE;
@@ -347,11 +344,11 @@ soup_xmlrpc_message_from_string (SoupXmlrpcMessage *message, const char *xmlstr)
        if (!body || strcmp ((const char *)body->name, "methodCall"))
                goto bad;
 
-       body = body->children;
+       body = soup_xml_real_node (body->children);
        if (!body || strcmp ((const char *)body->name, "methodName"))
                goto bad;
 
-       body = body->next;
+       body = soup_xml_real_node (body->next);
        if (!body || strcmp ((const char *)body->name, "params"))
                goto bad;
 
index b166610..1154c2b 100644 (file)
@@ -94,20 +94,11 @@ soup_xmlrpc_response_new_from_string (const char *xmlstr)
 static xmlNode *
 exactly_one_child (xmlNode *node)
 {
-       xmlNode *child, *tmp;
-
-       tmp = node->children;
-       while (tmp && xmlIsBlankNode (tmp))
-               tmp = tmp->next;
-
-       child = tmp;
-       if (tmp && tmp->next) {
-               tmp = tmp->next;
-               while (tmp && xmlIsBlankNode (tmp))
-                       tmp = tmp->next;
-               if (tmp)
-                       return NULL;
-       }
+       xmlNode *child;
+
+       child = soup_xml_real_node (node->children);
+       if (!child || soup_xml_real_node (child->next))
+               return NULL;
 
        return child;
 }
@@ -124,7 +115,6 @@ soup_xmlrpc_response_from_string (SoupXmlrpcResponse *response, const char *xmls
        priv = SOUP_XMLRPC_RESPONSE_GET_PRIVATE (response);
        g_return_val_if_fail (xmlstr != NULL, FALSE);
 
-       xmlKeepBlanksDefault (0);
        newdoc = xmlParseMemory (xmlstr, strlen (xmlstr));
        if (!newdoc)
                goto very_bad;
@@ -400,34 +390,41 @@ soup_xmlrpc_value_get_struct (SoupXmlrpcValue *value, GHashTable **table)
 
        t = g_hash_table_new_full (g_str_hash, g_str_equal, xmlFree, NULL);
 
-       for (xml = xml->children; xml; xml = xml->next) {
+       for (xml = soup_xml_real_node (xml->children);
+            xml;
+            xml = soup_xml_real_node (xml->next)) {
                xmlChar *name;
                xmlNode *val, *cur;
 
-               if (strcmp ((const char *)xml->name, "member") || !xml->children)
+               if (strcmp ((const char *)xml->name, "member") ||
+                   !xml->children)
                        goto bad;
 
                name = NULL;
                val = NULL;
 
-               for (cur = xml->children; cur; cur = cur->next) {
+               for (cur = soup_xml_real_node (xml->children);
+                    cur;
+                    cur = soup_xml_real_node (cur->next)) {
                        if (strcmp((const char *)cur->name, "name") == 0) {
                                if (name)
                                        goto local_bad;
                                name = xmlNodeGetContent (cur);
-                       }
-                       else if (strcmp ((const char *)cur->name, "value") == 0)
+                       } else if (strcmp ((const char *)cur->name, "value") == 0)
                                val = cur;
-                       else goto local_bad;
+                       else
+                               goto local_bad;
 
                        continue;
 local_bad:
-                       if (name) xmlFree (name);
+                       if (name)
+                               xmlFree (name);
                        goto bad;
                }
 
                if (!name || !val) {
-                       if (name) xmlFree (name);
+                       if (name)
+                               xmlFree (name);
                        goto bad;
                }
                g_hash_table_insert (t, name, val);
@@ -444,17 +441,21 @@ bad:
 gboolean
 soup_xmlrpc_value_array_get_iterator (SoupXmlrpcValue *value, SoupXmlrpcValueArrayIterator **iter)
 {
-       xmlNode *xml;
+       xmlNode *xml, *array, *data;
 
        xml = (xmlNode *) value;
 
-       if (!xml->children || strcmp((const char *)xml->children->name, "array") != 0 ||
-           xml->children->next || !xml->children->children ||
-           strcmp((const char *)xml->children->children->name, "data") != 0 ||
-           xml->children->children->next)
+       array = soup_xml_real_node (xml->children);
+       if (!array || strcmp((const char *)array->name, "array") != 0 ||
+           soup_xml_real_node (array->next))
+               return FALSE;
+
+       data = soup_xml_real_node (array->children);
+       if (!data || strcmp((const char *)data->name, "data") != 0 ||
+           soup_xml_real_node (data->next))
                return FALSE;
 
-       *iter = (SoupXmlrpcValueArrayIterator *) xml->children->children->children;
+       *iter = (SoupXmlrpcValueArrayIterator *) soup_xml_real_node (data->children);
        return TRUE;
 }
 
@@ -462,11 +463,15 @@ soup_xmlrpc_value_array_get_iterator (SoupXmlrpcValue *value, SoupXmlrpcValueArr
 SoupXmlrpcValueArrayIterator *
 soup_xmlrpc_value_array_iterator_prev (SoupXmlrpcValueArrayIterator *iter)
 {
-       xmlNode *xml;
+       xmlNode *xml, *prev;
 
        xml = (xmlNode *) iter;
 
-       return (SoupXmlrpcValueArrayIterator *) xml->prev;
+       prev = xml->prev;
+       while (prev != soup_xml_real_node (prev))
+               prev = prev->prev;
+
+       return (SoupXmlrpcValueArrayIterator *) prev;
 }
 
 SoupXmlrpcValueArrayIterator *
@@ -476,7 +481,7 @@ soup_xmlrpc_value_array_iterator_next (SoupXmlrpcValueArrayIterator *iter)
 
        xml = (xmlNode *) iter;
 
-       return (SoupXmlrpcValueArrayIterator *) xml->next;
+       return (SoupXmlrpcValueArrayIterator *) soup_xml_real_node (xml->next);
 }
 
 gboolean