/*  
 
 
 
xpath2 ini/config.xml '//anode'
 
 
 
 * section:     XPath
 
 * synopsis:    Load a document, locate subelements with XPath,
 
 * usage:       xpath2 <xml-file> <xpath-expr> 
 
 * test:        xpath2 test3.xml '//discarded' 
 
 */
 
#include <stdlib.h>
 
#include <stdio.h>
 
#include <string.h>
 
#include <assert.h>
 
#include <vector>
 
 
 
#include <libxml/tree.h>
 
#include <libxml/parser.h>
 
#include <libxml/xpath.h>
 
#include <libxml/xpathInternals.h>
 
 
 
#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED) && \
 
    defined(LIBXML_OUTPUT_ENABLED)
 
 
 
 
 
 
 
static int  getvalue(xmlXPathContextPtr xpathCtx, const xmlChar * xpathExpr, std::vector <xmlChar *> &retval);
 
static xmlChar * getvalue(xmlXPathContextPtr xpathCtx, const xmlChar * xpathExpr, int which=0);
 
 
 
 
 
int 
 
main(int argc, char **argv) {
 
    std::vector<xmlChar *> retval;
 
    xmlDocPtr doc;
 
    xmlXPathContextPtr xpathCtx;
 
    int size;
 
    
 
    xmlInitParser();
 
    LIBXML_TEST_VERSION
 
    
 
     /* Load XML document */
 
    doc = xmlParseFile(argv[1]);
 
    if (doc == NULL) {
 
        fprintf(stderr
, "Error: unable to parse file \"%s\"\n", argv
[1]);  
        return(-1);
 
    }
 
 
 
    /* Create xpath evaluation context */
 
    xpathCtx = xmlXPathNewContext(doc);
 
    if(xpathCtx == NULL) {
 
        fprintf(stderr
,"Error: unable to create new XPath context\n");  
        xmlFreeDoc(doc); 
 
        return(-1);
 
    }
 
    
 
    for (int i=2; i<argc;i++){     
 
      size = getvalue(xpathCtx, BAD_CAST argv[i] , retval); 
 
      printf ("-->size = %d value %s\n",size
, getvalue
(xpathCtx
, BAD_CAST argv
[i
])   );  
    }
 
     
 
    xmlXPathFreeContext(xpathCtx); 
 
    xmlFreeDoc(doc);     
 
    xmlCleanupParser();
 
    xmlMemoryDump();
 
    return 0;
 
}
 
 
 
 
 
/**
 
 * getvalue:
 
 * @xpathCtx:           the input xmlXPathContextPtr
 
 * @xpathExpr:          the xpath expression for evaluation.
 
 *
 
 * evaluates XPath expression 
 
 *
 
 * Returns node content
 
 */
 
int getvalue(xmlXPathContextPtr xpathCtx, const xmlChar* xpathExpr, std::vector<xmlChar *> &retval) {
 
    
 
    xmlXPathObjectPtr xpathObj;
 
    xmlNodeSetPtr nodes; 
 
    xmlChar * ret=NULL;
 
    int size;
 
    int i;
 
    /* Evaluate xpath expression */
 
    xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
 
    if(xpathObj == NULL) {
 
        fprintf(stderr
,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr
);  
        return retval.size();
 
    }
 
    
 
    nodes  = xpathObj->nodesetval;
 
    size   = (nodes) ? nodes->nodeNr : 0;
 
    for(i = 0; i< size; i++) {
 
      ret = xmlNodeGetContent(nodes->nodeTab[i]);
 
      if(ret) { 
 
        retval.push_back(ret);
 
        printf("[%d] %s         Return value: %s\n", i
, xpathExpr
, ret
);  
      }  
 
    }
 
    
 
    /* Cleanup of XPath data */
 
    xmlXPathFreeObject(xpathObj);
 
    
 
    return retval.size();
 
}
 
 
 
xmlChar *  getvalue(xmlXPathContextPtr xpathCtx, const xmlChar* xpathExpr, int which) {
 
    
 
    xmlXPathObjectPtr xpathObj;
 
    xmlNodeSetPtr nodes; 
 
    xmlChar * ret=NULL;
 
    int size;
 
    int i;
 
    /* Evaluate xpath expression */
 
    xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
 
    if(xpathObj == NULL) {
 
        fprintf(stderr
,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr
);  
        return NULL;
 
    }
 
    
 
    nodes  = xpathObj->nodesetval;
 
    size   = (nodes) ? nodes->nodeNr : 0;
 
    for(i = 0; i< size; i++) {
 
      ret = xmlNodeGetContent(nodes->nodeTab[i]);
 
      if(ret) {   
 
        printf("%s         Return value: %s\n",  xpathExpr
, ret
);  
        return ret;
 
      }  
 
    }
 
    
 
    /* Cleanup of XPath data */
 
    xmlXPathFreeObject(xpathObj);
 
    
 
    return NULL;
 
}
 
 
 
#endif