blob: 467f9ef9b44944980a11e93e73fffbc633df14c7 [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 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00006 * daniel@veillard.com
Daniel Veillardce8b83b2000-04-05 18:38:42 +00007 */
8
Bjorn Reese70a9da52001-04-21 16:57:29 +00009#include "libxml.h"
Daniel Veillardce8b83b2000-04-05 18:38:42 +000010
Daniel Veillardce8b83b2000-04-05 18:38:42 +000011#include <string.h>
Daniel Veillardce8b83b2000-04-05 18:38:42 +000012#include <stdarg.h>
Daniel Veillard28ae6362001-07-14 16:44:32 +000013
Daniel Veillard3c5ed912002-01-08 10:36:16 +000014#if defined (_WIN32) && !defined(__CYGWIN__)
Daniel Veillard2d90de42001-04-16 17:46:18 +000015#ifdef _MSC_VER
16#include <winsock2.h>
17#pragma comment(lib, "ws2_32.lib")
18#define gettimeofday(p1,p2)
Daniel Veillardf216d462002-02-08 13:44:24 +000019#include <time.h>
Daniel Veillard28ae6362001-07-14 16:44:32 +000020#else /* _MSC_VER */
21#include <sys/time.h>
Daniel Veillard2d90de42001-04-16 17:46:18 +000022#endif /* _MSC_VER */
23#else /* _WIN32 */
Daniel Veillarded472f32001-12-13 08:48:14 +000024#ifdef HAVE_SYS_TIME_H
Daniel Veillard48b2f892001-02-25 16:11:03 +000025#include <sys/time.h>
Daniel Veillarded472f32001-12-13 08:48:14 +000026#endif
Daniel Veillard01db67c2001-12-18 07:09:59 +000027#ifdef HAVE_TIME_H
28#include <time.h>
29#endif
Daniel Veillard2d90de42001-04-16 17:46:18 +000030#endif /* _WIN32 */
Daniel Veillard48b2f892001-02-25 16:11:03 +000031
Daniel Veillard90bc3712002-03-07 15:12:58 +000032#ifdef HAVE_SYS_TIMEB_H
33#include <sys/timeb.h>
34#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000035
36#ifdef HAVE_SYS_TYPES_H
37#include <sys/types.h>
38#endif
39#ifdef HAVE_SYS_STAT_H
40#include <sys/stat.h>
41#endif
42#ifdef HAVE_FCNTL_H
43#include <fcntl.h>
44#endif
45#ifdef HAVE_UNISTD_H
46#include <unistd.h>
47#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000048#ifdef HAVE_SYS_MMAN_H
49#include <sys/mman.h>
Daniel Veillard87b95392000-08-12 21:12:04 +000050/* seems needed for Solaris */
51#ifndef MAP_FAILED
52#define MAP_FAILED ((void *) -1)
53#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000054#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000055#ifdef HAVE_STDLIB_H
56#include <stdlib.h>
57#endif
58#ifdef HAVE_LIBREADLINE
59#include <readline/readline.h>
60#ifdef HAVE_LIBHISTORY
61#include <readline/history.h>
62#endif
63#endif
64
65#include <libxml/xmlmemory.h>
66#include <libxml/parser.h>
67#include <libxml/parserInternals.h>
68#include <libxml/HTMLparser.h>
69#include <libxml/HTMLtree.h>
70#include <libxml/tree.h>
71#include <libxml/xpath.h>
72#include <libxml/debugXML.h>
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +000073#include <libxml/xmlerror.h>
Daniel Veillard9e8bfae2000-11-06 16:43:11 +000074#ifdef LIBXML_XINCLUDE_ENABLED
75#include <libxml/xinclude.h>
76#endif
Daniel Veillard81418e32001-05-22 15:08:55 +000077#ifdef LIBXML_CATALOG_ENABLED
78#include <libxml/catalog.h>
79#endif
Daniel Veillard89cad532001-10-22 09:46:13 +000080#ifdef LIBXML_DOCB_ENABLED
81#include <libxml/DOCBparser.h>
82#endif
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000083#include <libxml/globals.h>
Daniel Veillardce8b83b2000-04-05 18:38:42 +000084
85#ifdef LIBXML_DEBUG_ENABLED
86static int debug = 0;
87static int shell = 0;
88static int debugent = 0;
89#endif
90static int copy = 0;
91static int recovery = 0;
92static int noent = 0;
93static int noout = 0;
94static int nowrap = 0;
95static int valid = 0;
96static int postvalid = 0;
Daniel Veillardcd429612000-10-11 15:57:05 +000097static char * dtdvalid = NULL;
Daniel Veillardce8b83b2000-04-05 18:38:42 +000098static int repeat = 0;
99static int insert = 0;
100static int compress = 0;
Daniel Veillard89cad532001-10-22 09:46:13 +0000101#ifdef LIBXML_DOCB_ENABLED
102static int sgml = 0;
103#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000104static int html = 0;
105static int htmlout = 0;
106static int push = 0;
Daniel Veillard46e370e2000-07-21 20:32:03 +0000107#ifdef HAVE_SYS_MMAN_H
108static int memory = 0;
109#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000110static int noblanks = 0;
Daniel Veillard90493a92001-08-14 14:12:47 +0000111static int format = 0;
Daniel Veillard5e873c42000-04-12 13:27:38 +0000112static int testIO = 0;
Daniel Veillardbe803962000-06-28 23:40:59 +0000113static char *encoding = NULL;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000114#ifdef LIBXML_XINCLUDE_ENABLED
115static int xinclude = 0;
116#endif
Daniel Veillard48da9102001-08-07 01:10:10 +0000117static int dtdattrs = 0;
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000118static int loaddtd = 0;
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000119static int progresult = 0;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000120static int timing = 0;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000121static int generate = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000122static int dropdtd = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000123#ifdef LIBXML_CATALOG_ENABLED
124static int catalogs = 0;
125static int nocatalogs = 0;
126#endif
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000127static const char *output = NULL;
128
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000129
Daniel Veillard01db67c2001-12-18 07:09:59 +0000130/*
131 * Internal timing routines to remove the necessity to have unix-specific
132 * function calls
133 */
134
Daniel Veillard8c1ae602002-03-07 11:21:00 +0000135#ifndef HAVE_GETTIMEOFDAY
136#ifdef HAVE_SYS_TIMEB_H
137#ifdef HAVE_SYS_TIME_H
138#ifdef HAVE_FTIME
139
140int
141my_gettimeofday(struct timeval *tvp, void *tzp)
142{
143 struct timeb timebuffer;
144
145 ftime(&timebuffer);
146 if (tvp) {
147 tvp->tv_sec = timebuffer.time;
148 tvp->tv_usec = timebuffer.millitm * 1000L;
149 }
150 return (0);
151}
152#define HAVE_GETTIMEOFDAY 1
153#define gettimeofday my_gettimeofday
154
155#endif /* HAVE_FTIME */
156#endif /* HAVE_SYS_TIME_H */
157#endif /* HAVE_SYS_TIMEB_H */
158#endif /* !HAVE_GETTIMEOFDAY */
159
Daniel Veillard01db67c2001-12-18 07:09:59 +0000160#if defined(HAVE_GETTIMEOFDAY)
161static struct timeval begin, end;
162
163/*
164 * startTimer: call where you want to start timing
165 */
166static void
167startTimer(void)
168{
169 gettimeofday(&begin, NULL);
170}
171
172/*
173 * endTimer: call where you want to stop timing and to print out a
174 * message about the timing performed; format is a printf
175 * type argument
176 */
177static void
178endTimer(const char *format, ...)
179{
180 long msec;
181 va_list ap;
182
183 gettimeofday(&end, NULL);
184 msec = end.tv_sec - begin.tv_sec;
185 msec *= 1000;
186 msec += (end.tv_usec - begin.tv_usec) / 1000;
187
188#ifndef HAVE_STDARG_H
189#error "endTimer required stdarg functions"
190#endif
191 va_start(ap, format);
192 vfprintf(stderr, format, ap);
193 va_end(ap);
194
195 fprintf(stderr, " took %ld ms\n", msec);
196}
197#elif defined(HAVE_TIME_H)
Daniel Veillard01db67c2001-12-18 07:09:59 +0000198/*
199 * No gettimeofday function, so we have to make do with calling clock.
200 * This is obviously less accurate, but there's little we can do about
201 * that.
202 */
Daniel Veillard90bc3712002-03-07 15:12:58 +0000203#ifndef CLOCKS_PER_SEC
204#define CLOCKS_PER_SEC 100
205#endif
Daniel Veillard01db67c2001-12-18 07:09:59 +0000206
207static clock_t begin, end;
208static void
209startTimer(void)
210{
211 begin = clock();
212}
213static void
214endTimer(const char *fmt, ...)
215{
216 long msec;
217 va_list ap;
218
219 end = clock();
220 msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
221
222#ifndef HAVE_STDARG_H
223#error "endTimer required stdarg functions"
224#endif
225 va_start(ap, fmt);
226 vfprintf(stderr, fmt, ap);
227 va_end(ap);
228 fprintf(stderr, " took %ld ms\n", msec);
229}
230#else
231
232/*
233 * We don't have a gettimeofday or time.h, so we just don't do timing
234 */
235static void
236startTimer(void)
237{
238 /*
239 * Do nothing
240 */
241}
242static void
243endTimer(char *format, ...)
244{
245 /*
246 * We cannot do anything because we don't have a timing function
247 */
248#ifdef HAVE_STDARG_H
249 va_start(ap, format);
250 vfprintf(stderr, format, ap);
251 va_end(ap);
252 fprintf(stderr, " was not timed\n", msec);
253#else
254 /* We don't have gettimeofday, time or stdarg.h, what crazy world is
255 * this ?!
256 */
257#endif
258}
259#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000260/************************************************************************
261 * *
262 * HTML ouput *
263 * *
264 ************************************************************************/
265char buffer[50000];
266
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000267static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000268xmlHTMLEncodeSend(void) {
269 char *result;
270
271 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
272 if (result) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000273 xmlGenericError(xmlGenericErrorContext, "%s", result);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000274 xmlFree(result);
275 }
276 buffer[0] = 0;
277}
278
279/**
280 * xmlHTMLPrintFileInfo:
281 * @input: an xmlParserInputPtr input
282 *
283 * Displays the associated file and line informations for the current input
284 */
285
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000286static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000287xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000288 xmlGenericError(xmlGenericErrorContext, "<p>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000289 if (input != NULL) {
290 if (input->filename) {
291 sprintf(&buffer[strlen(buffer)], "%s:%d: ", input->filename,
292 input->line);
293 } else {
294 sprintf(&buffer[strlen(buffer)], "Entity: line %d: ", input->line);
295 }
296 }
297 xmlHTMLEncodeSend();
298}
299
300/**
301 * xmlHTMLPrintFileContext:
302 * @input: an xmlParserInputPtr input
303 *
304 * Displays current context within the input content for error tracking
305 */
306
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000307static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000308xmlHTMLPrintFileContext(xmlParserInputPtr input) {
309 const xmlChar *cur, *base;
310 int n;
311
312 if (input == NULL) return;
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000313 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000314 cur = input->cur;
315 base = input->base;
316 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
317 cur--;
318 }
319 n = 0;
320 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
321 cur--;
322 if ((*cur == '\n') || (*cur == '\r')) cur++;
323 base = cur;
324 n = 0;
325 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
326 sprintf(&buffer[strlen(buffer)], "%c", (unsigned char) *cur++);
327 n++;
328 }
329 sprintf(&buffer[strlen(buffer)], "\n");
330 cur = input->cur;
331 while ((*cur == '\n') || (*cur == '\r'))
332 cur--;
333 n = 0;
334 while ((cur != base) && (n++ < 80)) {
335 sprintf(&buffer[strlen(buffer)], " ");
336 base++;
337 }
338 sprintf(&buffer[strlen(buffer)],"^\n");
339 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000340 xmlGenericError(xmlGenericErrorContext, "</pre>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000341}
342
343/**
344 * xmlHTMLError:
345 * @ctx: an XML parser context
346 * @msg: the message to display/transmit
347 * @...: extra parameters for the message display
348 *
349 * Display and format an error messages, gives file, line, position and
350 * extra parameters.
351 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000352static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000353xmlHTMLError(void *ctx, const char *msg, ...)
354{
355 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
356 xmlParserInputPtr input;
357 xmlParserInputPtr cur = NULL;
358 va_list args;
359
360 buffer[0] = 0;
361 input = ctxt->input;
362 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
363 cur = input;
364 input = ctxt->inputTab[ctxt->inputNr - 2];
365 }
366
367 xmlHTMLPrintFileInfo(input);
368
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000369 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000370 va_start(args, msg);
371 vsprintf(&buffer[strlen(buffer)], msg, args);
372 va_end(args);
373 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000374 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000375
376 xmlHTMLPrintFileContext(input);
377 xmlHTMLEncodeSend();
378}
379
380/**
381 * xmlHTMLWarning:
382 * @ctx: an XML parser context
383 * @msg: the message to display/transmit
384 * @...: extra parameters for the message display
385 *
386 * Display and format a warning messages, gives file, line, position and
387 * extra parameters.
388 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000389static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000390xmlHTMLWarning(void *ctx, const char *msg, ...)
391{
392 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
393 xmlParserInputPtr input;
394 xmlParserInputPtr cur = NULL;
395 va_list args;
396
397 buffer[0] = 0;
398 input = ctxt->input;
399 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
400 cur = input;
401 input = ctxt->inputTab[ctxt->inputNr - 2];
402 }
403
404
405 xmlHTMLPrintFileInfo(input);
406
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000407 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000408 va_start(args, msg);
409 vsprintf(&buffer[strlen(buffer)], msg, args);
410 va_end(args);
411 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000412 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000413
414 xmlHTMLPrintFileContext(input);
415 xmlHTMLEncodeSend();
416}
417
418/**
419 * xmlHTMLValidityError:
420 * @ctx: an XML parser context
421 * @msg: the message to display/transmit
422 * @...: extra parameters for the message display
423 *
424 * Display and format an validity error messages, gives file,
425 * line, position and extra parameters.
426 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000427static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000428xmlHTMLValidityError(void *ctx, const char *msg, ...)
429{
430 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
431 xmlParserInputPtr input;
432 va_list args;
433
434 buffer[0] = 0;
435 input = ctxt->input;
436 if ((input->filename == NULL) && (ctxt->inputNr > 1))
437 input = ctxt->inputTab[ctxt->inputNr - 2];
438
439 xmlHTMLPrintFileInfo(input);
440
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000441 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000442 va_start(args, msg);
443 vsprintf(&buffer[strlen(buffer)], msg, args);
444 va_end(args);
445 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000446 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000447
448 xmlHTMLPrintFileContext(input);
449 xmlHTMLEncodeSend();
450}
451
452/**
453 * xmlHTMLValidityWarning:
454 * @ctx: an XML parser context
455 * @msg: the message to display/transmit
456 * @...: extra parameters for the message display
457 *
458 * Display and format a validity warning messages, gives file, line,
459 * position and extra parameters.
460 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000461static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000462xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
463{
464 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
465 xmlParserInputPtr input;
466 va_list args;
467
468 buffer[0] = 0;
469 input = ctxt->input;
470 if ((input->filename == NULL) && (ctxt->inputNr > 1))
471 input = ctxt->inputTab[ctxt->inputNr - 2];
472
473 xmlHTMLPrintFileInfo(input);
474
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000475 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000476 va_start(args, msg);
477 vsprintf(&buffer[strlen(buffer)], msg, args);
478 va_end(args);
479 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000480 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000481
482 xmlHTMLPrintFileContext(input);
483 xmlHTMLEncodeSend();
484}
485
486/************************************************************************
487 * *
488 * Shell Interface *
489 * *
490 ************************************************************************/
491/**
492 * xmlShellReadline:
493 * @prompt: the prompt value
494 *
495 * Read a string
496 *
497 * Returns a pointer to it or NULL on EOF the caller is expected to
498 * free the returned string.
499 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000500static char *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000501xmlShellReadline(char *prompt) {
502#ifdef HAVE_LIBREADLINE
503 char *line_read;
504
505 /* Get a line from the user. */
506 line_read = readline (prompt);
507
508 /* If the line has any text in it, save it on the history. */
509 if (line_read && *line_read)
510 add_history (line_read);
511
512 return (line_read);
513#else
514 char line_read[501];
Daniel Veillard29e43992001-12-13 22:21:58 +0000515 char *ret;
516 int len;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000517
518 if (prompt != NULL)
519 fprintf(stdout, "%s", prompt);
520 if (!fgets(line_read, 500, stdin))
521 return(NULL);
522 line_read[500] = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000523 len = strlen(line_read);
524 ret = (char *) malloc(len + 1);
525 if (ret != NULL) {
526 memcpy (ret, line_read, len + 1);
527 }
528 return(ret);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000529#endif
530}
531
532/************************************************************************
533 * *
Daniel Veillard5e873c42000-04-12 13:27:38 +0000534 * I/O Interfaces *
535 * *
536 ************************************************************************/
537
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000538static int myRead(FILE *f, char * buf, int len) {
539 return(fread(buf, 1, len, f));
Daniel Veillard5e873c42000-04-12 13:27:38 +0000540}
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000541static void myClose(FILE *f) {
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000542 if (f != stdin) {
Daniel Veillard5e873c42000-04-12 13:27:38 +0000543 fclose(f);
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000544 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000545}
546
547/************************************************************************
548 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000549 * Test processing *
550 * *
551 ************************************************************************/
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000552static void parseAndPrintFile(char *filename) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000553 xmlDocPtr doc = NULL, tmp;
554
Daniel Veillard48b2f892001-02-25 16:11:03 +0000555 if ((timing) && (!repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +0000556 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000557
558
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000559 if (filename == NULL) {
560 if (generate) {
561 xmlNodePtr n;
562
563 doc = xmlNewDoc(BAD_CAST "1.0");
564 n = xmlNewNode(NULL, BAD_CAST "info");
565 xmlNodeSetContent(n, BAD_CAST "abc");
566 xmlDocSetRootElement(doc, n);
567 }
568 }
Daniel Veillard89cad532001-10-22 09:46:13 +0000569#ifdef LIBXML_DOCB_ENABLED
570 /*
571 * build an SGML tree from a string;
572 */
573 else if ((sgml) && (push)) {
574 FILE *f;
575
576 f = fopen(filename, "r");
577 if (f != NULL) {
578 int res, size = 3;
579 char chars[4096];
580 docbParserCtxtPtr ctxt;
581
582 /* if (repeat) */
583 size = 4096;
584 res = fread(chars, 1, 4, f);
585 if (res > 0) {
586 ctxt = docbCreatePushParserCtxt(NULL, NULL,
587 chars, res, filename, 0);
588 while ((res = fread(chars, 1, size, f)) > 0) {
589 docbParseChunk(ctxt, chars, res, 0);
590 }
591 docbParseChunk(ctxt, chars, 0, 1);
592 doc = ctxt->myDoc;
593 docbFreeParserCtxt(ctxt);
594 }
595 fclose(f);
596 }
597 } else if (sgml) {
598 doc = docbParseFile(filename, NULL);
599 }
600#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000601#ifdef LIBXML_HTML_ENABLED
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000602 else if (html) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000603 doc = htmlParseFile(filename, NULL);
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000604 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000605#endif /* LIBXML_HTML_ENABLED */
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000606 else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000607 /*
608 * build an XML tree from a string;
609 */
610 if (push) {
611 FILE *f;
612
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000613 /* '-' Usually means stdin -<sven@zen.org> */
614 if ((filename[0] == '-') && (filename[1] == 0)) {
615 f = stdin;
616 } else {
617 f = fopen(filename, "r");
618 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000619 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000620 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000621 int res, size = 3;
622 char chars[1024];
623 xmlParserCtxtPtr ctxt;
624
625 if (repeat)
626 size = 1024;
627 res = fread(chars, 1, 4, f);
628 if (res > 0) {
629 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
630 chars, res, filename);
631 while ((res = fread(chars, 1, size, f)) > 0) {
632 xmlParseChunk(ctxt, chars, res, 0);
633 }
634 xmlParseChunk(ctxt, chars, 0, 1);
635 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000636 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000637 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000638 if (!ret) {
639 xmlFreeDoc(doc);
640 doc = NULL;
641 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000642 }
643 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000644 } else if (testIO) {
645 int ret;
646 FILE *f;
647
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000648 /* '-' Usually means stdin -<sven@zen.org> */
649 if ((filename[0] == '-') && (filename[1] == 0)) {
650 f = stdin;
651 } else {
652 f = fopen(filename, "r");
653 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000654 if (f != NULL) {
655 xmlParserCtxtPtr ctxt;
656
657 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
658 (xmlInputReadCallback) myRead,
659 (xmlInputCloseCallback) myClose,
660 f, XML_CHAR_ENCODING_NONE);
661 xmlParseDocument(ctxt);
662
663 ret = ctxt->wellFormed;
664 doc = ctxt->myDoc;
665 xmlFreeParserCtxt(ctxt);
666 if (!ret) {
667 xmlFreeDoc(doc);
668 doc = NULL;
669 }
670 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000671 } else if (recovery) {
672 doc = xmlRecoverFile(filename);
673 } else if (htmlout) {
674 int ret;
675 xmlParserCtxtPtr ctxt;
676 xmlSAXHandler silent, *old;
677
678 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000679
680 if (ctxt == NULL) {
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000681 /* If xmlCreateFileParserCtxt() return NULL something
Daniel Veillard88a172f2000-08-04 18:23:10 +0000682 strange happened so we don't want to do anything. Do
683 we want to print an error message here?
684 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000685 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000686 } else {
687 memcpy(&silent, ctxt->sax, sizeof(silent));
688 old = ctxt->sax;
689 silent.error = xmlHTMLError;
690 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000691 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000692 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000693 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000694 silent.fatalError = xmlHTMLError;
695 ctxt->sax = &silent;
696 ctxt->vctxt.error = xmlHTMLValidityError;
697 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000698 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000699 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000700 ctxt->vctxt.warning = NULL;
701
Daniel Veillard88a172f2000-08-04 18:23:10 +0000702 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000703
Daniel Veillard88a172f2000-08-04 18:23:10 +0000704 ret = ctxt->wellFormed;
705 doc = ctxt->myDoc;
706 ctxt->sax = old;
707 xmlFreeParserCtxt(ctxt);
708 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000709 xmlFreeDoc(doc);
710 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000711 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000712 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000713#ifdef HAVE_SYS_MMAN_H
714 } else if (memory) {
715 int fd;
716 struct stat info;
717 const char *base;
718 if (stat(filename, &info) < 0)
719 return;
720 if ((fd = open(filename, O_RDONLY)) < 0)
721 return;
722 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000723 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000724 return;
725
726 doc = xmlParseMemory((char *) base, info.st_size);
727 munmap((char *) base, info.st_size);
728#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000729 } else
730 doc = xmlParseFile(filename);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000731 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000732
Daniel Veillard88a172f2000-08-04 18:23:10 +0000733 /*
734 * If we don't have a document we might as well give up. Do we
735 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000736 if (doc == NULL) {
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000737 progresult = 1;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000738 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000739 }
740
Daniel Veillard48b2f892001-02-25 16:11:03 +0000741 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000742 endTimer("Parsing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000743 }
744
Daniel Veillard29e43992001-12-13 22:21:58 +0000745 /*
746 * Remove DOCTYPE nodes
747 */
748 if (dropdtd) {
749 xmlDtdPtr dtd;
750
751 dtd = xmlGetIntSubset(doc);
752 if (dtd != NULL) {
753 xmlUnlinkNode((xmlNodePtr)dtd);
754 xmlFreeDtd(dtd);
755 }
756 }
757
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000758#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard48b2f892001-02-25 16:11:03 +0000759 if (xinclude) {
760 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000761 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000762 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000763 xmlXIncludeProcess(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000764 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000765 endTimer("Xinclude processing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000766 }
767 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000768#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000769
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000770#ifdef LIBXML_DEBUG_ENABLED
771 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000772 * shell interaction
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000773 */
774 if (shell)
775 xmlShell(doc, filename, xmlShellReadline, stdout);
776#endif
777
778 /*
779 * test intermediate copy if needed.
780 */
781 if (copy) {
782 tmp = doc;
783 doc = xmlCopyDoc(doc, 1);
784 xmlFreeDoc(tmp);
785 }
786
787 if ((insert) && (!html)) {
788 const xmlChar* list[256];
789 int nb, i;
790 xmlNodePtr node;
791
792 if (doc->children != NULL) {
793 node = doc->children;
794 while ((node != NULL) && (node->last == NULL)) node = node->next;
795 if (node != NULL) {
796 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
797 if (nb < 0) {
798 printf("could not get valid list of elements\n");
799 } else if (nb == 0) {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000800 printf("No element can be inserted under root\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000801 } else {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000802 printf("%d element types can be inserted under root:\n",
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000803 nb);
804 for (i = 0;i < nb;i++) {
805 printf("%s\n", list[i]);
806 }
807 }
808 }
809 }
810 }else if (noout == 0) {
811 /*
812 * print it.
813 */
814#ifdef LIBXML_DEBUG_ENABLED
815 if (!debug) {
816#endif
Daniel Veillard48b2f892001-02-25 16:11:03 +0000817 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000818 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000819 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000820#ifdef HAVE_SYS_MMAN_H
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000821 if (memory) {
822 xmlChar *result;
823 int len;
824
825 if (encoding != NULL) {
Daniel Veillardd536f702001-11-08 17:32:47 +0000826 if ( format ) {
827 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
828 } else {
829 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
830 }
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000831 } else {
Daniel Veillard90493a92001-08-14 14:12:47 +0000832 if (format)
833 xmlDocDumpFormatMemory(doc, &result, &len, 1);
834 else
835 xmlDocDumpMemory(doc, &result, &len);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000836 }
837 if (result == NULL) {
838 fprintf(stderr, "Failed to save\n");
839 } else {
840 write(1, result, len);
841 xmlFree(result);
842 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000843 } else
844#endif /* HAVE_SYS_MMAN_H */
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000845 if (compress) {
846 xmlSaveFile(output ? output : "-", doc);
847 }
Daniel Veillardd536f702001-11-08 17:32:47 +0000848 else if (encoding != NULL) {
849 if ( format ) {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000850 xmlSaveFormatFileEnc(output ? output : "-", doc, encoding, 1);
851 }
Daniel Veillardd536f702001-11-08 17:32:47 +0000852 else {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000853 xmlSaveFileEnc(output ? output : "-", doc, encoding);
Daniel Veillardd536f702001-11-08 17:32:47 +0000854 }
855 }
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000856 else if (format) {
857 xmlSaveFormatFile(output ? output : "-", doc, 1);
858 }
859 else {
860 FILE *out;
861 if (output == NULL)
862 out = stdout;
863 else {
864 out = fopen(output,"wb");
865 }
866 xmlDocDump(out, doc);
867
868 if (output)
869 fclose(out);
870 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000871 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000872 endTimer("Saving");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000873 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000874#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000875 } else {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000876 FILE *out;
877 if (output == NULL)
878 out = stdout;
879 else {
880 out = fopen(output,"wb");
881 }
882 xmlDebugDumpDocument(out, doc);
883
884 if (output)
885 fclose(out);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000886 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000887#endif
888 }
889
890 /*
891 * A posteriori validation test
892 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000893 if (dtdvalid != NULL) {
894 xmlDtdPtr dtd;
895
Daniel Veillard48b2f892001-02-25 16:11:03 +0000896 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000897 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000898 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000899 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000900 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000901 endTimer("Parsing DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000902 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000903 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000904 xmlGenericError(xmlGenericErrorContext,
905 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000906 progresult = 2;
Daniel Veillardcd429612000-10-11 15:57:05 +0000907 } else {
908 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000909 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000910 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000911 }
Daniel Veillard01db67c2001-12-18 07:09:59 +0000912 cvp.userData = (void *) stderr;
913 cvp.error = (xmlValidityErrorFunc) fprintf;
914 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000915 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000916 xmlGenericError(xmlGenericErrorContext,
917 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000918 filename, dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000919 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000920 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000921 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000922 endTimer("Validating against DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000923 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000924 xmlFreeDtd(dtd);
925 }
926 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000927 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000928 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000929 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000930 }
Daniel Veillardb7664f42001-08-19 13:00:43 +0000931 cvp.userData = (void *) stderr;
932 cvp.error = (xmlValidityErrorFunc) fprintf;
933 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000934 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000935 xmlGenericError(xmlGenericErrorContext,
936 "Document %s does not validate\n", filename);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000937 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000938 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000939 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000940 endTimer("Validating");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000941 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000942 }
943
944#ifdef LIBXML_DEBUG_ENABLED
945 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000946 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000947#endif
948
949 /*
950 * free it.
951 */
Daniel Veillard48b2f892001-02-25 16:11:03 +0000952 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000953 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000954 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000955 xmlFreeDoc(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000956 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000957 endTimer("Freeing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000958 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000959}
960
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000961/************************************************************************
962 * *
963 * Usage and Main *
964 * *
965 ************************************************************************/
966
967static void usage(const char *name) {
968 printf("Usage : %s [options] XMLfiles ...\n", name);
969 printf("\tParse the XML files and output the result of the parsing\n");
970 printf("\t--version : display the version of the XML library used\n");
971#ifdef LIBXML_DEBUG_ENABLED
972 printf("\t--debug : dump a debug tree of the in-memory document\n");
973 printf("\t--shell : run a navigating shell\n");
974 printf("\t--debugent : debug the entities defined in the document\n");
975#endif
976 printf("\t--copy : used to test the internal copy implementation\n");
977 printf("\t--recover : output what was parsable on broken XML documents\n");
978 printf("\t--noent : substitute entity references by their value\n");
979 printf("\t--noout : don't output the result tree\n");
980 printf("\t--htmlout : output results as HTML\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000981 printf("\t--nowrap : do not put HTML doc wrapper\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000982 printf("\t--valid : validate the document in addition to std well-formed check\n");
983 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
984 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
985 printf("\t--timing : print some timings\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000986 printf("\t--output file or -o file: save to a given file\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000987 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
988 printf("\t--insert : ad-hoc test for valid insertions\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000989#ifdef HAVE_ZLIB_H
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000990 printf("\t--compress : turn on gzip compression of output\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000991#endif
Daniel Veillard89cad532001-10-22 09:46:13 +0000992#ifdef LIBXML_DOCB_ENABLED
993 printf("\t--sgml : use the DocBook SGML parser\n");
994#endif
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000995#ifdef LIBXML_HTML_ENABLED
996 printf("\t--html : use the HTML parser\n");
997#endif
998 printf("\t--push : use the push mode of the parser\n");
999#ifdef HAVE_SYS_MMAN_H
1000 printf("\t--memory : parse from memory\n");
1001#endif
1002 printf("\t--nowarning : do not emit warnings from parser/validator\n");
1003 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard90493a92001-08-14 14:12:47 +00001004 printf("\t--format : reformat/reindent the input\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001005 printf("\t--testIO : test user I/O support\n");
1006 printf("\t--encode encoding : output in the given encoding\n");
1007#ifdef LIBXML_CATALOG_ENABLED
Daniel Veillardbd9b0e82001-11-26 10:32:08 +00001008 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
1009 printf("\t otherwise XML Catalogs starting from \n");
1010 printf("\t file:///etc/xml/catalog are activated by default\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +00001011 printf("\t--nocatalogs: deactivate all catalogs\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001012#endif
1013 printf("\t--auto : generate a small doc on the fly\n");
1014#ifdef LIBXML_XINCLUDE_ENABLED
1015 printf("\t--xinclude : do XInclude processing\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001016#endif
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001017 printf("\t--loaddtd : fetch external DTD\n");
Daniel Veillard48da9102001-08-07 01:10:10 +00001018 printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
Daniel Veillard29e43992001-12-13 22:21:58 +00001019 printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
Daniel Veillarda42f25f2002-01-25 14:15:40 +00001020 printf("\nLibxml project home page: http://xmlsoft.org/\n");
1021 printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001022}
Daniel Veillard4a6845d2001-01-03 13:32:39 +00001023int
1024main(int argc, char **argv) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001025 int i, count;
1026 int files = 0;
Daniel Veillard845cce42002-01-09 11:51:37 +00001027 int version = 0;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001028
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001029 if (argc <= 1) {
1030 usage(argv[0]);
1031 return(1);
1032 }
Daniel Veillardbe803962000-06-28 23:40:59 +00001033 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001034 for (i = 1; i < argc ; i++) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001035 if (!strcmp(argv[i], "-"))
1036 break;
1037
1038 if (argv[i][0] != '-')
1039 continue;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001040#ifdef LIBXML_DEBUG_ENABLED
1041 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
1042 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001043 else if ((!strcmp(argv[i], "-shell")) ||
1044 (!strcmp(argv[i], "--shell"))) {
1045 shell++;
1046 noout = 1;
1047 } else
1048#endif
1049 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
1050 copy++;
1051 else if ((!strcmp(argv[i], "-recover")) ||
1052 (!strcmp(argv[i], "--recover")))
1053 recovery++;
1054 else if ((!strcmp(argv[i], "-noent")) ||
1055 (!strcmp(argv[i], "--noent")))
1056 noent++;
Daniel Veillard4ec885a2001-06-17 10:31:07 +00001057 else if ((!strcmp(argv[i], "-version")) ||
Daniel Veillard845cce42002-01-09 11:51:37 +00001058 (!strcmp(argv[i], "--version"))) {
Daniel Veillard4ec885a2001-06-17 10:31:07 +00001059 fprintf(stderr, "xmllint: using libxml version %s\n",
1060 xmlParserVersion);
Daniel Veillard845cce42002-01-09 11:51:37 +00001061 version = 1;
1062 } else if ((!strcmp(argv[i], "-noout")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001063 (!strcmp(argv[i], "--noout")))
1064 noout++;
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001065 else if ((!strcmp(argv[i], "-o")) ||
1066 (!strcmp(argv[i], "-output")) ||
1067 (!strcmp(argv[i], "--output"))) {
1068 i++;
Daniel Veillard6e4f1c02002-04-09 09:55:20 +00001069 output = argv[i];
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001070 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001071 else if ((!strcmp(argv[i], "-htmlout")) ||
1072 (!strcmp(argv[i], "--htmlout")))
1073 htmlout++;
Daniel Veillard89cad532001-10-22 09:46:13 +00001074#ifdef LIBXML_DOCB_ENABLED
1075 else if ((!strcmp(argv[i], "-sgml")) ||
1076 (!strcmp(argv[i], "--sgml"))) {
1077 sgml++;
1078 }
1079#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001080#ifdef LIBXML_HTML_ENABLED
1081 else if ((!strcmp(argv[i], "-html")) ||
1082 (!strcmp(argv[i], "--html"))) {
1083 html++;
1084 }
1085#endif /* LIBXML_HTML_ENABLED */
1086 else if ((!strcmp(argv[i], "-nowrap")) ||
1087 (!strcmp(argv[i], "--nowrap")))
1088 nowrap++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001089 else if ((!strcmp(argv[i], "-loaddtd")) ||
1090 (!strcmp(argv[i], "--loaddtd")))
1091 loaddtd++;
Daniel Veillard48da9102001-08-07 01:10:10 +00001092 else if ((!strcmp(argv[i], "-dtdattr")) ||
1093 (!strcmp(argv[i], "--dtdattr"))) {
1094 loaddtd++;
1095 dtdattrs++;
1096 } else if ((!strcmp(argv[i], "-valid")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001097 (!strcmp(argv[i], "--valid")))
1098 valid++;
1099 else if ((!strcmp(argv[i], "-postvalid")) ||
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001100 (!strcmp(argv[i], "--postvalid"))) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001101 postvalid++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001102 loaddtd++;
1103 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
Daniel Veillardcd429612000-10-11 15:57:05 +00001104 (!strcmp(argv[i], "--dtdvalid"))) {
1105 i++;
1106 dtdvalid = argv[i];
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001107 loaddtd++;
Daniel Veillardcd429612000-10-11 15:57:05 +00001108 }
Daniel Veillard29e43992001-12-13 22:21:58 +00001109 else if ((!strcmp(argv[i], "-dropdtd")) ||
1110 (!strcmp(argv[i], "--dropdtd")))
1111 dropdtd++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001112 else if ((!strcmp(argv[i], "-insert")) ||
1113 (!strcmp(argv[i], "--insert")))
1114 insert++;
Daniel Veillard48b2f892001-02-25 16:11:03 +00001115 else if ((!strcmp(argv[i], "-timing")) ||
1116 (!strcmp(argv[i], "--timing")))
1117 timing++;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001118 else if ((!strcmp(argv[i], "-auto")) ||
1119 (!strcmp(argv[i], "--auto")))
1120 generate++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001121 else if ((!strcmp(argv[i], "-repeat")) ||
1122 (!strcmp(argv[i], "--repeat")))
1123 repeat++;
1124 else if ((!strcmp(argv[i], "-push")) ||
1125 (!strcmp(argv[i], "--push")))
1126 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +00001127#ifdef HAVE_SYS_MMAN_H
1128 else if ((!strcmp(argv[i], "-memory")) ||
1129 (!strcmp(argv[i], "--memory")))
1130 memory++;
1131#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +00001132 else if ((!strcmp(argv[i], "-testIO")) ||
1133 (!strcmp(argv[i], "--testIO")))
1134 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +00001135#ifdef LIBXML_XINCLUDE_ENABLED
1136 else if ((!strcmp(argv[i], "-xinclude")) ||
1137 (!strcmp(argv[i], "--xinclude")))
1138 xinclude++;
1139#endif
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001140#ifdef HAVE_ZLIB_H
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001141 else if ((!strcmp(argv[i], "-compress")) ||
1142 (!strcmp(argv[i], "--compress"))) {
1143 compress++;
1144 xmlSetCompressMode(9);
1145 }
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001146#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001147 else if ((!strcmp(argv[i], "-nowarning")) ||
1148 (!strcmp(argv[i], "--nowarning"))) {
1149 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001150 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001151 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001152 else if ((!strcmp(argv[i], "-pedantic")) ||
1153 (!strcmp(argv[i], "--pedantic"))) {
1154 xmlGetWarningsDefaultValue = 1;
1155 xmlPedanticParserDefault(1);
1156 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001157#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001158 else if ((!strcmp(argv[i], "-debugent")) ||
1159 (!strcmp(argv[i], "--debugent"))) {
1160 debugent++;
1161 xmlParserDebugEntities = 1;
1162 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001163#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00001164#ifdef LIBXML_CATALOG_ENABLED
1165 else if ((!strcmp(argv[i], "-catalogs")) ||
1166 (!strcmp(argv[i], "--catalogs"))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001167 catalogs++;
1168 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
1169 (!strcmp(argv[i], "--nocatalogs"))) {
1170 nocatalogs++;
Daniel Veillard81418e32001-05-22 15:08:55 +00001171 }
1172#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001173 else if ((!strcmp(argv[i], "-encode")) ||
1174 (!strcmp(argv[i], "--encode"))) {
1175 i++;
1176 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001177 /*
1178 * OK it's for testing purposes
1179 */
1180 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +00001181 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001182 else if ((!strcmp(argv[i], "-noblanks")) ||
1183 (!strcmp(argv[i], "--noblanks"))) {
1184 noblanks++;
1185 xmlKeepBlanksDefault(0);
Daniel Veillard90493a92001-08-14 14:12:47 +00001186 }
1187 else if ((!strcmp(argv[i], "-format")) ||
1188 (!strcmp(argv[i], "--format"))) {
1189 noblanks++;
1190 format++;
1191 xmlKeepBlanksDefault(0);
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001192 } else {
1193 fprintf(stderr, "Unknown option %s\n", argv[i]);
1194 usage(argv[0]);
1195 return(1);
1196 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001197 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001198
1199#ifdef LIBXML_CATALOG_ENABLED
1200 if (nocatalogs == 0) {
1201 if (catalogs) {
1202 const char *catal;
1203
1204 catal = getenv("SGML_CATALOG_FILES");
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00001205 if (catal != NULL) {
1206 xmlLoadCatalogs(catal);
1207 } else {
1208 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
1209 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001210 }
1211 }
1212#endif
Daniel Veillardd9bad132001-07-23 19:39:43 +00001213 xmlLineNumbersDefault(1);
Daniel Veillard48da9102001-08-07 01:10:10 +00001214 if (loaddtd != 0)
1215 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1216 if (dtdattrs)
1217 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001218 if (noent != 0) xmlSubstituteEntitiesDefault(1);
1219 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1220 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001221 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001222 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001223 xmlGenericError(xmlGenericErrorContext,
1224 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
1225 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001226 "<html><head><title>%s output</title></head>\n",
1227 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001228 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001229 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
1230 argv[0]);
1231 }
1232 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +00001233 if ((!strcmp(argv[i], "-encode")) ||
1234 (!strcmp(argv[i], "--encode"))) {
1235 i++;
1236 continue;
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001237 } else if ((!strcmp(argv[i], "-o")) ||
1238 (!strcmp(argv[i], "-output")) ||
1239 (!strcmp(argv[i], "--output"))) {
1240 i++;
1241 continue;
Daniel Veillardbe803962000-06-28 23:40:59 +00001242 }
Daniel Veillardcd429612000-10-11 15:57:05 +00001243 if ((!strcmp(argv[i], "-dtdvalid")) ||
1244 (!strcmp(argv[i], "--dtdvalid"))) {
1245 i++;
1246 continue;
1247 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001248 if ((timing) && (repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +00001249 startTimer();
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001250 /* Remember file names. "-" means stdin. <sven@zen.org> */
Daniel Veillard4a6845d2001-01-03 13:32:39 +00001251 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001252 if (repeat) {
1253 for (count = 0;count < 100 * repeat;count++)
1254 parseAndPrintFile(argv[i]);
1255 } else
1256 parseAndPrintFile(argv[i]);
1257 files ++;
Daniel Veillarda7866932001-12-04 13:14:44 +00001258 if ((timing) && (repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +00001259 endTimer("100 iterations");
Daniel Veillarda7866932001-12-04 13:14:44 +00001260 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001261 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001262 }
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001263 if (generate)
1264 parseAndPrintFile(NULL);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001265 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001266 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001267 }
Daniel Veillard845cce42002-01-09 11:51:37 +00001268 if ((files == 0) && (!generate) && (version == 0)) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001269 usage(argv[0]);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001270 }
1271 xmlCleanupParser();
Daniel Veillard97300512002-03-01 09:13:41 +00001272#ifdef WITH_MEM_DEBUG
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001273 xmlMemoryDump();
Daniel Veillard97300512002-03-01 09:13:41 +00001274#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001275
Daniel Veillardf7cd4812001-02-23 18:44:52 +00001276 return(progresult);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001277}
Daniel Veillard88a172f2000-08-04 18:23:10 +00001278