blob: 7d6ec8746776597c66e1699571cf79cd20fa1456 [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) {
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000375 if (f != stdin) {
Daniel Veillard5e873c42000-04-12 13:27:38 +0000376 fclose(f);
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000377 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000378}
379
380/************************************************************************
381 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000382 * Test processing *
383 * *
384 ************************************************************************/
385void parseAndPrintFile(char *filename) {
386 xmlDocPtr doc = NULL, tmp;
387
388#ifdef LIBXML_HTML_ENABLED
389 if (html) {
390 doc = htmlParseFile(filename, NULL);
391 } else {
392#endif /* LIBXML_HTML_ENABLED */
393 /*
394 * build an XML tree from a string;
395 */
396 if (push) {
397 FILE *f;
398
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000399 /* '-' Usually means stdin -<sven@zen.org> */
400 if ((filename[0] == '-') && (filename[1] == 0)) {
401 f = stdin;
402 } else {
403 f = fopen(filename, "r");
404 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000405 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000406 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000407 int res, size = 3;
408 char chars[1024];
409 xmlParserCtxtPtr ctxt;
410
411 if (repeat)
412 size = 1024;
413 res = fread(chars, 1, 4, f);
414 if (res > 0) {
415 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
416 chars, res, filename);
417 while ((res = fread(chars, 1, size, f)) > 0) {
418 xmlParseChunk(ctxt, chars, res, 0);
419 }
420 xmlParseChunk(ctxt, chars, 0, 1);
421 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000422 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000423 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000424 if (!ret) {
425 xmlFreeDoc(doc);
426 doc = NULL;
427 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000428 }
429 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000430 } else if (testIO) {
431 int ret;
432 FILE *f;
433
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000434 /* '-' Usually means stdin -<sven@zen.org> */
435 if ((filename[0] == '-') && (filename[1] == 0)) {
436 f = stdin;
437 } else {
438 f = fopen(filename, "r");
439 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000440 if (f != NULL) {
441 xmlParserCtxtPtr ctxt;
442
443 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
444 (xmlInputReadCallback) myRead,
445 (xmlInputCloseCallback) myClose,
446 f, XML_CHAR_ENCODING_NONE);
447 xmlParseDocument(ctxt);
448
449 ret = ctxt->wellFormed;
450 doc = ctxt->myDoc;
451 xmlFreeParserCtxt(ctxt);
452 if (!ret) {
453 xmlFreeDoc(doc);
454 doc = NULL;
455 }
456 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000457 } else if (recovery) {
458 doc = xmlRecoverFile(filename);
459 } else if (htmlout) {
460 int ret;
461 xmlParserCtxtPtr ctxt;
462 xmlSAXHandler silent, *old;
463
464 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000465
466 if (ctxt == NULL) {
467 /* If xmlCreateFileParseCtxt() return NULL something
468 strange happened so we don't want to do anything. Do
469 we want to print an error message here?
470 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000471 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000472 } else {
473 memcpy(&silent, ctxt->sax, sizeof(silent));
474 old = ctxt->sax;
475 silent.error = xmlHTMLError;
476 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000477 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000478 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000479 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000480 silent.fatalError = xmlHTMLError;
481 ctxt->sax = &silent;
482 ctxt->vctxt.error = xmlHTMLValidityError;
483 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000484 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000485 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000486 ctxt->vctxt.warning = NULL;
487
Daniel Veillard88a172f2000-08-04 18:23:10 +0000488 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000489
Daniel Veillard88a172f2000-08-04 18:23:10 +0000490 ret = ctxt->wellFormed;
491 doc = ctxt->myDoc;
492 ctxt->sax = old;
493 xmlFreeParserCtxt(ctxt);
494 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000495 xmlFreeDoc(doc);
496 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000497 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000498 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000499#ifdef HAVE_SYS_MMAN_H
500 } else if (memory) {
501 int fd;
502 struct stat info;
503 const char *base;
504 if (stat(filename, &info) < 0)
505 return;
506 if ((fd = open(filename, O_RDONLY)) < 0)
507 return;
508 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000509 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000510 return;
511
512 doc = xmlParseMemory((char *) base, info.st_size);
513 munmap((char *) base, info.st_size);
514#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000515 } else
516 doc = xmlParseFile(filename);
517#ifdef LIBXML_HTML_ENABLED
518 }
519#endif
520
Daniel Veillard88a172f2000-08-04 18:23:10 +0000521 /*
522 * If we don't have a document we might as well give up. Do we
523 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000524 if (doc == NULL) {
Daniel Veillard88a172f2000-08-04 18:23:10 +0000525 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000526 }
527
528#ifdef LIBXML_XINCLUDE_ENABLED
529 if (xinclude)
530 xmlXIncludeProcess(doc);
531#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000532
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000533#ifdef LIBXML_DEBUG_ENABLED
534 /*
535 * shell interraction
536 */
537 if (shell)
538 xmlShell(doc, filename, xmlShellReadline, stdout);
539#endif
540
541 /*
542 * test intermediate copy if needed.
543 */
544 if (copy) {
545 tmp = doc;
546 doc = xmlCopyDoc(doc, 1);
547 xmlFreeDoc(tmp);
548 }
549
550 if ((insert) && (!html)) {
551 const xmlChar* list[256];
552 int nb, i;
553 xmlNodePtr node;
554
555 if (doc->children != NULL) {
556 node = doc->children;
557 while ((node != NULL) && (node->last == NULL)) node = node->next;
558 if (node != NULL) {
559 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
560 if (nb < 0) {
561 printf("could not get valid list of elements\n");
562 } else if (nb == 0) {
563 printf("No element can be indersted under root\n");
564 } else {
565 printf("%d element types can be indersted under root:\n",
566 nb);
567 for (i = 0;i < nb;i++) {
568 printf("%s\n", list[i]);
569 }
570 }
571 }
572 }
573 }else if (noout == 0) {
574 /*
575 * print it.
576 */
577#ifdef LIBXML_DEBUG_ENABLED
578 if (!debug) {
579#endif
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000580 if (memory) {
581 xmlChar *result;
582 int len;
583
584 if (encoding != NULL) {
585 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
586 } else {
587 xmlDocDumpMemory(doc, &result, &len);
588 }
589 if (result == NULL) {
590 fprintf(stderr, "Failed to save\n");
591 } else {
592 write(1, result, len);
593 xmlFree(result);
594 }
595 } else if (compress)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000596 xmlSaveFile("-", doc);
Daniel Veillardbe803962000-06-28 23:40:59 +0000597 else if (encoding != NULL)
598 xmlSaveFileEnc("-", doc, encoding);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000599 else
600 xmlDocDump(stdout, doc);
601#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000602 } else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000603 xmlDebugDumpDocument(stdout, doc);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000604 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000605#endif
606 }
607
608 /*
609 * A posteriori validation test
610 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000611 if (dtdvalid != NULL) {
612 xmlDtdPtr dtd;
613
614 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
615 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000616 xmlGenericError(xmlGenericErrorContext,
617 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardcd429612000-10-11 15:57:05 +0000618 } else {
619 xmlValidCtxt cvp;
620 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
621 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000622 xmlGenericError(xmlGenericErrorContext,
623 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000624 filename, dtdvalid);
625 }
626 xmlFreeDtd(dtd);
627 }
628 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000629 xmlValidCtxt cvp;
630 cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000631 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000632 xmlGenericError(xmlGenericErrorContext,
633 "Document %s does not validate\n", filename);
Daniel Veillardcd429612000-10-11 15:57:05 +0000634 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000635 }
636
637#ifdef LIBXML_DEBUG_ENABLED
638 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000639 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000640#endif
641
642 /*
643 * free it.
644 */
645 xmlFreeDoc(doc);
646}
647
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000648int
649main(int argc, char **argv) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000650 int i, count;
651 int files = 0;
652
Daniel Veillardbe803962000-06-28 23:40:59 +0000653 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000654 for (i = 1; i < argc ; i++) {
655#ifdef LIBXML_DEBUG_ENABLED
656 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
657 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000658 else if ((!strcmp(argv[i], "-shell")) ||
659 (!strcmp(argv[i], "--shell"))) {
660 shell++;
661 noout = 1;
662 } else
663#endif
664 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
665 copy++;
666 else if ((!strcmp(argv[i], "-recover")) ||
667 (!strcmp(argv[i], "--recover")))
668 recovery++;
669 else if ((!strcmp(argv[i], "-noent")) ||
670 (!strcmp(argv[i], "--noent")))
671 noent++;
672 else if ((!strcmp(argv[i], "-noout")) ||
673 (!strcmp(argv[i], "--noout")))
674 noout++;
675 else if ((!strcmp(argv[i], "-htmlout")) ||
676 (!strcmp(argv[i], "--htmlout")))
677 htmlout++;
678#ifdef LIBXML_HTML_ENABLED
679 else if ((!strcmp(argv[i], "-html")) ||
680 (!strcmp(argv[i], "--html"))) {
681 html++;
682 }
683#endif /* LIBXML_HTML_ENABLED */
684 else if ((!strcmp(argv[i], "-nowrap")) ||
685 (!strcmp(argv[i], "--nowrap")))
686 nowrap++;
687 else if ((!strcmp(argv[i], "-valid")) ||
688 (!strcmp(argv[i], "--valid")))
689 valid++;
690 else if ((!strcmp(argv[i], "-postvalid")) ||
691 (!strcmp(argv[i], "--postvalid")))
692 postvalid++;
Daniel Veillardcd429612000-10-11 15:57:05 +0000693 else if ((!strcmp(argv[i], "-dtdvalid")) ||
694 (!strcmp(argv[i], "--dtdvalid"))) {
695 i++;
696 dtdvalid = argv[i];
697 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000698 else if ((!strcmp(argv[i], "-insert")) ||
699 (!strcmp(argv[i], "--insert")))
700 insert++;
701 else if ((!strcmp(argv[i], "-repeat")) ||
702 (!strcmp(argv[i], "--repeat")))
703 repeat++;
704 else if ((!strcmp(argv[i], "-push")) ||
705 (!strcmp(argv[i], "--push")))
706 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +0000707#ifdef HAVE_SYS_MMAN_H
708 else if ((!strcmp(argv[i], "-memory")) ||
709 (!strcmp(argv[i], "--memory")))
710 memory++;
711#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +0000712 else if ((!strcmp(argv[i], "-testIO")) ||
713 (!strcmp(argv[i], "--testIO")))
714 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000715#ifdef LIBXML_XINCLUDE_ENABLED
716 else if ((!strcmp(argv[i], "-xinclude")) ||
717 (!strcmp(argv[i], "--xinclude")))
718 xinclude++;
719#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000720 else if ((!strcmp(argv[i], "-compress")) ||
721 (!strcmp(argv[i], "--compress"))) {
722 compress++;
723 xmlSetCompressMode(9);
724 }
725 else if ((!strcmp(argv[i], "-nowarning")) ||
726 (!strcmp(argv[i], "--nowarning"))) {
727 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000728 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000729 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000730 else if ((!strcmp(argv[i], "-pedantic")) ||
731 (!strcmp(argv[i], "--pedantic"))) {
732 xmlGetWarningsDefaultValue = 1;
733 xmlPedanticParserDefault(1);
734 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +0000735#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000736 else if ((!strcmp(argv[i], "-debugent")) ||
737 (!strcmp(argv[i], "--debugent"))) {
738 debugent++;
739 xmlParserDebugEntities = 1;
740 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +0000741#endif
Daniel Veillardbe803962000-06-28 23:40:59 +0000742 else if ((!strcmp(argv[i], "-encode")) ||
743 (!strcmp(argv[i], "--encode"))) {
744 i++;
745 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000746 /*
747 * OK it's for testing purposes
748 */
749 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +0000750 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000751 else if ((!strcmp(argv[i], "-noblanks")) ||
752 (!strcmp(argv[i], "--noblanks"))) {
753 noblanks++;
754 xmlKeepBlanksDefault(0);
755 }
756 }
757 if (noent != 0) xmlSubstituteEntitiesDefault(1);
758 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
759 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000760 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000761 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000762 xmlGenericError(xmlGenericErrorContext,
763 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
764 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000765 "<html><head><title>%s output</title></head>\n",
766 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000767 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000768 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
769 argv[0]);
770 }
771 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000772 if ((!strcmp(argv[i], "-encode")) ||
773 (!strcmp(argv[i], "--encode"))) {
774 i++;
775 continue;
776 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000777 if ((!strcmp(argv[i], "-dtdvalid")) ||
778 (!strcmp(argv[i], "--dtdvalid"))) {
779 i++;
780 continue;
781 }
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000782 /* Remember file names. "-" means stding. <sven@zen.org> */
783 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000784 if (repeat) {
785 for (count = 0;count < 100 * repeat;count++)
786 parseAndPrintFile(argv[i]);
787 } else
788 parseAndPrintFile(argv[i]);
789 files ++;
790 }
791 }
792 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000793 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000794 }
795 if (files == 0) {
796 printf("Usage : %s [--debug] [--debugent] [--copy] [--recover] [--noent] [--noout] [--valid] [--repeat] XMLfiles ...\n",
797 argv[0]);
798 printf("\tParse the XML files and output the result of the parsing\n");
799#ifdef LIBXML_DEBUG_ENABLED
800 printf("\t--debug : dump a debug tree of the in-memory document\n");
801 printf("\t--shell : run a navigating shell\n");
802 printf("\t--debugent : debug the entities defined in the document\n");
803#endif
804 printf("\t--copy : used to test the internal copy implementation\n");
805 printf("\t--recover : output what was parsable on broken XML documents\n");
806 printf("\t--noent : substitute entity references by their value\n");
807 printf("\t--noout : don't output the result tree\n");
808 printf("\t--htmlout : output results as HTML\n");
809 printf("\t--nowarp : do not put HTML doc wrapper\n");
810 printf("\t--valid : validate the document in addition to std well-formed check\n");
811 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
Daniel Veillardcd429612000-10-11 15:57:05 +0000812 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000813 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
814 printf("\t--insert : ad-hoc test for valid insertions\n");
815 printf("\t--compress : turn on gzip compression of output\n");
816#ifdef LIBXML_HTML_ENABLED
817 printf("\t--html : use the HTML parser\n");
818#endif
819 printf("\t--push : use the push mode of the parser\n");
Daniel Veillard46e370e2000-07-21 20:32:03 +0000820#ifdef HAVE_SYS_MMAN_H
821 printf("\t--memory : parse from memory\n");
822#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000823 printf("\t--nowarning : do not emit warnings from parser/validator\n");
824 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard5e873c42000-04-12 13:27:38 +0000825 printf("\t--testIO : test user I/O support\n");
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000826 printf("\t--encode encoding : output in the given encoding\n");
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000827#ifdef LIBXML_XINCLUDE_ENABLED
828 printf("\t--xinclude : do XInclude processing\n");
829#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000830 }
831 xmlCleanupParser();
832 xmlMemoryDump();
833
834 return(0);
835}
Daniel Veillard88a172f2000-08-04 18:23:10 +0000836