diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/element.c | 38 | ||||
-rw-r--r-- | src/core/node.c | 106 | ||||
-rw-r--r-- | src/core/node.h | 5 | ||||
-rw-r--r-- | src/core/nodelist.c | 20 |
4 files changed, 113 insertions, 56 deletions
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 <dom/core/attr.h> #include <dom/core/element.h> +#include <dom/core/node.h> #include <dom/core/string.h> #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 <assert.h> #include <stdbool.h> +#include <stdio.h> #include <dom/core/attr.h> #include <dom/core/document.h> @@ -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++; } |