[collectd] [PATCH] Add support to aggregated value obtained by xpath functions

Antoine Monnet tonio+progs at xmon.net
Fri Nov 30 11:18:18 CET 2012


Hi,

This patch adds support to aggregated value obtained by xpath functions.
Ex:
        expression "count(//client)"
        returns the number of "client" node in the document

Thanks,
Antoine

---
 src/curl_xml.c |  130 +++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 81 insertions(+), 49 deletions(-)

diff --git a/src/curl_xml.c b/src/curl_xml.c
index 46e0d49..4248751 100644
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
@@ -237,69 +237,101 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
     cx_xpath_t *xpath,
     const data_set_t *ds, value_list_t *vl, int index)
 {
-  xmlXPathObjectPtr values_node_obj;
+  xmlXPathObjectPtr values_obj;
   xmlNodeSetPtr values_node;
   int tmp_size;
   char *node_value;
 
-  values_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST xpath->values[index].path);
-  if (values_node_obj == NULL)
+  values_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST xpath->values[index].path);
+  if (values_obj == NULL)
     return (-1); /* Error already logged. */
 
-  values_node = values_node_obj->nodesetval;
-  tmp_size = (values_node) ? values_node->nodeNr : 0;
+  switch (values_obj->type) {
+      
+  case XPATH_NODESET:     
+    values_node = values_obj->nodesetval;
+    tmp_size = (values_node) ? values_node->nodeNr : 0;
+      
+    if (tmp_size == 0)
+    {
+      WARNING ("curl_xml plugin: "
+               "relative xpath expression \"%s\" doesn't match any of the nodes. "
+               "Skipping...", xpath->values[index].path);
+      xmlXPathFreeObject (values_obj);
+      return (-1);
+    }
+      
+    if (tmp_size > 1)
+    {
+        WARNING ("curl_xml plugin: "
+                 "relative xpath expression \"%s\" is expected to return "
+                 "only one node. Skipping...", xpath->values[index].path);
+        xmlXPathFreeObject (values_obj);
+        return (-1);
+    }
+      
+    /* ignoring the element if other than textnode/attribute*/
+    if (cx_if_not_text_node(values_node->nodeTab[0]))
+    {
+      WARNING ("curl_xml plugin: "
+               "relative xpath expression \"%s\" is expected to return "
+               "only text/attribute node which is not the case. Skipping...", 
+               xpath->values[index].path);
+      xmlXPathFreeObject (values_obj);
+      return (-1);
+    }
+    node_value = (char *) xmlNodeGetContent(values_node->nodeTab[0]);
 
-  if (tmp_size == 0)
-  {
-    WARNING ("curl_xml plugin: "
-        "relative xpath expression \"%s\" doesn't match any of the nodes. "
-        "Skipping...", xpath->values[index].path);
-    xmlXPathFreeObject (values_node_obj);
-    return (-1);
-  }
+  case XPATH_STRING:
+    if (values_obj->type == XPATH_STRING)
+        node_value = (char *)values_obj->stringval;
 
-  if (tmp_size > 1)
-  {
-    WARNING ("curl_xml plugin: "
-        "relative xpath expression \"%s\" is expected to return "
-        "only one node. Skipping...", xpath->values[index].path);
-    xmlXPathFreeObject (values_node_obj);
-    return (-1);
-  }
+    switch (ds->ds[index].type)
+    {
+      case DS_TYPE_COUNTER:
+        vl->values[index].counter = (counter_t) strtoull (node_value,
+            /* endptr = */ NULL, /* base = */ 0);
+        break;
+      case DS_TYPE_DERIVE:
+        vl->values[index].derive = (derive_t) strtoll (node_value,
+            /* endptr = */ NULL, /* base = */ 0);
+        break;
+      case DS_TYPE_ABSOLUTE:
+        vl->values[index].absolute = (absolute_t) strtoull (node_value,
+            /* endptr = */ NULL, /* base = */ 0);
+        break;
+      case DS_TYPE_GAUGE: 
+        vl->values[index].gauge = (gauge_t) strtod (node_value,
+            /* endptr = */ NULL);
+    }
+    break;
 
-  /* ignoring the element if other than textnode/attribute*/
-  if (cx_if_not_text_node(values_node->nodeTab[0]))
-  {
+  case XPATH_NUMBER:
+    switch (ds->ds[index].type)
+    {
+      case DS_TYPE_COUNTER:
+        vl->values[index].counter = (counter_t) values_obj->floatval;
+        break;
+      case DS_TYPE_DERIVE:
+        vl->values[index].derive = (derive_t) values_obj->floatval;
+        break;
+      case DS_TYPE_ABSOLUTE:
+        vl->values[index].absolute = (absolute_t) values_obj->floatval;
+        break;
+      case DS_TYPE_GAUGE: 
+        vl->values[index].gauge = (gauge_t) values_obj->floatval;
+    }
+    break;
+  default:
     WARNING ("curl_xml plugin: "
-        "relative xpath expression \"%s\" is expected to return "
-        "only text/attribute node which is not the case. Skipping...", 
-        xpath->values[index].path);
-    xmlXPathFreeObject (values_node_obj);
+             "relative xpath expression \"%s\" result not handled. "
+             "Skipping...", xpath->values[index].path);
+    xmlXPathFreeObject (values_obj);
     return (-1);
   }
 
-  node_value = (char *) xmlNodeGetContent(values_node->nodeTab[0]);
-  switch (ds->ds[index].type)
-  {
-    case DS_TYPE_COUNTER:
-      vl->values[index].counter = (counter_t) strtoull (node_value,
-          /* endptr = */ NULL, /* base = */ 0);
-      break;
-    case DS_TYPE_DERIVE:
-      vl->values[index].derive = (derive_t) strtoll (node_value,
-          /* endptr = */ NULL, /* base = */ 0);
-      break;
-    case DS_TYPE_ABSOLUTE:
-      vl->values[index].absolute = (absolute_t) strtoull (node_value,
-          /* endptr = */ NULL, /* base = */ 0);
-      break;
-    case DS_TYPE_GAUGE: 
-      vl->values[index].gauge = (gauge_t) strtod (node_value,
-          /* endptr = */ NULL);
-  }
-
   /* free up object */
-  xmlXPathFreeObject (values_node_obj);
+  xmlXPathFreeObject (values_obj);
 
   /* We have reached here which means that
    * we have got something to work */
-- 
1.7.10.4



More information about the collectd mailing list