[libxml2] Adding a --xpath option to xmllint



commit 1934b0c0fa8dff467955ae51118b69716a75f62b
Author: Daniel Veillard <veillard redhat com>
Date:   Wed Oct 7 10:25:06 2009 +0200

    Adding a --xpath option to xmllint
    
    * xmllint.c: runs in --noout mode and dumps the result of the XPath
      argument query. Still need to be expanded in some ways to allow
      namespace binding.

 xmllint.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 130 insertions(+), 9 deletions(-)
---
diff --git a/xmllint.c b/xmllint.c
index 6e4138e..cb845c7 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -108,15 +108,16 @@
 
 typedef enum {
     XMLLINT_RETURN_OK = 0,	/* No error */
-    XMLLINT_ERR_UNCLASS,	/* Unclassified */
-    XMLLINT_ERR_DTD,		/* Error in DTD */
-    XMLLINT_ERR_VALID,		/* Validation error */
-    XMLLINT_ERR_RDFILE,		/* CtxtReadFile error */
-    XMLLINT_ERR_SCHEMACOMP,	/* Schema compilation */
-    XMLLINT_ERR_OUT,		/* Error writing output */
-    XMLLINT_ERR_SCHEMAPAT,	/* Error in schema pattern */
-    XMLLINT_ERR_RDREGIS,	/* Error in Reader registration */
-    XMLLINT_ERR_MEM		/* Out of memory error */
+    XMLLINT_ERR_UNCLASS = 1,	/* Unclassified */
+    XMLLINT_ERR_DTD = 2,	/* Error in DTD */
+    XMLLINT_ERR_VALID = 3,	/* Validation error */
+    XMLLINT_ERR_RDFILE = 4,	/* CtxtReadFile error */
+    XMLLINT_ERR_SCHEMACOMP = 5,	/* Schema compilation */
+    XMLLINT_ERR_OUT = 6,	/* Error writing output */
+    XMLLINT_ERR_SCHEMAPAT = 7,	/* Error in schema pattern */
+    XMLLINT_ERR_RDREGIS = 8,	/* Error in Reader registration */
+    XMLLINT_ERR_MEM = 9,	/* Out of memory error */
+    XMLLINT_ERR_XPATH = 10	/* XPath evaluation error */
 } xmllintReturnCode;
 #ifdef LIBXML_DEBUG_ENABLED
 static int shell = 0;
@@ -201,6 +202,9 @@ static const char *pattern = NULL;
 static xmlPatternPtr patternc = NULL;
 static xmlStreamCtxtPtr patstream = NULL;
 #endif
+#ifdef LIBXML_XPATH_ENABLED
+static const char *xpathquery = NULL;
+#endif
 static int options = XML_PARSE_COMPACT;
 static int sax = 0;
 static int oldxml10 = 0;
@@ -2050,6 +2054,100 @@ static void walkDoc(xmlDocPtr doc) {
 }
 #endif /* LIBXML_READER_ENABLED */
 
