summaryrefslogtreecommitdiff
path: root/xmllint.c
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@redhat.com>2009-10-07 10:25:06 +0200
committerDaniel Veillard <veillard@redhat.com>2009-10-07 10:25:06 +0200
commit1934b0c0fa8dff467955ae51118b69716a75f62b (patch)
treec8131edfa666f6ea28b3221890f274afbe7ae150 /xmllint.c
parent1e52172358f2356a51931ea710da0a09d0203bfe (diff)
downloadlibxml2-1934b0c0fa8dff467955ae51118b69716a75f62b.tar.gz
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.
Diffstat (limited to 'xmllint.c')
-rw-r--r--xmllint.c139
1 files changed, 130 insertions, 9 deletions
diff --git a/xmllint.c b/xmllint.c
index 6e4138e9..cb845c78 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> */