blob: 099084b8390aa38ba45be954055368179f4d40a7 [file] [log] [blame]
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001/*
2 * xmllint.c : a small tester program for XML input.
3 *
4 * See Copyright for the status of this software.
5 *
6 * Daniel.Veillard@w3.org
7 */
8
9#ifdef WIN32
10#include "win32config.h"
11#else
12#include "config.h"
13#endif
14
15#include <stdio.h>
16#include <string.h>
17#include <stdio.h>
18#include <stdarg.h>
19
20#ifdef HAVE_SYS_TYPES_H
21#include <sys/types.h>
22#endif
23#ifdef HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#ifdef HAVE_FCNTL_H
27#include <fcntl.h>
28#endif
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000032#ifdef HAVE_SYS_MMAN_H
33#include <sys/mman.h>
Daniel Veillard87b95392000-08-12 21:12:04 +000034/* seems needed for Solaris */
35#ifndef MAP_FAILED
36#define MAP_FAILED ((void *) -1)
37#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000038#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000039#ifdef HAVE_STDLIB_H
40#include <stdlib.h>
41#endif
42#ifdef HAVE_LIBREADLINE
43#include <readline/readline.h>
44#ifdef HAVE_LIBHISTORY
45#include <readline/history.h>
46#endif
47#endif
48
49#include <libxml/xmlmemory.h>
50#include <libxml/parser.h>
51#include <libxml/parserInternals.h>
52#include <libxml/HTMLparser.h>
53#include <libxml/HTMLtree.h>
54#include <libxml/tree.h>
55#include <libxml/xpath.h>
56#include <libxml/debugXML.h>
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +000057#include <libxml/xmlerror.h>
Daniel Veillard9e8bfae2000-11-06 16:43:11 +000058#ifdef LIBXML_XINCLUDE_ENABLED
59#include <libxml/xinclude.h>
60#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000061
62#ifdef LIBXML_DEBUG_ENABLED
63static int debug = 0;
64static int shell = 0;
65static int debugent = 0;
66#endif
67static int copy = 0;
68static int recovery = 0;
69static int noent = 0;
70static int noout = 0;
71static int nowrap = 0;
72static int valid = 0;
73static int postvalid = 0;
Daniel Veillardcd429612000-10-11 15:57:05 +000074static char * dtdvalid = NULL;
Daniel Veillardce8b83b2000-04-05 18:38:42 +000075static int repeat = 0;
76static int insert = 0;
77static int compress = 0;
78static int html = 0;
79static int htmlout = 0;
80static int push = 0;
Daniel Veillard46e370e2000-07-21 20:32:03 +000081#ifdef HAVE_SYS_MMAN_H
82static int memory = 0;
83#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000084static int noblanks = 0;
Daniel Veillard5e873c42000-04-12 13:27:38 +000085static int testIO = 0;
Daniel Veillardbe803962000-06-28 23:40:59 +000086static char *encoding = NULL;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +000087#ifdef LIBXML_XINCLUDE_ENABLED
88static int xinclude = 0;
89#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000090
Daniel Veillardce6e98d2000-11-25 09:54:49 +000091
92#ifdef VMS
93extern int xmlDoValidityCheckingDefaultVal;
94#define xmlDoValidityCheckingDefaultValue xmlDoValidityCheckingDefaultVal
95#else
Daniel Veillardce8b83b2000-04-05 18:38:42 +000096extern int xmlDoValidityCheckingDefaultValue;
Daniel Veillardce6e98d2000-11-25 09:54:49 +000097#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000098extern int xmlGetWarningsDefaultValue;
99
100/************************************************************************
101 * *
102 * HTML ouput *
103 * *
104 ************************************************************************/
105char buffer[50000];
106
107void
108xmlHTMLEncodeSend(void) {
109 char *result;
110
111 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
112 if (result) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000113 xmlGenericError(xmlGenericErrorContext, "%s", result);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000114 xmlFree(result);
115 }
116 buffer[0] = 0;
117}
118
119/**
120 * xmlHTMLPrintFileInfo:
121 * @input: an xmlParserInputPtr input
122 *
123 * Displays the associated file and line informations for the current input
124 */
125
126void
127xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000128 xmlGenericError(xmlGenericErrorContext, "<p>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000129 if (input != NULL) {
130 if (input->filename) {
131 sprintf(&buffer[strlen(buffer)], "%s:%d: ", input->filename,
132 input->line);
133 } else {
134 sprintf(&buffer[strlen(buffer)], "Entity: line %d: ", input->line);
135 }
136 }
137 xmlHTMLEncodeSend();
138}
139
140/**
141 * xmlHTMLPrintFileContext:
142 * @input: an xmlParserInputPtr input
143 *
144 * Displays current context within the input content for error tracking
145 */
146
147void
148xmlHTMLPrintFileContext(xmlParserInputPtr input) {
149 const xmlChar *cur, *base;
150 int n;
151
152 if (input == NULL) return;
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000153 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000154 cur = input->cur;
155 base = input->base;
156 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
157 cur--;
158 }
159 n = 0;
160 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
161 cur--;
162 if ((*cur == '\n') || (*cur == '\r')) cur++;
163 base = cur;
164 n = 0;
165 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
166 sprintf(&buffer[strlen(buffer)], "%c", (unsigned char) *cur++);
167 n++;
168 }
169 sprintf(&buffer[strlen(buffer)], "\n");
170 cur = input->cur;
171 while ((*cur == '\n') || (*cur == '\r'))
172 cur--;
173 n = 0;
174 while ((cur != base) && (n++ < 80)) {
175 sprintf(&buffer[strlen(buffer)], " ");
176 base++;
177 }
178 sprintf(&buffer[strlen(buffer)],"^\n");
179 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000180 xmlGenericError(xmlGenericErrorContext, "</pre>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000181}
182
183/**
184 * xmlHTMLError:
185 * @ctx: an XML parser context
186 * @msg: the message to display/transmit
187 * @...: extra parameters for the message display
188 *
189 * Display and format an error messages, gives file, line, position and
190 * extra parameters.
191 */
192void
193xmlHTMLError(void *ctx, const char *msg, ...)
194{
195 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
196 xmlParserInputPtr input;
197 xmlParserInputPtr cur = NULL;
198 va_list args;
199
200 buffer[0] = 0;
201 input = ctxt->input;
202 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
203 cur = input;
204 input = ctxt->inputTab[ctxt->inputNr - 2];
205 }
206
207 xmlHTMLPrintFileInfo(input);
208
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000209 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000210 va_start(args, msg);
211 vsprintf(&buffer[strlen(buffer)], msg, args);
212 va_end(args);
213 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000214 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000215
216 xmlHTMLPrintFileContext(input);
217 xmlHTMLEncodeSend();
218}
219
220/**
221 * xmlHTMLWarning:
222 * @ctx: an XML parser context
223 * @msg: the message to display/transmit
224 * @...: extra parameters for the message display
225 *
226 * Display and format a warning messages, gives file, line, position and
227 * extra parameters.
228 */
229void
230xmlHTMLWarning(void *ctx, const char *msg, ...)
231{
232 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
233 xmlParserInputPtr input;
234 xmlParserInputPtr cur = NULL;
235 va_list args;
236
237 buffer[0] = 0;
238 input = ctxt->input;
239 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
240 cur = input;
241 input = ctxt->inputTab[ctxt->inputNr - 2];
242 }
243
244
245 xmlHTMLPrintFileInfo(input);
246
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000247 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000248 va_start(args, msg);
249 vsprintf(&buffer[strlen(buffer)], msg, args);
250 va_end(args);
251 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000252 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000253
254 xmlHTMLPrintFileContext(input);
255 xmlHTMLEncodeSend();
256}
257
258/**
259 * xmlHTMLValidityError:
260 * @ctx: an XML parser context
261 * @msg: the message to display/transmit
262 * @...: extra parameters for the message display
263 *
264 * Display and format an validity error messages, gives file,
265 * line, position and extra parameters.
266 */
267void
268xmlHTMLValidityError(void *ctx, const char *msg, ...)
269{
270 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
271 xmlParserInputPtr input;
272 va_list args;
273
274 buffer[0] = 0;
275 input = ctxt->input;
276 if ((input->filename == NULL) && (ctxt->inputNr > 1))
277 input = ctxt->inputTab[ctxt->inputNr - 2];
278
279 xmlHTMLPrintFileInfo(input);
280
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000281 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000282 va_start(args, msg);
283 vsprintf(&buffer[strlen(buffer)], msg, args);
284 va_end(args);
285 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000286 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000287
288 xmlHTMLPrintFileContext(input);
289 xmlHTMLEncodeSend();
290}
291
292/**
293 * xmlHTMLValidityWarning:
294 * @ctx: an XML parser context
295 * @msg: the message to display/transmit
296 * @...: extra parameters for the message display
297 *
298 * Display and format a validity warning messages, gives file, line,
299 * position and extra parameters.
300 */
301void
302xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
303{
304 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
305 xmlParserInputPtr input;
306 va_list args;
307
308 buffer[0] = 0;
309 input = ctxt->input;
310 if ((input->filename == NULL) && (ctxt->inputNr > 1))
311 input = ctxt->inputTab[ctxt->inputNr - 2];
312
313 xmlHTMLPrintFileInfo(input);
314
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000315 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000316 va_start(args, msg);
317 vsprintf(&buffer[strlen(buffer)], msg, args);
318 va_end(args);
319 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000320 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000321
322 xmlHTMLPrintFileContext(input);
323 xmlHTMLEncodeSend();
324}
325
326/************************************************************************
327 * *
328 * Shell Interface *
329 * *
330 ************************************************************************/
331/**
332 * xmlShellReadline:
333 * @prompt: the prompt value
334 *
335 * Read a string
336 *
337 * Returns a pointer to it or NULL on EOF the caller is expected to
338 * free the returned string.
339 */
340char *
341xmlShellReadline(char *prompt) {
342#ifdef HAVE_LIBREADLINE
343 char *line_read;
344
345 /* Get a line from the user. */
346 line_read = readline (prompt);
347
348 /* If the line has any text in it, save it on the history. */
349 if (line_read && *line_read)
350 add_history (line_read);
351
352 return (line_read);
353#else
354 char line_read[501];
355
356 if (prompt != NULL)
357 fprintf(stdout, "%s", prompt);
358 if (!fgets(line_read, 500, stdin))
359 return(NULL);
360 line_read[500] = 0;
361 return(strdup(line_read));
362#endif
363}
364
365/************************************************************************
366 * *
Daniel Veillard5e873c42000-04-12 13:27:38 +0000367 * I/O Interfaces *
368 * *
369 ************************************************************************/
370
371int myRead(FILE *f, char * buffer, int len) {
372 return(fread(buffer, 1, len, f));
373}
374void myClose(FILE *f) {
375 fclose(f);
376}
377
378/************************************************************************
379 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000380 * Test processing *
381 * *
382 ************************************************************************/
383void parseAndPrintFile(char *filename) {
384 xmlDocPtr doc = NULL, tmp;
385
386#ifdef LIBXML_HTML_ENABLED
387 if (html) {
388 doc = htmlParseFile(filename, NULL);
389 } else {
390#endif /* LIBXML_HTML_ENABLED */
391 /*
392 * build an XML tree from a string;
393 */
394 if (push) {
395 FILE *f;
396
397 f = fopen(filename, "r");
398 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000399 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000400 int res, size = 3;
401 char chars[1024];
402 xmlParserCtxtPtr ctxt;
403
404 if (repeat)
405 size = 1024;
406 res = fread(chars, 1, 4, f);
407 if (res > 0) {
408 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
409 chars, res, filename);
410 while ((res = fread(chars, 1, size, f)) > 0) {
411 xmlParseChunk(ctxt, chars, res, 0);
412 }
413 xmlParseChunk(ctxt, chars, 0, 1);
414 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000415 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000416 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000417 if (!ret) {
418 xmlFreeDoc(doc);
419 doc = NULL;
420 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000421 }
422 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000423 } else if (testIO) {
424 int ret;
425 FILE *f;
426
427 f = fopen(filename, "r");
428 if (f != NULL) {
429 xmlParserCtxtPtr ctxt;
430
431 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
432 (xmlInputReadCallback) myRead,
433 (xmlInputCloseCallback) myClose,
434 f, XML_CHAR_ENCODING_NONE);
435 xmlParseDocument(ctxt);
436
437 ret = ctxt->wellFormed;
438 doc = ctxt->myDoc;
439 xmlFreeParserCtxt(ctxt);
440 if (!ret) {
441 xmlFreeDoc(doc);
442 doc = NULL;
443 }
444 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000445 } else if (recovery) {
446 doc = xmlRecoverFile(filename);
447 } else if (htmlout) {
448 int ret;
449 xmlParserCtxtPtr ctxt;
450 xmlSAXHandler silent, *old;
451
452 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000453
454 if (ctxt == NULL) {
455 /* If xmlCreateFileParseCtxt() return NULL something
456 strange happened so we don't want to do anything. Do
457 we want to print an error message here?
458 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000459 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000460 } else {
461 memcpy(&silent, ctxt->sax, sizeof(silent));
462 old = ctxt->sax;
463 silent.error = xmlHTMLError;
464 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000465 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000466 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000467 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000468 silent.fatalError = xmlHTMLError;
469 ctxt->sax = &silent;
470 ctxt->vctxt.error = xmlHTMLValidityError;
471 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000472 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000473 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000474 ctxt->vctxt.warning = NULL;
475
Daniel Veillard88a172f2000-08-04 18:23:10 +0000476 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000477
Daniel Veillard88a172f2000-08-04 18:23:10 +0000478 ret = ctxt->wellFormed;
479 doc = ctxt->myDoc;
480 ctxt->sax = old;
481 xmlFreeParserCtxt(ctxt);
482 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000483 xmlFreeDoc(doc);
484 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000485 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000486 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000487#ifdef HAVE_SYS_MMAN_H
488 } else if (memory) {
489 int fd;
490 struct stat info;
491 const char *base;
492 if (stat(filename, &info) < 0)
493 return;
494 if ((fd = open(filename, O_RDONLY)) < 0)
495 return;
496 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000497 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000498 return;
499
500 doc = xmlParseMemory((char *) base, info.st_size);
501 munmap((char *) base, info.st_size);
502#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000503 } else
504 doc = xmlParseFile(filename);
505#ifdef LIBXML_HTML_ENABLED
506 }
507#endif
508
Daniel Veillard88a172f2000-08-04 18:23:10 +0000509 /*
510 * If we don't have a document we might as well give up. Do we
511 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000512 if (doc == NULL) {
Daniel Veillard88a172f2000-08-04 18:23:10 +0000513 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000514 }
515
516#ifdef LIBXML_XINCLUDE_ENABLED
517 if (xinclude)
518 xmlXIncludeProcess(doc);
519#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000520
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000521#ifdef LIBXML_DEBUG_ENABLED
522 /*
523 * shell interraction
524 */
525 if (shell)
526 xmlShell(doc, filename, xmlShellReadline, stdout);
527#endif
528
529 /*
530 * test intermediate copy if needed.
531 */
532 if (copy) {
533 tmp = doc;
534 doc = xmlCopyDoc(doc, 1);
535 xmlFreeDoc(tmp);
536 }
537
538 if ((insert) && (!html)) {
539 const xmlChar* list[256];
540 int nb, i;
541 xmlNodePtr node;
542
543 if (doc->children != NULL) {
544 node = doc->children;
545 while ((node != NULL) && (node->last == NULL)) node = node->next;
546 if (node != NULL) {
547 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
548 if (nb < 0) {
549 printf("could not get valid list of elements\n");
550 } else if (nb == 0) {
551 printf("No element can be indersted under root\n");
552 } else {
553 printf("%d element types can be indersted under root:\n",
554 nb);
555 for (i = 0;i < nb;i++) {
556 printf("%s\n", list[i]);
557 }
558 }
559 }
560 }
561 }else if (noout == 0) {
562 /*
563 * print it.
564 */
565#ifdef LIBXML_DEBUG_ENABLED
566 if (!debug) {
567#endif
568 if (compress)
569 xmlSaveFile("-", doc);
Daniel Veillardbe803962000-06-28 23:40:59 +0000570 else if (encoding != NULL)
571 xmlSaveFileEnc("-", doc, encoding);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000572 else
573 xmlDocDump(stdout, doc);
574#ifdef LIBXML_DEBUG_ENABLED
575 } else
576 xmlDebugDumpDocument(stdout, doc);
577#endif
578 }
579
580 /*
581 * A posteriori validation test
582 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000583 if (dtdvalid != NULL) {
584 xmlDtdPtr dtd;
585
586 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
587 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000588 xmlGenericError(xmlGenericErrorContext,
589 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardcd429612000-10-11 15:57:05 +0000590 } else {
591 xmlValidCtxt cvp;
592 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
593 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000594 xmlGenericError(xmlGenericErrorContext,
595 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000596 filename, dtdvalid);
597 }
598 xmlFreeDtd(dtd);
599 }
600 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000601 xmlValidCtxt cvp;
602 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000603 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000604 xmlGenericError(xmlGenericErrorContext,
605 "Document %s does not validate\n", filename);
Daniel Veillardcd429612000-10-11 15:57:05 +0000606 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000607 }
608
609#ifdef LIBXML_DEBUG_ENABLED
610 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000611 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000612#endif
613
614 /*
615 * free it.
616 */
617 xmlFreeDoc(doc);
618}
619
620int main(int argc, char **argv) {
621 int i, count;
622 int files = 0;
623
Daniel Veillardbe803962000-06-28 23:40:59 +0000624 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000625 for (i = 1; i < argc ; i++) {
626#ifdef LIBXML_DEBUG_ENABLED
627 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
628 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000629 else if ((!strcmp(argv[i], "-shell")) ||
630 (!strcmp(argv[i], "--shell"))) {
631 shell++;
632 noout = 1;
633 } else
634#endif
635 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
636 copy++;
637 else if ((!strcmp(argv[i], "-recover")) ||
638 (!strcmp(argv[i], "--recover")))
639 recovery++;
640 else if ((!strcmp(argv[i], "-noent")) ||
641 (!strcmp(argv[i], "--noent")))
642 noent++;
643 else if ((!strcmp(argv[i], "-noout")) ||
644 (!strcmp(argv[i], "--noout")))
645 noout++;
646 else if ((!strcmp(argv[i], "-htmlout")) ||
647 (!strcmp(argv[i], "--htmlout")))
648 htmlout++;
649#ifdef LIBXML_HTML_ENABLED
650 else if ((!strcmp(argv[i], "-html")) ||
651 (!strcmp(argv[i], "--html"))) {
652 html++;
653 }
654#endif /* LIBXML_HTML_ENABLED */
655 else if ((!strcmp(argv[i], "-nowrap")) ||
656 (!strcmp(argv[i], "--nowrap")))
657 nowrap++;
658 else if ((!strcmp(argv[i], "-valid")) ||
659 (!strcmp(argv[i], "--valid")))
660 valid++;
661 else if ((!strcmp(argv[i], "-postvalid")) ||
662 (!strcmp(argv[i], "--postvalid")))
663 postvalid++;
Daniel Veillardcd429612000-10-11 15:57:05 +0000664 else if ((!strcmp(argv[i], "-dtdvalid")) ||
665 (!strcmp(argv[i], "--dtdvalid"))) {
666 i++;
667 dtdvalid = argv[i];
668 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000669 else if ((!strcmp(argv[i], "-insert")) ||
670 (!strcmp(argv[i], "--insert")))
671 insert++;
672 else if ((!strcmp(argv[i], "-repeat")) ||
673 (!strcmp(argv[i], "--repeat")))
674 repeat++;
675 else if ((!strcmp(argv[i], "-push")) ||
676 (!strcmp(argv[i], "--push")))
677 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +0000678#ifdef HAVE_SYS_MMAN_H
679 else if ((!strcmp(argv[i], "-memory")) ||
680 (!strcmp(argv[i], "--memory")))
681 memory++;
682#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +0000683 else if ((!strcmp(argv[i], "-testIO")) ||
684 (!strcmp(argv[i], "--testIO")))
685 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000686#ifdef LIBXML_XINCLUDE_ENABLED
687 else if ((!strcmp(argv[i], "-xinclude")) ||
688 (!strcmp(argv[i], "--xinclude")))
689 xinclude++;
690#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000691 else if ((!strcmp(argv[i], "-compress")) ||
692 (!strcmp(argv[i], "--compress"))) {
693 compress++;
694 xmlSetCompressMode(9);
695 }
696 else if ((!strcmp(argv[i], "-nowarning")) ||
697 (!strcmp(argv[i], "--nowarning"))) {
698 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000699 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000700 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000701 else if ((!strcmp(argv[i], "-pedantic")) ||
702 (!strcmp(argv[i], "--pedantic"))) {
703 xmlGetWarningsDefaultValue = 1;
704 xmlPedanticParserDefault(1);
705 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +0000706#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000707 else if ((!strcmp(argv[i], "-debugent")) ||
708 (!strcmp(argv[i], "--debugent"))) {
709 debugent++;
710 xmlParserDebugEntities = 1;
711 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +0000712#endif
Daniel Veillardbe803962000-06-28 23:40:59 +0000713 else if ((!strcmp(argv[i], "-encode")) ||
714 (!strcmp(argv[i], "--encode"))) {
715 i++;
716 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000717 /*
718 * OK it's for testing purposes
719 */
720 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +0000721 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000722 else if ((!strcmp(argv[i], "-noblanks")) ||
723 (!strcmp(argv[i], "--noblanks"))) {
724 noblanks++;
725 xmlKeepBlanksDefault(0);
726 }
727 }
728 if (noent != 0) xmlSubstituteEntitiesDefault(1);
729 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
730 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000731 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000732 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000733 xmlGenericError(xmlGenericErrorContext,
734 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
735 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000736 "<html><head><title>%s output</title></head>\n",
737 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000738 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000739 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
740 argv[0]);
741 }
742 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000743 if ((!strcmp(argv[i], "-encode")) ||
744 (!strcmp(argv[i], "--encode"))) {
745 i++;
746 continue;
747 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000748 if ((!strcmp(argv[i], "-dtdvalid")) ||
749 (!strcmp(argv[i], "--dtdvalid"))) {
750 i++;
751 continue;
752 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000753 if (argv[i][0] != '-') {
754 if (repeat) {
755 for (count = 0;count < 100 * repeat;count++)
756 parseAndPrintFile(argv[i]);
757 } else
758 parseAndPrintFile(argv[i]);
759 files ++;
760 }
761 }
762 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000763 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000764 }
765 if (files == 0) {
766 printf("Usage : %s [--debug] [--debugent] [--copy] [--recover] [--noent] [--noout] [--valid] [--repeat] XMLfiles ...\n",
767 argv[0]);
768 printf("\tParse the XML files and output the result of the parsing\n");
769#ifdef LIBXML_DEBUG_ENABLED
770 printf("\t--debug : dump a debug tree of the in-memory document\n");
771 printf("\t--shell : run a navigating shell\n");
772 printf("\t--debugent : debug the entities defined in the document\n");
773#endif
774 printf("\t--copy : used to test the internal copy implementation\n");
775 printf("\t--recover : output what was parsable on broken XML documents\n");
776 printf("\t--noent : substitute entity references by their value\n");
777 printf("\t--noout : don't output the result tree\n");
778 printf("\t--htmlout : output results as HTML\n");
779 printf("\t--nowarp : do not put HTML doc wrapper\n");
780 printf("\t--valid : validate the document in addition to std well-formed check\n");
781 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
Daniel Veillardcd429612000-10-11 15:57:05 +0000782 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000783 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
784 printf("\t--insert : ad-hoc test for valid insertions\n");
785 printf("\t--compress : turn on gzip compression of output\n");
786#ifdef LIBXML_HTML_ENABLED
787 printf("\t--html : use the HTML parser\n");
788#endif
789 printf("\t--push : use the push mode of the parser\n");
Daniel Veillard46e370e2000-07-21 20:32:03 +0000790#ifdef HAVE_SYS_MMAN_H
791 printf("\t--memory : parse from memory\n");
792#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000793 printf("\t--nowarning : do not emit warnings from parser/validator\n");
794 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard5e873c42000-04-12 13:27:38 +0000795 printf("\t--testIO : test user I/O support\n");
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000796 printf("\t--encode encoding : output in the given encoding\n");
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000797#ifdef LIBXML_XINCLUDE_ENABLED
798 printf("\t--xinclude : do XInclude processing\n");
799#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000800 }
801 xmlCleanupParser();
802 xmlMemoryDump();
803
804 return(0);
805}
Daniel Veillard88a172f2000-08-04 18:23:10 +0000806