[libgdata] [core] Add namespace checks to all parse_xml() functions



commit 469f55d88d624252641aeb76b6703a208b740c8b
Author: Philip Withnall <philip tecnocode co uk>
Date:   Wed Mar 24 23:35:49 2010 +0000

    [core] Add namespace checks to all parse_xml() functions
    
    This should (theoretically, though untested) speed up parsing a little, since
    whole chunks of unrelated elements can now be skipped at once in the search
    for the right element.
    
    Important: these changes accidentally fix the behaviour of
    gdata_entry_get_id() for #GDataPicasaWebAlbum, which was returning incorrect
    results before. Any applications which depend on the broken behaviour should
    be updated to deal with the correct form IDs (i.e. URIs), or use a new
    gdata_picasaweb_album_get_id() function which will be added shortly.

 gdata/atom/gdata-author.c                         |    8 +-
 gdata/exif/gdata-exif-tags.c                      |   12 +-
 gdata/gd/gdata-gd-name.c                          |   13 +-
 gdata/gd/gdata-gd-organization.c                  |   15 +-
 gdata/gd/gdata-gd-postal-address.c                |   23 +-
 gdata/gd/gdata-gd-when.c                          |    3 +-
 gdata/gdata-access-rule.c                         |   63 +++---
 gdata/gdata-entry.c                               |   44 ++--
 gdata/gdata-feed.c                                |  166 +++++++------
 gdata/gdata-parser.c                              |   23 ++-
 gdata/gdata-parser.h                              |    3 +
 gdata/georss/gdata-georss-where.c                 |    9 +-
 gdata/media/gdata-media-group.c                   |  140 ++++++------
 gdata/services/calendar/gdata-calendar-calendar.c |  111 +++++----
 gdata/services/calendar/gdata-calendar-event.c    |  217 +++++++++--------
 gdata/services/calendar/gdata-calendar-feed.c     |    6 +-
 gdata/services/contacts/gdata-contacts-contact.c  |   96 ++++----
 gdata/services/documents/gdata-documents-entry.c  |   75 +++---
 gdata/services/documents/gdata-documents-feed.c   |   10 +-
 gdata/services/picasaweb/gdata-picasaweb-album.c  |  170 +++++++------
 gdata/services/picasaweb/gdata-picasaweb-feed.c   |  107 +++++----
 gdata/services/picasaweb/gdata-picasaweb-file.c   |  153 +++++++------
 gdata/services/picasaweb/gdata-picasaweb-user.c   |    8 +-
 gdata/services/youtube/gdata-youtube-control.c    |   11 +-
 gdata/services/youtube/gdata-youtube-group.c      |   61 +++---
 gdata/services/youtube/gdata-youtube-video.c      |  271 +++++++++++----------
 gdata/tests/picasaweb.c                           |    4 +-
 27 files changed, 963 insertions(+), 859 deletions(-)
---
diff --git a/gdata/atom/gdata-author.c b/gdata/atom/gdata-author.c
index 17c0a45..f88f6f5 100644
--- a/gdata/atom/gdata-author.c
+++ b/gdata/atom/gdata-author.c
@@ -193,9 +193,11 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataAuthorPrivate *priv = GDATA_AUTHOR (parsable)->priv;
 
