blob: 28391091cbc3a2b395fef3317ecce08f4db4ceb1 [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 Veillardce8b83b2000-04-05 18:38:42 +000032
33#ifdef HAVE_SYS_TYPES_H
34#include <sys/types.h>
35#endif
36#ifdef HAVE_SYS_STAT_H
37#include <sys/stat.h>
38#endif
39#ifdef HAVE_FCNTL_H
40#include <fcntl.h>
41#endif
42#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000045#ifdef HAVE_SYS_MMAN_H
46#include <sys/mman.h>
Daniel Veillard87b95392000-08-12 21:12:04 +000047/* seems needed for Solaris */
48#ifndef MAP_FAILED
49#define MAP_FAILED ((void *) -1)
50#endif
Daniel Veillard46e370e2000-07-21 20:32:03 +000051#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +000052#ifdef HAVE_STDLIB_H
53#include <stdlib.h>
54#endif
55#ifdef HAVE_LIBREADLINE
56#include <readline/readline.h>
57#ifdef HAVE_LIBHISTORY
58#include <readline/history.h>
59#endif
60#endif
61
62#include <libxml/xmlmemory.h>
63#include <libxml/parser.h>
64#include <libxml/parserInternals.h>
65#include <libxml/HTMLparser.h>
66#include <libxml/HTMLtree.h>
67#include <libxml/tree.h>
68#include <libxml/xpath.h>
69#include <libxml/debugXML.h>
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +000070#include <libxml/xmlerror.h>
Daniel Veillard9e8bfae2000-11-06 16:43:11 +000071#ifdef LIBXML_XINCLUDE_ENABLED
72#include <libxml/xinclude.h>
73#endif
Daniel Veillard81418e32001-05-22 15:08:55 +000074#ifdef LIBXML_CATALOG_ENABLED
75#include <libxml/catalog.h>
76#endif
Daniel Veillard89cad532001-10-22 09:46:13 +000077#ifdef LIBXML_DOCB_ENABLED
78#include <libxml/DOCBparser.h>
79#endif
Daniel Veillard3c01b1d2001-10-17 15:58:35 +000080#include <libxml/globals.h>
Daniel Veillardce8b83b2000-04-05 18:38:42 +000081
82#ifdef LIBXML_DEBUG_ENABLED
83static int debug = 0;
84static int shell = 0;
85static int debugent = 0;
86#endif
87static int copy = 0;
88static int recovery = 0;
89static int noent = 0;
90static int noout = 0;
91static int nowrap = 0;
92static int valid = 0;
93static int postvalid = 0;
Daniel Veillardcd429612000-10-11 15:57:05 +000094static char * dtdvalid = NULL;
Daniel Veillardce8b83b2000-04-05 18:38:42 +000095static int repeat = 0;
96static int insert = 0;
97static int compress = 0;
Daniel Veillard89cad532001-10-22 09:46:13 +000098#ifdef LIBXML_DOCB_ENABLED
99static int sgml = 0;
100#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000101static int html = 0;
102static int htmlout = 0;
103static int push = 0;
Daniel Veillard46e370e2000-07-21 20:32:03 +0000104#ifdef HAVE_SYS_MMAN_H
105static int memory = 0;
106#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000107static int noblanks = 0;
Daniel Veillard90493a92001-08-14 14:12:47 +0000108static int format = 0;
Daniel Veillard5e873c42000-04-12 13:27:38 +0000109static int testIO = 0;
Daniel Veillardbe803962000-06-28 23:40:59 +0000110static char *encoding = NULL;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000111#ifdef LIBXML_XINCLUDE_ENABLED
112static int xinclude = 0;
113#endif
Daniel Veillard48da9102001-08-07 01:10:10 +0000114static int dtdattrs = 0;
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000115static int loaddtd = 0;
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000116static int progresult = 0;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000117static int timing = 0;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000118static int generate = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000119static int dropdtd = 0;
Daniel Veillarde2940dd2001-08-22 00:06:49 +0000120#ifdef LIBXML_CATALOG_ENABLED
121static int catalogs = 0;
122static int nocatalogs = 0;
123#endif
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000124static const char *output = NULL;
125
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000126
Daniel Veillard01db67c2001-12-18 07:09:59 +0000127/*
128 * Internal timing routines to remove the necessity to have unix-specific
129 * function calls
130 */
131
132#if defined(HAVE_GETTIMEOFDAY)
133static struct timeval begin, end;
134
135/*
136 * startTimer: call where you want to start timing
137 */
138static void
139startTimer(void)
140{
141 gettimeofday(&begin, NULL);
142}
143
144/*
145 * endTimer: call where you want to stop timing and to print out a
146 * message about the timing performed; format is a printf
147 * type argument
148 */
149static void
150endTimer(const char *format, ...)
151{
152 long msec;
153 va_list ap;
154
155 gettimeofday(&end, NULL);
156 msec = end.tv_sec - begin.tv_sec;
157 msec *= 1000;
158 msec += (end.tv_usec - begin.tv_usec) / 1000;
159
160#ifndef HAVE_STDARG_H
161#error "endTimer required stdarg functions"
162#endif
163 va_start(ap, format);
164 vfprintf(stderr, format, ap);
165 va_end(ap);
166
167 fprintf(stderr, " took %ld ms\n", msec);
168}
169#elif defined(HAVE_TIME_H)
170
171/*
172 * No gettimeofday function, so we have to make do with calling clock.
173 * This is obviously less accurate, but there's little we can do about
174 * that.
175 */
176
177static clock_t begin, end;
178static void
179startTimer(void)
180{
181 begin = clock();
182}
183static void
184endTimer(const char *fmt, ...)
185{
186 long msec;
187 va_list ap;
188
189 end = clock();
190 msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
191
192#ifndef HAVE_STDARG_H
193#error "endTimer required stdarg functions"
194#endif
195 va_start(ap, fmt);
196 vfprintf(stderr, fmt, ap);
197 va_end(ap);
198 fprintf(stderr, " took %ld ms\n", msec);
199}
200#else
201
202/*
203 * We don't have a gettimeofday or time.h, so we just don't do timing
204 */
205static void
206startTimer(void)
207{
208 /*
209 * Do nothing
210 */
211}
212static void
213endTimer(char *format, ...)
214{
215 /*
216 * We cannot do anything because we don't have a timing function
217 */
218#ifdef HAVE_STDARG_H
219 va_start(ap, format);
220 vfprintf(stderr, format, ap);
221 va_end(ap);
222 fprintf(stderr, " was not timed\n", msec);
223#else
224 /* We don't have gettimeofday, time or stdarg.h, what crazy world is
225 * this ?!
226 */
227#endif
228}
229#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000230/************************************************************************
231 * *
232 * HTML ouput *
233 * *
234 ************************************************************************/
235char buffer[50000];
236
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000237static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000238xmlHTMLEncodeSend(void) {
239 char *result;
240
241 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
242 if (result) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000243 xmlGenericError(xmlGenericErrorContext, "%s", result);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000244 xmlFree(result);
245 }
246 buffer[0] = 0;
247}
248
249/**
250 * xmlHTMLPrintFileInfo:
251 * @input: an xmlParserInputPtr input
252 *
253 * Displays the associated file and line informations for the current input
254 */
255
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000256static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000257xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000258 xmlGenericError(xmlGenericErrorContext, "<p>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000259 if (input != NULL) {
260 if (input->filename) {
261 sprintf(&buffer[strlen(buffer)], "%s:%d: ", input->filename,
262 input->line);
263 } else {
264 sprintf(&buffer[strlen(buffer)], "Entity: line %d: ", input->line);
265 }
266 }
267 xmlHTMLEncodeSend();
268}
269
270/**
271 * xmlHTMLPrintFileContext:
272 * @input: an xmlParserInputPtr input
273 *
274 * Displays current context within the input content for error tracking
275 */
276
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000277static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000278xmlHTMLPrintFileContext(xmlParserInputPtr input) {
279 const xmlChar *cur, *base;
280 int n;
281
282 if (input == NULL) return;
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000283 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000284 cur = input->cur;
285 base = input->base;
286 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
287 cur--;
288 }
289 n = 0;
290 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
291 cur--;
292 if ((*cur == '\n') || (*cur == '\r')) cur++;
293 base = cur;
294 n = 0;
295 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
296 sprintf(&buffer[strlen(buffer)], "%c", (unsigned char) *cur++);
297 n++;
298 }
299 sprintf(&buffer[strlen(buffer)], "\n");
300 cur = input->cur;
301 while ((*cur == '\n') || (*cur == '\r'))
302 cur--;
303 n = 0;
304 while ((cur != base) && (n++ < 80)) {
305 sprintf(&buffer[strlen(buffer)], " ");
306 base++;
307 }
308 sprintf(&buffer[strlen(buffer)],"^\n");
309 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000310 xmlGenericError(xmlGenericErrorContext, "</pre>");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000311}
312
313/**
314 * xmlHTMLError:
315 * @ctx: an XML parser context
316 * @msg: the message to display/transmit
317 * @...: extra parameters for the message display
318 *
319 * Display and format an error messages, gives file, line, position and
320 * extra parameters.
321 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000322static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000323xmlHTMLError(void *ctx, const char *msg, ...)
324{
325 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
326 xmlParserInputPtr input;
327 xmlParserInputPtr cur = NULL;
328 va_list args;
329
330 buffer[0] = 0;
331 input = ctxt->input;
332 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
333 cur = input;
334 input = ctxt->inputTab[ctxt->inputNr - 2];
335 }
336
337 xmlHTMLPrintFileInfo(input);
338
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000339 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000340 va_start(args, msg);
341 vsprintf(&buffer[strlen(buffer)], msg, args);
342 va_end(args);
343 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000344 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000345
346 xmlHTMLPrintFileContext(input);
347 xmlHTMLEncodeSend();
348}
349
350/**
351 * xmlHTMLWarning:
352 * @ctx: an XML parser context
353 * @msg: the message to display/transmit
354 * @...: extra parameters for the message display
355 *
356 * Display and format a warning messages, gives file, line, position and
357 * extra parameters.
358 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000359static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000360xmlHTMLWarning(void *ctx, const char *msg, ...)
361{
362 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
363 xmlParserInputPtr input;
364 xmlParserInputPtr cur = NULL;
365 va_list args;
366
367 buffer[0] = 0;
368 input = ctxt->input;
369 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
370 cur = input;
371 input = ctxt->inputTab[ctxt->inputNr - 2];
372 }
373
374
375 xmlHTMLPrintFileInfo(input);
376
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000377 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000378 va_start(args, msg);
379 vsprintf(&buffer[strlen(buffer)], msg, args);
380 va_end(args);
381 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000382 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000383
384 xmlHTMLPrintFileContext(input);
385 xmlHTMLEncodeSend();
386}
387
388/**
389 * xmlHTMLValidityError:
390 * @ctx: an XML parser context
391 * @msg: the message to display/transmit
392 * @...: extra parameters for the message display
393 *
394 * Display and format an validity error messages, gives file,
395 * line, position and extra parameters.
396 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000397static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000398xmlHTMLValidityError(void *ctx, const char *msg, ...)
399{
400 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
401 xmlParserInputPtr input;
402 va_list args;
403
404 buffer[0] = 0;
405 input = ctxt->input;
406 if ((input->filename == NULL) && (ctxt->inputNr > 1))
407 input = ctxt->inputTab[ctxt->inputNr - 2];
408
409 xmlHTMLPrintFileInfo(input);
410
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000411 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000412 va_start(args, msg);
413 vsprintf(&buffer[strlen(buffer)], msg, args);
414 va_end(args);
415 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000416 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000417
418 xmlHTMLPrintFileContext(input);
419 xmlHTMLEncodeSend();
420}
421
422/**
423 * xmlHTMLValidityWarning:
424 * @ctx: an XML parser context
425 * @msg: the message to display/transmit
426 * @...: extra parameters for the message display
427 *
428 * Display and format a validity warning messages, gives file, line,
429 * position and extra parameters.
430 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000431static void
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000432xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
433{
434 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
435 xmlParserInputPtr input;
436 va_list args;
437
438 buffer[0] = 0;
439 input = ctxt->input;
440 if ((input->filename == NULL) && (ctxt->inputNr > 1))
441 input = ctxt->inputTab[ctxt->inputNr - 2];
442
443 xmlHTMLPrintFileInfo(input);
444
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000445 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000446 va_start(args, msg);
447 vsprintf(&buffer[strlen(buffer)], msg, args);
448 va_end(args);
449 xmlHTMLEncodeSend();
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000450 xmlGenericError(xmlGenericErrorContext, "</p>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000451
452 xmlHTMLPrintFileContext(input);
453 xmlHTMLEncodeSend();
454}
455
456/************************************************************************
457 * *
458 * Shell Interface *
459 * *
460 ************************************************************************/
461/**
462 * xmlShellReadline:
463 * @prompt: the prompt value
464 *
465 * Read a string
466 *
467 * Returns a pointer to it or NULL on EOF the caller is expected to
468 * free the returned string.
469 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000470static char *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000471xmlShellReadline(char *prompt) {
472#ifdef HAVE_LIBREADLINE
473 char *line_read;
474
475 /* Get a line from the user. */
476 line_read = readline (prompt);
477
478 /* If the line has any text in it, save it on the history. */
479 if (line_read && *line_read)
480 add_history (line_read);
481
482 return (line_read);
483#else
484 char line_read[501];
Daniel Veillard29e43992001-12-13 22:21:58 +0000485 char *ret;
486 int len;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000487
488 if (prompt != NULL)
489 fprintf(stdout, "%s", prompt);
490 if (!fgets(line_read, 500, stdin))
491 return(NULL);
492 line_read[500] = 0;
Daniel Veillard29e43992001-12-13 22:21:58 +0000493 len = strlen(line_read);
494 ret = (char *) malloc(len + 1);
495 if (ret != NULL) {
496 memcpy (ret, line_read, len + 1);
497 }
498 return(ret);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000499#endif
500}
501
502/************************************************************************
503 * *
Daniel Veillard5e873c42000-04-12 13:27:38 +0000504 * I/O Interfaces *
505 * *
506 ************************************************************************/
507
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000508static int myRead(FILE *f, char * buf, int len) {
509 return(fread(buf, 1, len, f));
Daniel Veillard5e873c42000-04-12 13:27:38 +0000510}
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000511static void myClose(FILE *f) {
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000512 if (f != stdin) {
Daniel Veillard5e873c42000-04-12 13:27:38 +0000513 fclose(f);
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000514 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000515}
516
517/************************************************************************
518 * *
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000519 * Test processing *
520 * *
521 ************************************************************************/
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000522static void parseAndPrintFile(char *filename) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000523 xmlDocPtr doc = NULL, tmp;
524
Daniel Veillard48b2f892001-02-25 16:11:03 +0000525 if ((timing) && (!repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +0000526 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000527
528
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000529 if (filename == NULL) {
530 if (generate) {
531 xmlNodePtr n;
532
533 doc = xmlNewDoc(BAD_CAST "1.0");
534 n = xmlNewNode(NULL, BAD_CAST "info");
535 xmlNodeSetContent(n, BAD_CAST "abc");
536 xmlDocSetRootElement(doc, n);
537 }
538 }
Daniel Veillard89cad532001-10-22 09:46:13 +0000539#ifdef LIBXML_DOCB_ENABLED
540 /*
541 * build an SGML tree from a string;
542 */
543 else if ((sgml) && (push)) {
544 FILE *f;
545
546 f = fopen(filename, "r");
547 if (f != NULL) {
548 int res, size = 3;
549 char chars[4096];
550 docbParserCtxtPtr ctxt;
551
552 /* if (repeat) */
553 size = 4096;
554 res = fread(chars, 1, 4, f);
555 if (res > 0) {
556 ctxt = docbCreatePushParserCtxt(NULL, NULL,
557 chars, res, filename, 0);
558 while ((res = fread(chars, 1, size, f)) > 0) {
559 docbParseChunk(ctxt, chars, res, 0);
560 }
561 docbParseChunk(ctxt, chars, 0, 1);
562 doc = ctxt->myDoc;
563 docbFreeParserCtxt(ctxt);
564 }
565 fclose(f);
566 }
567 } else if (sgml) {
568 doc = docbParseFile(filename, NULL);
569 }
570#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000571#ifdef LIBXML_HTML_ENABLED
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000572 else if (html) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000573 doc = htmlParseFile(filename, NULL);
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000574 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000575#endif /* LIBXML_HTML_ENABLED */
Daniel Veillardd2f3ec72001-04-11 07:50:02 +0000576 else {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000577 /*
578 * build an XML tree from a string;
579 */
580 if (push) {
581 FILE *f;
582
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000583 /* '-' Usually means stdin -<sven@zen.org> */
584 if ((filename[0] == '-') && (filename[1] == 0)) {
585 f = stdin;
586 } else {
587 f = fopen(filename, "r");
588 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000589 if (f != NULL) {
Daniel Veillarde715dd22000-08-29 18:29:38 +0000590 int ret;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000591 int res, size = 3;
592 char chars[1024];
593 xmlParserCtxtPtr ctxt;
594
595 if (repeat)
596 size = 1024;
597 res = fread(chars, 1, 4, f);
598 if (res > 0) {
599 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
600 chars, res, filename);
601 while ((res = fread(chars, 1, size, f)) > 0) {
602 xmlParseChunk(ctxt, chars, res, 0);
603 }
604 xmlParseChunk(ctxt, chars, 0, 1);
605 doc = ctxt->myDoc;
Daniel Veillarde715dd22000-08-29 18:29:38 +0000606 ret = ctxt->wellFormed;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000607 xmlFreeParserCtxt(ctxt);
Daniel Veillarde715dd22000-08-29 18:29:38 +0000608 if (!ret) {
609 xmlFreeDoc(doc);
610 doc = NULL;
611 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000612 }
613 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000614 } else if (testIO) {
615 int ret;
616 FILE *f;
617
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000618 /* '-' Usually means stdin -<sven@zen.org> */
619 if ((filename[0] == '-') && (filename[1] == 0)) {
620 f = stdin;
621 } else {
622 f = fopen(filename, "r");
623 }
Daniel Veillard5e873c42000-04-12 13:27:38 +0000624 if (f != NULL) {
625 xmlParserCtxtPtr ctxt;
626
627 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
628 (xmlInputReadCallback) myRead,
629 (xmlInputCloseCallback) myClose,
630 f, XML_CHAR_ENCODING_NONE);
631 xmlParseDocument(ctxt);
632
633 ret = ctxt->wellFormed;
634 doc = ctxt->myDoc;
635 xmlFreeParserCtxt(ctxt);
636 if (!ret) {
637 xmlFreeDoc(doc);
638 doc = NULL;
639 }
640 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000641 } else if (recovery) {
642 doc = xmlRecoverFile(filename);
643 } else if (htmlout) {
644 int ret;
645 xmlParserCtxtPtr ctxt;
646 xmlSAXHandler silent, *old;
647
648 ctxt = xmlCreateFileParserCtxt(filename);
Daniel Veillard88a172f2000-08-04 18:23:10 +0000649
650 if (ctxt == NULL) {
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000651 /* If xmlCreateFileParserCtxt() return NULL something
Daniel Veillard88a172f2000-08-04 18:23:10 +0000652 strange happened so we don't want to do anything. Do
653 we want to print an error message here?
654 <sven@zen.org> */
Daniel Veillard7ebb1ee2000-08-04 18:24:45 +0000655 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000656 } else {
657 memcpy(&silent, ctxt->sax, sizeof(silent));
658 old = ctxt->sax;
659 silent.error = xmlHTMLError;
660 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000661 silent.warning = xmlHTMLWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000662 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000663 silent.warning = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000664 silent.fatalError = xmlHTMLError;
665 ctxt->sax = &silent;
666 ctxt->vctxt.error = xmlHTMLValidityError;
667 if (xmlGetWarningsDefaultValue)
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000668 ctxt->vctxt.warning = xmlHTMLValidityWarning;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000669 else
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000670 ctxt->vctxt.warning = NULL;
671
Daniel Veillard88a172f2000-08-04 18:23:10 +0000672 xmlParseDocument(ctxt);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000673
Daniel Veillard88a172f2000-08-04 18:23:10 +0000674 ret = ctxt->wellFormed;
675 doc = ctxt->myDoc;
676 ctxt->sax = old;
677 xmlFreeParserCtxt(ctxt);
678 if (!ret) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000679 xmlFreeDoc(doc);
680 doc = NULL;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000681 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000682 }
Daniel Veillard46e370e2000-07-21 20:32:03 +0000683#ifdef HAVE_SYS_MMAN_H
684 } else if (memory) {
685 int fd;
686 struct stat info;
687 const char *base;
688 if (stat(filename, &info) < 0)
689 return;
690 if ((fd = open(filename, O_RDONLY)) < 0)
691 return;
692 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
Daniel Veillard29579362000-08-14 17:57:48 +0000693 if (base == (void *) MAP_FAILED)
Daniel Veillard46e370e2000-07-21 20:32:03 +0000694 return;
695
696 doc = xmlParseMemory((char *) base, info.st_size);
697 munmap((char *) base, info.st_size);
698#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000699 } else
700 doc = xmlParseFile(filename);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000701 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000702
Daniel Veillard88a172f2000-08-04 18:23:10 +0000703 /*
704 * If we don't have a document we might as well give up. Do we
705 * want an error message here? <sven@zen.org> */
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000706 if (doc == NULL) {
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000707 progresult = 1;
Daniel Veillard88a172f2000-08-04 18:23:10 +0000708 return;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000709 }
710
Daniel Veillard48b2f892001-02-25 16:11:03 +0000711 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000712 endTimer("Parsing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000713 }
714
Daniel Veillard29e43992001-12-13 22:21:58 +0000715 /*
716 * Remove DOCTYPE nodes
717 */
718 if (dropdtd) {
719 xmlDtdPtr dtd;
720
721 dtd = xmlGetIntSubset(doc);
722 if (dtd != NULL) {
723 xmlUnlinkNode((xmlNodePtr)dtd);
724 xmlFreeDtd(dtd);
725 }
726 }
727
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000728#ifdef LIBXML_XINCLUDE_ENABLED
Daniel Veillard48b2f892001-02-25 16:11:03 +0000729 if (xinclude) {
730 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000731 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000732 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000733 xmlXIncludeProcess(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000734 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000735 endTimer("Xinclude processing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000736 }
737 }
Daniel Veillard9e8bfae2000-11-06 16:43:11 +0000738#endif
Daniel Veillard88a172f2000-08-04 18:23:10 +0000739
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000740#ifdef LIBXML_DEBUG_ENABLED
741 /*
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000742 * shell interaction
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000743 */
744 if (shell)
745 xmlShell(doc, filename, xmlShellReadline, stdout);
746#endif
747
748 /*
749 * test intermediate copy if needed.
750 */
751 if (copy) {
752 tmp = doc;
753 doc = xmlCopyDoc(doc, 1);
754 xmlFreeDoc(tmp);
755 }
756
757 if ((insert) && (!html)) {
758 const xmlChar* list[256];
759 int nb, i;
760 xmlNodePtr node;
761
762 if (doc->children != NULL) {
763 node = doc->children;
764 while ((node != NULL) && (node->last == NULL)) node = node->next;
765 if (node != NULL) {
766 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
767 if (nb < 0) {
768 printf("could not get valid list of elements\n");
769 } else if (nb == 0) {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000770 printf("No element can be inserted under root\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000771 } else {
MDT 2001 John Fleckbbb9e432001-09-24 03:08:43 +0000772 printf("%d element types can be inserted under root:\n",
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000773 nb);
774 for (i = 0;i < nb;i++) {
775 printf("%s\n", list[i]);
776 }
777 }
778 }
779 }
780 }else if (noout == 0) {
781 /*
782 * print it.
783 */
784#ifdef LIBXML_DEBUG_ENABLED
785 if (!debug) {
786#endif
Daniel Veillard48b2f892001-02-25 16:11:03 +0000787 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000788 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000789 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000790#ifdef HAVE_SYS_MMAN_H
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000791 if (memory) {
792 xmlChar *result;
793 int len;
794
795 if (encoding != NULL) {
Daniel Veillardd536f702001-11-08 17:32:47 +0000796 if ( format ) {
797 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
798 } else {
799 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
800 }
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000801 } else {
Daniel Veillard90493a92001-08-14 14:12:47 +0000802 if (format)
803 xmlDocDumpFormatMemory(doc, &result, &len, 1);
804 else
805 xmlDocDumpMemory(doc, &result, &len);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000806 }
807 if (result == NULL) {
808 fprintf(stderr, "Failed to save\n");
809 } else {
810 write(1, result, len);
811 xmlFree(result);
812 }
Daniel Veillard3b2c2612001-04-04 00:09:00 +0000813 } else
814#endif /* HAVE_SYS_MMAN_H */
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000815 if (compress) {
816 xmlSaveFile(output ? output : "-", doc);
817 }
Daniel Veillardd536f702001-11-08 17:32:47 +0000818 else if (encoding != NULL) {
819 if ( format ) {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000820 xmlSaveFormatFileEnc(output ? output : "-", doc, encoding, 1);
821 }
Daniel Veillardd536f702001-11-08 17:32:47 +0000822 else {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000823 xmlSaveFileEnc(output ? output : "-", doc, encoding);
Daniel Veillardd536f702001-11-08 17:32:47 +0000824 }
825 }
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000826 else if (format) {
827 xmlSaveFormatFile(output ? output : "-", doc, 1);
828 }
829 else {
830 FILE *out;
831 if (output == NULL)
832 out = stdout;
833 else {
834 out = fopen(output,"wb");
835 }
836 xmlDocDump(out, doc);
837
838 if (output)
839 fclose(out);
840 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000841 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000842 endTimer("Saving");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000843 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000844#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000845 } else {
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000846 FILE *out;
847 if (output == NULL)
848 out = stdout;
849 else {
850 out = fopen(output,"wb");
851 }
852 xmlDebugDumpDocument(out, doc);
853
854 if (output)
855 fclose(out);
Daniel Veillarda6d8eb62000-12-27 10:46:47 +0000856 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000857#endif
858 }
859
860 /*
861 * A posteriori validation test
862 */
Daniel Veillardcd429612000-10-11 15:57:05 +0000863 if (dtdvalid != NULL) {
864 xmlDtdPtr dtd;
865
Daniel Veillard48b2f892001-02-25 16:11:03 +0000866 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000867 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000868 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000869 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000870 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000871 endTimer("Parsing DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000872 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000873 if (dtd == NULL) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000874 xmlGenericError(xmlGenericErrorContext,
875 "Could not parse DTD %s\n", dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000876 progresult = 2;
Daniel Veillardcd429612000-10-11 15:57:05 +0000877 } else {
878 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000879 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000880 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000881 }
Daniel Veillard01db67c2001-12-18 07:09:59 +0000882 cvp.userData = (void *) stderr;
883 cvp.error = (xmlValidityErrorFunc) fprintf;
884 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000885 if (!xmlValidateDtd(&cvp, doc, dtd)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000886 xmlGenericError(xmlGenericErrorContext,
887 "Document %s does not validate against %s\n",
Daniel Veillardcd429612000-10-11 15:57:05 +0000888 filename, dtdvalid);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000889 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000890 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000891 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000892 endTimer("Validating against DTD");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000893 }
Daniel Veillardcd429612000-10-11 15:57:05 +0000894 xmlFreeDtd(dtd);
895 }
896 } else if (postvalid) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000897 xmlValidCtxt cvp;
Daniel Veillard48b2f892001-02-25 16:11:03 +0000898 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000899 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000900 }
Daniel Veillardb7664f42001-08-19 13:00:43 +0000901 cvp.userData = (void *) stderr;
902 cvp.error = (xmlValidityErrorFunc) fprintf;
903 cvp.warning = (xmlValidityWarningFunc) fprintf;
Daniel Veillardcd429612000-10-11 15:57:05 +0000904 if (!xmlValidateDocument(&cvp, doc)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000905 xmlGenericError(xmlGenericErrorContext,
906 "Document %s does not validate\n", filename);
Daniel Veillardf7cd4812001-02-23 18:44:52 +0000907 progresult = 3;
Daniel Veillardcd429612000-10-11 15:57:05 +0000908 }
Daniel Veillard48b2f892001-02-25 16:11:03 +0000909 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000910 endTimer("Validating");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000911 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000912 }
913
914#ifdef LIBXML_DEBUG_ENABLED
915 if ((debugent) && (!html))
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000916 xmlDebugDumpEntities(stderr, doc);
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000917#endif
918
919 /*
920 * free it.
921 */
Daniel Veillard48b2f892001-02-25 16:11:03 +0000922 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000923 startTimer();
Daniel Veillard48b2f892001-02-25 16:11:03 +0000924 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000925 xmlFreeDoc(doc);
Daniel Veillard48b2f892001-02-25 16:11:03 +0000926 if ((timing) && (!repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +0000927 endTimer("Freeing");
Daniel Veillard48b2f892001-02-25 16:11:03 +0000928 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000929}
930
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000931/************************************************************************
932 * *
933 * Usage and Main *
934 * *
935 ************************************************************************/
936
937static void usage(const char *name) {
938 printf("Usage : %s [options] XMLfiles ...\n", name);
939 printf("\tParse the XML files and output the result of the parsing\n");
940 printf("\t--version : display the version of the XML library used\n");
941#ifdef LIBXML_DEBUG_ENABLED
942 printf("\t--debug : dump a debug tree of the in-memory document\n");
943 printf("\t--shell : run a navigating shell\n");
944 printf("\t--debugent : debug the entities defined in the document\n");
945#endif
946 printf("\t--copy : used to test the internal copy implementation\n");
947 printf("\t--recover : output what was parsable on broken XML documents\n");
948 printf("\t--noent : substitute entity references by their value\n");
949 printf("\t--noout : don't output the result tree\n");
950 printf("\t--htmlout : output results as HTML\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000951 printf("\t--nowrap : do not put HTML doc wrapper\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000952 printf("\t--valid : validate the document in addition to std well-formed check\n");
953 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
954 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
955 printf("\t--timing : print some timings\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000956 printf("\t--output file or -o file: save to a given file\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000957 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
958 printf("\t--insert : ad-hoc test for valid insertions\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000959#ifdef HAVE_ZLIB_H
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000960 printf("\t--compress : turn on gzip compression of output\n");
Daniel Veillard1df3dfc2001-12-18 11:14:16 +0000961#endif
Daniel Veillard89cad532001-10-22 09:46:13 +0000962#ifdef LIBXML_DOCB_ENABLED
963 printf("\t--sgml : use the DocBook SGML parser\n");
964#endif
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000965#ifdef LIBXML_HTML_ENABLED
966 printf("\t--html : use the HTML parser\n");
967#endif
968 printf("\t--push : use the push mode of the parser\n");
969#ifdef HAVE_SYS_MMAN_H
970 printf("\t--memory : parse from memory\n");
971#endif
972 printf("\t--nowarning : do not emit warnings from parser/validator\n");
973 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
Daniel Veillard90493a92001-08-14 14:12:47 +0000974 printf("\t--format : reformat/reindent the input\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000975 printf("\t--testIO : test user I/O support\n");
976 printf("\t--encode encoding : output in the given encoding\n");
977#ifdef LIBXML_CATALOG_ENABLED
Daniel Veillardbd9b0e82001-11-26 10:32:08 +0000978 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
979 printf("\t otherwise XML Catalogs starting from \n");
980 printf("\t file:///etc/xml/catalog are activated by default\n");
Daniel Veillard05c13a22001-09-09 08:38:09 +0000981 printf("\t--nocatalogs: deactivate all catalogs\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000982#endif
983 printf("\t--auto : generate a small doc on the fly\n");
984#ifdef LIBXML_XINCLUDE_ENABLED
985 printf("\t--xinclude : do XInclude processing\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000986#endif
Daniel Veillardcbaf3992001-12-31 16:16:02 +0000987 printf("\t--loaddtd : fetch external DTD\n");
Daniel Veillard48da9102001-08-07 01:10:10 +0000988 printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
Daniel Veillard29e43992001-12-13 22:21:58 +0000989 printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
Daniel Veillarda42f25f2002-01-25 14:15:40 +0000990 printf("\nLibxml project home page: http://xmlsoft.org/\n");
991 printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000992}
Daniel Veillard4a6845d2001-01-03 13:32:39 +0000993int
994main(int argc, char **argv) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000995 int i, count;
996 int files = 0;
Daniel Veillard845cce42002-01-09 11:51:37 +0000997 int version = 0;
Daniel Veillardce8b83b2000-04-05 18:38:42 +0000998
Daniel Veillard10ea86c2001-06-20 13:55:33 +0000999 if (argc <= 1) {
1000 usage(argv[0]);
1001 return(1);
1002 }
Daniel Veillardbe803962000-06-28 23:40:59 +00001003 LIBXML_TEST_VERSION
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001004 for (i = 1; i < argc ; i++) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001005 if (!strcmp(argv[i], "-"))
1006 break;
1007
1008 if (argv[i][0] != '-')
1009 continue;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001010#ifdef LIBXML_DEBUG_ENABLED
1011 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
1012 debug++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001013 else if ((!strcmp(argv[i], "-shell")) ||
1014 (!strcmp(argv[i], "--shell"))) {
1015 shell++;
1016 noout = 1;
1017 } else
1018#endif
1019 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
1020 copy++;
1021 else if ((!strcmp(argv[i], "-recover")) ||
1022 (!strcmp(argv[i], "--recover")))
1023 recovery++;
1024 else if ((!strcmp(argv[i], "-noent")) ||
1025 (!strcmp(argv[i], "--noent")))
1026 noent++;
Daniel Veillard4ec885a2001-06-17 10:31:07 +00001027 else if ((!strcmp(argv[i], "-version")) ||
Daniel Veillard845cce42002-01-09 11:51:37 +00001028 (!strcmp(argv[i], "--version"))) {
Daniel Veillard4ec885a2001-06-17 10:31:07 +00001029 fprintf(stderr, "xmllint: using libxml version %s\n",
1030 xmlParserVersion);
Daniel Veillard845cce42002-01-09 11:51:37 +00001031 version = 1;
1032 } else if ((!strcmp(argv[i], "-noout")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001033 (!strcmp(argv[i], "--noout")))
1034 noout++;
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001035 else if ((!strcmp(argv[i], "-o")) ||
1036 (!strcmp(argv[i], "-output")) ||
1037 (!strcmp(argv[i], "--output"))) {
1038 i++;
1039 output = argv[i++];
1040 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001041 else if ((!strcmp(argv[i], "-htmlout")) ||
1042 (!strcmp(argv[i], "--htmlout")))
1043 htmlout++;
Daniel Veillard89cad532001-10-22 09:46:13 +00001044#ifdef LIBXML_DOCB_ENABLED
1045 else if ((!strcmp(argv[i], "-sgml")) ||
1046 (!strcmp(argv[i], "--sgml"))) {
1047 sgml++;
1048 }
1049#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001050#ifdef LIBXML_HTML_ENABLED
1051 else if ((!strcmp(argv[i], "-html")) ||
1052 (!strcmp(argv[i], "--html"))) {
1053 html++;
1054 }
1055#endif /* LIBXML_HTML_ENABLED */
1056 else if ((!strcmp(argv[i], "-nowrap")) ||
1057 (!strcmp(argv[i], "--nowrap")))
1058 nowrap++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001059 else if ((!strcmp(argv[i], "-loaddtd")) ||
1060 (!strcmp(argv[i], "--loaddtd")))
1061 loaddtd++;
Daniel Veillard48da9102001-08-07 01:10:10 +00001062 else if ((!strcmp(argv[i], "-dtdattr")) ||
1063 (!strcmp(argv[i], "--dtdattr"))) {
1064 loaddtd++;
1065 dtdattrs++;
1066 } else if ((!strcmp(argv[i], "-valid")) ||
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001067 (!strcmp(argv[i], "--valid")))
1068 valid++;
1069 else if ((!strcmp(argv[i], "-postvalid")) ||
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001070 (!strcmp(argv[i], "--postvalid"))) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001071 postvalid++;
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001072 loaddtd++;
1073 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
Daniel Veillardcd429612000-10-11 15:57:05 +00001074 (!strcmp(argv[i], "--dtdvalid"))) {
1075 i++;
1076 dtdvalid = argv[i];
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001077 loaddtd++;
Daniel Veillardcd429612000-10-11 15:57:05 +00001078 }
Daniel Veillard29e43992001-12-13 22:21:58 +00001079 else if ((!strcmp(argv[i], "-dropdtd")) ||
1080 (!strcmp(argv[i], "--dropdtd")))
1081 dropdtd++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001082 else if ((!strcmp(argv[i], "-insert")) ||
1083 (!strcmp(argv[i], "--insert")))
1084 insert++;
Daniel Veillard48b2f892001-02-25 16:11:03 +00001085 else if ((!strcmp(argv[i], "-timing")) ||
1086 (!strcmp(argv[i], "--timing")))
1087 timing++;
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001088 else if ((!strcmp(argv[i], "-auto")) ||
1089 (!strcmp(argv[i], "--auto")))
1090 generate++;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001091 else if ((!strcmp(argv[i], "-repeat")) ||
1092 (!strcmp(argv[i], "--repeat")))
1093 repeat++;
1094 else if ((!strcmp(argv[i], "-push")) ||
1095 (!strcmp(argv[i], "--push")))
1096 push++;
Daniel Veillard46e370e2000-07-21 20:32:03 +00001097#ifdef HAVE_SYS_MMAN_H
1098 else if ((!strcmp(argv[i], "-memory")) ||
1099 (!strcmp(argv[i], "--memory")))
1100 memory++;
1101#endif
Daniel Veillard5e873c42000-04-12 13:27:38 +00001102 else if ((!strcmp(argv[i], "-testIO")) ||
1103 (!strcmp(argv[i], "--testIO")))
1104 testIO++;
Daniel Veillard9e8bfae2000-11-06 16:43:11 +00001105#ifdef LIBXML_XINCLUDE_ENABLED
1106 else if ((!strcmp(argv[i], "-xinclude")) ||
1107 (!strcmp(argv[i], "--xinclude")))
1108 xinclude++;
1109#endif
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001110#ifdef HAVE_ZLIB_H
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001111 else if ((!strcmp(argv[i], "-compress")) ||
1112 (!strcmp(argv[i], "--compress"))) {
1113 compress++;
1114 xmlSetCompressMode(9);
1115 }
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001116#endif
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001117 else if ((!strcmp(argv[i], "-nowarning")) ||
1118 (!strcmp(argv[i], "--nowarning"))) {
1119 xmlGetWarningsDefaultValue = 0;
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001120 xmlPedanticParserDefault(0);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001121 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001122 else if ((!strcmp(argv[i], "-pedantic")) ||
1123 (!strcmp(argv[i], "--pedantic"))) {
1124 xmlGetWarningsDefaultValue = 1;
1125 xmlPedanticParserDefault(1);
1126 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001127#ifdef LIBXML_DEBUG_ENABLED
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001128 else if ((!strcmp(argv[i], "-debugent")) ||
1129 (!strcmp(argv[i], "--debugent"))) {
1130 debugent++;
1131 xmlParserDebugEntities = 1;
1132 }
Daniel Veillard64c20ed2000-09-22 16:07:02 +00001133#endif
Daniel Veillard81418e32001-05-22 15:08:55 +00001134#ifdef LIBXML_CATALOG_ENABLED
1135 else if ((!strcmp(argv[i], "-catalogs")) ||
1136 (!strcmp(argv[i], "--catalogs"))) {
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001137 catalogs++;
1138 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
1139 (!strcmp(argv[i], "--nocatalogs"))) {
1140 nocatalogs++;
Daniel Veillard81418e32001-05-22 15:08:55 +00001141 }
1142#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001143 else if ((!strcmp(argv[i], "-encode")) ||
1144 (!strcmp(argv[i], "--encode"))) {
1145 i++;
1146 encoding = argv[i];
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +00001147 /*
1148 * OK it's for testing purposes
1149 */
1150 xmlAddEncodingAlias("UTF-8", "DVEnc");
Daniel Veillardbe803962000-06-28 23:40:59 +00001151 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001152 else if ((!strcmp(argv[i], "-noblanks")) ||
1153 (!strcmp(argv[i], "--noblanks"))) {
1154 noblanks++;
1155 xmlKeepBlanksDefault(0);
Daniel Veillard90493a92001-08-14 14:12:47 +00001156 }
1157 else if ((!strcmp(argv[i], "-format")) ||
1158 (!strcmp(argv[i], "--format"))) {
1159 noblanks++;
1160 format++;
1161 xmlKeepBlanksDefault(0);
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001162 } else {
1163 fprintf(stderr, "Unknown option %s\n", argv[i]);
1164 usage(argv[0]);
1165 return(1);
1166 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001167 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001168
1169#ifdef LIBXML_CATALOG_ENABLED
1170 if (nocatalogs == 0) {
1171 if (catalogs) {
1172 const char *catal;
1173
1174 catal = getenv("SGML_CATALOG_FILES");
Daniel Veillard6c5f9d12001-08-25 13:33:14 +00001175 if (catal != NULL) {
1176 xmlLoadCatalogs(catal);
1177 } else {
1178 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
1179 }
Daniel Veillarde2940dd2001-08-22 00:06:49 +00001180 }
1181 }
1182#endif
Daniel Veillardd9bad132001-07-23 19:39:43 +00001183 xmlLineNumbersDefault(1);
Daniel Veillard48da9102001-08-07 01:10:10 +00001184 if (loaddtd != 0)
1185 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1186 if (dtdattrs)
1187 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001188 if (noent != 0) xmlSubstituteEntitiesDefault(1);
1189 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1190 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001191 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001192 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001193 xmlGenericError(xmlGenericErrorContext,
1194 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
1195 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001196 "<html><head><title>%s output</title></head>\n",
1197 argv[0]);
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001198 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001199 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
1200 argv[0]);
1201 }
1202 for (i = 1; i < argc ; i++) {
Daniel Veillardbe803962000-06-28 23:40:59 +00001203 if ((!strcmp(argv[i], "-encode")) ||
1204 (!strcmp(argv[i], "--encode"))) {
1205 i++;
1206 continue;
Daniel Veillard1df3dfc2001-12-18 11:14:16 +00001207 } else if ((!strcmp(argv[i], "-o")) ||
1208 (!strcmp(argv[i], "-output")) ||
1209 (!strcmp(argv[i], "--output"))) {
1210 i++;
1211 continue;
Daniel Veillardbe803962000-06-28 23:40:59 +00001212 }
Daniel Veillardcd429612000-10-11 15:57:05 +00001213 if ((!strcmp(argv[i], "-dtdvalid")) ||
1214 (!strcmp(argv[i], "--dtdvalid"))) {
1215 i++;
1216 continue;
1217 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001218 if ((timing) && (repeat))
Daniel Veillard01db67c2001-12-18 07:09:59 +00001219 startTimer();
Daniel Veillardcbaf3992001-12-31 16:16:02 +00001220 /* Remember file names. "-" means stdin. <sven@zen.org> */
Daniel Veillard4a6845d2001-01-03 13:32:39 +00001221 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001222 if (repeat) {
1223 for (count = 0;count < 100 * repeat;count++)
1224 parseAndPrintFile(argv[i]);
1225 } else
1226 parseAndPrintFile(argv[i]);
1227 files ++;
Daniel Veillarda7866932001-12-04 13:14:44 +00001228 if ((timing) && (repeat)) {
Daniel Veillard01db67c2001-12-18 07:09:59 +00001229 endTimer("100 iterations");
Daniel Veillarda7866932001-12-04 13:14:44 +00001230 }
Daniel Veillard48b2f892001-02-25 16:11:03 +00001231 }
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001232 }
Daniel Veillardd2f3ec72001-04-11 07:50:02 +00001233 if (generate)
1234 parseAndPrintFile(NULL);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001235 if ((htmlout) && (!nowrap)) {
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001236 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001237 }
Daniel Veillard845cce42002-01-09 11:51:37 +00001238 if ((files == 0) && (!generate) && (version == 0)) {
Daniel Veillard10ea86c2001-06-20 13:55:33 +00001239 usage(argv[0]);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001240 }
1241 xmlCleanupParser();
1242 xmlMemoryDump();
1243
Daniel Veillardf7cd4812001-02-23 18:44:52 +00001244 return(progresult);
Daniel Veillardce8b83b2000-04-05 18:38:42 +00001245}
Daniel Veillard88a172f2000-08-04 18:23:10 +00001246