diff --git a/modules_k/xcap_server/xcap_misc.c b/modules_k/xcap_server/xcap_misc.c index 57abf3f..89ae3a1 100644 --- a/modules_k/xcap_server/xcap_misc.c +++ b/modules_k/xcap_server/xcap_misc.c @@ -433,13 +433,18 @@ int xcaps_xpath_set(str *inbuf, str *xpaths, str *val, str *outbuf) xmlNodePtr parent = NULL; int size; int i; + char *p; doc = xmlParseMemory(inbuf->s, inbuf->len); if(doc == NULL) return -1; if(val!=NULL) + { newnode = xmlParseMemory(val->s, val->len); + if(newnode==NULL) + goto error; + } outbuf->s = NULL; outbuf->len = 0; @@ -462,12 +467,53 @@ int xcaps_xpath_set(str *inbuf, str *xpaths, str *val, str *outbuf) nodes = xpathObj->nodesetval; if(nodes==NULL) { + /* no selection for xpath expression */ LM_DBG("no selection for xpath expression [%s]\n", xpaths->s); - goto done; - } - size = nodes->nodeNr; - if(val!=NULL) - value = (const xmlChar*)val->s; + if(val==NULL) + goto done; + /* could be an insert - locate the selection of parent node */ + p = strrchr(xpaths->s, '/'); + if(p==NULL) + goto done; + /* evaluate xpath expression for parrent node */ + *p = 0; + xpathObj = xmlXPathEvalExpression( + (const xmlChar*)xpaths->s, xpathCtx); + if(xpathObj == NULL) + { + LM_DBG("unable to evaluate xpath parent expression [%s]\n", + xpaths->s); + *p = '/'; + goto done; + } + *p = '/'; + nodes = xpathObj->nodesetval; + if(nodes==NULL) + { + LM_DBG("no selection for xpath parent expression [%s]\n", + xpaths->s); + goto done; + } + /* add the new content as child to first selected element node */ + if(nodes->nodeTab[0]==NULL) + { + LM_DBG("selection for xpath parent expression has first child" + " NULL [%s]\n", xpaths->s); + goto done; + } + if(nodes->nodeTab[0]->type==XML_ELEMENT_NODE) + { + xmlAddChild(nodes->nodeTab[0], xmlCopyNode(newnode->children, 1)); + } else { + LM_DBG("selection for xpath parent expression is not element" + " node [%s]\n", xpaths->s); + goto done; + } + } else { + /* selection for xpath expression */ + size = nodes->nodeNr; + if(val!=NULL) + value = (const xmlChar*)val->s; /* * NOTE: the nodes are processed in reverse order, i.e. reverse document @@ -477,22 +523,22 @@ int xcaps_xpath_set(str *inbuf, str *xpaths, str *val, str *outbuf) * they get removed. Mixing XPath and modifications on a tree must be * done carefully ! */ - for(i = size - 1; i >= 0; i--) { - if(nodes->nodeTab[i]==NULL) - continue; - - if(nodes->nodeTab[i]->type==XML_ELEMENT_NODE) - { - parent = nodes->nodeTab[i]->parent; - xmlUnlinkNode(nodes->nodeTab[i]); - if(val!=NULL && newnode!=NULL) - xmlAddChild(parent, xmlCopyNode(newnode->children, 1)); - } else { - if(val!=NULL) - xmlNodeSetContent(nodes->nodeTab[i], value); - else - xmlNodeSetContent(nodes->nodeTab[i], (const xmlChar*)""); - } + for(i = size - 1; i >= 0; i--) { + if(nodes->nodeTab[i]==NULL) + continue; + + if(nodes->nodeTab[i]->type==XML_ELEMENT_NODE) + { + parent = nodes->nodeTab[i]->parent; + xmlUnlinkNode(nodes->nodeTab[i]); + if(val!=NULL && newnode!=NULL) + xmlAddChild(parent, xmlCopyNode(newnode->children, 1)); + } else { + if(val!=NULL) + xmlNodeSetContent(nodes->nodeTab[i], value); + else + xmlNodeSetContent(nodes->nodeTab[i], (const xmlChar*)""); + } /* * All the elements returned by an XPath query are pointers to * elements from the tree *except* namespace nodes where the XPath @@ -510,8 +556,9 @@ int xcaps_xpath_set(str *inbuf, str *xpaths, str *val, str *outbuf) * - remove the reference to the modified nodes from the node set * as they are processed, if they are not namespace nodes. */ - if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) - nodes->nodeTab[i] = NULL; + if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) + nodes->nodeTab[i] = NULL; + } } xmlDocDumpMemory(doc, &xmem, &size);