[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