-	if (gdata_parser_string_from_element (node, "name", P_NO_DUPES | P_REQUIRED | P_NON_EMPTY, &(priv->name), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "uri", P_NO_DUPES | P_REQUIRED | P_NON_EMPTY, &(priv->uri), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "email", P_NO_DUPES | P_REQUIRED | P_NON_EMPTY, &(priv->email_address), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2005/Atom";) == TRUE && (
+	     gdata_parser_string_from_element (node, "name", P_NO_DUPES | P_REQUIRED | P_NON_EMPTY, &(priv->name), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "uri", P_NO_DUPES | P_REQUIRED | P_NON_EMPTY, &(priv->uri), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "email", P_NO_DUPES | P_REQUIRED | P_NON_EMPTY, &(priv->email_address), &success, error) == TRUE
+	    )) {
 		return success;
 	} else {
 		return GDATA_PARSABLE_CLASS (gdata_author_parent_class)->parse_xml (parsable, doc, node, user_data, error);
diff --git a/gdata/exif/gdata-exif-tags.c b/gdata/exif/gdata-exif-tags.c
index 03f094d..4139f6a 100644
--- a/gdata/exif/gdata-exif-tags.c
+++ b/gdata/exif/gdata-exif-tags.c
@@ -109,6 +109,9 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataExifTags *self = GDATA_EXIF_TAGS (parsable);
 
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/photos/exif/2007";) == FALSE)
+		return GDATA_PARSABLE_CLASS (gdata_exif_tags_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+
 	if (xmlStrcmp (node->name, (xmlChar*) "distance") == 0 ) {
 		/* exif:distance */
 		xmlChar *distance = xmlNodeListGetString (doc, node->children, TRUE);
@@ -120,8 +123,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		self->priv->fstop = g_ascii_strtod ((gchar*) fstop, NULL);
 		xmlFree (fstop);
 	} else if (gdata_parser_string_from_element (node, "make", P_NONE, &(self->priv->make), &success, error) == TRUE ||
-	           gdata_parser_string_from_element (node, "model", P_NONE, &(self->priv->model), &success, error) == TRUE ||
-	           gdata_parser_string_from_element (node, "imageUniqueID", P_NONE, &(self->priv->image_unique_id), &success, error) == TRUE) {
+		   gdata_parser_string_from_element (node, "model", P_NONE, &(self->priv->model), &success, error) == TRUE ||
+		   gdata_parser_string_from_element (node, "imageUniqueID", P_NONE, &(self->priv->image_unique_id), &success, error) == TRUE) {
 		return success;
 	} else if (xmlStrcmp (node->name, (xmlChar*) "exposure") == 0) {
 		/* exif:exposure */
@@ -156,9 +159,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 
 		self->priv->_time.tv_sec = (glong) (milliseconds / 1000);
 		self->priv->_time.tv_usec = (glong) ((milliseconds % 1000) * 1000);
-	} else if (GDATA_PARSABLE_CLASS (gdata_exif_tags_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_exif_tags_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/gd/gdata-gd-name.c b/gdata/gd/gdata-gd-name.c
index 689aeb8..ddf843b 100644
--- a/gdata/gd/gdata-gd-name.c
+++ b/gdata/gd/gdata-gd-name.c
@@ -280,12 +280,13 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataGDNamePrivate *priv = GDATA_GD_NAME (parsable)->priv;
 
-	if (gdata_parser_string_from_element (node, "givenName", P_NO_DUPES, &(priv->given_name), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "additionalName", P_NO_DUPES, &(priv->additional_name), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "familyName", P_NO_DUPES, &(priv->family_name), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "namePrefix", P_NO_DUPES, &(priv->prefix), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "nameSuffix", P_NO_DUPES, &(priv->suffix), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "fullName", P_NO_DUPES, &(priv->full_name), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE && (
+	     gdata_parser_string_from_element (node, "givenName", P_NO_DUPES, &(priv->given_name), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "additionalName", P_NO_DUPES, &(priv->additional_name), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "familyName", P_NO_DUPES, &(priv->family_name), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "namePrefix", P_NO_DUPES, &(priv->prefix), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "nameSuffix", P_NO_DUPES, &(priv->suffix), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "fullName", P_NO_DUPES, &(priv->full_name), &success, error) == TRUE)) {
 		return success;
 	} else {
 		return GDATA_PARSABLE_CLASS (gdata_gd_name_parent_class)->parse_xml (parsable, doc, node, user_data, error);
diff --git a/gdata/gd/gdata-gd-organization.c b/gdata/gd/gdata-gd-organization.c
index 8fa64e3..a23b7c9 100644
--- a/gdata/gd/gdata-gd-organization.c
+++ b/gdata/gd/gdata-gd-organization.c
@@ -387,13 +387,14 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataGDOrganizationPrivate *priv = GDATA_GD_ORGANIZATION (parsable)->priv;
 
-	if (gdata_parser_string_from_element (node, "orgName", P_NO_DUPES, &(priv->name), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "orgTitle", P_NO_DUPES, &(priv->title), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "orgDepartment", P_NO_DUPES, &(priv->department), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "orgJobDescription", P_NO_DUPES, &(priv->job_description), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "orgSymbol", P_NO_DUPES, &(priv->symbol), &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "where", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_GD_WHERE,
-	                                      &(priv->location), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE && (
+	     gdata_parser_string_from_element (node, "orgName", P_NO_DUPES, &(priv->name), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "orgTitle", P_NO_DUPES, &(priv->title), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "orgDepartment", P_NO_DUPES, &(priv->department), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "orgJobDescription", P_NO_DUPES, &(priv->job_description), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "orgSymbol", P_NO_DUPES, &(priv->symbol), &success, error) == TRUE ||
+	     gdata_parser_object_from_element (node, "where", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_GD_WHERE,
+	                                      &(priv->location), &success, error) == TRUE)) {
 		return success;
 	} else {
 		return GDATA_PARSABLE_CLASS (gdata_gd_organization_parent_class)->parse_xml (parsable, doc, node, user_data, error);
diff --git a/gdata/gd/gdata-gd-postal-address.c b/gdata/gd/gdata-gd-postal-address.c
index 4c21557..98f2bc9 100644
--- a/gdata/gd/gdata-gd-postal-address.c
+++ b/gdata/gd/gdata-gd-postal-address.c
@@ -574,17 +574,18 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataGDPostalAddressPrivate *priv = GDATA_GD_POSTAL_ADDRESS (parsable)->priv;
 
-	if (gdata_parser_string_from_element (node, "agent", P_NO_DUPES, &(priv->agent), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "housename", P_NO_DUPES, &(priv->house_name), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "pobox", P_NO_DUPES, &(priv->po_box), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "street", P_NO_DUPES, &(priv->street), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "neighborhood", P_NO_DUPES, &(priv->neighborhood), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "city", P_NO_DUPES, &(priv->city), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "subregion", P_NO_DUPES, &(priv->subregion), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "region", P_NO_DUPES, &(priv->region), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "postcode", P_NO_DUPES, &(priv->postcode), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "country", P_NO_DUPES, &(priv->country), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "formattedAddress", P_NO_DUPES, &(priv->formatted_address), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE && (
+	     gdata_parser_string_from_element (node, "agent", P_NO_DUPES, &(priv->agent), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "housename", P_NO_DUPES, &(priv->house_name), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "pobox", P_NO_DUPES, &(priv->po_box), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "street", P_NO_DUPES, &(priv->street), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "neighborhood", P_NO_DUPES, &(priv->neighborhood), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "city", P_NO_DUPES, &(priv->city), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "subregion", P_NO_DUPES, &(priv->subregion), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "region", P_NO_DUPES, &(priv->region), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "postcode", P_NO_DUPES, &(priv->postcode), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "country", P_NO_DUPES, &(priv->country), &success, error) == TRUE ||
+	     gdata_parser_string_from_element (node, "formattedAddress", P_NO_DUPES, &(priv->formatted_address), &success, error) == TRUE)) {
 		return success;
 	} else {
 		return GDATA_PARSABLE_CLASS (gdata_gd_postal_address_parent_class)->parse_xml (parsable, doc, node, user_data, error);
diff --git a/gdata/gd/gdata-gd-when.c b/gdata/gd/gdata-gd-when.c
index 1ca161b..361dc2a 100644
--- a/gdata/gd/gdata-gd-when.c
+++ b/gdata/gd/gdata-gd-when.c
@@ -293,7 +293,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 {
 	gboolean success;
 
-	if (gdata_parser_object_from_element_setter (node, "reminder", P_REQUIRED, GDATA_TYPE_GD_REMINDER,
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE &&
+	    gdata_parser_object_from_element_setter (node, "reminder", P_REQUIRED, GDATA_TYPE_GD_REMINDER,
 	                                             gdata_gd_when_add_reminder, parsable, &success, error) == TRUE) {
 		return success;
 	} else {
diff --git a/gdata/gdata-access-rule.c b/gdata/gdata-access-rule.c
index 618b30a..29f6ce3 100644
--- a/gdata/gdata-access-rule.c
+++ b/gdata/gdata-access-rule.c
@@ -206,40 +206,37 @@ gdata_access_rule_finalize (GObject *object)
 static gboolean
 parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
 {
-	GDataAccessRule *self;
-
-	g_return_val_if_fail (GDATA_IS_ACCESS_RULE (parsable), FALSE);
-	g_return_val_if_fail (doc != NULL, FALSE);
-	g_return_val_if_fail (node != NULL, FALSE);
-
-	self = GDATA_ACCESS_RULE (parsable);
-
-	if (xmlStrcmp (node->name, (xmlChar*) "role") == 0) {
-		/* gAcl:role */
-		xmlChar *role = xmlGetProp (node, (xmlChar*) "value");
-		if (role == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->role = (gchar*) role;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "scope") == 0) {
-		/* gAcl:scope */
-		xmlChar *scope_type, *scope_value;
-
-		scope_type = xmlGetProp (node, (xmlChar*) "type");
-		if (scope_type == NULL)
-			return gdata_parser_error_required_property_missing (node, "type", error);
-
-		scope_value = xmlGetProp (node, (xmlChar*) "value");
-
-		if (xmlStrcmp (scope_type, (xmlChar*) "default") == 0 && scope_value == NULL) {
-			xmlFree (scope_type);
-			return gdata_parser_error_required_property_missing (node, "value", error);
+	GDataAccessRule *self = GDATA_ACCESS_RULE (parsable);
+
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/acl/2007";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "role") == 0) {
+			/* gAcl:role */
+			xmlChar *role = xmlGetProp (node, (xmlChar*) "value");
+			if (role == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->role = (gchar*) role;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "scope") == 0) {
+			/* gAcl:scope */
+			xmlChar *scope_type, *scope_value;
+
+			scope_type = xmlGetProp (node, (xmlChar*) "type");
+			if (scope_type == NULL)
+				return gdata_parser_error_required_property_missing (node, "type", error);
+
+			scope_value = xmlGetProp (node, (xmlChar*) "value");
+
+			if (xmlStrcmp (scope_type, (xmlChar*) "default") == 0 && scope_value == NULL) {
+				xmlFree (scope_type);
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			}
+
+			self->priv->scope_type = (gchar*) scope_type;
+			self->priv->scope_value = (gchar*) scope_value;
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
-
-		self->priv->scope_type = (gchar*) scope_type;
-		self->priv->scope_value = (gchar*) scope_value;
-	} else if (GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/gdata-entry.c b/gdata/gdata-entry.c
index e5ec364..7a8cbe6 100644
--- a/gdata/gdata-entry.c
+++ b/gdata/gdata-entry.c
@@ -375,27 +375,29 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataEntryPrivate *priv = GDATA_ENTRY (parsable)->priv;
 
-	if (gdata_parser_string_from_element (node, "title", P_DEFAULT, &(priv->title), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "id", P_REQUIRED | P_NON_EMPTY | P_NO_DUPES, &(priv->id), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "summary", P_NONE, &(priv->summary), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "rights", P_NONE, &(priv->rights), &success, error) == TRUE ||
-	    gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(priv->updated), &success, error) == TRUE ||
-	    gdata_parser_time_val_from_element (node, "published", P_REQUIRED | P_NO_DUPES, &(priv->published), &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
-	                                             gdata_entry_add_category, parsable, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
-	                                             gdata_entry_add_link, parsable, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
-	                                             gdata_entry_add_author, parsable, &success, error) == TRUE) {
-		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "content") == 0) {
-		/* atom:content */
-		xmlChar *content = xmlNodeListGetString (doc, node->children, TRUE);
-		if (content == NULL)
-			content = xmlGetProp (node, (xmlChar*) "src");
-		priv->content = (gchar*) content;
-
-		return TRUE;
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2005/Atom";) == TRUE) {
+		if (gdata_parser_string_from_element (node, "title", P_DEFAULT, &(priv->title), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "id", P_REQUIRED | P_NON_EMPTY | P_NO_DUPES, &(priv->id), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "summary", P_NONE, &(priv->summary), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "rights", P_NONE, &(priv->rights), &success, error) == TRUE ||
+		    gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(priv->updated), &success, error) == TRUE ||
+		    gdata_parser_time_val_from_element (node, "published", P_REQUIRED | P_NO_DUPES, &(priv->published), &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
+			                                     gdata_entry_add_category, parsable, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
+			                                     gdata_entry_add_link, parsable, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
+			                                     gdata_entry_add_author, parsable, &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "content") == 0) {
+			/* atom:content */
+			xmlChar *content = xmlNodeListGetString (doc, node->children, TRUE);
+			if (content == NULL)
+				content = xmlGetProp (node, (xmlChar*) "src");
+			priv->content = (gchar*) content;
+
+			return TRUE;
+		}
 	}
 
 	return GDATA_PARSABLE_CLASS (gdata_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error);
diff --git a/gdata/gdata-feed.c b/gdata/gdata-feed.c
index 65f91cf..b2ac68c 100644
--- a/gdata/gdata-feed.c
+++ b/gdata/gdata-feed.c
@@ -412,86 +412,92 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 
 	self = GDATA_FEED (parsable);
 
-	if (xmlStrcmp (node->name, (xmlChar*) "entry") == 0) {
-		/* atom:entry */
-		GDataEntry *entry;
-		GType entry_type;
-
-		/* Allow @data to be %NULL, and assume we're parsing a vanilla feed, so that we can test #GDataFeed in tests/general.c. A little hacky,
-		 * but not too much so, and valuable for testing. */
-		entry_type = (data != NULL) ? data->entry_type : GDATA_TYPE_ENTRY;
-		entry = GDATA_ENTRY (_gdata_parsable_new_from_xml_node (entry_type, doc, node, NULL, error));
-		if (entry == NULL)
-			return FALSE;
-
-		/* Calls the callbacks in the main thread */
-		if (data != NULL)
-			_gdata_feed_call_progress_callback (self, data, entry);
-		_gdata_feed_add_entry (self, entry);
-	} else if (gdata_parser_string_from_element (node, "title", P_NO_DUPES, &(self->priv->title), &success, error) == TRUE ||
-	           gdata_parser_string_from_element (node, "subtitle", P_NO_DUPES, &(self->priv->subtitle), &success, error) == TRUE ||
-	           gdata_parser_string_from_element (node, "id", P_NO_DUPES, &(self->priv->id), &success, error) == TRUE ||
-	           gdata_parser_string_from_element (node, "logo", P_NO_DUPES, &(self->priv->logo), &success, error) == TRUE ||
-	           gdata_parser_string_from_element (node, "icon", P_NO_DUPES, &(self->priv->icon), &success, error) == TRUE ||
-	           gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
-	                                                    _gdata_feed_add_category, self, &success, error) == TRUE ||
-	           gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
-	                                                    _gdata_feed_add_link, self, &success, error) == TRUE ||
-	           gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
-	                                                    _gdata_feed_add_author, self, &success, error) == TRUE ||
-	           gdata_parser_object_from_element (node, "generator", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_GENERATOR,
-	                                             &(self->priv->generator), &success, error) == TRUE ||
-	           gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(self->priv->updated), &success, error) == TRUE) {
-		return success;
-	/*TODO for atom:id: xmlStrcmp (node->ns->href, (xmlChar*) "http://www.w3.org/2005/Atom";) == 0) {*/
-	} else if (xmlStrcmp (node->name, (xmlChar*) "totalResults") == 0) {
-		/* openSearch:totalResults */
-		xmlChar *total_results_string;
-
-		/* Duplicate checking */
-		if (self->priv->total_results != 0)
-			return gdata_parser_error_duplicate_element (node, error);
-
-		/* Parse the number */
-		total_results_string = xmlNodeListGetString (doc, node->children, TRUE);
-		if (total_results_string == NULL)
-			return gdata_parser_error_required_content_missing (node, error);
-
-		self->priv->total_results = strtoul ((gchar*) total_results_string, NULL, 10);
-		xmlFree (total_results_string);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "startIndex") == 0) {
-		/* openSearch:startIndex */
-		xmlChar *start_index_string;
-
-		/* Duplicate checking */
-		if (self->priv->start_index != 0)
-			return gdata_parser_error_duplicate_element (node, error);
-
-		/* Parse the number */
-		start_index_string = xmlNodeListGetString (doc, node->children, TRUE);
-		if (start_index_string == NULL)
-			return gdata_parser_error_required_content_missing (node, error);
-
-		self->priv->start_index = strtoul ((gchar*) start_index_string, NULL, 10);
-		xmlFree (start_index_string);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "itemsPerPage") == 0) {
-		/* openSearch:itemsPerPage */
-		xmlChar *items_per_page_string;
-
-		/* Duplicate checking */
-		if (self->priv->items_per_page != 0)
-			return gdata_parser_error_duplicate_element (node, error);
-
-		/* Parse the number */
-		items_per_page_string = xmlNodeListGetString (doc, node->children, TRUE);
-		if (items_per_page_string == NULL)
-			return gdata_parser_error_required_content_missing (node, error);
-
-		self->priv->items_per_page = strtoul ((gchar*) items_per_page_string, NULL, 10);
-		xmlFree (items_per_page_string);
-	} else if (GDATA_PARSABLE_CLASS (gdata_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2005/Atom";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "entry") == 0) {
+			/* atom:entry */
+			GDataEntry *entry;
+			GType entry_type;
+
+			/* Allow @data to be %NULL, and assume we're parsing a vanilla feed, so that we can test #GDataFeed in tests/general.c. A little hacky,
+			 * but not too much so, and valuable for testing. */
+			entry_type = (data != NULL) ? data->entry_type : GDATA_TYPE_ENTRY;
+			entry = GDATA_ENTRY (_gdata_parsable_new_from_xml_node (entry_type, doc, node, NULL, error));
+			if (entry == NULL)
+				return FALSE;
+
+			/* Calls the callbacks in the main thread */
+			if (data != NULL)
+				_gdata_feed_call_progress_callback (self, data, entry);
+			_gdata_feed_add_entry (self, entry);
+		} else if (gdata_parser_string_from_element (node, "title", P_NO_DUPES, &(self->priv->title), &success, error) == TRUE ||
+			   gdata_parser_string_from_element (node, "subtitle", P_NO_DUPES, &(self->priv->subtitle), &success, error) == TRUE ||
+			   gdata_parser_string_from_element (node, "id", P_NO_DUPES, &(self->priv->id), &success, error) == TRUE ||
+			   gdata_parser_string_from_element (node, "logo", P_NO_DUPES, &(self->priv->logo), &success, error) == TRUE ||
+			   gdata_parser_string_from_element (node, "icon", P_NO_DUPES, &(self->priv->icon), &success, error) == TRUE ||
+			   gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_CATEGORY,
+			                                            _gdata_feed_add_category, self, &success, error) == TRUE ||
+			   gdata_parser_object_from_element_setter (node, "link", P_REQUIRED, GDATA_TYPE_LINK,
+			                                            _gdata_feed_add_link, self, &success, error) == TRUE ||
+			   gdata_parser_object_from_element_setter (node, "author", P_REQUIRED, GDATA_TYPE_AUTHOR,
+			                                            _gdata_feed_add_author, self, &success, error) == TRUE ||
+			   gdata_parser_object_from_element (node, "generator", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_GENERATOR,
+			                                     &(self->priv->generator), &success, error) == TRUE ||
+			   gdata_parser_time_val_from_element (node, "updated", P_REQUIRED | P_NO_DUPES, &(self->priv->updated), &success, error) == TRUE) {
+			return success;
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else if (gdata_parser_is_namespace (node, "http://a9.com/-/spec/opensearch/1.1/";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "totalResults") == 0) {
+			/* openSearch:totalResults */
+			xmlChar *total_results_string;
+
+			/* Duplicate checking */
+			if (self->priv->total_results != 0)
+				return gdata_parser_error_duplicate_element (node, error);
+
+			/* Parse the number */
+			total_results_string = xmlNodeListGetString (doc, node->children, TRUE);
+			if (total_results_string == NULL)
+				return gdata_parser_error_required_content_missing (node, error);
+
+			self->priv->total_results = strtoul ((gchar*) total_results_string, NULL, 10);
+			xmlFree (total_results_string);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "startIndex") == 0) {
+			/* openSearch:startIndex */
+			xmlChar *start_index_string;
+
+			/* Duplicate checking */
+			if (self->priv->start_index != 0)
+				return gdata_parser_error_duplicate_element (node, error);
+
+			/* Parse the number */
+			start_index_string = xmlNodeListGetString (doc, node->children, TRUE);
+			if (start_index_string == NULL)
+				return gdata_parser_error_required_content_missing (node, error);
+
+			self->priv->start_index = strtoul ((gchar*) start_index_string, NULL, 10);
+			xmlFree (start_index_string);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "itemsPerPage") == 0) {
+			/* openSearch:itemsPerPage */
+			xmlChar *items_per_page_string;
+
+			/* Duplicate checking */
+			if (self->priv->items_per_page != 0)
+				return gdata_parser_error_duplicate_element (node, error);
+
+			/* Parse the number */
+			items_per_page_string = xmlNodeListGetString (doc, node->children, TRUE);
+			if (items_per_page_string == NULL)
+				return gdata_parser_error_required_content_missing (node, error);
+
+			self->priv->items_per_page = strtoul ((gchar*) items_per_page_string, NULL, 10);
+			xmlFree (items_per_page_string);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/gdata-parser.c b/gdata/gdata-parser.c
index 3cb9cc4..b580076 100644
--- a/gdata/gdata-parser.c
+++ b/gdata/gdata-parser.c
@@ -251,6 +251,27 @@ gdata_parser_boolean_from_property (xmlNode *element, const gchar *property_name
 }
 
 /*
+ * gdata_parser_is_namespace:
+ * @element: the element to check
+ * @namespace_uri: the URI of the desired namespace
+ *
+ * Checks whether @element is in the namespace identified by @namespace_uri. If @element isn't in a namespace,
+ * %FALSE is returned.
+ *
+ * Return value: %TRUE if @element is in @namespace_uri; %FALSE otherwise
+ *
+ * Since: 0.7.0
+ */
+gboolean
+gdata_parser_is_namespace (xmlNode *element, const gchar *namespace_uri)
+{
+	if ((element->ns != NULL && xmlStrcmp (element->ns->href, (const xmlChar*) namespace_uri) == 0) ||
+	    (element->ns == NULL && strcmp (namespace_uri, "http://www.w3.org/2005/Atom";) == 0))
+		return TRUE;
+	return FALSE;
+}
+
+/*
  * gdata_parser_string_from_element:
  * @element: the element to check against
  * @element_name: the name of the element to parse
@@ -359,7 +380,7 @@ gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name,
 
 	/* Get the string and check it for NULLness */
 	text = xmlNodeListGetString (element->doc, element->children, TRUE);
-	if (options & P_REQUIRED && text == NULL) {
+	if (options & P_REQUIRED && (text == NULL || *text == '\0')) {
 		xmlFree (text);
 		*success = gdata_parser_error_required_content_missing (element, error);
 		return TRUE;
diff --git a/gdata/gdata-parser.h b/gdata/gdata-parser.h
index 7938eca..198846b 100644
--- a/gdata/gdata-parser.h
+++ b/gdata/gdata-parser.h
@@ -63,6 +63,9 @@ typedef enum {
 typedef void (*GDataParserSetterFunc) (GDataParsable *parent_parsable, GDataParsable *parsable);
 
 gboolean gdata_parser_boolean_from_property (xmlNode *element, const gchar *property_name, gboolean *output, gint default_output, GError **error);
+
+gboolean gdata_parser_is_namespace (xmlNode *element, const gchar *namespace_uri);
+
 gboolean gdata_parser_string_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
                                            gchar **output, gboolean *success, GError **error);
 gboolean gdata_parser_time_val_from_element (xmlNode *element, const gchar *element_name, GDataParserOptions options,
diff --git a/gdata/georss/gdata-georss-where.c b/gdata/georss/gdata-georss-where.c
index fcc1b12..b6ed56e 100644
--- a/gdata/georss/gdata-georss-where.c
+++ b/gdata/georss/gdata-georss-where.c
@@ -85,7 +85,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 {
 	GDataGeoRSSWhere *self = GDATA_GEORSS_WHERE (parsable);
 
-	if (xmlStrcmp (node->name, (xmlChar*) "Point") == 0) {
+	if (gdata_parser_is_namespace (node, "http://www.opengis.net/gml";) == TRUE &&
+	    xmlStrcmp (node->name, (xmlChar*) "Point") == 0) {
 		/* gml:Point */
 		gboolean found_pos = FALSE;
 		xmlNode *child;
@@ -115,12 +116,10 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 
 		if (found_pos == FALSE)
 			return gdata_parser_error_required_element_missing ("pos", "gml:Point", error);
-	} else if (GDATA_PARSABLE_CLASS (gdata_georss_where_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+		return TRUE;
 	}
 
-	return TRUE;
+	return GDATA_PARSABLE_CLASS (gdata_georss_where_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 }
 
 static void
diff --git a/gdata/media/gdata-media-group.c b/gdata/media/gdata-media-group.c
index 065154b..b06e241 100644
--- a/gdata/media/gdata-media-group.c
+++ b/gdata/media/gdata-media-group.c
@@ -141,78 +141,80 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataMediaGroup *self = GDATA_MEDIA_GROUP (parsable);
 
-	if (gdata_parser_string_from_element (node, "title", P_NONE, &(self->priv->title), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "description", P_NONE, &(self->priv->description), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "keywords", P_NONE, &(self->priv->keywords), &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_MEDIA_CATEGORY,
-	                                             gdata_media_group_set_category, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "content", P_REQUIRED, GDATA_TYPE_MEDIA_CONTENT,
-	                                             _gdata_media_group_add_content, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "thumbnail", P_REQUIRED, GDATA_TYPE_MEDIA_THUMBNAIL,
-	                                             _gdata_media_group_add_thumbnail, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "credit", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_MEDIA_CREDIT,
-	                                      &(self->priv->credit), &success, error) == TRUE) {
-		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "player") == 0) {
-		/* media:player */
-		xmlChar *player_uri = xmlGetProp (node, (xmlChar*) "url");
-
-		g_free (self->priv->player_uri);
-		self->priv->player_uri = (gchar*) player_uri;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "rating") == 0) {
-		/* media:rating */
-		xmlChar *countries;
-		gchar **country_list, **country;
-
-		countries = xmlGetProp (node, (xmlChar*) "country");
-		country_list = g_strsplit ((const gchar*) countries, ",", -1);
-		xmlFree (countries);
-
-		/* Add all the listed countries to the restricted countries table */
-		for (country = country_list; *country != NULL; country++)
-			g_hash_table_insert (self->priv->restricted_countries, *country, GUINT_TO_POINTER (TRUE));
-		g_free (country_list);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "restriction") == 0) {
-		/* media:restriction */
-		xmlChar *type, *countries, *relationship;
-		gchar **country_list, **country;
-		gboolean relationship_bool;
-
-		/* Check the type property is "country" */
-		type = xmlGetProp (node, (xmlChar*) "type");
-		if (xmlStrcmp (type, (xmlChar*) "country") != 0) {
-			gdata_parser_error_unknown_property_value (node, "type", (gchar*) type, error);
+	if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE) {
+		if (gdata_parser_string_from_element (node, "title", P_NONE, &(self->priv->title), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "description", P_NONE, &(self->priv->description), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "keywords", P_NONE, &(self->priv->keywords), &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "category", P_REQUIRED, GDATA_TYPE_MEDIA_CATEGORY,
+			                                     gdata_media_group_set_category, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "content", P_REQUIRED, GDATA_TYPE_MEDIA_CONTENT,
+			                                     _gdata_media_group_add_content, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "thumbnail", P_REQUIRED, GDATA_TYPE_MEDIA_THUMBNAIL,
+			                                     _gdata_media_group_add_thumbnail, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element (node, "credit", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_MEDIA_CREDIT,
+			                              &(self->priv->credit), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "player") == 0) {
+			/* media:player */
+			xmlChar *player_uri = xmlGetProp (node, (xmlChar*) "url");
+			g_free (self->priv->player_uri);
+			self->priv->player_uri = (gchar*) player_uri;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "rating") == 0) {
+			/* media:rating */
+			xmlChar *countries;
+			gchar **country_list, **country;
+
+			countries = xmlGetProp (node, (xmlChar*) "country");
+			country_list = g_strsplit ((const gchar*) countries, ",", -1);
+			xmlFree (countries);
+
+			/* Add all the listed countries to the restricted countries table */
+			for (country = country_list; *country != NULL; country++)
+				g_hash_table_insert (self->priv->restricted_countries, *country, GUINT_TO_POINTER (TRUE));
+			g_free (country_list);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "restriction") == 0) {
+			/* media:restriction */
+			xmlChar *type, *countries, *relationship;
+			gchar **country_list, **country;
+			gboolean relationship_bool;
+
+			/* Check the type property is "country" */
+			type = xmlGetProp (node, (xmlChar*) "type");
+			if (xmlStrcmp (type, (xmlChar*) "country") != 0) {
+				gdata_parser_error_unknown_property_value (node, "type", (gchar*) type, error);
+				xmlFree (type);
+				return FALSE;
+			}
 			xmlFree (type);
-			return FALSE;
-		}
-		xmlFree (type);
-
-		relationship = xmlGetProp (node, (xmlChar*) "relationship");
-		if (xmlStrcmp (relationship, (xmlChar*) "allow") == 0)
-			relationship_bool = FALSE; /* it's *not* a restricted country */
-		else if (xmlStrcmp (relationship, (xmlChar*) "deny") == 0)
-			relationship_bool = TRUE; /* it *is* a restricted country */
-		else {
-			gdata_parser_error_unknown_property_value (node, "relationship", (gchar*) relationship, error);
+
+			relationship = xmlGetProp (node, (xmlChar*) "relationship");
+			if (xmlStrcmp (relationship, (xmlChar*) "allow") == 0)
+				relationship_bool = FALSE; /* it's *not* a restricted country */
+			else if (xmlStrcmp (relationship, (xmlChar*) "deny") == 0)
+				relationship_bool = TRUE; /* it *is* a restricted country */
+			else {
+				gdata_parser_error_unknown_property_value (node, "relationship", (gchar*) relationship, error);
+				xmlFree (relationship);
+				return FALSE;
+			}
 			xmlFree (relationship);
-			return FALSE;
+
+			countries = xmlNodeListGetString (doc, node->children, TRUE);
+			country_list = g_strsplit ((const gchar*) countries, " ", -1);
+			xmlFree (countries);
+
+			/* Add "all" to the table, since it's an exception table */
+			g_hash_table_insert (self->priv->restricted_countries, g_strdup ("all"), GUINT_TO_POINTER (!relationship_bool));
+
+			/* Add all the listed countries to the restricted countries table */
+			for (country = country_list; *country != NULL; country++)
+				g_hash_table_insert (self->priv->restricted_countries, *country, GUINT_TO_POINTER (relationship_bool));
+			g_free (country_list);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_media_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
-		xmlFree (relationship);
-
-		countries = xmlNodeListGetString (doc, node->children, TRUE);
-		country_list = g_strsplit ((const gchar*) countries, " ", -1);
-		xmlFree (countries);
-
-		/* Add "all" to the table, since it's an exception table */
-		g_hash_table_insert (self->priv->restricted_countries, g_strdup ("all"), GUINT_TO_POINTER (!relationship_bool));
-
-		/* Add all the listed countries to the restricted countries table */
-		for (country = country_list; *country != NULL; country++)
-			g_hash_table_insert (self->priv->restricted_countries, *country, GUINT_TO_POINTER (relationship_bool));
-		g_free (country_list);
-	} else if (GDATA_PARSABLE_CLASS (gdata_media_group_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_media_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/calendar/gdata-calendar-calendar.c b/gdata/services/calendar/gdata-calendar-calendar.c
index 265e6a8..282eb60 100644
--- a/gdata/services/calendar/gdata-calendar-calendar.c
+++ b/gdata/services/calendar/gdata-calendar-calendar.c
@@ -291,61 +291,66 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataCalendarCalendar *self = GDATA_CALENDAR_CALENDAR (parsable);
 
-	if (xmlStrcmp (node->name, (xmlChar*) "timezone") == 0) {
-		/* gCal:timezone */
-		xmlChar *_timezone = xmlGetProp (node, (xmlChar*) "value");
-		if (_timezone == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->timezone = (gchar*) _timezone;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "timesCleaned") == 0) {
-		/* gCal:timesCleaned */
-		xmlChar *times_cleaned = xmlGetProp (node, (xmlChar*) "value");
-		if (times_cleaned == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->times_cleaned = strtoul ((gchar*) times_cleaned, NULL, 10);
-		xmlFree (times_cleaned);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "hidden") == 0) {
-		/* gCal:hidden */
-		if (gdata_parser_boolean_from_property (node, "value", &(self->priv->is_hidden), -1, error) == FALSE)
-			return FALSE;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "color") == 0) {
-		/* gCal:color */
-		xmlChar *value;
-		GDataColor colour;
-
-		value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		if (gdata_color_from_hexadecimal ((gchar*) value, &colour) == FALSE) {
-			/* Error */
-			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
-				     /* Translators: the first parameter is the name of an XML element (including the angle brackets ("<" and ">"),
-				      * and the second parameter is the erroneous value (which was not in hexadecimal RGB format).
-				      *
-				      * For example:
-				      *  The content of a <entry/gCal:color> element ("00FG56") was not in hexadecimal RGB format. */
-				     _("The content of a %s element (\"%s\") was not in hexadecimal RGB format."), "<entry/gCal:color>", value);
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
+	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/gCal/2005";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "timezone") == 0) {
+			/* gCal:timezone */
+			xmlChar *_timezone = xmlGetProp (node, (xmlChar*) "value");
+			if (_timezone == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->timezone = (gchar*) _timezone;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "timesCleaned") == 0) {
+			/* gCal:timesCleaned */
+			xmlChar *times_cleaned = xmlGetProp (node, (xmlChar*) "value");
+			if (times_cleaned == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->times_cleaned = strtoul ((gchar*) times_cleaned, NULL, 10);
+			xmlFree (times_cleaned);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "hidden") == 0) {
+			/* gCal:hidden */
+			if (gdata_parser_boolean_from_property (node, "value", &(self->priv->is_hidden), -1, error) == FALSE)
+				return FALSE;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "color") == 0) {
+			/* gCal:color */
+			xmlChar *value;
+			GDataColor colour;
+
+			value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			if (gdata_color_from_hexadecimal ((gchar*) value, &colour) == FALSE) {
+				/* Error */
+				g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
+					     /* Translators: the first parameter is the name of an XML element (including the angle brackets
+					      * ("<" and ">"), and the second parameter is the erroneous value (which was not in hexadecimal
+					      * RGB format).
+					      *
+					      * For example:
+					      *  The content of a <entry/gCal:color> element ("00FG56") was not in hexadecimal RGB format. */
+					     _("The content of a %s element (\"%s\") was not in hexadecimal RGB format."), "<entry/gCal:color>", value);
+				xmlFree (value);
+
+				return FALSE;
+			}
+
+			gdata_calendar_calendar_set_color (self, &colour);
 			xmlFree (value);
-
-			return FALSE;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "selected") == 0) {
+			/* gCal:selected */
+			if (gdata_parser_boolean_from_property (node, "value", &(self->priv->is_selected), -1, error) == FALSE)
+				return FALSE;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "accesslevel") == 0) {
+			/* gCal:accesslevel */
+			self->priv->access_level = (gchar*) xmlGetProp (node, (xmlChar*) "value");
+			if (self->priv->access_level == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_calendar_calendar_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
-
-		gdata_calendar_calendar_set_color (self, &colour);
-		xmlFree (value);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "selected") == 0) {
-		/* gCal:selected */
-		if (gdata_parser_boolean_from_property (node, "value", &(self->priv->is_selected), -1, error) == FALSE)
-			return FALSE;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "accesslevel") == 0) {
-		/* gCal:accesslevel */
-		self->priv->access_level = (gchar*) xmlGetProp (node, (xmlChar*) "value");
-		if (self->priv->access_level == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-	} else if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
-		return success;
-	} else if (GDATA_PARSABLE_CLASS (gdata_calendar_calendar_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_calendar_calendar_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/calendar/gdata-calendar-event.c b/gdata/services/calendar/gdata-calendar-event.c
index 8a73a9b..eca717e 100644
--- a/gdata/services/calendar/gdata-calendar-event.c
+++ b/gdata/services/calendar/gdata-calendar-event.c
@@ -456,111 +456,120 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataCalendarEvent *self = GDATA_CALENDAR_EVENT (parsable);
 
-	if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "when", P_REQUIRED, GDATA_TYPE_GD_WHEN,
-	                                             gdata_calendar_event_add_time, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "who", P_REQUIRED, GDATA_TYPE_GD_WHO,
-	                                             gdata_calendar_event_add_person, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "where", P_REQUIRED, GDATA_TYPE_GD_WHERE,
-	                                             gdata_calendar_event_add_place, self, &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
+	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "comments") == 0) {
-		/* gd:comments */
-		xmlChar *rel, *href, *count_hint;
-		xmlNode *child_node;
-		guint count_hint_uint;
-		/*GDataGDFeedLink *feed_link;*/
-
-		/* This is actually the child of the <comments> element */
-		child_node = node->children;
-
-		count_hint = xmlGetProp (child_node, (xmlChar*) "countHint");
-		if (count_hint == NULL)
-			count_hint_uint = 0;
-		else
-			count_hint_uint = strtoul ((gchar*) count_hint, NULL, 10);
-		xmlFree (count_hint);
-
-		rel = xmlGetProp (child_node, (xmlChar*) "rel");
-		href = xmlGetProp (child_node, (xmlChar*) "href");
-
-		/* TODO */
-		/*feed_link = gdata_gd_feed_link_new ((gchar*) href, (gchar*) rel, count_hint_uint);*/
-		/*gdata_calendar_event_set_comments_feed_link (self, feed_link);*/
-
-		xmlFree (rel);
-		xmlFree (href);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "eventStatus") == 0) {
-		/* gd:eventStatus */
-		xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->status = (gchar*) value;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "visibility") == 0) {
-		/* gd:visibility */
-		xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->visibility = (gchar*) value;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "transparency") == 0) {
-		/* gd:transparency */
-		xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->transparency = (gchar*) value;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "uid") == 0) {
-		/* gCal:uid */
-		xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		self->priv->uid = (gchar*) value;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "sequence") == 0) {
-		/* gCal:sequence */
-		xmlChar *value;
-		guint value_uint;
-
-		value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL)
-			return gdata_parser_error_required_property_missing (node, "value", error);
-		else
-			value_uint = strtoul ((gchar*) value, NULL, 10);
-		xmlFree (value);
-
-		gdata_calendar_event_set_sequence (self, value_uint);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanModify") == 0) {
-		/* gCal:guestsCanModify */
-		gboolean guests_can_modify;
-		if (gdata_parser_boolean_from_property (node, "value", &guests_can_modify, -1, error) == FALSE)
-			return FALSE;
-		gdata_calendar_event_set_guests_can_modify (self, guests_can_modify);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanInviteOthers") == 0) {
-		/* gCal:guestsCanInviteOthers */
-		gboolean guests_can_invite_others;
-		if (gdata_parser_boolean_from_property (node, "value", &guests_can_invite_others, -1, error) == FALSE)
-			return FALSE;
-		gdata_calendar_event_set_guests_can_invite_others (self, guests_can_invite_others);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanSeeGuests") == 0) {
-		/* gCal:guestsCanSeeGuests */
-		gboolean guests_can_see_guests;
-		if (gdata_parser_boolean_from_property (node, "value", &guests_can_see_guests, -1, error) == FALSE)
-			return FALSE;
-		gdata_calendar_event_set_guests_can_see_guests (self, guests_can_see_guests);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "anyoneCanAddSelf") == 0) {
-		/* gCal:anyoneCanAddSelf */
-		gboolean anyone_can_add_self;
-		if (gdata_parser_boolean_from_property (node, "value", &anyone_can_add_self, -1, error) == FALSE)
-			return FALSE;
-		gdata_calendar_event_set_anyone_can_add_self (self, anyone_can_add_self);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "recurrence") == 0) {
-		/* gd:recurrence */
-		self->priv->recurrence = (gchar*) xmlNodeListGetString (doc, node->children, TRUE);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "originalEvent") == 0) {
-		/* gd:originalEvent */
-		self->priv->original_event_id = (gchar*) xmlGetProp (node, (xmlChar*) "id");
-		self->priv->original_event_uri = (gchar*) xmlGetProp (node, (xmlChar*) "href");
-	} else if (GDATA_PARSABLE_CLASS (gdata_calendar_event_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE) {
+		if (gdata_parser_object_from_element_setter (node, "when", P_REQUIRED, GDATA_TYPE_GD_WHEN,
+		                                             gdata_calendar_event_add_time, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "who", P_REQUIRED, GDATA_TYPE_GD_WHO,
+		                                             gdata_calendar_event_add_person, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "where", P_REQUIRED, GDATA_TYPE_GD_WHERE,
+		                                             gdata_calendar_event_add_place, self, &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "comments") == 0) {
+			/* gd:comments */
+			xmlChar *rel, *href, *count_hint;
+			xmlNode *child_node;
+			guint count_hint_uint;
+			/*GDataGDFeedLink *feed_link;*/
+
+			/* This is actually the child of the <comments> element */
+			child_node = node->children;
+
+			count_hint = xmlGetProp (child_node, (xmlChar*) "countHint");
+			if (count_hint == NULL)
+				count_hint_uint = 0;
+			else
+				count_hint_uint = strtoul ((gchar*) count_hint, NULL, 10);
+			xmlFree (count_hint);
+
+			rel = xmlGetProp (child_node, (xmlChar*) "rel");
+			href = xmlGetProp (child_node, (xmlChar*) "href");
+
+			/* TODO */
+			/*feed_link = gdata_gd_feed_link_new ((gchar*) href, (gchar*) rel, count_hint_uint);*/
+			/*gdata_calendar_event_set_comments_feed_link (self, feed_link);*/
+
+			xmlFree (rel);
+			xmlFree (href);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "eventStatus") == 0) {
+			/* gd:eventStatus */
+			xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->status = (gchar*) value;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "visibility") == 0) {
+			/* gd:visibility */
+			xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->visibility = (gchar*) value;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "transparency") == 0) {
+			/* gd:transparency */
+			xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->transparency = (gchar*) value;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "recurrence") == 0) {
+			/* gd:recurrence */
+			self->priv->recurrence = (gchar*) xmlNodeListGetString (doc, node->children, TRUE);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "originalEvent") == 0) {
+			/* gd:originalEvent */
+			self->priv->original_event_id = (gchar*) xmlGetProp (node, (xmlChar*) "id");
+			self->priv->original_event_uri = (gchar*) xmlGetProp (node, (xmlChar*) "href");
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_calendar_event_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/gCal/2005";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "uid") == 0) {
+			/* gCal:uid */
+			xmlChar *value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			self->priv->uid = (gchar*) value;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "sequence") == 0) {
+			/* gCal:sequence */
+			xmlChar *value;
+			guint value_uint;
+
+			value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL)
+				return gdata_parser_error_required_property_missing (node, "value", error);
+			else
+				value_uint = strtoul ((gchar*) value, NULL, 10);
+			xmlFree (value);
+
+			gdata_calendar_event_set_sequence (self, value_uint);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanModify") == 0) {
+			/* gCal:guestsCanModify */
+			gboolean guests_can_modify;
+			if (gdata_parser_boolean_from_property (node, "value", &guests_can_modify, -1, error) == FALSE)
+				return FALSE;
+			gdata_calendar_event_set_guests_can_modify (self, guests_can_modify);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanInviteOthers") == 0) {
+			/* gCal:guestsCanInviteOthers */
+			gboolean guests_can_invite_others;
+			if (gdata_parser_boolean_from_property (node, "value", &guests_can_invite_others, -1, error) == FALSE)
+				return FALSE;
+			gdata_calendar_event_set_guests_can_invite_others (self, guests_can_invite_others);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "guestsCanSeeGuests") == 0) {
+			/* gCal:guestsCanSeeGuests */
+			gboolean guests_can_see_guests;
+			if (gdata_parser_boolean_from_property (node, "value", &guests_can_see_guests, -1, error) == FALSE)
+				return FALSE;
+			gdata_calendar_event_set_guests_can_see_guests (self, guests_can_see_guests);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "anyoneCanAddSelf") == 0) {
+			/* gCal:anyoneCanAddSelf */
+			gboolean anyone_can_add_self;
+			if (gdata_parser_boolean_from_property (node, "value", &anyone_can_add_self, -1, error) == FALSE)
+				return FALSE;
+			gdata_calendar_event_set_anyone_can_add_self (self, anyone_can_add_self);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_calendar_event_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_calendar_event_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/calendar/gdata-calendar-feed.c b/gdata/services/calendar/gdata-calendar-feed.c
index 4e0fa67..591a9a3 100644
--- a/gdata/services/calendar/gdata-calendar-feed.c
+++ b/gdata/services/calendar/gdata-calendar-feed.c
@@ -132,6 +132,9 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 {
 	GDataCalendarFeed *self = GDATA_CALENDAR_FEED (parsable);
 
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/gCal/2005";) == FALSE)
+		return GDATA_PARSABLE_CLASS (gdata_calendar_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+
 	if (xmlStrcmp (node->name, (xmlChar*) "timezone") == 0) {
 		/* gCal:timezone */
 		xmlChar *_timezone = xmlGetProp (node, (xmlChar*) "value");
@@ -146,9 +149,6 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 			return gdata_parser_error_required_property_missing (node, "value", error);
 		self->priv->times_cleaned = strtoul ((gchar*) times_cleaned, NULL, 10);
 		xmlFree (times_cleaned);
-	} else if (GDATA_PARSABLE_CLASS (gdata_calendar_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
 	}
 
 	return TRUE;
diff --git a/gdata/services/contacts/gdata-contacts-contact.c b/gdata/services/contacts/gdata-contacts-contact.c
index c14cbd4..68d6259 100644
--- a/gdata/services/contacts/gdata-contacts-contact.c
+++ b/gdata/services/contacts/gdata-contacts-contact.c
@@ -296,47 +296,57 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataContactsContact *self = GDATA_CONTACTS_CONTACT (parsable);
 
-	if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "email", P_REQUIRED, GDATA_TYPE_GD_EMAIL_ADDRESS,
-	                                             gdata_contacts_contact_add_email_address, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "im", P_REQUIRED, GDATA_TYPE_GD_IM_ADDRESS,
-	                                             gdata_contacts_contact_add_im_address, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "phoneNumber", P_REQUIRED, GDATA_TYPE_GD_PHONE_NUMBER,
-	                                             gdata_contacts_contact_add_phone_number, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "structuredPostalAddress", P_REQUIRED, GDATA_TYPE_GD_POSTAL_ADDRESS,
-	                                             gdata_contacts_contact_add_postal_address, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "organization", P_REQUIRED, GDATA_TYPE_GD_ORGANIZATION,
-	                                             gdata_contacts_contact_add_organization, self, &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "name", P_REQUIRED, GDATA_TYPE_GD_NAME, &(self->priv->name), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
+	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "extendedProperty") == 0) {
-		/* gd:extendedProperty */
-		xmlChar *name, *value;
-		xmlBuffer *buffer = NULL;
-
-		name = xmlGetProp (node, (xmlChar*) "name");
-		if (name == NULL)
-			return gdata_parser_error_required_property_missing (node, "name", error);
-
-		/* Get either the value property, or the element's content */
-		value = xmlGetProp (node, (xmlChar*) "value");
-		if (value == NULL) {
-			xmlNode *child_node;
-
-			/* Use the element's content instead (arbitrary XML) */
-			buffer = xmlBufferCreate ();
-			for (child_node = node->children; child_node != NULL; child_node = child_node->next)
-				xmlNodeDump (buffer, doc, child_node, 0, 0);
-			value = (xmlChar*) xmlBufferContent (buffer);
-		}
-
-		gdata_contacts_contact_set_extended_property (self, (gchar*) name, (gchar*) value);
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE) {
+		if (gdata_parser_object_from_element_setter (node, "email", P_REQUIRED, GDATA_TYPE_GD_EMAIL_ADDRESS,
+		                                             gdata_contacts_contact_add_email_address, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "im", P_REQUIRED, GDATA_TYPE_GD_IM_ADDRESS,
+		                                             gdata_contacts_contact_add_im_address, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "phoneNumber", P_REQUIRED, GDATA_TYPE_GD_PHONE_NUMBER,
+		                                             gdata_contacts_contact_add_phone_number, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "structuredPostalAddress", P_REQUIRED, GDATA_TYPE_GD_POSTAL_ADDRESS,
+		                                             gdata_contacts_contact_add_postal_address, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "organization", P_REQUIRED, GDATA_TYPE_GD_ORGANIZATION,
+		                                             gdata_contacts_contact_add_organization, self, &success, error) == TRUE ||
+		    gdata_parser_object_from_element (node, "name", P_REQUIRED, GDATA_TYPE_GD_NAME, &(self->priv->name), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "extendedProperty") == 0) {
+			/* gd:extendedProperty */
+			xmlChar *name, *value;
+			xmlBuffer *buffer = NULL;
+
+			name = xmlGetProp (node, (xmlChar*) "name");
+			if (name == NULL)
+				return gdata_parser_error_required_property_missing (node, "name", error);
+
+			/* Get either the value property, or the element's content */
+			value = xmlGetProp (node, (xmlChar*) "value");
+			if (value == NULL) {
+				xmlNode *child_node;
+
+				/* Use the element's content instead (arbitrary XML) */
+				buffer = xmlBufferCreate ();
+				for (child_node = node->children; child_node != NULL; child_node = child_node->next)
+					xmlNodeDump (buffer, doc, child_node, 0, 0);
+				value = (xmlChar*) xmlBufferContent (buffer);
+			}
 
-		if (buffer != NULL)
-			xmlBufferFree (buffer);
-		else
-			g_free (value);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "groupMembershipInfo") == 0) {
+			gdata_contacts_contact_set_extended_property (self, (gchar*) name, (gchar*) value);
+
+			if (buffer != NULL)
+				xmlBufferFree (buffer);
+			else
+				g_free (value);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "deleted") == 0) {
+			/* gd:deleted */
+			self->priv->deleted = TRUE;
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_contacts_contact_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/contact/2008";) == TRUE &&
+	           xmlStrcmp (node->name, (xmlChar*) "groupMembershipInfo") == 0) {
 		/* gContact:groupMembershipInfo */
 		xmlChar *href;
 		gboolean deleted_bool;
@@ -351,9 +361,6 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 
 		/* Insert it into the hash table */
 		g_hash_table_insert (self->priv->groups, (gchar*) href, GUINT_TO_POINTER (deleted_bool));
-	} else if (xmlStrcmp (node->name, (xmlChar*) "deleted") == 0) {
-		/* gd:deleted */
-		self->priv->deleted = TRUE;
 	} else {
 		/* If we haven't yet found a photo, check to see if it's a photo <link> element */
 		if (self->priv->photo_etag == NULL && xmlStrcmp (node->name, (xmlChar*) "link") == 0) {
@@ -366,10 +373,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 			xmlFree (rel);
 		}
 
-		if (GDATA_PARSABLE_CLASS (gdata_contacts_contact_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-			/* Error! */
-			return FALSE;
-		}
+		return GDATA_PARSABLE_CLASS (gdata_contacts_contact_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/documents/gdata-documents-entry.c b/gdata/services/documents/gdata-documents-entry.c
index 5833ca5..c62bf8a 100644
--- a/gdata/services/documents/gdata-documents-entry.c
+++ b/gdata/services/documents/gdata-documents-entry.c
@@ -218,46 +218,53 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataDocumentsEntry *self = GDATA_DOCUMENTS_ENTRY (parsable);
 
-	if (gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE ||
-	    gdata_parser_time_val_from_element (node, "lastViewed", P_REQUIRED | P_NO_DUPES, &(self->priv->last_viewed), &success, error) == TRUE ||
-	    gdata_parser_object_from_element_setter (node, "feedLink", P_REQUIRED, GDATA_TYPE_LINK,
-	                                             gdata_entry_add_link, self,  &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "lastModifiedBy", P_REQUIRED, GDATA_TYPE_AUTHOR,
-	                                      &(self->priv->last_modified_by), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
+	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "writersCanInvite") ==  0) {
-		if (gdata_parser_boolean_from_property (node, "value", &(self->priv->writers_can_invite), -1, error) == FALSE)
-			return FALSE;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "deleted") ==  0) {
-		/* <gd:deleted> */
-		/* Note that it doesn't have any parameters, so we unconditionally set priv->is_deleted to TRUE */
-		self->priv->is_deleted = TRUE;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "resourceId") ==  0) {
-		gchar **document_id_parts;
-		xmlChar *resource_id;
-
-		if (self->priv->document_id != NULL)
-			return gdata_parser_error_duplicate_element (node, error);
-
-		resource_id = xmlNodeListGetString (doc, node->children, TRUE);
-		if (resource_id == NULL || *resource_id == '\0') {
-			xmlFree (resource_id);
-			return gdata_parser_error_required_content_missing (node, error);
-		}
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE) {
+		if (gdata_parser_time_val_from_element (node, "lastViewed", P_REQUIRED | P_NO_DUPES,
+		                                        &(self->priv->last_viewed), &success, error) == TRUE ||
+		    gdata_parser_object_from_element_setter (node, "feedLink", P_REQUIRED, GDATA_TYPE_LINK,
+		                                             gdata_entry_add_link, self,  &success, error) == TRUE ||
+		    gdata_parser_object_from_element (node, "lastModifiedBy", P_REQUIRED, GDATA_TYPE_AUTHOR,
+		                                      &(self->priv->last_modified_by), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "deleted") ==  0) {
+			/* <gd:deleted> */
+			/* Note that it doesn't have any parameters, so we unconditionally set priv->is_deleted to TRUE */
+			self->priv->is_deleted = TRUE;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "resourceId") ==  0) {
+			gchar **document_id_parts;
+			xmlChar *resource_id;
+
+			if (self->priv->document_id != NULL)
+				return gdata_parser_error_duplicate_element (node, error);
+
+			resource_id = xmlNodeListGetString (doc, node->children, TRUE);
+			if (resource_id == NULL || *resource_id == '\0') {
+				xmlFree (resource_id);
+				return gdata_parser_error_required_content_missing (node, error);
+			}
 
-		document_id_parts = g_strsplit ((gchar*) resource_id, ":", 2);
-		if (document_id_parts == NULL) {
-			gdata_parser_error_unknown_content (node, (gchar*) resource_id, error);
+			document_id_parts = g_strsplit ((gchar*) resource_id, ":", 2);
+			if (document_id_parts == NULL) {
+				gdata_parser_error_unknown_content (node, (gchar*) resource_id, error);
+				xmlFree (resource_id);
+				return FALSE;
+			}
 			xmlFree (resource_id);
-			return FALSE;
-		}
-		xmlFree (resource_id);
 
-		self->priv->document_id = g_strdup (document_id_parts[1]);
-		g_strfreev (document_id_parts);
-	} else if (GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+			self->priv->document_id = g_strdup (document_id_parts[1]);
+			g_strfreev (document_id_parts);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/docs/2007";) == TRUE &&
+	           xmlStrcmp (node->name, (xmlChar*) "writersCanInvite") ==  0) {
+		if (gdata_parser_boolean_from_property (node, "value", &(self->priv->writers_can_invite), -1, error) == FALSE)
+			return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/documents/gdata-documents-feed.c b/gdata/services/documents/gdata-documents-feed.c
index df62f45..cac9951 100644
--- a/gdata/services/documents/gdata-documents-feed.c
+++ b/gdata/services/documents/gdata-documents-feed.c
@@ -94,7 +94,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 {
 	GDataDocumentsFeed *self = GDATA_DOCUMENTS_FEED (parsable);
 
-	if (xmlStrcmp (node->name, (xmlChar*) "entry") == 0) {
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2005/Atom";) == TRUE &&
+	    xmlStrcmp (node->name, (xmlChar*) "entry") == 0) {
 		GDataEntry *entry = NULL;
 		gchar *kind = get_kind (doc, node);
 
@@ -119,10 +120,9 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		/* Call the progress callback in the main thread */
 		_gdata_feed_call_progress_callback (GDATA_FEED (self), user_data, entry);
 		_gdata_feed_add_entry (GDATA_FEED (self), entry);
-	} else if (GDATA_PARSABLE_CLASS (gdata_documents_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+
+		return TRUE;
 	}
 
-	return TRUE;
+	return GDATA_PARSABLE_CLASS (gdata_documents_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 }
diff --git a/gdata/services/picasaweb/gdata-picasaweb-album.c b/gdata/services/picasaweb/gdata-picasaweb-album.c
index a06d64f..972ac81 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-album.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-album.c
@@ -546,96 +546,106 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataPicasaWebAlbum *self = GDATA_PICASAWEB_ALBUM (parsable);
 
-	/* TODO: This should also be P_NO_DUPES, but we can't, as priv->media_group has to be pre-populated
+	/* TODO: media:group should also be P_NO_DUPES, but we can't, as priv->media_group has to be pre-populated
 	 * in order for things like gdata_picasaweb_album_get_tags() to work. */
-	if (gdata_parser_object_from_element (node, "group", P_REQUIRED, GDATA_TYPE_MEDIA_GROUP,
-	                                      &(self->priv->media_group), &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "where", P_REQUIRED, GDATA_TYPE_GEORSS_WHERE,
-	                                      &(self->priv->georss_where), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "user", P_REQUIRED | P_NON_EMPTY, &(self->priv->user), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "nickname", P_REQUIRED | P_NON_EMPTY, &(self->priv->nickname), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "location", P_NONE, &(self->priv->location), &success, error) == TRUE ||
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
 	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
-		/* gphoto:access */
-		xmlChar *access = xmlNodeListGetString (doc, node->children, TRUE);
-		if (xmlStrcmp (access, (xmlChar*) "public") == 0) {
-			gdata_picasaweb_album_set_visibility (self, GDATA_PICASAWEB_PUBLIC);
-		} else if (xmlStrcmp (access, (xmlChar*) "private") == 0) {
-			gdata_picasaweb_album_set_visibility (self, GDATA_PICASAWEB_PRIVATE);
-		} else {
-			gdata_parser_error_unknown_content (node, (gchar*) access, error);
+	} else if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE &&
+	           gdata_parser_object_from_element (node, "group", P_REQUIRED, GDATA_TYPE_MEDIA_GROUP,
+	                                             &(self->priv->media_group), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://www.georss.org/georss";) == TRUE &&
+	           gdata_parser_object_from_element (node, "where", P_REQUIRED, GDATA_TYPE_GEORSS_WHERE,
+	                                             &(self->priv->georss_where), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/photos/2007";) == TRUE) {
+		if (gdata_parser_string_from_element (node, "user", P_REQUIRED | P_NON_EMPTY, &(self->priv->user), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "nickname", P_REQUIRED | P_NON_EMPTY, &(self->priv->nickname), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "location", P_NONE, &(self->priv->location), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
+			/* gphoto:access */
+			xmlChar *access = xmlNodeListGetString (doc, node->children, TRUE);
+			if (xmlStrcmp (access, (xmlChar*) "public") == 0) {
+				gdata_picasaweb_album_set_visibility (self, GDATA_PICASAWEB_PUBLIC);
+			} else if (xmlStrcmp (access, (xmlChar*) "private") == 0) {
+				gdata_picasaweb_album_set_visibility (self, GDATA_PICASAWEB_PRIVATE);
+			} else {
+				gdata_parser_error_unknown_content (node, (gchar*) access, error);
+				xmlFree (access);
+				return FALSE;
+			}
 			xmlFree (access);
-			return FALSE;
-		}
-		xmlFree (access);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "timestamp") == 0) {
-		/* gphoto:timestamp */
-		xmlChar *timestamp_str;
-		guint64 milliseconds;
-		GTimeVal timestamp;
-
-		timestamp_str = xmlNodeListGetString (doc, node->children, TRUE);
-		milliseconds = g_ascii_strtoull ((gchar*) timestamp_str, NULL, 10);
-		xmlFree (timestamp_str);
-
-		timestamp.tv_sec = (glong) (milliseconds / 1000);
-		timestamp.tv_usec = (glong) ((milliseconds % 1000) * 1000);
-
-		gdata_picasaweb_album_set_timestamp (self, &timestamp);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "numphotos") == 0) {
-		/* gphoto:numphotos */
-		xmlChar *num_photos = xmlNodeListGetString (doc, node->children, TRUE);
-		if (num_photos == NULL || *num_photos == '\0') {
+		} else if (xmlStrcmp (node->name, (xmlChar*) "timestamp") == 0) {
+			/* gphoto:timestamp */
+			xmlChar *timestamp_str;
+			guint64 milliseconds;
+			GTimeVal timestamp;
+
+			timestamp_str = xmlNodeListGetString (doc, node->children, TRUE);
+			milliseconds = g_ascii_strtoull ((gchar*) timestamp_str, NULL, 10);
+			xmlFree (timestamp_str);
+
+			timestamp.tv_sec = (glong) (milliseconds / 1000);
+			timestamp.tv_usec = (glong) ((milliseconds % 1000) * 1000);
+
+			gdata_picasaweb_album_set_timestamp (self, &timestamp);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "numphotos") == 0) {
+			/* gphoto:numphotos */
+			xmlChar *num_photos = xmlNodeListGetString (doc, node->children, TRUE);
+			if (num_photos == NULL || *num_photos == '\0') {
+				xmlFree (num_photos);
+				return gdata_parser_error_required_content_missing (node, error);
+			}
+
+			self->priv->num_photos = strtoul ((char*) num_photos, NULL, 10);
 			xmlFree (num_photos);
-			return gdata_parser_error_required_content_missing (node, error);
-		}
-
-		self->priv->num_photos = strtoul ((char*) num_photos, NULL, 10);
-		xmlFree (num_photos);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "numphotosremaining") == 0) {
-		/* gphoto:numphotosremaining */
-		xmlChar *num_photos_remaining = xmlNodeListGetString (doc, node->children, TRUE);
-		if (num_photos_remaining == NULL || *num_photos_remaining == '\0') {
+		} else if (xmlStrcmp (node->name, (xmlChar*) "numphotosremaining") == 0) {
+			/* gphoto:numphotosremaining */
+			xmlChar *num_photos_remaining = xmlNodeListGetString (doc, node->children, TRUE);
+			if (num_photos_remaining == NULL || *num_photos_remaining == '\0') {
+				xmlFree (num_photos_remaining);
+				return gdata_parser_error_required_content_missing (node, error);
+			}
+
+			self->priv->num_photos_remaining = strtoul ((char*) num_photos_remaining, NULL, 10);
 			xmlFree (num_photos_remaining);
-			return gdata_parser_error_required_content_missing (node, error);
-		}
-
-		self->priv->num_photos_remaining = strtoul ((char*) num_photos_remaining, NULL, 10);
-		xmlFree (num_photos_remaining);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "bytesUsed") == 0) {
-		/* gphoto:bytesUsed */
-		xmlChar *bytes_used = xmlNodeListGetString (doc, node->children, TRUE);
-		if (bytes_used == NULL || *bytes_used == '\0') {
+		} else if (xmlStrcmp (node->name, (xmlChar*) "bytesUsed") == 0) {
+			/* gphoto:bytesUsed */
+			xmlChar *bytes_used = xmlNodeListGetString (doc, node->children, TRUE);
+			if (bytes_used == NULL || *bytes_used == '\0') {
+				xmlFree (bytes_used);
+				return gdata_parser_error_required_content_missing (node, error);
+			}
+
+			self->priv->bytes_used = strtol ((char*) bytes_used, NULL, 10);
 			xmlFree (bytes_used);
-			return gdata_parser_error_required_content_missing (node, error);
-		}
-
-		self->priv->bytes_used = strtol ((char*) bytes_used, NULL, 10);
-		xmlFree (bytes_used);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "commentingEnabled") == 0) {
-		/* gphoto:commentingEnabled */
-		xmlChar *commenting_enabled = xmlNodeListGetString (doc, node->children, TRUE);
-		if (commenting_enabled == NULL || *commenting_enabled == '\0') {
+		} else if (xmlStrcmp (node->name, (xmlChar*) "commentingEnabled") == 0) {
+			/* gphoto:commentingEnabled */
+			xmlChar *commenting_enabled = xmlNodeListGetString (doc, node->children, TRUE);
+			if (commenting_enabled == NULL || *commenting_enabled == '\0') {
+				xmlFree (commenting_enabled);
+				return gdata_parser_error_required_content_missing (node, error);
+			}
+
+			gdata_picasaweb_album_set_is_commenting_enabled (self, (xmlStrcmp (commenting_enabled, (xmlChar*) "true") == 0) ? TRUE : FALSE);
 			xmlFree (commenting_enabled);
-			return gdata_parser_error_required_content_missing (node, error);
-		}
-
-		gdata_picasaweb_album_set_is_commenting_enabled (self, (xmlStrcmp (commenting_enabled, (xmlChar*) "true") == 0) ? TRUE : FALSE);
-		xmlFree (commenting_enabled);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "commentCount") == 0) {
-		xmlChar *comment_count = xmlNodeListGetString (doc, node->children, TRUE);
-		if (comment_count == NULL || *comment_count == '\0') {
+		} else if (xmlStrcmp (node->name, (xmlChar*) "commentCount") == 0) {
+			/* gphoto:commentCount */
+			xmlChar *comment_count = xmlNodeListGetString (doc, node->children, TRUE);
+			if (comment_count == NULL || *comment_count == '\0') {
+				xmlFree (comment_count);
+				return gdata_parser_error_required_content_missing (node, error);
+			}
+
+			self->priv->comment_count = strtoul ((char*) comment_count, NULL, 10);
 			xmlFree (comment_count);
-			return gdata_parser_error_required_content_missing (node, error);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_picasaweb_album_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
-
-		self->priv->comment_count = strtoul ((char*) comment_count, NULL, 10);
-		xmlFree (comment_count);
-	} else if (GDATA_PARSABLE_CLASS (gdata_picasaweb_album_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_picasaweb_album_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/picasaweb/gdata-picasaweb-feed.c b/gdata/services/picasaweb/gdata-picasaweb-feed.c
index 01e6b0f..c297ef6 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-feed.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-feed.c
@@ -58,60 +58,63 @@ gdata_picasaweb_feed_init (GDataPicasaWebFeed *self)
 static gboolean
 parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
 {
-	if (xmlStrcmp (node->name, (xmlChar*) "user") == 0) {
-		/* gphoto:user */
-		/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "nickname") == 0) {
-		/* gphoto:nickname */
-		/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "quotacurrent") == 0) {
-		/* gphoto:quota-current */
-		/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "quotalimit") == 0) {
-		/* gphoto:quota-limit */
-		/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "maxPhotosPerAlbum") == 0) {
-		/* gphoto:max-photos-per-album */
-		/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "thumbnail") == 0) {
-		/* gphoto:thumbnail */
-		/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "allowDownloads") == 0) {
-		/* gphoto:allowDownloads */
-		/* Not part of public API so we're capturing and ignoring for now.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "allowPrints") == 0) {
-		/* gphoto:allowPrints */
-		/* Not part of public API so we're capturing and ignoring for now.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "id") == 0 && xmlStrcmp (node->ns->href, (xmlChar*) "http://schemas.google.com/photos/2007";) == 0) {
-		/* gphoto:id */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "rights") == 0) {
-		/* gphoto:rights */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "location") == 0) {
-		/* gphoto:location */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
-		/* gphoto:access */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "timestamp") == 0) {
-		/* gphoto:timestamp */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "numphotos") == 0) {
-		/* gphoto:numphotos */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "numphotosremaining") == 0) {
-		/* gphoto:numphotosremaining */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "bytesUsed") == 0) {
-		/* gphoto:bytesUsed */
-		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "where") == 0) {
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/photos/2007";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "user") == 0) {
+			/* gphoto:user */
+			/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "nickname") == 0) {
+			/* gphoto:nickname */
+			/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "quotacurrent") == 0) {
+			/* gphoto:quota-current */
+			/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "quotalimit") == 0) {
+			/* gphoto:quota-limit */
+			/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "maxPhotosPerAlbum") == 0) {
+			/* gphoto:max-photos-per-album */
+			/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "thumbnail") == 0) {
+			/* gphoto:thumbnail */
+			/* From user's feed of album entries.  Redundant with user entry represented by GDataPicasaWebUser.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "allowDownloads") == 0) {
+			/* gphoto:allowDownloads */
+			/* Not part of public API so we're capturing and ignoring for now.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "allowPrints") == 0) {
+			/* gphoto:allowPrints */
+			/* Not part of public API so we're capturing and ignoring for now.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "id") == 0 && xmlStrcmp (node->ns->href, (xmlChar*) "http://schemas.google.com/photos/2007";) == 0) {
+			/* gphoto:id */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "rights") == 0) {
+			/* gphoto:rights */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "location") == 0) {
+			/* gphoto:location */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
+			/* gphoto:access */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "timestamp") == 0) {
+			/* gphoto:timestamp */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "numphotos") == 0) {
+			/* gphoto:numphotos */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "numphotosremaining") == 0) {
+			/* gphoto:numphotosremaining */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "bytesUsed") == 0) {
+			/* gphoto:bytesUsed */
+			/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_picasaweb_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else if (gdata_parser_is_namespace (node, "http://www.georss.org/georss";) == TRUE && xmlStrcmp (node->name, (xmlChar*) "where") == 0) {
 		/* georss:where */
 		/* From album's feed of file entries.  Redundant with album entries represented by GDataPicasaWebAlbum.  Capturing and ignoring.  See bgo #589858. */
-	} else if (GDATA_PARSABLE_CLASS (gdata_picasaweb_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_picasaweb_feed_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/picasaweb/gdata-picasaweb-file.c b/gdata/services/picasaweb/gdata-picasaweb-file.c
index 851551a..2f50009 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-file.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-file.c
@@ -792,80 +792,91 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataPicasaWebFile *self = GDATA_PICASAWEB_FILE (parsable);
 
-	/* TODO: This should also be P_NO_DUPES, but we can't, as priv->media_group has to be pre-populated
+	/* TODO: media:group should also be P_NO_DUPES, but we can't, as priv->media_group has to be pre-populated
 	 * in order for things like gdata_picasaweb_file_set_description() to work. */
-	if (gdata_parser_object_from_element (node, "group", P_REQUIRED, GDATA_TYPE_MEDIA_GROUP,
-	                                      &(self->priv->media_group), &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "where", P_REQUIRED, GDATA_TYPE_GEORSS_WHERE,
-	                                      &(self->priv->georss_where), &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "tags", P_REQUIRED, GDATA_TYPE_EXIF_TAGS,
-	                                      &(self->priv->exif_tags), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "videostatus", P_NO_DUPES, &(self->priv->video_status), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "imageVersion", P_NONE, &(self->priv->version), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "albumid", P_NONE, &(self->priv->album_id), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "client", P_NONE, &(self->priv->client), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "checksum", P_NONE, &(self->priv->client), &success, error) == TRUE ||
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
 	    gdata_parser_time_val_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
 		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "position") == 0) {
-		/* gphoto:position */
-		xmlChar *position_str = xmlNodeListGetString (doc, node->children, TRUE);
-		gdata_picasaweb_file_set_position (self, g_ascii_strtod ((gchar*) position_str, NULL));
-		xmlFree (position_str);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "width") == 0) {
-		/* gphoto:width */
-		xmlChar *width = xmlNodeListGetString (doc, node->children, TRUE);
-		self->priv->width = strtoul ((gchar*) width, NULL, 10);
-		xmlFree (width);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "height") == 0) {
-		/* gphoto:height */
-		xmlChar *height = xmlNodeListGetString (doc, node->children, TRUE);
-		self->priv->height = strtoul ((gchar*) height, NULL, 10);
-		xmlFree (height);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "size") == 0) {
-		/* gphoto:size */
-		xmlChar *size = xmlNodeListGetString (doc, node->children, TRUE);
-		self->priv->size = strtoul ((gchar*) size, NULL, 10);
-		xmlFree (size);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "timestamp") == 0) {
-		/* gphoto:timestamp */
-		xmlChar *timestamp_str;
-		guint64 milliseconds;
-		GTimeVal timestamp;
-
-		timestamp_str = xmlNodeListGetString (doc, node->children, TRUE);
-		milliseconds = g_ascii_strtoull ((gchar*) timestamp_str, NULL, 10);
-		xmlFree (timestamp_str);
-
-		timestamp.tv_sec = (glong) (milliseconds / 1000);
-		timestamp.tv_usec = (glong) ((milliseconds % 1000) * 1000);
-
-		gdata_picasaweb_file_set_timestamp (self, &timestamp);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "commentingEnabled") == 0) {
-		/* gphoto:commentingEnabled */
-		xmlChar *is_commenting_enabled = xmlNodeListGetString (doc, node->children, TRUE);
-		if (is_commenting_enabled == NULL)
-			return gdata_parser_error_required_content_missing (node, error);
-		self->priv->is_commenting_enabled = (xmlStrcmp (is_commenting_enabled, (xmlChar*) "true") == 0 ? TRUE : FALSE);
-		xmlFree (is_commenting_enabled);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "commentCount") == 0) {
-		/* gphoto:commentCount */
-		xmlChar *comment_count = xmlNodeListGetString (doc, node->children, TRUE);
-		self->priv->comment_count = strtoul ((gchar*) comment_count, NULL, 10);
-		xmlFree (comment_count);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
-		/* gphoto:access */
-		/* Visibility is already obtained through the album. When PicasaWeb supports per-file access restrictions,
-		   we'll expose this property. Until then, we'll catch this to suppress the Unhandled XML warning.
-		   See https://bugzilla.gnome.org/show_bug.cgi?id=589858 */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "rotation") == 0) {
-		/* gphoto:rotation */
-		xmlChar *rotation = xmlNodeListGetString (doc, node->children, TRUE);
-		gdata_picasaweb_file_set_rotation (self, strtoul ((gchar*) rotation, NULL, 10));
-		xmlFree (rotation);
-	} else if (GDATA_PARSABLE_CLASS (gdata_picasaweb_file_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE &&
+	           gdata_parser_object_from_element (node, "group", P_REQUIRED, GDATA_TYPE_MEDIA_GROUP,
+	                                             &(self->priv->media_group), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://www.georss.org/georss";) == TRUE &&
+	          gdata_parser_object_from_element (node, "where", P_REQUIRED, GDATA_TYPE_GEORSS_WHERE,
+	                                            &(self->priv->georss_where), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/photos/exif/2007";) == TRUE &&
+	           gdata_parser_object_from_element (node, "tags", P_REQUIRED, GDATA_TYPE_EXIF_TAGS,
+	                                             &(self->priv->exif_tags), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/photos/2007";) == TRUE) {
+		if (gdata_parser_string_from_element (node, "videostatus", P_NO_DUPES, &(self->priv->video_status), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "imageVersion", P_NONE, &(self->priv->version), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "albumid", P_NONE, &(self->priv->album_id), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "client", P_NONE, &(self->priv->client), &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "checksum", P_NONE, &(self->priv->client), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "position") == 0) {
+			/* gphoto:position */
+			xmlChar *position_str = xmlNodeListGetString (doc, node->children, TRUE);
+			gdata_picasaweb_file_set_position (self, g_ascii_strtod ((gchar*) position_str, NULL));
+			xmlFree (position_str);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "width") == 0) {
+			/* gphoto:width */
+			xmlChar *width = xmlNodeListGetString (doc, node->children, TRUE);
+			self->priv->width = strtoul ((gchar*) width, NULL, 10);
+			xmlFree (width);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "height") == 0) {
+			/* gphoto:height */
+			xmlChar *height = xmlNodeListGetString (doc, node->children, TRUE);
+			self->priv->height = strtoul ((gchar*) height, NULL, 10);
+			xmlFree (height);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "size") == 0) {
+			/* gphoto:size */
+			xmlChar *size = xmlNodeListGetString (doc, node->children, TRUE);
+			self->priv->size = strtoul ((gchar*) size, NULL, 10);
+			xmlFree (size);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "timestamp") == 0) {
+			/* gphoto:timestamp */
+			xmlChar *timestamp_str;
+			guint64 milliseconds;
+			GTimeVal timestamp;
+
+			timestamp_str = xmlNodeListGetString (doc, node->children, TRUE);
+			milliseconds = g_ascii_strtoull ((gchar*) timestamp_str, NULL, 10);
+			xmlFree (timestamp_str);
+
+			timestamp.tv_sec = (glong) (milliseconds / 1000);
+			timestamp.tv_usec = (glong) ((milliseconds % 1000) * 1000);
+
+			gdata_picasaweb_file_set_timestamp (self, &timestamp);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "commentingEnabled") == 0) {
+			/* gphoto:commentingEnabled */
+			xmlChar *is_commenting_enabled = xmlNodeListGetString (doc, node->children, TRUE);
+			if (is_commenting_enabled == NULL)
+				return gdata_parser_error_required_content_missing (node, error);
+			self->priv->is_commenting_enabled = (xmlStrcmp (is_commenting_enabled, (xmlChar*) "true") == 0 ? TRUE : FALSE);
+			xmlFree (is_commenting_enabled);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "commentCount") == 0) {
+			/* gphoto:commentCount */
+			xmlChar *comment_count = xmlNodeListGetString (doc, node->children, TRUE);
+			self->priv->comment_count = strtoul ((gchar*) comment_count, NULL, 10);
+			xmlFree (comment_count);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "access") == 0) {
+			/* gphoto:access */
+			/* Visibility is already obtained through the album. When PicasaWeb supports per-file access restrictions,
+			   we'll expose this property. Until then, we'll catch this to suppress the Unhandled XML warning.
+			   See https://bugzilla.gnome.org/show_bug.cgi?id=589858 */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "rotation") == 0) {
+			/* gphoto:rotation */
+			xmlChar *rotation = xmlNodeListGetString (doc, node->children, TRUE);
+			gdata_picasaweb_file_set_rotation (self, strtoul ((gchar*) rotation, NULL, 10));
+			xmlFree (rotation);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_picasaweb_file_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+		}
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_picasaweb_file_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/picasaweb/gdata-picasaweb-user.c b/gdata/services/picasaweb/gdata-picasaweb-user.c
index 2863bc8..5513360 100644
--- a/gdata/services/picasaweb/gdata-picasaweb-user.c
+++ b/gdata/services/picasaweb/gdata-picasaweb-user.c
@@ -221,6 +221,9 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataPicasaWebUser *self = GDATA_PICASAWEB_USER (parsable);
 
