blob: dc0a34710e9bc01f45ce80ee772db7bdf8fb5fe3 [file] [log] [blame]
Daniel Veillard1566d3a1999-07-15 14:24:29 +00001/*
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
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard1566d3a1999-07-15 14:24:29 +000011#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +000012#include "config.h"
Daniel Veillard1566d3a1999-07-15 14:24:29 +000013#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014
Daniel Veillard361d8452000-04-03 19:48:13 +000015#include "xmlversion.h"
16#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_DEBUG_ENABLED)
17
Daniel Veillard7f7d1111999-09-22 09:46:25 +000018#include <stdio.h>
19#include <string.h>
20
21#ifdef HAVE_SYS_TYPES_H
Daniel Veillard1566d3a1999-07-15 14:24:29 +000022#include <sys/types.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000023#endif
Daniel Veillard1566d3a1999-07-15 14:24:29 +000024#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
Daniel Veillard7f7d1111999-09-22 09:46:25 +000033#ifdef HAVE_STDLIB_H
Daniel Veillard1566d3a1999-07-15 14:24:29 +000034#include <stdlib.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000035#endif
36
Daniel Veillard1566d3a1999-07-15 14:24:29 +000037
Daniel Veillard361d8452000-04-03 19:48:13 +000038#include <libxml/xpath.h>
39#include <libxml/tree.h>
40#include <libxml/parser.h>
41#include <libxml/debugXML.h>
42#include <libxml/xmlmemory.h>
Daniel Veillard740abf52000-10-02 23:04:54 +000043#include <libxml/parserInternals.h>
Daniel Veillardac260302000-10-04 13:33:43 +000044#if defined(LIBXML_XPTR_ENABLED)
45#include <libxml/xpointer.h>
46static int xptr = 0;
47#endif
Daniel Veillard1566d3a1999-07-15 14:24:29 +000048static int debug = 0;
Daniel Veillard740abf52000-10-02 23:04:54 +000049static int valid = 0;
Daniel Veillard1566d3a1999-07-15 14:24:29 +000050static int expr = 0;
51static xmlDocPtr document = NULL;
52
53/*
54 * Default document
55 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000056static xmlChar buffer[] =
Daniel Veillard1566d3a1999-07-15 14:24:29 +000057"<?xml version=\"1.0\"?>\n\
58<EXAMPLE prop1=\"gnome is great\" prop2=\"&amp; 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\
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\
84</EXAMPLE>\n\
85";
86
Daniel Veillard7e99c632000-10-06 12:59:53 +000087void 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;
Daniel Veillard55b91f22000-10-05 16:30:11 +000094 if (cur == NULL) {
Daniel Veillard7e99c632000-10-06 12:59:53 +000095 fprintf(output, shift);
Daniel Veillard55b91f22000-10-05 16:30:11 +000096 fprintf(output, "Node is NULL !\n");
97 return;
98
99 }
100
Daniel Veillard7e99c632000-10-06 12:59:53 +0000101 if ((cur->type == XML_DOCUMENT_NODE) ||
102 (cur->type == XML_HTML_DOCUMENT_NODE)) {
103 fprintf(output, shift);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000104 fprintf(output, " /\n");
Daniel Veillard7e99c632000-10-06 12:59:53 +0000105 } else if (cur->type == XML_ATTRIBUTE_NODE)
106 xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000107 else
Daniel Veillard7e99c632000-10-06 12:59:53 +0000108 xmlDebugDumpOneNode(output, cur, depth);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000109}
110
Daniel Veillard7e99c632000-10-06 12:59:53 +0000111void xmlXPAthDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000112 int i;
Daniel Veillard7e99c632000-10-06 12:59:53 +0000113 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;
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000118
119 if (cur == NULL) {
Daniel Veillard7e99c632000-10-06 12:59:53 +0000120 fprintf(output, shift);
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000121 fprintf(output, "NodeSet is NULL !\n");
122 return;
123
124 }
125
126 fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
127 for (i = 0;i < cur->nodeNr;i++) {
Daniel Veillard7e99c632000-10-06 12:59:53 +0000128 fprintf(output, shift);
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000129 fprintf(output, "%d", i + 1);
Daniel Veillard7e99c632000-10-06 12:59:53 +0000130 xmlXPAthDebugDumpNode(output, cur->nodeTab[i], depth + 1);
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000131 }
132}
133
Daniel Veillard55b91f22000-10-05 16:30:11 +0000134#if defined(LIBXML_XPTR_ENABLED)
Daniel Veillard7e99c632000-10-06 12:59:53 +0000135void xmlXPAthDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth);
136void xmlXPAthDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
Daniel Veillard55b91f22000-10-05 16:30:11 +0000137 int i;
Daniel Veillard7e99c632000-10-06 12:59:53 +0000138 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;
Daniel Veillard55b91f22000-10-05 16:30:11 +0000143
144 if (cur == NULL) {
Daniel Veillard7e99c632000-10-06 12:59:53 +0000145 fprintf(output, shift);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000146 fprintf(output, "LocationSet is NULL !\n");
147 return;
148
149 }
150
Daniel Veillard55b91f22000-10-05 16:30:11 +0000151 for (i = 0;i < cur->locNr;i++) {
Daniel Veillard7e99c632000-10-06 12:59:53 +0000152 fprintf(output, shift);
153 fprintf(output, "%d :\n", i + 1);
154 xmlXPAthDebugDumpObject(output, cur->locTab[i], depth + 1);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000155 }
156}
157#endif
158
Daniel Veillard7e99c632000-10-06 12:59:53 +0000159void 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
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000169 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");
Daniel Veillard7e99c632000-10-06 12:59:53 +0000179 xmlXPAthDebugDumpNodeSet(output, cur->nodesetval, depth);
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000180 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:
187 fprintf(output, "Object is a number : %0g\n", cur->floatval);
188 break;
189 case XPATH_STRING:
190 fprintf(output, "Object is a string : ");
191 xmlDebugDumpString(output, cur->stringval);
192 fprintf(output, "\n");
193 break;
Daniel Veillard55b91f22000-10-05 16:30:11 +0000194 case XPATH_POINT:
195 fprintf(output, "Object is a point : index %d in node", cur->index);
Daniel Veillard7e99c632000-10-06 12:59:53 +0000196 xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000197 fprintf(output, "\n");
198 break;
199 case XPATH_RANGE:
Daniel Veillard7e99c632000-10-06 12:59:53 +0000200 fprintf(output, "Object is a range : from ");
Daniel Veillard55b91f22000-10-05 16:30:11 +0000201 if (cur->index >= 0)
202 fprintf(output, "index %d in ", cur->index);
203 fprintf(output, "node");
Daniel Veillard7e99c632000-10-06 12:59:53 +0000204 xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
205 fprintf(output, shift);
206 fprintf(output, " to ");
Daniel Veillard55b91f22000-10-05 16:30:11 +0000207 if (cur->index2 >= 0)
208 fprintf(output, "index %d in ", cur->index2);
209 fprintf(output, "node");
Daniel Veillard7e99c632000-10-06 12:59:53 +0000210 xmlXPAthDebugDumpNode(output, (xmlNodePtr) cur->user2, depth + 1);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000211 fprintf(output, "\n");
Daniel Veillard7e99c632000-10-06 12:59:53 +0000212 break;
Daniel Veillard55b91f22000-10-05 16:30:11 +0000213 case XPATH_LOCATIONSET:
214#if defined(LIBXML_XPTR_ENABLED)
Daniel Veillard7e99c632000-10-06 12:59:53 +0000215 fprintf(output, "Object is a Location Set:\n");
216 xmlXPAthDebugDumpLocationSet(output,
217 (xmlLocationSetPtr) cur->user, depth);
Daniel Veillard55b91f22000-10-05 16:30:11 +0000218#endif
Daniel Veillard7e99c632000-10-06 12:59:53 +0000219 break;
Daniel Veillard55b91f22000-10-05 16:30:11 +0000220 case XPATH_USERS:
221 fprintf(output, "Object is user defined\n");
Daniel Veillard7e99c632000-10-06 12:59:53 +0000222 break;
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000223 }
224}
225
226void testXPath(const char *str) {
227 xmlXPathObjectPtr res;
228 xmlXPathContextPtr ctxt;
229
Daniel Veillardac260302000-10-04 13:33:43 +0000230#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
Daniel Veillard7e99c632000-10-06 12:59:53 +0000244 xmlXPAthDebugDumpObject(stdout, res, 0);
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000245 xmlXPathFreeObject(res);
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000246 xmlXPathFreeContext(ctxt);
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000247}
248
249void testXPathFile(const char *filename) {
250 FILE *input;
251 char expr[5000];
Daniel Veillard7e99c632000-10-06 12:59:53 +0000252 int len;
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000253
254 input = fopen(filename, "r");
255 if (input == NULL) {
256 fprintf(stderr, "Cannot open %s for reading\n", filename);
257 return;
258 }
Daniel Veillard7e99c632000-10-06 12:59:53 +0000259 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;
266 if (len >= 0) {
267 printf("\n========================\nExpression: %s\n", expr) ;
268 testXPath(expr);
269 }
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000270 }
271
272 fclose(input);
273}
274
275int main(int argc, char **argv) {
276 int i;
277 int strings = 0;
278 int usefile = 0;
279 char *filename = NULL;
280
281 for (i = 1; i < argc ; i++) {
Daniel Veillardac260302000-10-04 13:33:43 +0000282#if defined(LIBXML_XPTR_ENABLED)
283 if ((!strcmp(argv[i], "-xptr")) || (!strcmp(argv[i], "--xptr")))
284 xptr++;
285#endif
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000286 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
287 debug++;
Daniel Veillard740abf52000-10-02 23:04:54 +0000288 if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid")))
289 valid++;
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000290 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 }
Daniel Veillard740abf52000-10-02 23:04:54 +0000297 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000298 if (document == NULL) {
299 if (filename == NULL)
300 document = xmlParseDoc(buffer);
301 else
302 document = xmlParseFile(filename);
303 }
304 for (i = 1; i < argc ; i++) {
305 if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input"))) {
306 i++; continue;
307 }
308 if (argv[i][0] != '-') {
309 if (usefile)
310 testXPathFile(argv[i]);
311 else
312 testXPath(argv[i]);
313 strings ++;
314 }
315 }
316 if (strings == 0) {
317 printf("Usage : %s [--debug] [--copy] stringsorfiles ...\n",
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");
Daniel Veillard740abf52000-10-02 23:04:54 +0000321 printf("\t--valid : switch on DTD support in the parser\n");
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000322 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");
327 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000328 if (document != NULL)
329 xmlFreeDoc(document);
330 xmlCleanupParser();
331 xmlMemoryDump();
Daniel Veillard1566d3a1999-07-15 14:24:29 +0000332
333 return(0);
334}
Daniel Veillard361d8452000-04-03 19:48:13 +0000335#else
336#include <stdio.h>
337int 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 */