+#ifdef LIBXML_XPATH_ENABLED
+/************************************************************************
+ *									*
+ *			XPath Query                                     *
+ *									*
+ ************************************************************************/
+
+static void doXPathDump(xmlXPathObjectPtr cur) {
+    switch(cur->type) {
+        case XPATH_NODESET: {
+            int i;
+            xmlNodePtr node;
+#ifdef LIBXML_OUTPUT_ENABLED
+            xmlSaveCtxtPtr ctxt;
+
+            if (cur->nodesetval->nodeNr <= 0) {
+                fprintf(stderr, "XPath set is empty\n");
+                progresult = XMLLINT_ERR_XPATH;
+                break;
+            }
+            ctxt = xmlSaveToFd(1, NULL, 0);
+            if (ctxt == NULL) {
+                fprintf(stderr, "Out of memory for XPath\n");
+                progresult = XMLLINT_ERR_MEM;
+                return;
+            }
+            for (i = 0;i < cur->nodesetval->nodeNr;i++) {
+                node = cur->nodesetval->nodeTab[i];
+                xmlSaveTree(ctxt, node);
+            }
+            xmlSaveClose(ctxt);
+#else
+            printf("xpath returned %d nodes\n", cur->nodesetval->nodeNr);
+#endif
+	    break;
+        }
+        case XPATH_BOOLEAN:
+	    if (cur->boolval) printf("true");
+	    else printf("false");
+	    break;
+        case XPATH_NUMBER:
+	    switch (xmlXPathIsInf(cur->floatval)) {
+	    case 1:
+		printf("Infinity");
+		break;
+	    case -1:
+		printf("-Infinity");
+		break;
+	    default:
+		if (xmlXPathIsNaN(cur->floatval)) {
+		    printf("NaN");
+		} else {
+		    printf("%0g", cur->floatval);
+		}
+	    }
+	    break;
+        case XPATH_STRING:
+	    printf("%s", (const char *) cur->stringval);
+	    break;
+        case XPATH_UNDEFINED:
+	    fprintf(stderr, "XPath Object is uninitialized\n");
+            progresult = XMLLINT_ERR_XPATH;
+	    break;
+	default:
+	    fprintf(stderr, "XPath object of unexpected type\n");
+            progresult = XMLLINT_ERR_XPATH;
+	    break;
+    }
+}
+
+static void doXPathQuery(xmlDocPtr doc, const char *query) {
+    xmlXPathContextPtr ctxt;
+    xmlXPathObjectPtr res;
+
+    ctxt = xmlXPathNewContext(doc);
+    if (ctxt == NULL) {
+        fprintf(stderr, "Out of memory for XPath\n");
+        progresult = XMLLINT_ERR_MEM;
+        return;
+    }
+    ctxt->node = xmlDocGetRootElement(doc);
+    res = xmlXPathEval(BAD_CAST query, ctxt);
+    xmlXPathFreeContext(ctxt);
+
+    if (res == NULL) {
+        fprintf(stderr, "XPath evaluation failure\n");
+        progresult = XMLLINT_ERR_XPATH;
+        return;
+    }
+    doXPathDump(res);
+    xmlXPathFreeObject(res);
+}
+#endif /* LIBXML_XPATH_ENABLED */
+
 /************************************************************************
  *									*
  *			Tree Test processing				*
@@ -2318,6 +2416,12 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
     }
 #endif
 
+#ifdef LIBXML_XPATH_ENABLED
+    if (xpathquery != NULL) {
+        doXPathQuery(doc, xpathquery);
+    }
+#endif
+
 #ifdef LIBXML_DEBUG_ENABLED
 #ifdef LIBXML_XPATH_ENABLED
     /*
@@ -2945,6 +3049,9 @@ static void usage(const char *name) {
 #endif
     printf("\t--sax: do not build a tree but work just at the SAX level\n");
     printf("\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
+#ifdef LIBXML_XPATH_ENABLED
+    printf("\t--xpath expr: evaluate the XPath expression, inply --noout\n");
+#endif
 
     printf("\nLibxml project home page: http://xmlsoft.org/\n";);
     printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n";);
@@ -3285,6 +3392,13 @@ main(int argc, char **argv) {
 	    i++;
 	    pattern = argv[i];
 #endif
+#ifdef LIBXML_XPATH_ENABLED
+        } else if ((!strcmp(argv[i], "-xpath")) ||
+                   (!strcmp(argv[i], "--xpath"))) {
+	    i++;
+	    noout++;
+	    xpathquery = argv[i];
+#endif
 	} else if ((!strcmp(argv[i], "-oldxml10")) ||
 	           (!strcmp(argv[i], "--oldxml10"))) {
 	    oldxml10++;
@@ -3516,6 +3630,13 @@ main(int argc, char **argv) {
 	    continue;
 	}
 #endif
+#ifdef LIBXML_XPATH_ENABLED
+        if ((!strcmp(argv[i], "-xpath")) ||
+	    (!strcmp(argv[i], "--xpath"))) {
+	    i++;
+	    continue;
+	}
+#endif
 	if ((timing) && (repeat))
 	    startTimer();
 	/* Remember file names.  "-" means stdin.  <sven zen org> */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]