From 72f8877d57343fbc2bb42785da9d0c26bd3f0d7a Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Mon, 1 Jun 2009 09:28:28 +0000 Subject: Ticket #868: Added functions to search XML child nodes recursively git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2727 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib-util/include/pjlib-util/xml.h | 57 ++++++++++++++++--- pjlib-util/src/pjlib-util/xml.c | 106 +++++++++++++++++++++++++++++------- 2 files changed, 135 insertions(+), 28 deletions(-) (limited to 'pjlib-util') diff --git a/pjlib-util/include/pjlib-util/xml.h b/pjlib-util/include/pjlib-util/xml.h index 5595c20c..9188ae6b 100644 --- a/pjlib-util/include/pjlib-util/xml.h +++ b/pjlib-util/include/pjlib-util/xml.h @@ -149,17 +149,18 @@ PJ_DECL(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node ); PJ_DECL(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr ); /** - * Find first node with the specified name. + * Find first direct child node with the specified name. * * @param parent Parent node. * @param name Node name to find. * * @return XML node found or NULL. */ -PJ_DECL(pj_xml_node*) pj_xml_find_node(pj_xml_node *parent, const pj_str_t *name); +PJ_DECL(pj_xml_node*) pj_xml_find_node(const pj_xml_node *parent, + const pj_str_t *name); /** - * Find first node with the specified name. + * Find next direct child node with the specified name. * * @param parent Parent node. * @param node node->next is the starting point. @@ -167,11 +168,26 @@ PJ_DECL(pj_xml_node*) pj_xml_find_node(pj_xml_node *parent, const pj_str_t *name * * @return XML node found or NULL. */ -PJ_DECL(pj_xml_node*) pj_xml_find_next_node(pj_xml_node *parent, pj_xml_node *node, +PJ_DECL(pj_xml_node*) pj_xml_find_next_node(const pj_xml_node *parent, + const pj_xml_node *node, const pj_str_t *name); /** - * Find first attribute within a node with the specified name and optional value. + * Recursively find the first node with the specified name in the child nodes + * and their children. + * + * @param parent Parent node. + * @param name Node name to find. + * + * @return XML node found or NULL. + */ +PJ_DECL(pj_xml_node*) pj_xml_find_node_rec(const pj_xml_node *parent, + const pj_str_t *name); + + +/** + * Find first attribute within a node with the specified name and optional + * value. * * @param node XML Node. * @param name Attribute name to find. @@ -179,7 +195,8 @@ PJ_DECL(pj_xml_node*) pj_xml_find_next_node(pj_xml_node *parent, pj_xml_node *no * * @return XML attribute found, or NULL. */ -PJ_DECL(pj_xml_attr*) pj_xml_find_attr(pj_xml_node *node, const pj_str_t *name, +PJ_DECL(pj_xml_attr*) pj_xml_find_attr(const pj_xml_node *node, + const pj_str_t *name, const pj_str_t *value); @@ -187,15 +204,37 @@ PJ_DECL(pj_xml_attr*) pj_xml_find_attr(pj_xml_node *node, const pj_str_t *name, * Find a direct child node with the specified name and match the function. * * @param parent Parent node. - * @param name Optional name. + * @param name Optional name. If this is NULL, the name will not be + * matched. * @param data Data to be passed to matching function. * @param match Optional matching function. * * @return The first matched node, or NULL. */ -PJ_DECL(pj_xml_node*) pj_xml_find( pj_xml_node *parent, const pj_str_t *name, +PJ_DECL(pj_xml_node*) pj_xml_find( const pj_xml_node *parent, + const pj_str_t *name, const void *data, - pj_bool_t (*match)(pj_xml_node *, const void*)); + pj_bool_t (*match)(const pj_xml_node *, + const void*)); + + +/** + * Recursively find a child node with the specified name and match the + * function. + * + * @param parent Parent node. + * @param name Optional name. If this is NULL, the name will not be + * matched. + * @param data Data to be passed to matching function. + * @param match Optional matching function. + * + * @return The first matched node, or NULL. + */ +PJ_DECL(pj_xml_node*) pj_xml_find_rec(const pj_xml_node *parent, + const pj_str_t *name, + const void *data, + pj_bool_t (*match)(const pj_xml_node*, + const void*)); /** diff --git a/pjlib-util/src/pjlib-util/xml.c b/pjlib-util/src/pjlib-util/xml.c index e1bb43eb..b7b8faa5 100644 --- a/pjlib-util/src/pjlib-util/xml.c +++ b/pjlib-util/src/pjlib-util/xml.c @@ -340,22 +340,42 @@ PJ_DEF(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr ) pj_list_push_back(&node->attr_head, attr); } -PJ_DEF(pj_xml_node*) pj_xml_find_node(pj_xml_node *parent, const pj_str_t *name) +PJ_DEF(pj_xml_node*) pj_xml_find_node(const pj_xml_node *parent, + const pj_str_t *name) { - pj_xml_node *node = parent->node_head.next; + const pj_xml_node *node = parent->node_head.next; PJ_CHECK_STACK(); while (node != (void*)&parent->node_head) { if (pj_stricmp(&node->name, name) == 0) - return node; + return (pj_xml_node*)node; node = node->next; } return NULL; } +PJ_DEF(pj_xml_node*) pj_xml_find_node_rec(const pj_xml_node *parent, + const pj_str_t *name) +{ + const pj_xml_node *node = parent->node_head.next; + + PJ_CHECK_STACK(); + + while (node != (void*)&parent->node_head) { + pj_xml_node *found; + if (pj_stricmp(&node->name, name) == 0) + return (pj_xml_node*)node; + found = pj_xml_find_node_rec(node, name); + if (found) + return (pj_xml_node*)found; + node = node->next; + } + return NULL; +} -PJ_DEF(pj_xml_node*) pj_xml_find_next_node( pj_xml_node *parent, pj_xml_node *node, +PJ_DEF(pj_xml_node*) pj_xml_find_next_node( const pj_xml_node *parent, + const pj_xml_node *node, const pj_str_t *name) { PJ_CHECK_STACK(); @@ -363,24 +383,25 @@ PJ_DEF(pj_xml_node*) pj_xml_find_next_node( pj_xml_node *parent, pj_xml_node *no node = node->next; while (node != (void*)&parent->node_head) { if (pj_stricmp(&node->name, name) == 0) - return node; + return (pj_xml_node*)node; node = node->next; } return NULL; } -PJ_DEF(pj_xml_attr*) pj_xml_find_attr( pj_xml_node *node, const pj_str_t *name, +PJ_DEF(pj_xml_attr*) pj_xml_find_attr( const pj_xml_node *node, + const pj_str_t *name, const pj_str_t *value) { - pj_xml_attr *attr = node->attr_head.next; + const pj_xml_attr *attr = node->attr_head.next; while (attr != (void*)&node->attr_head) { if (pj_stricmp(&attr->name, name)==0) { if (value) { if (pj_stricmp(&attr->value, value)==0) - return attr; + return (pj_xml_attr*)attr; } else { - return attr; + return (pj_xml_attr*)attr; } } attr = attr->next; @@ -390,26 +411,73 @@ PJ_DEF(pj_xml_attr*) pj_xml_find_attr( pj_xml_node *node, const pj_str_t *name, -PJ_DEF(pj_xml_node*) pj_xml_find( pj_xml_node *parent, const pj_str_t *name, +PJ_DEF(pj_xml_node*) pj_xml_find( const pj_xml_node *parent, + const pj_str_t *name, const void *data, - pj_bool_t (*match)(pj_xml_node *, const void*)) + pj_bool_t (*match)(const pj_xml_node *, + const void*)) { - pj_xml_node *head = (pj_xml_node*) &parent->node_head, *node = head->next; + const pj_xml_node *node = (const pj_xml_node *)parent->node_head.next; - while (node != (void*)head) { - if (name && pj_stricmp(&node->name, name)==0) { - if (match) { - if (match(node, data)) - return node; - } else { - return node; + if (!name && !match) + return NULL; + + while (node != (const pj_xml_node*) &parent->node_head) { + if (name) { + if (pj_stricmp(&node->name, name)!=0) { + node = node->next; + continue; } } + if (match) { + if (match(node, data)) + return (pj_xml_node*)node; + } else { + return (pj_xml_node*)node; + } + node = node->next; } return NULL; } +PJ_DEF(pj_xml_node*) pj_xml_find_rec( const pj_xml_node *parent, + const pj_str_t *name, + const void *data, + pj_bool_t (*match)(const pj_xml_node*, + const void*)) +{ + const pj_xml_node *node = (const pj_xml_node *)parent->node_head.next; + + if (!name && !match) + return NULL; + + while (node != (const pj_xml_node*) &parent->node_head) { + pj_xml_node *found; + + if (name) { + if (pj_stricmp(&node->name, name)==0) { + if (match) { + if (match(node, data)) + return (pj_xml_node*)node; + } else { + return (pj_xml_node*)node; + } + } + + } else if (match) { + if (match(node, data)) + return (pj_xml_node*)node; + } + + found = pj_xml_find_rec(node, name, data, match); + if (found) + return found; + + node = node->next; + } + return NULL; +} PJ_DEF(pj_xml_node*) pj_xml_clone( pj_pool_t *pool, const pj_xml_node *rhs) { -- cgit v1.2.3