+	if (gdata_parser_is_namespace (node, "http://schemas.google.com/photos/2007";) == FALSE)
+		return GDATA_PARSABLE_CLASS (gdata_picasaweb_user_parent_class)->parse_xml (parsable, doc, node, user_data, error);
+
 	if (gdata_parser_string_from_element (node, "user", P_REQUIRED | P_NON_EMPTY, &(self->priv->user), &success, error) == TRUE ||
 	    gdata_parser_string_from_element (node, "nickname", P_REQUIRED | P_NON_EMPTY, &(self->priv->nickname), &success, error) == TRUE ||
 	    gdata_parser_string_from_element (node, "thumbnail", P_REQUIRED | P_NON_EMPTY, &(self->priv->thumbnail_uri), &success, error) == TRUE) {
@@ -246,9 +249,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	} else if (xmlStrcmp (node->name, (xmlChar*) "x-allowPrints") == 0) { /* RHSTODO: see if this comes with the user */
 		/* gphoto:allowPrints */
 		/* TODO: Not part of public API so we're capturing and ignoring for now.  See bgo #589858. */
-	} else if (GDATA_PARSABLE_CLASS (gdata_picasaweb_user_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_picasaweb_user_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/youtube/gdata-youtube-control.c b/gdata/services/youtube/gdata-youtube-control.c
index 9937d65..0cb052c 100644
--- a/gdata/services/youtube/gdata-youtube-control.c
+++ b/gdata/services/youtube/gdata-youtube-control.c
@@ -99,7 +99,8 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataYouTubeControl *self = GDATA_YOUTUBE_CONTROL (parsable);
 
-	if (xmlStrcmp (node->name, (xmlChar*) "draft") == 0) {
+	if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
+	    xmlStrcmp (node->name, (xmlChar*) "draft") == 0) {
 		/* app:draft */
 		xmlChar *draft = xmlNodeListGetString (doc, node, TRUE);
 		if (xmlStrcmp (draft, (xmlChar*) "no") == 0)
@@ -107,12 +108,12 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		else
 			self->priv->is_draft = TRUE;
 		xmlFree (draft);
-	} else if (gdata_parser_object_from_element (node, "state", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_YOUTUBE_STATE,
+	} else if (gdata_parser_is_namespace (node, "http://gdata.youtube.com/schemas/2007";) == TRUE &&
+	           gdata_parser_object_from_element (node, "state", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_YOUTUBE_STATE,
 	                                             &(self->priv->state), &success, error) == TRUE) {
 		return success;
-	} else if (GDATA_PARSABLE_CLASS (gdata_youtube_control_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_youtube_control_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/youtube/gdata-youtube-group.c b/gdata/services/youtube/gdata-youtube-group.c
index 1b431a7..3f21761 100644
--- a/gdata/services/youtube/gdata-youtube-group.c
+++ b/gdata/services/youtube/gdata-youtube-group.c
@@ -93,12 +93,7 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataYouTubeGroup *self = GDATA_YOUTUBE_GROUP (parsable);
 
-	if (gdata_parser_object_from_element_setter (node, "content", P_REQUIRED, GDATA_TYPE_YOUTUBE_CONTENT,
-	                                             _gdata_media_group_add_content, self, &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "videoid", P_NO_DUPES, &(self->priv->video_id), &success, error) == TRUE ||
-	    gdata_parser_time_val_from_element (node, "uploaded", P_REQUIRED | P_NO_DUPES, &(self->priv->uploaded), &success, error) == TRUE) {
-		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "credit") == 0) {
+	if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE && xmlStrcmp (node->name, (xmlChar*) "credit") == 0) {
 		/* media:credit */
 		GDataYouTubeCredit *credit = GDATA_YOUTUBE_CREDIT (_gdata_parsable_new_from_xml_node (GDATA_TYPE_YOUTUBE_CREDIT, doc,
 												      node, NULL, error));
@@ -111,31 +106,39 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 		}
 
 		_gdata_media_group_set_credit (GDATA_MEDIA_GROUP (self), GDATA_MEDIA_CREDIT (credit));
-	} else if (xmlStrcmp (node->name, (xmlChar*) "duration") == 0) {
-		/* yt:duration */
-		xmlChar *duration = xmlGetProp (node, (xmlChar*) "seconds");
-		if (duration == NULL)
-			return gdata_parser_error_required_property_missing (node, "seconds", error);
-
-		self->priv->duration = strtoul ((gchar*) duration, NULL, 10);
-		xmlFree (duration);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "private") == 0) {
-		/* yt:private */
-		gdata_youtube_group_set_is_private (self, TRUE);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "aspectRatio") == 0) {
-		/* yt:aspectRatio */
-		xmlChar *aspect_ratio = xmlNodeGetContent (node);
-		if (xmlStrcmp (aspect_ratio, (xmlChar*) "widescreen") == 0) {
-			gdata_youtube_group_set_aspect_ratio (self, GDATA_YOUTUBE_ASPECT_RATIO_WIDESCREEN);
-		} else {
-			gdata_parser_error_unknown_content (node, (const gchar*) aspect_ratio, error);
+	} else if (gdata_parser_is_namespace (node, "http://gdata.youtube.com/schemas/2007";) == TRUE) {
+		if (gdata_parser_object_from_element_setter (node, "content", P_REQUIRED, GDATA_TYPE_YOUTUBE_CONTENT,
+		                                             _gdata_media_group_add_content, self, &success, error) == TRUE ||
+		    gdata_parser_string_from_element (node, "videoid", P_NO_DUPES, &(self->priv->video_id), &success, error) == TRUE ||
+		    gdata_parser_time_val_from_element (node, "uploaded", P_REQUIRED | P_NO_DUPES, &(self->priv->uploaded), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "duration") == 0) {
+			/* yt:duration */
+			xmlChar *duration = xmlGetProp (node, (xmlChar*) "seconds");
+			if (duration == NULL)
+				return gdata_parser_error_required_property_missing (node, "seconds", error);
+
+			self->priv->duration = strtoul ((gchar*) duration, NULL, 10);
+			xmlFree (duration);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "private") == 0) {
+			/* yt:private */
+			gdata_youtube_group_set_is_private (self, TRUE);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "aspectRatio") == 0) {
+			/* yt:aspectRatio */
+			xmlChar *aspect_ratio = xmlNodeGetContent (node);
+			if (xmlStrcmp (aspect_ratio, (xmlChar*) "widescreen") == 0) {
+				gdata_youtube_group_set_aspect_ratio (self, GDATA_YOUTUBE_ASPECT_RATIO_WIDESCREEN);
+			} else {
+				gdata_parser_error_unknown_content (node, (const gchar*) aspect_ratio, error);
+				xmlFree (aspect_ratio);
+				return FALSE;
+			}
 			xmlFree (aspect_ratio);
-			return FALSE;
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_youtube_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
-		xmlFree (aspect_ratio);
-	} else if (GDATA_PARSABLE_CLASS (gdata_youtube_group_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_youtube_group_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/services/youtube/gdata-youtube-video.c b/gdata/services/youtube/gdata-youtube-video.c
index 4b9ac81..11fbf33 100644
--- a/gdata/services/youtube/gdata-youtube-video.c
+++ b/gdata/services/youtube/gdata-youtube-video.c
@@ -627,140 +627,151 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
 	gboolean success;
 	GDataYouTubeVideo *self = GDATA_YOUTUBE_VIDEO (parsable);
 
-	if (gdata_parser_object_from_element (node, "group", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_YOUTUBE_GROUP,
-	                                      &(self->priv->media_group), &success, error) == TRUE ||
-	    gdata_parser_object_from_element (node, "control", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_YOUTUBE_CONTROL,
-	                                      &(self->priv->youtube_control), &success, error) == TRUE ||
-	    gdata_parser_string_from_element (node, "location", P_NONE, &(self->priv->location), &success, error) == TRUE) {
+	if (gdata_parser_is_namespace (node, "http://search.yahoo.com/mrss/";) == TRUE &&
+	    gdata_parser_object_from_element (node, "group", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_YOUTUBE_GROUP,
+	                                      &(self->priv->media_group), &success, error) == TRUE) {
 		return success;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "rating") == 0) {
-		/* gd:rating */
-		xmlChar *min, *max, *num_raters, *average;
-		guint num_raters_uint;
-		gdouble average_double;
-
-		min = xmlGetProp (node, (xmlChar*) "min");
-		if (min == NULL)
-			return gdata_parser_error_required_property_missing (node, "min", error);
-
-		max = xmlGetProp (node, (xmlChar*) "max");
-		if (max == NULL) {
-			gdata_parser_error_required_property_missing (node, "max", error);
-			xmlFree (min);
-			return FALSE;
-		}
+	} else if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app";) == TRUE &&
+	           gdata_parser_object_from_element (node, "control", P_REQUIRED | P_NO_DUPES, GDATA_TYPE_YOUTUBE_CONTROL,
+		                                     &(self->priv->youtube_control), &success, error) == TRUE) {
+		return success;
+	} else if (gdata_parser_is_namespace (node, "http://gdata.youtube.com/schemas/2007";) == TRUE) {
+		if (gdata_parser_string_from_element (node, "location", P_NONE, &(self->priv->location), &success, error) == TRUE) {
+			return success;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "statistics") == 0) {
+			/* yt:statistics */
+			xmlChar *view_count, *favorite_count;
+
+			/* View count */
+			view_count = xmlGetProp (node, (xmlChar*) "viewCount");
+			if (view_count == NULL)
+				return gdata_parser_error_required_property_missing (node, "viewCount", error);
+			self->priv->view_count = strtoul ((gchar*) view_count, NULL, 10);
+			xmlFree (view_count);
+
+			/* Favourite count */
+			favorite_count = xmlGetProp (node, (xmlChar*) "favoriteCount");
+			self->priv->favorite_count = (favorite_count != NULL) ? strtoul ((gchar*) favorite_count, NULL, 10) : 0;
+			xmlFree (favorite_count);
+		} else if (xmlStrcmp (node->name, (xmlChar*) "noembed") == 0) {
+			/* yt:noembed */
+			/* Ignore this now; it's been superceded by yt:accessControl.
+			   See http://apiblog.youtube.com/2010/02/extended-access-controls-available-via.html */
+		} else if (xmlStrcmp (node->name, (xmlChar*) "accessControl") == 0) {
+			/* yt:accessControl */
+			xmlChar *action, *permission;
+			GDataYouTubePermission permission_enum;
+
+			action = xmlGetProp (node, (xmlChar*) "action");
+			if (action == NULL)
+				return gdata_parser_error_required_property_missing (node, "action", error);
+			permission = xmlGetProp (node, (xmlChar*) "permission");
+			if (permission == NULL) {
+				xmlFree (action);
+				return gdata_parser_error_required_property_missing (node, "permission", error);
+			}
 
-		num_raters = xmlGetProp (node, (xmlChar*) "numRaters");
-		if (num_raters == NULL)
-			num_raters_uint = 0;
-		else
-			num_raters_uint = strtoul ((gchar*) num_raters, NULL, 10);
-		xmlFree (num_raters);
-
-		average = xmlGetProp (node, (xmlChar*) "average");
-		if (average == NULL)
-			average_double = 0;
-		else
-			average_double = g_ascii_strtod ((gchar*) average, NULL);
-		xmlFree (average);
-
-		self->priv->rating.min = strtoul ((gchar*) min, NULL, 10);
-		self->priv->rating.max = strtoul ((gchar*) max, NULL, 10);
-		self->priv->rating.count = num_raters_uint;
-		self->priv->rating.average = average_double;
-	} else if (xmlStrcmp (node->name, (xmlChar*) "comments") == 0) {
-		/* gd:comments */
-		xmlChar *rel, *href, *count_hint, *read_only;
-		xmlNode *child_node;
-		guint count_hint_uint;
-
-		/* This is actually the child of the <comments> element */
-		child_node = node->children;
-
-		count_hint = xmlGetProp (child_node, (xmlChar*) "countHint");
-		if (count_hint == NULL)
-			count_hint_uint = 0;
-		else
-			count_hint_uint = strtoul ((gchar*) count_hint, NULL, 10);
-		xmlFree (count_hint);
-
-		read_only = xmlGetProp (child_node, (xmlChar*) "readOnly");
-		rel = xmlGetProp (child_node, (xmlChar*) "rel");
-		href = xmlGetProp (child_node, (xmlChar*) "href");
-
-		/* TODO */
-		/*gdata_gd_feed_link_free (self->priv->comments_feed_link);
-		self->priv->comments_feed_link = gdata_gd_feed_link_new ((gchar*) href, (gchar*) rel, count_hint_uint,
-									 ((xmlStrcmp (read_only, (xmlChar*) "true") == 0) ? TRUE : FALSE));*/
-
-		xmlFree (rel);
-		xmlFree (href);
-		xmlFree (read_only);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "statistics") == 0) {
-		/* yt:statistics */
-		xmlChar *view_count, *favorite_count;
-
-		/* View count */
-		view_count = xmlGetProp (node, (xmlChar*) "viewCount");
-		if (view_count == NULL)
-			return gdata_parser_error_required_property_missing (node, "viewCount", error);
-		self->priv->view_count = strtoul ((gchar*) view_count, NULL, 10);
-		xmlFree (view_count);
-
-		/* Favourite count */
-		favorite_count = xmlGetProp (node, (xmlChar*) "favoriteCount");
-		self->priv->favorite_count = (favorite_count != NULL) ? strtoul ((gchar*) favorite_count, NULL, 10) : 0;
-		xmlFree (favorite_count);
-	} else if (xmlStrcmp (node->name, (xmlChar*) "noembed") == 0) {
-		/* yt:noembed */
-		/* Ignore this now; it's been superceded by yt:accessControl.
-		   See http://apiblog.youtube.com/2010/02/extended-access-controls-available-via.html */
-	} else if (xmlStrcmp (node->name, (xmlChar*) "accessControl") == 0) {
-		/* yt:accessControl */
-		xmlChar *action, *permission;
-		GDataYouTubePermission permission_enum;
-
-		action = xmlGetProp (node, (xmlChar*) "action");
-		if (action == NULL)
-			return gdata_parser_error_required_property_missing (node, "action", error);
-		permission = xmlGetProp (node, (xmlChar*) "permission");
-		if (permission == NULL) {
-			xmlFree (action);
-			return gdata_parser_error_required_property_missing (node, "permission", error);
-		}
+			/* Work out what the permission is */
+			if (xmlStrcmp (permission, (xmlChar*) "allowed") == 0) {
+				permission_enum = GDATA_YOUTUBE_PERMISSION_ALLOWED;
+			} else if (xmlStrcmp (permission, (xmlChar*) "denied") == 0) {
+				permission_enum = GDATA_YOUTUBE_PERMISSION_DENIED;
+			} else if (xmlStrcmp (permission, (xmlChar*) "moderated") == 0) {
+				permission_enum = GDATA_YOUTUBE_PERMISSION_MODERATED;
+			} else {
+				xmlFree (action);
+				xmlFree (permission);
+				return gdata_parser_error_unknown_property_value (node, "permission", (gchar*) permission, error);
+			}
 
-		/* Work out what the permission is */
-		if (xmlStrcmp (permission, (xmlChar*) "allowed") == 0) {
-			permission_enum = GDATA_YOUTUBE_PERMISSION_ALLOWED;
-		} else if (xmlStrcmp (permission, (xmlChar*) "denied") == 0) {
-			permission_enum = GDATA_YOUTUBE_PERMISSION_DENIED;
-		} else if (xmlStrcmp (permission, (xmlChar*) "moderated") == 0) {
-			permission_enum = GDATA_YOUTUBE_PERMISSION_MODERATED;
+			/* Store the access control */
+			g_hash_table_insert (self->priv->access_controls, (gchar*) action, GINT_TO_POINTER (permission_enum));
+		} else if (xmlStrcmp (node->name, (xmlChar*) "recorded") == 0) {
+			/* yt:recorded */
+			xmlChar *recorded;
+			GTimeVal recorded_timeval;
+
+			recorded = xmlNodeListGetString (doc, node->children, TRUE);
+			if (gdata_parser_time_val_from_date ((gchar*) recorded, &recorded_timeval) == FALSE) {
+				/* Error */
+				gdata_parser_error_not_iso8601_format (node, (gchar*) recorded, error);
+				xmlFree (recorded);
+				return FALSE;
+			}
+			xmlFree (recorded);
+			gdata_youtube_video_set_recorded (self, &recorded_timeval);
 		} else {
-			xmlFree (action);
-			xmlFree (permission);
-			return gdata_parser_error_unknown_property_value (node, "permission", (gchar*) permission, error);
+			return GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
+	} else if (gdata_parser_is_namespace (node, "http://schemas.google.com/g/2005";) == TRUE) {
+		if (xmlStrcmp (node->name, (xmlChar*) "rating") == 0) {
+			/* gd:rating */
+			xmlChar *min, *max, *num_raters, *average;
+			guint num_raters_uint;
+			gdouble average_double;
+
+			min = xmlGetProp (node, (xmlChar*) "min");
+			if (min == NULL)
+				return gdata_parser_error_required_property_missing (node, "min", error);
+
+			max = xmlGetProp (node, (xmlChar*) "max");
+			if (max == NULL) {
+				gdata_parser_error_required_property_missing (node, "max", error);
+				xmlFree (min);
+				return FALSE;
+			}
 
-		/* Store the access control */
-		g_hash_table_insert (self->priv->access_controls, (gchar*) action, GINT_TO_POINTER (permission_enum));
-	} else if (xmlStrcmp (node->name, (xmlChar*) "recorded") == 0) {
-		/* yt:recorded */
-		xmlChar *recorded;
-		GTimeVal recorded_timeval;
-
-		recorded = xmlNodeListGetString (doc, node->children, TRUE);
-		if (gdata_parser_time_val_from_date ((gchar*) recorded, &recorded_timeval) == FALSE) {
-			/* Error */
-			gdata_parser_error_not_iso8601_format (node, (gchar*) recorded, error);
-			xmlFree (recorded);
-			return FALSE;
+			num_raters = xmlGetProp (node, (xmlChar*) "numRaters");
+			if (num_raters == NULL)
+				num_raters_uint = 0;
+			else
+				num_raters_uint = strtoul ((gchar*) num_raters, NULL, 10);
+			xmlFree (num_raters);
+
+			average = xmlGetProp (node, (xmlChar*) "average");
+			if (average == NULL)
+				average_double = 0;
+			else
+				average_double = g_ascii_strtod ((gchar*) average, NULL);
+			xmlFree (average);
+
+			self->priv->rating.min = strtoul ((gchar*) min, NULL, 10);
+			self->priv->rating.max = strtoul ((gchar*) max, NULL, 10);
+			self->priv->rating.count = num_raters_uint;
+			self->priv->rating.average = average_double;
+		} else if (xmlStrcmp (node->name, (xmlChar*) "comments") == 0) {
+			/* gd:comments */
+			xmlChar *rel, *href, *count_hint, *read_only;
+			xmlNode *child_node;
+			guint count_hint_uint;
+
+			/* This is actually the child of the <comments> element */
+			child_node = node->children;
+
+			count_hint = xmlGetProp (child_node, (xmlChar*) "countHint");
+			if (count_hint == NULL)
+				count_hint_uint = 0;
+			else
+				count_hint_uint = strtoul ((gchar*) count_hint, NULL, 10);
+			xmlFree (count_hint);
+
+			read_only = xmlGetProp (child_node, (xmlChar*) "readOnly");
+			rel = xmlGetProp (child_node, (xmlChar*) "rel");
+			href = xmlGetProp (child_node, (xmlChar*) "href");
+
+			/* TODO */
+			/*gdata_gd_feed_link_free (self->priv->comments_feed_link);
+			self->priv->comments_feed_link = gdata_gd_feed_link_new ((gchar*) href, (gchar*) rel, count_hint_uint,
+										 ((xmlStrcmp (read_only, (xmlChar*) "true") == 0) ? TRUE : FALSE));*/
+
+			xmlFree (rel);
+			xmlFree (href);
+			xmlFree (read_only);
+		} else {
+			return GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 		}
-		xmlFree (recorded);
-		gdata_youtube_video_set_recorded (self, &recorded_timeval);
-	} else if (GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->parse_xml (parsable, doc, node, user_data, error) == FALSE) {
-		/* Error! */
-		return FALSE;
+	} else {
+		return GDATA_PARSABLE_CLASS (gdata_youtube_video_parent_class)->parse_xml (parsable, doc, node, user_data, error);
 	}
 
 	return TRUE;
diff --git a/gdata/tests/picasaweb.c b/gdata/tests/picasaweb.c
index 88db110..a16ae34 100644
--- a/gdata/tests/picasaweb.c
+++ b/gdata/tests/picasaweb.c
@@ -777,7 +777,7 @@ test_photo_feed_entry (gconstpointer service)
 	g_assert_cmpuint (g_list_length (files), ==, 1);
 
 	g_assert_cmpstr (gdata_entry_get_title (photo_entry), ==, "100_0269.jpg");
-	g_assert_cmpstr (gdata_entry_get_id (photo_entry), ==, "5328890138794566386");
+	g_assert_cmpstr (gdata_entry_get_id (photo_entry), ==, "http://picasaweb.google.com/data/entry/user/libgdata.picasaweb/albumid/5328889949261497249/photoid/5328890138794566386";);
 	g_assert_cmpstr (gdata_entry_get_etag (photo_entry), !=, NULL);
 
 	gdata_entry_get_updated (photo_entry, &_time);
@@ -984,7 +984,7 @@ test_album_feed_entry (gconstpointer service)
 
 	/* Tests */
 	g_assert_cmpstr (gdata_entry_get_title (entry), ==, "Test Album 1 - Venice - Public");
-	g_assert_cmpstr (gdata_entry_get_id (entry), ==, "5328889949261497249");
+	g_assert_cmpstr (gdata_entry_get_id (entry), ==, "http://picasaweb.google.com/data/entry/user/libgdata.picasaweb/albumid/5328889949261497249";);
 	g_assert_cmpstr (gdata_entry_get_etag (entry), !=, NULL);
 	g_assert_cmpstr (gdata_entry_get_rights (entry), ==, "public");
 



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