blob: 8bb3e595d175db27be525f21b91bb73b73a5e0e3 [file] [log] [blame]
Daniel Veillard01791d51998-07-24 19:24:09 +00001/*
2 * tester.c : a small tester program for XML input.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00006 * Daniel.Veillard@w3.org
Daniel Veillard01791d51998-07-24 19:24:09 +00007 */
8
Daniel Veillard260a68f1998-08-13 03:39:55 +00009#ifdef WIN32
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000011#else
Daniel Veillard7f7d1111999-09-22 09:46:25 +000012#include "config.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000013#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +000014
15#include <stdio.h>
16#include <string.h>
17
18#ifdef HAVE_SYS_TYPES_H
Daniel Veillard01791d51998-07-24 19:24:09 +000019#include <sys/types.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000020#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000021#ifdef HAVE_SYS_STAT_H
Daniel Veillard01791d51998-07-24 19:24:09 +000022#include <sys/stat.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000023#endif
24#ifdef HAVE_FCNTL_H
Daniel Veillard01791d51998-07-24 19:24:09 +000025#include <fcntl.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000026#endif
27#ifdef HAVE_UNISTD_H
Daniel Veillard01791d51998-07-24 19:24:09 +000028#include <unistd.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000029#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +000030#ifdef HAVE_STDLIB_H
Seth Alvese7f12e61998-10-01 20:51:15 +000031#include <stdlib.h>
Daniel Veillard7f7d1111999-09-22 09:46:25 +000032#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +000033#ifdef HAVE_LIBREADLINE
34#include <readline/readline.h>
35#ifdef HAVE_LIBHISTORY
36#include <readline/history.h>
37#endif
38#endif
Daniel Veillard01791d51998-07-24 19:24:09 +000039
Daniel Veillard6454aec1999-09-02 22:04:43 +000040#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000041#include "parser.h"
Daniel Veillarddbfd6411999-12-28 16:35:14 +000042#include "HTMLparser.h"
43#include "HTMLtree.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000044#include "tree.h"
Daniel Veillarddbfd6411999-12-28 16:35:14 +000045#include "xpath.h"
Daniel Veillardbaf4cd51998-10-27 22:56:57 +000046#include "debugXML.h"
47
48static int debug = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000049static int debugent = 0;
Daniel Veillardbe36afe1998-11-27 06:39:50 +000050static int copy = 0;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000051static int recovery = 0;
Daniel Veillard011b63c1999-06-02 17:44:04 +000052static int noent = 0;
Daniel Veillarde2d034d1999-07-27 19:52:06 +000053static int noout = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +000054static int valid = 0;
Daniel Veillard944b5ff1999-12-15 19:08:24 +000055static int postvalid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +000056static int repeat = 0;
Daniel Veillard7c1206f1999-10-14 09:10:25 +000057static int insert = 0;
Daniel Veillard11a48ec1999-11-23 10:40:46 +000058static int compress = 0;
Daniel Veillarddbfd6411999-12-28 16:35:14 +000059static int html = 0;
60static int shell = 0;
61static int push = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +000062
63extern int xmlDoValidityCheckingDefaultValue;
Daniel Veillard01791d51998-07-24 19:24:09 +000064
Daniel Veillarddbfd6411999-12-28 16:35:14 +000065/**
66 * xmlShellReadline:
67 * @prompt: the prompt value
68 *
69 * Read a string
70 *
71 * Returns a pointer to it or NULL on EOF the caller is expected to
72 * free the returned string.
73 */
74char *
75xmlShellReadline(char *prompt) {
76#ifdef HAVE_LIBREADLINE
77 char *line_read;
78
79 /* Get a line from the user. */
80 line_read = readline (prompt);
81
82 /* If the line has any text in it, save it on the history. */
83 if (line_read && *line_read)
84 add_history (line_read);
85
86 return (line_read);
87#else
88 char line_read[501];
89
90 if (prompt != NULL)
91 fprintf(stdout, "%s", prompt);
92 if (!fgets(line_read, 500, stdin))
93 return(NULL);
94 line_read[500] = 0;
95 return(strdup(line_read));
96#endif
97}
Daniel Veillard01791d51998-07-24 19:24:09 +000098
Daniel Veillard260a68f1998-08-13 03:39:55 +000099void parseAndPrintFile(char *filename) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000100 xmlDocPtr doc = NULL, tmp;
101
102 if (html) {
103 doc = htmlParseFile(filename, NULL);
104 } else {
105 /*
106 * build an XML tree from a string;
107 */
108 if (push) {
109 FILE *f;
110
111 f = fopen(filename, "r");
112 if (f != NULL) {
113 int res, size = 3;
114 char chars[1024];
115 xmlParserCtxtPtr ctxt;
116
117 if (repeat)
118 size = 1024;
119 res = fread(chars, 1, 4, f);
120 if (res > 0) {
121 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
122 chars, res, filename);
123 while ((res = fread(chars, 1, size, f)) > 0) {
124 xmlParseChunk(ctxt, chars, res, 0);
125 }
126 xmlParseChunk(ctxt, chars, 0, 1);
127 doc = ctxt->myDoc;
128 xmlFreeParserCtxt(ctxt);
129 }
130 }
131 } else if (recovery)
132 doc = xmlRecoverFile(filename);
133 else
134 doc = xmlParseFile(filename);
135 }
Daniel Veillard01791d51998-07-24 19:24:09 +0000136
137 /*
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000138 * shell interraction
Daniel Veillard260a68f1998-08-13 03:39:55 +0000139 */
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000140 if (shell)
141 xmlShell(doc, filename, xmlShellReadline, stdout);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000142
143 /*
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000144 * test intermediate copy if needed.
145 */
146 if (copy) {
147 tmp = doc;
148 doc = xmlCopyDoc(doc, 1);
149 xmlFreeDoc(tmp);
150 }
151
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000152 if ((insert) && (!html)) {
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000153 const xmlChar* list[256];
154 int nb, i;
155 xmlNodePtr node;
156
157 if (doc->root != NULL) {
158 node = doc->root;
159 while ((node != NULL) && (node->last == NULL)) node = node->next;
160 if (node != NULL) {
161 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
162 if (nb < 0) {
163 printf("could not get valid list of elements\n");
164 } else if (nb == 0) {
165 printf("No element can be indersted under root\n");
166 } else {
167 printf("%d element types can be indersted under root:\n",
168 nb);
169 for (i = 0;i < nb;i++) {
170 printf("%s\n", list[i]);
171 }
172 }
173 }
174 }
175 }else if (noout == 0) {
176 /*
177 * print it.
178 */
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000179 if (!debug) {
180 if (compress)
181 xmlSaveFile("-", doc);
182 else
183 xmlDocDump(stdout, doc);
184 } else
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000185 xmlDebugDumpDocument(stdout, doc);
186 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187
188 /*
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000189 * A posteriori validation test
Daniel Veillard260a68f1998-08-13 03:39:55 +0000190 */
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000191 if (postvalid) {
192 xmlValidCtxt cvp;
193 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
194 xmlValidateDocument(&cvp, doc);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000195 }
196
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000197 if ((debugent) && (!html))
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000198 xmlDebugDumpEntities(stdout, doc);
Daniel Veillard01791d51998-07-24 19:24:09 +0000199
200 /*
201 * free it.
202 */
203 xmlFreeDoc(doc);
204}
205
206int main(int argc, char **argv) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000207 int i, count;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000208 int files = 0;
Daniel Veillard01791d51998-07-24 19:24:09 +0000209
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000210 for (i = 1; i < argc ; i++) {
211 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
212 debug++;
Daniel Veillard10a2c651999-12-12 13:03:50 +0000213 if ((!strcmp(argv[i], "-debugent")) || (!strcmp(argv[i], "--debugent")))
214 debugent++;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000215 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
216 copy++;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000217 else if ((!strcmp(argv[i], "-recover")) ||
218 (!strcmp(argv[i], "--recover")))
219 recovery++;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000220 else if ((!strcmp(argv[i], "-noent")) ||
221 (!strcmp(argv[i], "--noent")))
222 noent++;
Daniel Veillarde2d034d1999-07-27 19:52:06 +0000223 else if ((!strcmp(argv[i], "-noout")) ||
224 (!strcmp(argv[i], "--noout")))
225 noout++;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000226 else if ((!strcmp(argv[i], "-valid")) ||
227 (!strcmp(argv[i], "--valid")))
228 valid++;
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000229 else if ((!strcmp(argv[i], "-postvalid")) ||
230 (!strcmp(argv[i], "--postvalid")))
231 postvalid++;
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000232 else if ((!strcmp(argv[i], "-insert")) ||
233 (!strcmp(argv[i], "--insert")))
234 insert++;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000235 else if ((!strcmp(argv[i], "-repeat")) ||
236 (!strcmp(argv[i], "--repeat")))
237 repeat++;
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000238 else if ((!strcmp(argv[i], "-push")) ||
239 (!strcmp(argv[i], "--push")))
240 push++;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000241 else if ((!strcmp(argv[i], "-compress")) ||
242 (!strcmp(argv[i], "--compress"))) {
243 compress++;
244 xmlSetCompressMode(9);
245 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000246 else if ((!strcmp(argv[i], "-html")) ||
247 (!strcmp(argv[i], "--html"))) {
248 html++;
249 }
250 else if ((!strcmp(argv[i], "-shell")) ||
251 (!strcmp(argv[i], "--shell"))) {
252 shell++;
253 noout = 1;
254 }
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000255 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000256 if (noent != 0) xmlSubstituteEntitiesDefault(1);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000257 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000258 for (i = 1; i < argc ; i++) {
259 if (argv[i][0] != '-') {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000260 if (repeat) {
261 for (count = 0;count < 100 * repeat;count++)
262 parseAndPrintFile(argv[i]);
263 } else
264 parseAndPrintFile(argv[i]);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000265 files ++;
Daniel Veillard01791d51998-07-24 19:24:09 +0000266 }
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000267 }
268 if (files == 0) {
Daniel Veillard10a2c651999-12-12 13:03:50 +0000269 printf("Usage : %s [--debug] [--debugent] [--copy] [--recover] [--noent] [--noout] [--valid] [--repeat] XMLfiles ...\n",
Daniel Veillard14fff061999-06-22 21:49:07 +0000270 argv[0]);
271 printf("\tParse the XML files and output the result of the parsing\n");
272 printf("\t--debug : dump a debug tree of the in-memory document\n");
Daniel Veillard10a2c651999-12-12 13:03:50 +0000273 printf("\t--debugent : debug the entities defined in the document\n");
Daniel Veillard14fff061999-06-22 21:49:07 +0000274 printf("\t--copy : used to test the internal copy implementation\n");
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000275 printf("\t--recover : output what was parsable on broken XML documents\n");
Daniel Veillard14fff061999-06-22 21:49:07 +0000276 printf("\t--noent : substitute entity references by their value\n");
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000277 printf("\t--noout : don't output the result tree\n");
Daniel Veillard6077d031999-10-09 09:11:45 +0000278 printf("\t--valid : validate the document in addition to std well-formed check\n");
Daniel Veillard944b5ff1999-12-15 19:08:24 +0000279 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
280 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
281 printf("\t--insert : ad-hoc test for valid insertions\n");
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000282 printf("\t--compress : turn on gzip compression of output\n");
Daniel Veillarddbfd6411999-12-28 16:35:14 +0000283 printf("\t--html : use the HTML parser\n");
284 printf("\t--shell : run a navigating shell\n");
285 printf("\t--push : use the push mode of the parser\n");
Daniel Veillard25940b71998-10-29 05:51:30 +0000286 }
Daniel Veillarda819dac1999-11-24 18:04:22 +0000287 xmlCleanupParser();
Daniel Veillard6454aec1999-09-02 22:04:43 +0000288 xmlMemoryDump();
Daniel Veillard01791d51998-07-24 19:24:09 +0000289
290 return(0);
291}