Annotation of XML/testXPath.c, revision 1.24
1.1 daniel 1: /*
2: * testXPath.c : a small tester program for XPath.
3: *
4: * See Copyright for the status of this software.
5: *
6: * Daniel.Veillard@w3.org
7: */
8:
9: #ifdef WIN32
1.16 daniel 10: #include "win32config.h"
1.1 daniel 11: #else
1.12 daniel 12: #include "config.h"
1.1 daniel 13: #endif
1.11 daniel 14:
1.24 ! veillard 15: #include <libxml/xmlversion.h>
1.17 daniel 16: #if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_DEBUG_ENABLED)
17:
1.11 daniel 18: #include <stdio.h>
19: #include <string.h>
20:
21: #ifdef HAVE_SYS_TYPES_H
1.1 daniel 22: #include <sys/types.h>
1.11 daniel 23: #endif
1.1 daniel 24: #ifdef HAVE_SYS_STAT_H
25: #include <sys/stat.h>
26: #endif
27: #ifdef HAVE_FCNTL_H
28: #include <fcntl.h>
29: #endif
30: #ifdef HAVE_UNISTD_H
31: #include <unistd.h>
32: #endif
1.11 daniel 33: #ifdef HAVE_STDLIB_H
1.1 daniel 34: #include <stdlib.h>
1.11 daniel 35: #endif
36:
1.1 daniel 37:
1.17 daniel 38: #include <libxml/xpath.h>
39: #include <libxml/tree.h>
40: #include <libxml/parser.h>
41: #include <libxml/debugXML.h>
42: #include <libxml/xmlmemory.h>
1.18 veillard 43: #include <libxml/parserInternals.h>
1.19 veillard 44: #if defined(LIBXML_XPTR_ENABLED)
45: #include <libxml/xpointer.h>
46: static int xptr = 0;
47: #endif
1.1 daniel 48: static int debug = 0;
1.18 veillard 49: static int valid = 0;
1.5 daniel 50: static int expr = 0;
1.2 daniel 51: static xmlDocPtr document = NULL;
52:
53: /*
54: * Default document
55: */
1.13 daniel 56: static xmlChar buffer[] =
1.2 daniel 57: "<?xml version=\"1.0\"?>\n\
58: <EXAMPLE prop1=\"gnome is great\" prop2=\"& linux too\">\n\
59: <head>\n\
60: <title>Welcome to Gnome</title>\n\
61: </head>\n\
62: <chapter>\n\
63: <title>The Linux adventure</title>\n\
64: <p>bla bla bla ...</p>\n\
65: <image href=\"linus.gif\"/>\n\
66: <p>...</p>\n\
67: </chapter>\n\
1.5 daniel 68: <chapter>\n\
69: <title>Chapter 2</title>\n\
70: <p>this is chapter 2 ...</p>\n\
71: </chapter>\n\
72: <chapter>\n\
73: <title>Chapter 3</title>\n\
74: <p>this is chapter 3 ...</p>\n\
75: </chapter>\n\
76: <chapter>\n\
77: <title>Chapter 4</title>\n\
78: <p>this is chapter 4 ...</p>\n\
79: </chapter>\n\
80: <chapter>\n\
81: <title>Chapter 5</title>\n\
82: <p>this is chapter 5 ...</p>\n\
83: </chapter>\n\
1.2 daniel 84: </EXAMPLE>\n\
85: ";
1.1 daniel 86:
1.22 veillard 87: void xmlXPAthDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
88: int i;
89: char shift[100];
90:
91: for (i = 0;((i < depth) && (i < 25));i++)
92: shift[2 * i] = shift[2 * i + 1] = ' ';
93: shift[2 * i] = shift[2 * i + 1] = 0;
1.20 veillard 94: if (cur == NULL) {
1.22 veillard 95: fprintf(output, shift);
1.20 veillard 96: fprintf(output, "Node is NULL !\n");
97: return;
98:
99: }
100:
1.22 veillard 101: if ((cur->type == XML_DOCUMENT_NODE) ||
102: (cur->type == XML_HTML_DOCUMENT_NODE)) {
103: fprintf(output, shift);
1.20 veillard 104: fprintf(output, " /\n");
1.22 veillard 105: } else if (cur->type == XML_ATTRIBUTE_NODE)
106: xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
1.20 veillard 107: else
1.22 veillard 108: xmlDebugDumpOneNode(output, cur, depth);
1.20 veillard 109: }
110:
1.22 veillard 111: void xmlXPAthDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
1.2 daniel 112: int i;
1.22 veillard 113: char shift[100];
114:
115: for (i = 0;((i < depth) && (i < 25));i++)
116: shift[2 * i] = shift[2 * i + 1] = ' ';
117: shift[2 * i] = shift[2 * i + 1] = 0;
1.2 daniel 118:
1.4 daniel 119: if (cur == NULL) {
1.22 veillard 120: fprintf(output, shift);
1.4 daniel 121: fprintf(output, "NodeSet is NULL !\n");
122: return;
123:
124: }
1.2 daniel 125:
126: fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
127: for (i = 0;i < cur->nodeNr;i++) {
1.22 veillard 128: fprintf(output, shift);
1.2 daniel 129: fprintf(output, "%d", i + 1);
1.22 veillard 130: xmlXPAthDebugDumpNode(output, cur->nodeTab[i], depth + 1);
1.20 veillard 131: }
132: }
133:
1.21 veillard 134: #if defined(LIBXML_XPTR_ENABLED)
1.22 veillard 135: void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
136: void xmlXPAthDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
1.20 veillard 137: int i;
1.22 veillard 138: char shift[100];
139:
140: for (i = 0;((i < depth) && (i < 25));i++)
141: shift[2 * i] = shift[2 * i + 1] = ' ';
142: shift[2 * i] = shift[2 * i + 1] = 0;
1.20 veillard 143:
144: if (cur == NULL) {
1.22 veillard 145: fprintf(output, shift);
1.20 veillard 146: fprintf(output, "LocationSet is NULL !\n");
147: return;
148:
149: }
150:
151: for (i = 0;i < cur->locNr;i++) {
1.22 veillard 152: fprintf(output, shift);
153: fprintf(output, "%d :\n", i + 1);
154: xmlXPAthDebugDumpObject(output, cur->locTab[i], depth + 1);
1.2 daniel 155: }
1.1 daniel 156: }
1.21 veillard 157: #endif
1.1 daniel 158:
1.22 veillard 159: void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
160: int i;
161: char shift[100];
162:
163: for (i = 0;((i < depth) && (i < 25));i++)
164: shift[2 * i] = shift[2 * i + 1] = ' ';
165: shift[2 * i] = shift[2 * i + 1] = 0;
166:
167: fprintf(output, shift);
168:
1.1 daniel 169: if (cur == NULL) {
170: fprintf(output, "Object is empty (NULL)\n");
171: return;
172: }
173: switch(cur->type) {
174: case XPATH_UNDEFINED:
175: fprintf(output, "Object is uninitialized\n");
176: break;
177: case XPATH_NODESET:
178: fprintf(output, "Object is a Node Set :\n");
1.22 veillard 179: xmlXPAthDebugDumpNodeSet(output, cur->nodesetval, depth);
1.1 daniel 180: break;
181: case XPATH_BOOLEAN:
182: fprintf(output, "Object is a Boolean : ");
183: if (cur->boolval) fprintf(output, "true\n");
184: else fprintf(output, "false\n");
185: break;
186: case XPATH_NUMBER:
1.5 daniel 187: fprintf(output, "Object is a number : %0g\n", cur->floatval);
1.1 daniel 188: break;
189: case XPATH_STRING:
190: fprintf(output, "Object is a string : ");
191: xmlDebugDumpString(output, cur->stringval);
1.5 daniel 192: fprintf(output, "\n");
1.1 daniel 193: break;
1.20 veillard 194: case XPATH_POINT:
195: fprintf(output, "Object is a point : index %d in node", cur->index);
1.22 veillard 196: xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
1.20 veillard 197: fprintf(output, "\n");
198: break;
199: case XPATH_RANGE:
1.22 veillard 200: fprintf(output, "Object is a range : from ");
1.20 veillard 201: if (cur->index >= 0)
202: fprintf(output, "index %d in ", cur->index);
203: fprintf(output, "node");
1.22 veillard 204: xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
205: fprintf(output, shift);
206: fprintf(output, " to ");
1.20 veillard 207: if (cur->index2 >= 0)
208: fprintf(output, "index %d in ", cur->index2);
209: fprintf(output, "node");
1.22 veillard 210: xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user2, depth + 1);
1.20 veillard 211: fprintf(output, "\n");
1.22 veillard 212: break;
1.20 veillard 213: case XPATH_LOCATIONSET:
1.21 veillard 214: #if defined(LIBXML_XPTR_ENABLED)
1.22 veillard 215: fprintf(output, "Object is a Location Set:\n");
216: xmlXPAthDebugDumpLocationSet(output,
217: (xmlLocationSetPtr) cur->user, depth);
1.21 veillard 218: #endif
1.22 veillard 219: break;
1.20 veillard 220: case XPATH_USERS:
221: fprintf(output, "Object is user defined\n");
1.22 veillard 222: break;
1.1 daniel 223: }
224: }
225:
226: void testXPath(const char *str) {
227: xmlXPathObjectPtr res;
228: xmlXPathContextPtr ctxt;
229:
1.19 veillard 230: #if defined(LIBXML_XPTR_ENABLED)
231: if (xptr) {
232: ctxt = xmlXPtrNewContext(document, NULL, NULL);
233: res = xmlXPtrEval(BAD_CAST str, ctxt);
234: } else {
235: #endif
236: ctxt = xmlXPathNewContext(document);
237: if (expr)
238: res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
239: else
240: res = xmlXPathEval(BAD_CAST str, ctxt);
241: #if defined(LIBXML_XPTR_ENABLED)
242: }
243: #endif
1.22 veillard 244: xmlXPAthDebugDumpObject(stdout, res, 0);
1.1 daniel 245: xmlXPathFreeObject(res);
1.6 veillard 246: xmlXPathFreeContext(ctxt);
1.1 daniel 247: }
248:
1.5 daniel 249: void testXPathFile(const char *filename) {
250: FILE *input;
251: char expr[5000];
1.22 veillard 252: int len;
1.5 daniel 253:
254: input = fopen(filename, "r");
255: if (input == NULL) {
256: fprintf(stderr, "Cannot open %s for reading\n", filename);
257: return;
258: }
1.22 veillard 259: while (fgets(expr, 4500, input) != NULL) {
260: len = strlen(expr);
261: len--;
262: while ((len >= 0) &&
263: ((expr[len] == '\n') || (expr[len] == '\t') ||
264: (expr[len] == '\r') || (expr[len] == ' '))) len--;
265: expr[len + 1] = 0;
1.23 veillard 266: if (len >= 0) {
267: printf("\n========================\nExpression: %s\n", expr) ;
268: testXPath(expr);
269: }
1.5 daniel 270: }
271:
272: fclose(input);
273: }
274:
1.1 daniel 275: int main(int argc, char **argv) {
276: int i;
277: int strings = 0;
1.5 daniel 278: int usefile = 0;
279: char *filename = NULL;
1.1 daniel 280:
281: for (i = 1; i < argc ; i++) {
1.19 veillard 282: #if defined(LIBXML_XPTR_ENABLED)
283: if ((!strcmp(argv[i], "-xptr")) || (!strcmp(argv[i], "--xptr")))
284: xptr++;
285: #endif
1.1 daniel 286: if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
287: debug++;
1.18 veillard 288: if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid")))
289: valid++;
1.5 daniel 290: if ((!strcmp(argv[i], "-expr")) || (!strcmp(argv[i], "--expr")))
291: expr++;
292: if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input")))
293: filename = argv[++i];
294: if ((!strcmp(argv[i], "-f")) || (!strcmp(argv[i], "--file")))
295: usefile++;
296: }
1.18 veillard 297: if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1.5 daniel 298: if (document == NULL) {
299: if (filename == NULL)
300: document = xmlParseDoc(buffer);
301: else
302: document = xmlParseFile(filename);
1.1 daniel 303: }
304: for (i = 1; i < argc ; i++) {
1.5 daniel 305: if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input"))) {
306: i++; continue;
307: }
1.1 daniel 308: if (argv[i][0] != '-') {
1.5 daniel 309: if (usefile)
310: testXPathFile(argv[i]);
311: else
312: testXPath(argv[i]);
1.1 daniel 313: strings ++;
314: }
315: }
316: if (strings == 0) {
1.5 daniel 317: printf("Usage : %s [--debug] [--copy] stringsorfiles ...\n",
1.1 daniel 318: argv[0]);
319: printf("\tParse the XPath strings and output the result of the parsing\n");
320: printf("\t--debug : dump a debug version of the result\n");
1.18 veillard 321: printf("\t--valid : switch on DTD support in the parser\n");
1.5 daniel 322: printf("\t--expr : debug XPath expressions only\n");
323: printf("\t--input filename : or\n");
324: printf("\t-i filename : read the document from filename\n");
325: printf("\t--file : or\n");
326: printf("\t-f : read queries from files, args\n");
1.1 daniel 327: }
1.15 daniel 328: if (document != NULL)
329: xmlFreeDoc(document);
330: xmlCleanupParser();
331: xmlMemoryDump();
1.1 daniel 332:
333: return(0);
334: }
1.17 daniel 335: #else
336: #include <stdio.h>
337: int main(int argc, char **argv) {
338: printf("%s : XPath/Debug support not compiled in\n", argv[0]);
339: return(0);
340: }
341: #endif /* LIBXML_XPATH_ENABLED */
Webmaster