[sr-dev] git:master: xcap_server: ability to insert new nodes in xcap docs
Daniel-Constantin Mierla
miconda at gmail.com
Thu Sep 8 16:06:31 CEST 2011
Module: sip-router
Branch: master
Commit: b123fcd6009a7d13091233556963f84d2a850ed5
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b123fcd6009a7d13091233556963f84d2a850ed5
Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date: Thu Sep 8 16:02:49 2011 +0200
xcap_server: ability to insert new nodes in xcap docs
- xpath cannot do it alone when the selected node is missing
- reported by Laura Testi - credits for testing and further patching
---
modules_k/xcap_server/xcap_misc.c | 97 +++++++++++++++++++++++++++----------
1 files changed, 72 insertions(+), 25 deletions(-)
diff --git a/modules_k/xcap_server/xcap_misc.c b/modules_k/xcap_server/xcap_misc.c
index 57abf3f..f8a0228 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;
@@ -459,15 +464,56 @@ int xcaps_xpath_set(str *inbuf, str *xpaths, str *val, str *outbuf)
LM_ERR("unable to evaluate xpath expression [%s]\n", xpaths->s);
goto error;
}
- nodes = xpathObj->nodesetval;
- if(nodes==NULL)
+ nodes = xpathObj->nodesetval;
+ if(nodes==NULL || nodes->nodeNr==0 || nodes->nodeTab == 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 || nodes->nodeNr==0 || nodes->nodeTab == 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);
More information about the sr-dev
mailing list