blob: df4b4c1b51fb1125a4f2974614b78ce6c37fd3e5 [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 Veillardf7cd4812001-02-23 18:44:52 +000090static int progresult = 0;
Daniel Veillardce8b83b2000-04-05 18:38:42 +000091
Daniel Veillardce6e98d2000-11-25 09:54:49 +000092
93#ifdef VMS
94extern int xmlDoValidityCheckingDefaultVal;
95#define xmlDoValidityCheckingDefaultValue xmlDoValidityCheckingDefaultVal
96#else
Daniel Veillardce8b83b2000-04-05 18:38:42 +000097extern int xmlDoValidityCheckingDefaultValue;
Daniel Veillardce6e98d2000-11-25 09:54:49 +000098#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000099extern int xmlGetWarningsDefaultValue;
100
101/************************************************************************
102 * *
103 * HTML ouput *
104 * *
105 ************************************************************************/
106char buffer[50000];
107
108void
109xmlHTMLEncodeSend(void) {
110 char *result;
111
112 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
113 if (result) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000114 xmlGenericError(xmlGenericErrorContext, "%s", result);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000115 xmlFree(result);
116 }
117 buffer[0] = 0;
118}
119
120/**
121 * xmlHTMLPrintFileInfo:
122 * @input: an xmlParserInputPtr input
123 *
124 * Displays the associated file and line informations for the current input
125 */
126
127void
128xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000129 xmlGenericError(xmlGenericErrorContext, "<p>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000130 if (input != NULL) {
131 if (input->filename) {
132 sprintf(&buffer[strlen(buffer)], "%s:%d: ", input->filename,
133 input->line);
134 } else {
135 sprintf(&buffer[strlen(buffer)], "Entity: line %d: ", input->line);
136 }
137 }
138 xmlHTMLEncodeSend();
139}
140
141/**
142 * xmlHTMLPrintFileContext:
143 * @input: an xmlParserInputPtr input
144 *
145 * Displays current context within the input content for error tracking
146 */
147
148void
149xmlHTMLPrintFileContext(xmlParserInputPtr input) {
150 const xmlChar *cur, *base;
151 int n;
152
153 if (input == NULL) return;
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000154 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000155 cur = input->cur;
156 base = input->base;
157 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
158 cur--;
159 }
160 n = 0;
161 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
162 cur--;
163 if ((*cur == '\n') || (*cur == '\r')) cur++;
164 base = cur;
165 n = 0;
166 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
167 sprintf(&buffer[strlen(buffer)], "%c", (unsigned char) *cur++);
168 n++;
169 }
170 sprintf(&buffer[strlen(buffer)], "\n");
171 cur = input->cur;
172 while ((*cur == '\n') || (*cur == '\r'))
173 cur--;
174 n = 0;
175 while ((cur != base) && (n++ < 80)) {
176 sprintf(&buffer[strlen(buffer)], " ");
177 base++;
178 }
179 sprintf(&buffer[strlen(buffer)],"^\n");
180 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000181 xmlGenericError(xmlGenericErrorContext, "</pre>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000182}
183
184/**
185 * xmlHTMLError:
186 * @ctx: an XML parser context
187 * @msg: the message to display/transmit
188 * @...: extra parameters for the message display
189 *
190 * Display and format an error messages, gives file, line, position and
191 * extra parameters.
192 */
193void
194xmlHTMLError(void *ctx, const char *msg, ...)
195{
196 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
197 xmlParserInputPtr input;
198 xmlParserInputPtr cur = NULL;
199 va_list args;
200
201 buffer[0] = 0;
202 input = ctxt->input;
203 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
204 cur = input;
205 input = ctxt->inputTab[ctxt->inputNr - 2];
206 }
207
208 xmlHTMLPrintFileInfo(input);
209
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000210 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000211 va_start(args, msg);
212 vsprintf(&buffer[strlen(buffer)], msg, args);
213 va_end(args);
214 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000215 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000216
217 xmlHTMLPrintFileContext(input);
218 xmlHTMLEncodeSend();
219}
220
221/**
222 * xmlHTMLWarning:
223 * @ctx: an XML parser context
224 * @msg: the message to display/transmit
225 * @...: extra parameters for the message display
226 *
227 * Display and format a warning messages, gives file, line, position and
228 * extra parameters.
229 */
230void
231xmlHTMLWarning(void *ctx, const char *msg, ...)
232{
233 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
234 xmlParserInputPtr input;
235 xmlParserInputPtr cur = NULL;
236 va_list args;
237
238 buffer[0] = 0;
239 input = ctxt->input;
240 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
241 cur = input;
242 input = ctxt->inputTab[ctxt->inputNr - 2];
243 }
244
245
246 xmlHTMLPrintFileInfo(input);
247
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000248 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000249 va_start(args, msg);
250 vsprintf(&buffer[strlen(buffer)], msg, args);
251 va_end(args);
252 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000253 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000254
255 xmlHTMLPrintFileContext(input);
256 xmlHTMLEncodeSend();
257}
258
259/**
260 * xmlHTMLValidityError:
261 * @ctx: an XML parser context
262 * @msg: the message to display/transmit
263 * @...: extra parameters for the message display
264 *
265 * Display and format an validity error messages, gives file,
266 * line, position and extra parameters.
267 */
268void
269xmlHTMLValidityError(void *ctx, const char *msg, ...)
270{
271 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
272 xmlParserInputPtr input;
273 va_list args;
274
275 buffer[0] = 0;
276 input = ctxt->input;
277 if ((input->filename == NULL) && (ctxt->inputNr > 1))
278 input = ctxt->inputTab[ctxt->inputNr - 2];
279
280 xmlHTMLPrintFileInfo(input);
281
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000282 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000283 va_start(args, msg);
284 vsprintf(&buffer[strlen(buffer)], msg, args);
285 va_end(args);
286 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000287 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000288
289 xmlHTMLPrintFileContext(input);
290 xmlHTMLEncodeSend();
291}
292
293/**
294 * xmlHTMLValidityWarning:
295 * @ctx: an XML parser context
296 * @msg: the message to display/transmit
297 * @...: extra parameters for the message display
298 *
299 * Display and format a validity warning messages, gives file, line,
300 * position and extra parameters.
301 */
302void
303xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
304{
305 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
306 xmlParserInputPtr input;
307 va_list args;
308
309 buffer[0] = 0;
310 input = ctxt->input;
311 if ((input->filename == NULL) && (ctxt->inputNr > 1))
312 input = ctxt->inputTab[ctxt->inputNr - 2];
313
314 xmlHTMLPrintFileInfo(input);
315
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000316 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000317 va_start(args, msg);
318 vsprintf(&buffer[strlen(buffer)], msg, args);
319 va_end(args);
320 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000321 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000322
323 xmlHTMLPrintFileContext(input);
324 xmlHTMLEncodeSend();
325}
326
327/************************************************************************
328 * *
329 * Shell Interface *
330 * *
331 ************************************************************************/
332/**
333 * xmlShellReadline:
334 * @prompt: the prompt value
335 *
336 * Read a string
337 *
338 * Returns a pointer to it or NULL on EOF the caller is expected to
339 * free the returned string.
340 */
341char *
342xmlShellReadline(char *prompt) {
343#ifdef HAVE_LIBREADLINE
344 char *line_read;
345
346 /* Get a line from the user. */
347 line_read = readline (prompt);
348
349 /* If the line has any text in it, save it on the history. */
350 if (line_read && *line_read)
351 add_history (line_read);
352
353 return (line_read);
354#else
355 char line_read[501];
356
357 if (prompt != NULL)
358 fprintf(stdout, "%s", prompt);
359 if (!fgets(line_read, 500, stdin))
360 return(NULL);
361 line_read[500] = 0;
362 return(strdup(line_read));
363#endif
364}
365
366/************************************************************************
367 * *
Daniel Veillard5e873c42000-04-12 13:27:38 +0000368 * I/O Interfaces *
369 * *
370 ************************************************************************/
371
372int myRead(FILE *f, char * buffer, int len) {
373 return(fread(buffer, 1, len, f));
374}
375void myClose(FILE *f) {
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000376 if (f != stdin) {
Daniel Veillard5e873c42000-04-12 13:27:38 +0000377 fclose(f);
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000378 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000379}
380
381/************************************************************************
382 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000383 * Test processing *
384 * *
385 ************************************************************************/
386void parseAndPrintFile(char *filename) {
387 xmlDocPtr doc = NULL, tmp;
388
389#ifdef LIBXML_HTML_ENABLED
390 if (html) {
391 doc = htmlParseFile(filename, NULL);
392 } else {
393#endif /* LIBXML_HTML_ENABLED */
394 /*
395 * build an XML tree from a string;
396 */
397 if (push) {
398 FILE *f;
399
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000400 /* '-' Usually means stdin -<sven@zen.org> */
401 if ((filename[0] == '-') && (filename[1] == 0)) {
402 f = stdin;
403 } else {
404 f = fopen(filename, "r");
405 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000406 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000407 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000408 int res, size = 3;
409 char chars[1024];
410 xmlParserCtxtPtr ctxt;
411
412 if (repeat)
413 size = 1024;
414 res = fread(chars, 1, 4, f);
415 if (res > 0) {
416 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
417 chars, res, filename);
418 while ((res = fread(chars, 1, size, f)) > 0) {
419 xmlParseChunk(ctxt, chars, res, 0);
420 }
421 xmlParseChunk(ctxt, chars, 0, 1);
422 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000423 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000424 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000425 if (!ret) {
426 xmlFreeDoc(doc);
427 doc = NULL;
428 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000429 }
430 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000431 } else if (testIO) {
432 int ret;
433 FILE *f;
434
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000435 /* '-' Usually means stdin -<sven@zen.org> */
436 if ((filename[0] == '-') && (filename[1] == 0)) {
437 f = stdin;
438 } else {
439 f = fopen(filename, "r");
440 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000441 if (f != NULL) {
442 xmlParserCtxtPtr ctxt;
443
444 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
445 (xmlInputReadCallback) myRead,
446 (xmlInputCloseCallback) myClose,
447 f, XML_CHAR_ENCODING_NONE);
448 xmlParseDocument(ctxt);
449
450 ret = ctxt->wellFormed;
451 doc = ctxt->myDoc;
452 xmlFreeParserCtxt(ctxt);
453 if (!ret) {
454 xmlFreeDoc(doc);
455 doc = NULL;
456 }
457 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000458 } else if (recovery) {
459 doc = xmlRecoverFile(filename);
460 } else if (htmlout) {
461 int ret;
462 xmlParserCtxtPtr ctxt;
463 xmlSAXHandler silent, *old;
464
465 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000466
467 if (ctxt == NULL) {
468 /* If xmlCreateFileParseCtxt() return NULL something
469 strange happened so we don't want to do anything. Do
470 we want to print an error message here?
471 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000472 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000473 } else {
474 memcpy(&silent, ctxt->sax, sizeof(silent));
475 old = ctxt->sax;
476 silent.error = xmlHTMLError;
477 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000478 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000479 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000480 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000481 silent.fatalError = xmlHTMLError;
482 ctxt->sax = &silent;
483 ctxt->vctxt.error = xmlHTMLValidityError;
484 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000485 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000486 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000487 ctxt->vctxt.warning = NULL;
488
Daniel Veillard88a172f2000-08-04 18:23:10 +0000489 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000490
Daniel Veillard88a172f2000-08-04 18:23:10 +0000491 ret = ctxt->wellFormed;
492 doc = ctxt->myDoc;
493 ctxt->sax = old;
494 xmlFreeParserCtxt(ctxt);
495 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000496 xmlFreeDoc(doc);
497 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000498 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000499 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000500#ifdef HAVE_SYS_MMAN_H
501 } else if (memory) {
502 int fd;
503 struct stat info;
504 const char *base;
505 if (stat(filename, &info) < 0)
506 return;
507 if ((fd = open(filename, O_RDONLY)) < 0)
508 return;
509 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000510 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000511 return;
512
513 doc = xmlParseMemory((char *) base, info.st_size);
514 munmap((char *) base, info.st_size);
515#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000516 } else
517 doc = xmlParseFile(filename);
518#ifdef LIBXML_HTML_ENABLED
519 }
520#endif
521
Daniel Veillard88a172f2000-08-04 18:23:10 +0000522 /*
523 * If we don't have a document we might as well give up. Do we
524 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000525 if (doc == NULL) {
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000526 progresult = 1;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000527 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000528 }
529
530#ifdef LIBXML_XINCLUDE_ENABLED
531 if (xinclude)
532 xmlXIncludeProcess(doc);
533#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000534
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000535#ifdef LIBXML_DEBUG_ENABLED
536 /*
537 * shell interraction
538 */
539 if (shell)
540 xmlShell(doc, filename, xmlShellReadline, stdout);
541#endif
542
543 /*
544 * test intermediate copy if needed.
545 */
546 if (copy) {
547 tmp = doc;
548 doc = xmlCopyDoc(doc, 1);
549 xmlFreeDoc(tmp);
550 }
551
552 if ((insert) && (!html)) {
553 const xmlChar* list[256];
554 int nb, i;
555 xmlNodePtr node;
556
557 if (doc->children != NULL) {
558 node = doc->children;
559 while ((node != NULL) && (node->last == NULL)) node = node->next;
560 if (node != NULL) {
561 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
562 if (nb < 0) {
563 printf("could not get valid list of elements\n");
564 } else if (nb == 0) {
565 printf("No element can be indersted under root\n");
566 } else {
567 printf("%d element types can be indersted under root:\n",
568 nb);
569 for (i = 0;i < nb;i++) {
570 printf("%s\n", list[i]);
571 }
572 }
573 }
574 }
575 }else if (noout == 0) {
576 /*
577 * print it.
578 */
579#ifdef LIBXML_DEBUG_ENABLED
580 if (!debug) {
581#endif
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000582 if (memory) {
583 xmlChar *result;
584 int len;
585
586 if (encoding != NULL) {
587 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
588 } else {
589 xmlDocDumpMemory(doc, &result, &len);
590 }
591 if (result == NULL) {
592 fprintf(stderr, "Failed to save\n");
593 } else {
594 write(1, result, len);
595 xmlFree(result);
596 }
597 } else if (compress)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000598 xmlSaveFile("-", doc);
Daniel Veillardbe803962000-06-28 23:40:59 +0000599 else if (encoding != NULL)
600 xmlSaveFileEnc("-", doc, encoding);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000601 else
602 xmlDocDump(stdout, doc);
603#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000604 } else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000605 xmlDebugDumpDocument(stdout, doc);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000606 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000607#endif
608 }
609
610 /*
611 * A posteriori validation test
612 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000613 if (dtdvalid != NULL) {
614 xmlDtdPtr dtd;
615
616 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
617 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000618 xmlGenericError(xmlGenericErrorContext,
619 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000620 progresult = 2;
Daniel Veillardcd429612000-10-11 15:57:05 +0000621 } else {
622 xmlValidCtxt cvp;
623 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
624 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000625 xmlGenericError(xmlGenericErrorContext,
626 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000627 filename, dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000628 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000629 }
630 xmlFreeDtd(dtd);
631 }
632 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000633 xmlValidCtxt cvp;
634 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000635 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000636 xmlGenericError(xmlGenericErrorContext,
637 "Document %s does not validate\n", filename);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000638 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000639 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000640 }
641
642#ifdef LIBXML_DEBUG_ENABLED
643 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000644 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000645#endif
646
647 /*
648 * free it.
649 */
650 xmlFreeDoc(doc);
651}
652
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000653int
654main(int argc, char **argv) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000655 int i, count;
656 int files = 0;
657
Daniel Veillardbe803962000-06-28 23:40:59 +0000658 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000659 for (i = 1; i < argc ; i++) {
660#ifdef LIBXML_DEBUG_ENABLED
661 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
662 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000663 else if ((!strcmp(argv[i], "-shell")) ||
664 (!strcmp(argv[i], "--shell"))) {
665 shell++;
666 noout = 1;
667 } else
668#endif
669 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
670 copy++;
671 else if ((!strcmp(argv[i], "-recover")) ||
672 (!strcmp(argv[i], "--recover")))
673 recovery++;
674 else if ((!strcmp(argv[i], "-noent")) ||
675 (!strcmp(argv[i], "--noent")))
676 noent++;
677 else if ((!strcmp(argv[i], "-noout")) ||
678 (!strcmp(argv[i], "--noout")))
679 noout++;
680 else if ((!strcmp(argv[i], "-htmlout")) ||
681 (!strcmp(argv[i], "--htmlout")))
682 htmlout++;
683#ifdef LIBXML_HTML_ENABLED
684 else if ((!strcmp(argv[i], "-html")) ||
685 (!strcmp(argv[i], "--html"))) {
686 html++;
687 }
688#endif /* LIBXML_HTML_ENABLED */
689 else if ((!strcmp(argv[i], "-nowrap")) ||
690 (!strcmp(argv[i], "--nowrap")))
691 nowrap++;
692 else if ((!strcmp(argv[i], "-valid")) ||
693 (!strcmp(argv[i], "--valid")))
694 valid++;
695 else if ((!strcmp(argv[i], "-postvalid")) ||
696 (!strcmp(argv[i], "--postvalid")))
697 postvalid++;
Daniel Veillardcd429612000-10-11 15:57:05 +0000698 else if ((!strcmp(argv[i], "-dtdvalid")) ||
699 (!strcmp(argv[i], "--dtdvalid"))) {
700 i++;
701 dtdvalid = argv[i];
702 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000703 else if ((!strcmp(argv[i], "-insert")) ||
704 (!strcmp(argv[i], "--insert")))
705 insert++;
706 else if ((!strcmp(argv[i], "-repeat")) ||
707 (!strcmp(argv[i], "--repeat")))
708 repeat++;
709 else if ((!strcmp(argv[i], "-push")) ||
710 (!strcmp(argv[i], "--push")))
711 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +0000712#ifdef HAVE_SYS_MMAN_H
713 else if ((!strcmp(argv[i], "-memory")) ||
714 (!strcmp(argv[i], "--memory")))
715 memory++;
716#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +0000717 else if ((!strcmp(argv[i], "-testIO")) ||
718 (!strcmp(argv[i], "--testIO")))
719 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000720#ifdef LIBXML_XINCLUDE_ENABLED
721 else if ((!strcmp(argv[i], "-xinclude")) ||
722 (!strcmp(argv[i], "--xinclude")))
723 xinclude++;
724#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000725 else if ((!strcmp(argv[i], "-compress")) ||
726 (!strcmp(argv[i], "--compress"))) {
727 compress++;
728 xmlSetCompressMode(9);
729 }
730 else if ((!strcmp(argv[i], "-nowarning")) ||
731 (!strcmp(argv[i], "--nowarning"))) {
732 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000733 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000734 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000735 else if ((!strcmp(argv[i], "-pedantic")) ||
736 (!strcmp(argv[i], "--pedantic"))) {
737 xmlGetWarningsDefaultValue = 1;
738 xmlPedanticParserDefault(1);
739 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +0000740#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000741 else if ((!strcmp(argv[i], "-debugent")) ||
742 (!strcmp(argv[i], "--debugent"))) {
743 debugent++;
744 xmlParserDebugEntities = 1;
745 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +0000746#endif
Daniel Veillardbe803962000-06-28 23:40:59 +0000747 else if ((!strcmp(argv[i], "-encode")) ||
748 (!strcmp(argv[i], "--encode"))) {
749 i++;
750 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000751 /*
752 * OK it's for testing purposes
753 */
754 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +0000755 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000756 else if ((!strcmp(argv[i], "-noblanks")) ||
757 (!strcmp(argv[i], "--noblanks"))) {
758 noblanks++;
759 xmlKeepBlanksDefault(0);
760 }
761 }
762 if (noent != 0) xmlSubstituteEntitiesDefault(1);
763 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
764 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000765 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000766 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000767 xmlGenericError(xmlGenericErrorContext,
768 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
769 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000770 "<html><head><title>%s output</title></head>\n",
771 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000772 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000773 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
774 argv[0]);
775 }
776 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000777 if ((!strcmp(argv[i], "-encode")) ||
778 (!strcmp(argv[i], "--encode"))) {
779 i++;
780 continue;
781 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000782 if ((!strcmp(argv[i], "-dtdvalid")) ||
783 (!strcmp(argv[i], "--dtdvalid"))) {
784 i++;
785 continue;
786 }
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000787 /* Remember file names. "-" means stding. <sven@zen.org> */
788 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000789 if (repeat) {
790 for (count = 0;count < 100 * repeat;count++)
791 parseAndPrintFile(argv[i]);
792 } else
793 parseAndPrintFile(argv[i]);
794 files ++;
795 }
796 }
797 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000798 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000799 }
800 if (files == 0) {
801 printf("Usage : %s [--debug] [--debugent] [--copy] [--recover] [--noent] [--noout] [--valid] [--repeat] XMLfiles ...\n",
802 argv[0]);
803 printf("\tParse the XML files and output the result of the parsing\n");
804#ifdef LIBXML_DEBUG_ENABLED
805 printf("\t--debug : dump a debug tree of the in-memory document\n");
806 printf("\t--shell : run a navigating shell\n");
807 printf("\t--debugent : debug the entities defined in the document\n");
808#endif
809 printf("\t--copy : used to test the internal copy implementation\n");
810 printf("\t--recover : output what was parsable on broken XML documents\n");
811 printf("\t--noent : substitute entity references by their value\n");
812 printf("\t--noout : don't output the result tree\n");
813 printf("\t--htmlout : output results as HTML\n");
814 printf("\t--nowarp : do not put HTML doc wrapper\n");
815 printf("\t--valid : validate the document in addition to std well-formed check\n");
816 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
Daniel Veillardcd429612000-10-11 15:57:05 +0000817 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000818 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
819 printf("\t--insert : ad-hoc test for valid insertions\n");
820 printf("\t--compress : turn on gzip compression of output\n");
821#ifdef LIBXML_HTML_ENABLED
822 printf("\t--html : use the HTML parser\n");
823#endif
824 printf("\t--push : use the push mode of the parser\n");
Daniel Veillard46e370e2000-07-21 20:32:03 +0000825#ifdef HAVE_SYS_MMAN_H
826 printf("\t--memory : parse from memory\n");
827#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000828 printf("\t--nowarning : do not emit warnings from parser/validator\n");
829 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard5e873c42000-04-12 13:27:38 +0000830 printf("\t--testIO : test user I/O support\n");
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000831 printf("\t--encode encoding : output in the given encoding\n");
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000832#ifdef LIBXML_XINCLUDE_ENABLED
833 printf("\t--xinclude : do XInclude processing\n");
834#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000835 }
836 xmlCleanupParser();
837 xmlMemoryDump();
838
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000839 return(progresult);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000840}
Daniel Veillard88a172f2000-08-04 18:23:10 +0000841