From 6a274638b1458f1c98a228255c7058f32d400199 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 26 Sep 2007 23:55:36 +0000 Subject: Begin to cater for XML namespaces. The localname member of Node has been removed. The name member already caters for this. Fix NodeList to cope with this and add some pointer vs NULL comparisons for sanity. Replace implementation of dom_element_get_tag_name() with a simple call to dom_node_get_node_name(), which is where the gory details lie. Add the QName building stuff to dom_node_get_node_name() (as per previous implementation of dom_element_get_tag_name()). Implement dom_node_set_prefix(). Ensure dom_node_get_local_name() returns NULL for nodes created by non-namespace-aware methods (nodes must also be Elements or Attributes) svn path=/trunk/dom/; revision=3596 --- src/core/element.c | 38 ++----------------- src/core/node.c | 106 +++++++++++++++++++++++++++++++++++++++++++++------- src/core/node.h | 5 ++- src/core/nodelist.c | 20 +++++++--- 4 files changed, 113 insertions(+), 56 deletions(-) (limited to 'src/core') diff --git a/src/core/element.c b/src/core/element.c index 1b351ce..027d597 100644 --- a/src/core/element.c +++ b/src/core/element.c @@ -9,6 +9,7 @@ #include #include +#include #include #include "core/attr.h" @@ -156,41 +157,8 @@ void dom_element_destroy(struct dom_document *doc, dom_exception dom_element_get_tag_name(struct dom_element *element, struct dom_string **name) { - struct dom_node *e = (struct dom_node *) element; - struct dom_string *tag_name; - - if (e->localname != NULL) { - /* Has a localname, so build a qname string */ - size_t local_len = 0, prefix_len = 0; - const uint8_t *local = NULL, *prefix = NULL; - dom_exception err; - - if (e->prefix != NULL) - dom_string_get_data(e->prefix, &prefix, &prefix_len); - - dom_string_get_data(e->localname, &local, &local_len); - - uint8_t qname[prefix_len + 1 /* : */ + local_len + 1 /* \0 */]; - - sprintf((char *) qname, "%s:%s", - prefix ? (const char *) prefix : "", - (const char *) local); - - err = dom_string_create_from_ptr(e->owner, qname, - prefix_len + 1 + local_len, &tag_name); - if (err != DOM_NO_ERR) - return err; - - /* tag_name is referenced for us */ - } else { - tag_name = e->name; - - dom_string_ref(tag_name); - } - - *name = tag_name; - - return DOM_NO_ERR; + /* This is the same as nodeName */ + return dom_node_get_node_name((struct dom_node *) element, name); } /** diff --git a/src/core/node.c b/src/core/node.c index ea957e4..2a90df8 100644 --- a/src/core/node.c +++ b/src/core/node.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -181,7 +182,6 @@ dom_exception dom_node_initialise(struct dom_node *node, /** \todo Namespace handling */ node->namespace = NULL; node->prefix = NULL; - node->localname = NULL; node->user_data = NULL; @@ -216,9 +216,6 @@ void dom_node_finalise(struct dom_document *doc, struct dom_node *node) dom_document_alloc(doc, u, 0); } - if (node->localname != NULL) - dom_string_unref(node->localname); - if (node->prefix != NULL) dom_string_unref(node->prefix); @@ -286,10 +283,45 @@ void dom_node_unref(struct dom_node *node) dom_exception dom_node_get_node_name(struct dom_node *node, struct dom_string **result) { - if (node->name != NULL) + struct dom_string *node_name; + + assert(node->name != NULL); + + /* If this node was created using a namespace-aware method and + * has a defined prefix, then nodeName is a QName comprised + * of prefix:name. */ + if ((node->type == DOM_ELEMENT_NODE || + node->type == DOM_ATTRIBUTE_NODE) && + node->prefix != NULL) { + const uint8_t *prefix, *localname; + size_t prefix_len, local_len; + dom_exception err; + + dom_string_get_data(node->prefix, &prefix, &prefix_len); + + dom_string_get_data(node->name, &localname, &local_len); + + uint8_t qname[prefix_len + 1 /* : */ + local_len + 1 /* \0 */]; + + sprintf((char *) qname, "%.*s:%.*s", + prefix_len, (const char *) prefix, + local_len, (const char *) localname); + + /* Create the string */ + err = dom_string_create_from_ptr(node->owner, qname, + prefix_len + 1 + local_len, &node_name); + if (err != DOM_NO_ERR) { + return err; + } + + /* QName is referenced on exit from constructor */ + } else { dom_string_ref(node->name); - *result = node->name; + node_name = node->name; + } + + *result = node_name; return DOM_NO_ERR; } @@ -1064,10 +1096,45 @@ dom_exception dom_node_get_prefix(struct dom_node *node, dom_exception dom_node_set_prefix(struct dom_node *node, struct dom_string *prefix) { - UNUSED(node); - UNUSED(prefix); + /* Only Element and Attribute nodes created using + * namespace-aware methods may have a prefix */ + if ((node->type != DOM_ELEMENT_NODE && + node->type != DOM_ATTRIBUTE_NODE) || + node->namespace == NULL) { + return DOM_NO_ERR; + } - return DOM_NOT_SUPPORTED_ERR; + /** \todo validate prefix */ + + /* Ensure node is writable */ + if (_dom_node_readonly(node)) { + return DOM_NO_MODIFICATION_ALLOWED_ERR; + } + + /* No longer want existing prefix */ + if (node->prefix != NULL) { + dom_string_unref(node->prefix); + } + + /* Set the prefix */ + if (prefix != NULL) { + const uint8_t *data; + size_t len; + + dom_string_get_data(prefix, &data, &len); + + /* Empty string is treated as NULL */ + if (len == 0) { + node->prefix = NULL; + } else { + dom_string_ref(prefix); + node->prefix = prefix; + } + } else { + node->prefix = NULL; + } + + return DOM_NO_ERR; } /** @@ -1084,11 +1151,24 @@ dom_exception dom_node_set_prefix(struct dom_node *node, dom_exception dom_node_get_local_name(struct dom_node *node, struct dom_string **result) { - /* If there is a local name, increase its reference count */ - if (node->localname != NULL) - dom_string_ref(node->localname); + /* Only Element and Attribute nodes may have a local name */ + if (node->type != DOM_ELEMENT_NODE && + node->type != DOM_ATTRIBUTE_NODE) { + *result = NULL; + return DOM_NO_ERR; + } - *result = node->localname; + /* Node must have been created using a namespace-aware method */ + if (node->namespace == NULL) { + *result = NULL; + return DOM_NO_ERR; + } + + /* The node may have a local name, reference it if so */ + if (node->name != NULL) { + dom_string_ref(node->name); + } + *result = node->name; return DOM_NO_ERR; } diff --git a/src/core/node.h b/src/core/node.h index 2297ca5..fd23625 100644 --- a/src/core/node.h +++ b/src/core/node.h @@ -32,7 +32,9 @@ struct dom_user_data { * DOM nodes are reference counted */ struct dom_node { - struct dom_string *name; /**< Node name */ + struct dom_string *name; /**< Node name (this is the local part + * of a QName in the cases where a + * namespace exists) */ struct dom_string *value; /**< Node value */ dom_node_type type; /**< Node type */ struct dom_node *parent; /**< Parent node */ @@ -45,7 +47,6 @@ struct dom_node { struct dom_string *namespace; /**< Namespace URI */ struct dom_string *prefix; /**< Namespace prefix */ - struct dom_string *localname; /**< Local part of qualified name */ struct dom_user_data *user_data; /**< User data list */ diff --git a/src/core/nodelist.c b/src/core/nodelist.c index 6cdd099..4377426 100644 --- a/src/core/nodelist.c +++ b/src/core/nodelist.c @@ -174,13 +174,17 @@ dom_exception dom_nodelist_get_length(struct dom_nodelist *list, if (list->type == DOM_NODELIST_CHILDREN) { len++; } else if (list->type == DOM_NODELIST_BY_NAME) { - if (dom_string_cmp(cur->name, list->data.name) == 0) { + if (cur->name != NULL && + dom_string_cmp(cur->name, + list->data.name) == 0) { len++; } } else { - if (dom_string_cmp(cur->namespace, + if (cur->namespace != NULL && + dom_string_cmp(cur->namespace, list->data.ns.namespace) == 0 && - dom_string_cmp(cur->localname, + cur->name != NULL && + dom_string_cmp(cur->name, list->data.ns.localname) == 0) { len++; } @@ -245,13 +249,17 @@ dom_exception dom_nodelist_item(struct dom_nodelist *list, if (list->type == DOM_NODELIST_CHILDREN) { count++; } else if (list->type == DOM_NODELIST_BY_NAME) { - if (dom_string_cmp(cur->name, list->data.name) == 0) { + if (cur->name != NULL && + dom_string_cmp(cur->name, + list->data.name) == 0) { count++; } } else { - if (dom_string_cmp(cur->namespace, + if (cur->namespace != NULL && + dom_string_cmp(cur->namespace, list->data.ns.namespace) == 0 && - dom_string_cmp(cur->localname, + cur->name != NULL && + dom_string_cmp(cur->name, list->data.ns.localname) == 0) { count++; } -- cgit v1.2.3