2 * xmllint.c : a small tester program for XML input.
4 * See Copyright for the status of this software.
16 #if defined (_WIN32) && !defined(__CYGWIN__)
19 #pragma comment(lib, "ws2_32.lib")
20 #define gettimeofday(p1,p2)
26 #ifdef HAVE_SYS_TIME_H
36 #include <wsockcompat.h>
39 #define SOCKLEN_T unsigned int
43 #ifdef HAVE_SYS_TIMEB_H
44 #include <sys/timeb.h>
47 #ifdef HAVE_SYS_TYPES_H
48 #include <sys/types.h>
50 #ifdef HAVE_SYS_STAT_H
59 #ifdef HAVE_SYS_MMAN_H
61 /* seems needed for Solaris */
63 #define MAP_FAILED ((void *) -1)
69 #ifdef HAVE_LIBREADLINE
70 #include <readline/readline.h>
71 #ifdef HAVE_LIBHISTORY
72 #include <readline/history.h>
76 #include <libxml/xmlmemory.h>
77 #include <libxml/parser.h>
78 #include <libxml/parserInternals.h>
79 #include <libxml/HTMLparser.h>
80 #include <libxml/HTMLtree.h>
81 #include <libxml/tree.h>
82 #include <libxml/xpath.h>
83 #include <libxml/debugXML.h>
84 #include <libxml/xmlerror.h>
85 #ifdef LIBXML_XINCLUDE_ENABLED
86 #include <libxml/xinclude.h>
88 #ifdef LIBXML_CATALOG_ENABLED
89 #include <libxml/catalog.h>
91 #ifdef LIBXML_DOCB_ENABLED
92 #include <libxml/DOCBparser.h>
94 #include <libxml/globals.h>
95 #include <libxml/xmlreader.h>
96 #ifdef LIBXML_SCHEMAS_ENABLED
97 #include <libxml/relaxng.h>
98 #include <libxml/xmlschemas.h>
101 #ifndef XML_XML_DEFAULT_CATALOG
102 #define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
105 #ifdef LIBXML_DEBUG_ENABLED
106 static int shell = 0;
107 static int debugent = 0;
109 static int debug = 0;
111 static int recovery = 0;
112 static int noent = 0;
113 static int noout = 0;
114 static int nowrap = 0;
115 static int valid = 0;
116 static int postvalid = 0;
117 static char * dtdvalid = NULL;
118 #ifdef LIBXML_SCHEMAS_ENABLED
119 static char * relaxng = NULL;
120 static xmlRelaxNGPtr relaxngschemas = NULL;
121 static char * schema = NULL;
122 static xmlSchemaPtr wxschemas = NULL;
124 static int repeat = 0;
125 static int insert = 0;
126 static int compress = 0;
127 #ifdef LIBXML_DOCB_ENABLED
131 static int htmlout = 0;
133 #ifdef HAVE_SYS_MMAN_H
134 static int memory = 0;
136 static int noblanks = 0;
137 static int format = 0;
138 static int testIO = 0;
139 static char *encoding = NULL;
140 #ifdef LIBXML_XINCLUDE_ENABLED
141 static int xinclude = 0;
143 static int dtdattrs = 0;
144 static int loaddtd = 0;
145 static int progresult = 0;
146 static int timing = 0;
147 static int generate = 0;
148 static int dropdtd = 0;
149 #ifdef LIBXML_CATALOG_ENABLED
150 static int catalogs = 0;
151 static int nocatalogs = 0;
153 static int stream = 0;
154 static int chkregister = 0;
155 static const char *output = NULL;
158 * Internal timing routines to remove the necessity to have unix-specific
162 #ifndef HAVE_GETTIMEOFDAY
163 #ifdef HAVE_SYS_TIMEB_H
164 #ifdef HAVE_SYS_TIME_H
168 my_gettimeofday(struct timeval *tvp, void *tzp)
170 struct timeb timebuffer;
174 tvp->tv_sec = timebuffer.time;
175 tvp->tv_usec = timebuffer.millitm * 1000L;
179 #define HAVE_GETTIMEOFDAY 1
180 #define gettimeofday my_gettimeofday
182 #endif /* HAVE_FTIME */
183 #endif /* HAVE_SYS_TIME_H */
184 #endif /* HAVE_SYS_TIMEB_H */
185 #endif /* !HAVE_GETTIMEOFDAY */
187 #if defined(HAVE_GETTIMEOFDAY)
188 static struct timeval begin, end;
191 * startTimer: call where you want to start timing
196 gettimeofday(&begin, NULL);
200 * endTimer: call where you want to stop timing and to print out a
201 * message about the timing performed; format is a printf
205 endTimer(const char *fmt, ...)
210 gettimeofday(&end, NULL);
211 msec = end.tv_sec - begin.tv_sec;
213 msec += (end.tv_usec - begin.tv_usec) / 1000;
215 #ifndef HAVE_STDARG_H
216 #error "endTimer required stdarg functions"
219 vfprintf(stderr, fmt, ap);
222 fprintf(stderr, " took %ld ms\n", msec);
224 #elif defined(HAVE_TIME_H)
226 * No gettimeofday function, so we have to make do with calling clock.
227 * This is obviously less accurate, but there's little we can do about
230 #ifndef CLOCKS_PER_SEC
231 #define CLOCKS_PER_SEC 100
234 static clock_t begin, end;
241 endTimer(const char *fmt, ...)
247 msec = ((end - begin) * 1000) / CLOCKS_PER_SEC;
249 #ifndef HAVE_STDARG_H
250 #error "endTimer required stdarg functions"
253 vfprintf(stderr, fmt, ap);
255 fprintf(stderr, " took %ld ms\n", msec);
260 * We don't have a gettimeofday or time.h, so we just don't do timing
270 endTimer(char *format, ...)
273 * We cannot do anything because we don't have a timing function
276 va_start(ap, format);
277 vfprintf(stderr, format, ap);
279 fprintf(stderr, " was not timed\n", msec);
281 /* We don't have gettimeofday, time or stdarg.h, what crazy world is
287 /************************************************************************
291 ************************************************************************/
295 xmlHTMLEncodeSend(void) {
298 result = (char *) xmlEncodeEntitiesReentrant(NULL, BAD_CAST buffer);
300 xmlGenericError(xmlGenericErrorContext, "%s", result);
307 * xmlHTMLPrintFileInfo:
308 * @input: an xmlParserInputPtr input
310 * Displays the associated file and line informations for the current input
314 xmlHTMLPrintFileInfo(xmlParserInputPtr input) {
316 xmlGenericError(xmlGenericErrorContext, "<p>");
318 len = strlen(buffer);
320 if (input->filename) {
321 snprintf(&buffer[len], sizeof(buffer) - len, "%s:%d: ", input->filename,
324 snprintf(&buffer[len], sizeof(buffer) - len, "Entity: line %d: ", input->line);
331 * xmlHTMLPrintFileContext:
332 * @input: an xmlParserInputPtr input
334 * Displays current context within the input content for error tracking
338 xmlHTMLPrintFileContext(xmlParserInputPtr input) {
339 const xmlChar *cur, *base;
343 if (input == NULL) return;
344 xmlGenericError(xmlGenericErrorContext, "<pre>\n");
347 while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
351 while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
353 if ((*cur == '\n') || (*cur == '\r')) cur++;
356 while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
357 len = strlen(buffer);
358 snprintf(&buffer[len], sizeof(buffer) - len, "%c",
359 (unsigned char) *cur++);
362 len = strlen(buffer);
363 snprintf(&buffer[len], sizeof(buffer) - len, "\n");
365 while ((*cur == '\n') || (*cur == '\r'))
368 while ((cur != base) && (n++ < 80)) {
369 len = strlen(buffer);
370 snprintf(&buffer[len], sizeof(buffer) - len, " ");
373 len = strlen(buffer);
374 snprintf(&buffer[len], sizeof(buffer) - len, "^\n");
376 xmlGenericError(xmlGenericErrorContext, "</pre>");
381 * @ctx: an XML parser context
382 * @msg: the message to display/transmit
383 * @...: extra parameters for the message display
385 * Display and format an error messages, gives file, line, position and
389 xmlHTMLError(void *ctx, const char *msg, ...)
391 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
392 xmlParserInputPtr input;
398 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
399 input = ctxt->inputTab[ctxt->inputNr - 2];
402 xmlHTMLPrintFileInfo(input);
404 xmlGenericError(xmlGenericErrorContext, "<b>error</b>: ");
406 len = strlen(buffer);
407 vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args);
410 xmlGenericError(xmlGenericErrorContext, "</p>\n");
412 xmlHTMLPrintFileContext(input);
418 * @ctx: an XML parser context
419 * @msg: the message to display/transmit
420 * @...: extra parameters for the message display
422 * Display and format a warning messages, gives file, line, position and
426 xmlHTMLWarning(void *ctx, const char *msg, ...)
428 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
429 xmlParserInputPtr input;
435 if ((input != NULL) && (input->filename == NULL) && (ctxt->inputNr > 1)) {
436 input = ctxt->inputTab[ctxt->inputNr - 2];
440 xmlHTMLPrintFileInfo(input);
442 xmlGenericError(xmlGenericErrorContext, "<b>warning</b>: ");
444 len = strlen(buffer);
445 vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args);
448 xmlGenericError(xmlGenericErrorContext, "</p>\n");
450 xmlHTMLPrintFileContext(input);
455 * xmlHTMLValidityError:
456 * @ctx: an XML parser context
457 * @msg: the message to display/transmit
458 * @...: extra parameters for the message display
460 * Display and format an validity error messages, gives file,
461 * line, position and extra parameters.
464 xmlHTMLValidityError(void *ctx, const char *msg, ...)
466 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
467 xmlParserInputPtr input;
473 if ((input->filename == NULL) && (ctxt->inputNr > 1))
474 input = ctxt->inputTab[ctxt->inputNr - 2];
476 xmlHTMLPrintFileInfo(input);
478 xmlGenericError(xmlGenericErrorContext, "<b>validity error</b>: ");
479 len = strlen(buffer);
481 vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args);
484 xmlGenericError(xmlGenericErrorContext, "</p>\n");
486 xmlHTMLPrintFileContext(input);
491 * xmlHTMLValidityWarning:
492 * @ctx: an XML parser context
493 * @msg: the message to display/transmit
494 * @...: extra parameters for the message display
496 * Display and format a validity warning messages, gives file, line,
497 * position and extra parameters.
500 xmlHTMLValidityWarning(void *ctx, const char *msg, ...)
502 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
503 xmlParserInputPtr input;
509 if ((input->filename == NULL) && (ctxt->inputNr > 1))
510 input = ctxt->inputTab[ctxt->inputNr - 2];
512 xmlHTMLPrintFileInfo(input);
514 xmlGenericError(xmlGenericErrorContext, "<b>validity warning</b>: ");
516 len = strlen(buffer);
517 vsnprintf(&buffer[len], sizeof(buffer) - len, msg, args);
520 xmlGenericError(xmlGenericErrorContext, "</p>\n");
522 xmlHTMLPrintFileContext(input);
526 /************************************************************************
530 ************************************************************************/
531 #ifdef LIBXML_DEBUG_ENABLED
534 * @prompt: the prompt value
538 * Returns a pointer to it or NULL on EOF the caller is expected to
539 * free the returned string.
542 xmlShellReadline(char *prompt) {
543 #ifdef HAVE_LIBREADLINE
546 /* Get a line from the user. */
547 line_read = readline (prompt);
549 /* If the line has any text in it, save it on the history. */
550 if (line_read && *line_read)
551 add_history (line_read);
560 fprintf(stdout, "%s", prompt);
561 if (!fgets(line_read, 500, stdin))
564 len = strlen(line_read);
565 ret = (char *) malloc(len + 1);
567 memcpy (ret, line_read, len + 1);
572 #endif /* LIBXML_DEBUG_ENABLED */
574 /************************************************************************
578 ************************************************************************/
580 static int myRead(FILE *f, char * buf, int len) {
581 return(fread(buf, 1, len, f));
583 static void myClose(FILE *f) {
589 /************************************************************************
591 * Stream Test processing *
593 ************************************************************************/
594 static void processNode(xmlTextReaderPtr reader) {
595 xmlChar *name, *value;
597 name = xmlTextReaderName(reader);
599 name = xmlStrdup(BAD_CAST "--");
601 value = xmlTextReaderValue(reader);
603 printf("%d %d %s %d %d",
604 xmlTextReaderDepth(reader),
605 xmlTextReaderNodeType(reader),
607 xmlTextReaderIsEmptyElement(reader),
608 xmlTextReaderHasValue(reader));
613 printf(" %s\n", value);
618 static void streamFile(char *filename) {
619 xmlTextReaderPtr reader;
622 reader = xmlNewTextReaderFilename(filename);
623 if (reader != NULL) {
625 xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
627 xmlTextReaderSetParserProp(reader, XML_PARSER_LOADDTD, 1);
628 #ifdef LIBXML_SCHEMAS_ENABLED
629 if (relaxng != NULL) {
633 ret = xmlTextReaderRelaxNGValidate(reader, relaxng);
635 xmlGenericError(xmlGenericErrorContext,
636 "Relax-NG schema %s failed to compile\n", relaxng);
640 endTimer("Compiling the schemas");
646 * Process all nodes in sequence
651 ret = xmlTextReaderRead(reader);
655 ret = xmlTextReaderRead(reader);
658 #ifdef LIBXML_SCHEMAS_ENABLED
659 if ((valid) || (relaxng != NULL))
663 endTimer("Parsing and validating");
669 if (xmlTextReaderIsValid(reader) != 1) {
670 xmlGenericError(xmlGenericErrorContext,
671 "Document %s does not validate\n", filename);
675 #ifdef LIBXML_SCHEMAS_ENABLED
676 if (relaxng != NULL) {
677 if (xmlTextReaderIsValid(reader) != 1) {
678 printf("%s fails to validate\n", filename);
681 printf("%s validates\n", filename);
686 * Done, cleanup and status
688 xmlFreeTextReader(reader);
690 printf("%s : failed to parse\n", filename);
694 fprintf(stderr, "Unable to open %s\n", filename);
699 /************************************************************************
701 * Tree Test processing *
703 ************************************************************************/
704 static void parseAndPrintFile(char *filename) {
705 xmlDocPtr doc = NULL, tmp;
707 if ((timing) && (!repeat))
711 if (filename == NULL) {
715 doc = xmlNewDoc(BAD_CAST "1.0");
716 n = xmlNewNode(NULL, BAD_CAST "info");
717 xmlNodeSetContent(n, BAD_CAST "abc");
718 xmlDocSetRootElement(doc, n);
721 #ifdef LIBXML_DOCB_ENABLED
723 * build an SGML tree from a string;
725 else if ((sgml) && (push)) {
728 f = fopen(filename, "r");
732 docbParserCtxtPtr ctxt;
736 res = fread(chars, 1, 4, f);
738 ctxt = docbCreatePushParserCtxt(NULL, NULL,
739 chars, res, filename, XML_CHAR_ENCODING_NONE);
740 while ((res = fread(chars, 1, size, f)) > 0) {
741 docbParseChunk(ctxt, chars, res, 0);
743 docbParseChunk(ctxt, chars, 0, 1);
745 docbFreeParserCtxt(ctxt);
750 doc = docbParseFile(filename, NULL);
753 #ifdef LIBXML_HTML_ENABLED
754 else if ((html) && (push)) {
757 f = fopen(filename, "r");
761 htmlParserCtxtPtr ctxt;
765 res = fread(chars, 1, 4, f);
767 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
768 chars, res, filename, 0);
769 while ((res = fread(chars, 1, size, f)) > 0) {
770 htmlParseChunk(ctxt, chars, res, 0);
772 htmlParseChunk(ctxt, chars, 0, 1);
774 htmlFreeParserCtxt(ctxt);
780 doc = htmlParseFile(filename, NULL);
782 #endif /* LIBXML_HTML_ENABLED */
785 * build an XML tree from a string;
790 /* '-' Usually means stdin -<sven@zen.org> */
791 if ((filename[0] == '-') && (filename[1] == 0)) {
794 f = fopen(filename, "r");
798 int res, size = 1024;
800 xmlParserCtxtPtr ctxt;
802 /* if (repeat) size = 1024; */
803 res = fread(chars, 1, 4, f);
805 ctxt = xmlCreatePushParserCtxt(NULL, NULL,
806 chars, res, filename);
807 while ((res = fread(chars, 1, size, f)) > 0) {
808 xmlParseChunk(ctxt, chars, res, 0);
810 xmlParseChunk(ctxt, chars, 0, 1);
812 ret = ctxt->wellFormed;
813 xmlFreeParserCtxt(ctxt);
824 /* '-' Usually means stdin -<sven@zen.org> */
825 if ((filename[0] == '-') && (filename[1] == 0)) {
828 f = fopen(filename, "r");
831 xmlParserCtxtPtr ctxt;
833 ctxt = xmlCreateIOParserCtxt(NULL, NULL,
834 (xmlInputReadCallback) myRead,
835 (xmlInputCloseCallback) myClose,
836 f, XML_CHAR_ENCODING_NONE);
837 xmlParseDocument(ctxt);
839 ret = ctxt->wellFormed;
841 xmlFreeParserCtxt(ctxt);
847 } else if (recovery) {
848 doc = xmlRecoverFile(filename);
849 } else if (htmlout) {
851 xmlParserCtxtPtr ctxt;
852 xmlSAXHandler silent, *old;
854 ctxt = xmlCreateFileParserCtxt(filename);
857 /* If xmlCreateFileParserCtxt() return NULL something
858 strange happened so we don't want to do anything. Do
859 we want to print an error message here?
863 memcpy(&silent, ctxt->sax, sizeof(silent));
865 silent.error = xmlHTMLError;
866 if (xmlGetWarningsDefaultValue)
867 silent.warning = xmlHTMLWarning;
869 silent.warning = NULL;
870 silent.fatalError = xmlHTMLError;
872 ctxt->vctxt.error = xmlHTMLValidityError;
873 if (xmlGetWarningsDefaultValue)
874 ctxt->vctxt.warning = xmlHTMLValidityWarning;
876 ctxt->vctxt.warning = NULL;
878 xmlParseDocument(ctxt);
880 ret = ctxt->wellFormed;
883 xmlFreeParserCtxt(ctxt);
889 #ifdef HAVE_SYS_MMAN_H
894 if (stat(filename, &info) < 0)
896 if ((fd = open(filename, O_RDONLY)) < 0)
898 base = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0) ;
899 if (base == (void *) MAP_FAILED)
902 doc = xmlParseMemory((char *) base, info.st_size);
903 munmap((char *) base, info.st_size);
907 xmlParserCtxtPtr ctxt;
909 ctxt = xmlCreateFileParserCtxt(filename);
914 xmlParseDocument(ctxt);
915 if (ctxt->valid == 0)
917 ret = ctxt->wellFormed;
919 xmlFreeParserCtxt(ctxt);
926 doc = xmlParseFile(filename);
931 * If we don't have a document we might as well give up. Do we
932 * want an error message here? <sven@zen.org> */
938 if ((timing) && (!repeat)) {
943 * Remove DOCTYPE nodes
948 dtd = xmlGetIntSubset(doc);
950 xmlUnlinkNode((xmlNodePtr)dtd);
955 #ifdef LIBXML_XINCLUDE_ENABLED
957 if ((timing) && (!repeat)) {
960 xmlXIncludeProcess(doc);
961 if ((timing) && (!repeat)) {
962 endTimer("Xinclude processing");
967 #ifdef LIBXML_DEBUG_ENABLED
972 xmlShell(doc, filename, xmlShellReadline, stdout);
976 * test intermediate copy if needed.
980 doc = xmlCopyDoc(doc, 1);
984 if ((insert) && (!html)) {
985 const xmlChar* list[256];
989 if (doc->children != NULL) {
990 node = doc->children;
991 while ((node != NULL) && (node->last == NULL)) node = node->next;
993 nb = xmlValidGetValidElements(node->last, NULL, list, 256);
995 printf("could not get valid list of elements\n");
996 } else if (nb == 0) {
997 printf("No element can be inserted under root\n");
999 printf("%d element types can be inserted under root:\n",
1001 for (i = 0;i < nb;i++) {
1002 printf("%s\n", (char *) list[i]);
1007 }else if (noout == 0) {
1011 #ifdef LIBXML_DEBUG_ENABLED
1014 if ((timing) && (!repeat)) {
1017 #ifdef HAVE_SYS_MMAN_H
1022 if (encoding != NULL) {
1024 xmlDocDumpFormatMemoryEnc(doc, &result, &len, encoding, 1);
1026 xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
1030 xmlDocDumpFormatMemory(doc, &result, &len, 1);
1032 xmlDocDumpMemory(doc, &result, &len);
1034 if (result == NULL) {
1035 fprintf(stderr, "Failed to save\n");
1037 write(1, result, len);
1041 #endif /* HAVE_SYS_MMAN_H */
1043 xmlSaveFile(output ? output : "-", doc);
1045 else if (encoding != NULL) {
1047 xmlSaveFormatFileEnc(output ? output : "-", doc, encoding, 1);
1050 xmlSaveFileEnc(output ? output : "-", doc, encoding);
1054 xmlSaveFormatFile(output ? output : "-", doc, 1);
1061 out = fopen(output,"wb");
1063 xmlDocDump(out, doc);
1068 if ((timing) && (!repeat)) {
1071 #ifdef LIBXML_DEBUG_ENABLED
1077 out = fopen(output,"wb");
1079 xmlDebugDumpDocument(out, doc);
1088 * A posteriori validation test
1090 if (dtdvalid != NULL) {
1093 if ((timing) && (!repeat)) {
1096 dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid);
1097 if ((timing) && (!repeat)) {
1098 endTimer("Parsing DTD");
1101 xmlGenericError(xmlGenericErrorContext,
1102 "Could not parse DTD %s\n", dtdvalid);
1105 xmlValidCtxtPtr cvp;
1107 if ((cvp = xmlNewValidCtxt()) == NULL) {
1108 xmlGenericError(xmlGenericErrorContext,
1109 "Couldn't allocate validation context\n");
1112 cvp->userData = (void *) stderr;
1113 cvp->error = (xmlValidityErrorFunc) fprintf;
1114 cvp->warning = (xmlValidityWarningFunc) fprintf;
1116 if ((timing) && (!repeat)) {
1119 if (!xmlValidateDtd(cvp, doc, dtd)) {
1120 xmlGenericError(xmlGenericErrorContext,
1121 "Document %s does not validate against %s\n",
1122 filename, dtdvalid);
1125 if ((timing) && (!repeat)) {
1126 endTimer("Validating against DTD");
1128 xmlFreeValidCtxt(cvp);
1131 } else if (postvalid) {
1132 xmlValidCtxtPtr cvp;
1134 if ((cvp = xmlNewValidCtxt()) == NULL) {
1135 xmlGenericError(xmlGenericErrorContext,
1136 "Couldn't allocate validation context\n");
1140 if ((timing) && (!repeat)) {
1143 cvp->userData = (void *) stderr;
1144 cvp->error = (xmlValidityErrorFunc) fprintf;
1145 cvp->warning = (xmlValidityWarningFunc) fprintf;
1146 if (!xmlValidateDocument(cvp, doc)) {
1147 xmlGenericError(xmlGenericErrorContext,
1148 "Document %s does not validate\n", filename);
1151 if ((timing) && (!repeat)) {
1152 endTimer("Validating");
1154 xmlFreeValidCtxt(cvp);
1155 #ifdef LIBXML_SCHEMAS_ENABLED
1156 } else if (relaxngschemas != NULL) {
1157 xmlRelaxNGValidCtxtPtr ctxt;
1160 if ((timing) && (!repeat)) {
1164 ctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
1165 xmlRelaxNGSetValidErrors(ctxt,
1166 (xmlRelaxNGValidityErrorFunc) fprintf,
1167 (xmlRelaxNGValidityWarningFunc) fprintf,
1169 ret = xmlRelaxNGValidateDoc(ctxt, doc);
1171 printf("%s validates\n", filename);
1172 } else if (ret > 0) {
1173 printf("%s fails to validate\n", filename);
1175 printf("%s validation generated an internal error\n",
1178 xmlRelaxNGFreeValidCtxt(ctxt);
1179 if ((timing) && (!repeat)) {
1180 endTimer("Validating");
1182 } else if (wxschemas != NULL) {
1183 xmlSchemaValidCtxtPtr ctxt;
1186 if ((timing) && (!repeat)) {
1190 ctxt = xmlSchemaNewValidCtxt(wxschemas);
1191 xmlSchemaSetValidErrors(ctxt,
1192 (xmlSchemaValidityErrorFunc) fprintf,
1193 (xmlSchemaValidityWarningFunc) fprintf,
1195 ret = xmlSchemaValidateDoc(ctxt, doc);
1197 printf("%s validates\n", filename);
1198 } else if (ret > 0) {
1199 printf("%s fails to validate\n", filename);
1201 printf("%s validation generated an internal error\n",
1204 xmlSchemaFreeValidCtxt(ctxt);
1205 if ((timing) && (!repeat)) {
1206 endTimer("Validating");
1211 #ifdef LIBXML_DEBUG_ENABLED
1212 if ((debugent) && (!html))
1213 xmlDebugDumpEntities(stderr, doc);
1219 if ((timing) && (!repeat)) {
1223 if ((timing) && (!repeat)) {
1224 endTimer("Freeing");
1228 /************************************************************************
1232 ************************************************************************/
1234 static void showVersion(const char *name) {
1235 fprintf(stderr, "%s: using libxml version %s\n", name, xmlParserVersion);
1236 fprintf(stderr, " compiled with: ");
1237 #ifdef LIBXML_FTP_ENABLED
1238 fprintf(stderr, "FTP ");
1240 #ifdef LIBXML_HTTP_ENABLED
1241 fprintf(stderr, "HTTP ");
1243 #ifdef LIBXML_HTML_ENABLED
1244 fprintf(stderr, "HTML ");
1246 #ifdef LIBXML_C14N_ENABLED
1247 fprintf(stderr, "C14N ");
1249 #ifdef LIBXML_CATALOG_ENABLED
1250 fprintf(stderr, "Catalog ");
1252 #ifdef LIBXML_DOCB_ENABLED
1253 fprintf(stderr, "DocBook ");
1255 #ifdef LIBXML_XPATH_ENABLED
1256 fprintf(stderr, "XPath ");
1258 #ifdef LIBXML_XPTR_ENABLED
1259 fprintf(stderr, "XPointer ");
1261 #ifdef LIBXML_XINCLUDE_ENABLED
1262 fprintf(stderr, "XInclude ");
1264 #ifdef LIBXML_ICONV_ENABLED
1265 fprintf(stderr, "Iconv ");
1267 #ifdef DEBUG_MEMORY_LOCATION
1268 fprintf(stderr, "MemDebug ");
1270 #ifdef LIBXML_UNICODE_ENABLED
1271 fprintf(stderr, "Unicode ");
1273 #ifdef LIBXML_REGEXP_ENABLED
1274 fprintf(stderr, "Regexps ");
1276 #ifdef LIBXML_AUTOMATA_ENABLED
1277 fprintf(stderr, "Automata ");
1279 #ifdef LIBXML_SCHEMAS_ENABLED
1280 fprintf(stderr, "Schemas ");
1282 fprintf(stderr, "\n");
1285 static void usage(const char *name) {
1286 printf("Usage : %s [options] XMLfiles ...\n", name);
1287 printf("\tParse the XML files and output the result of the parsing\n");
1288 printf("\t--version : display the version of the XML library used\n");
1289 #ifdef LIBXML_DEBUG_ENABLED
1290 printf("\t--debug : dump a debug tree of the in-memory document\n");
1291 printf("\t--shell : run a navigating shell\n");
1292 printf("\t--debugent : debug the entities defined in the document\n");
1294 printf("\t--debug : dump the nodes content when using --stream\n");
1296 printf("\t--copy : used to test the internal copy implementation\n");
1297 printf("\t--recover : output what was parsable on broken XML documents\n");
1298 printf("\t--noent : substitute entity references by their value\n");
1299 printf("\t--noout : don't output the result tree\n");
1300 printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
1301 printf("\t--htmlout : output results as HTML\n");
1302 printf("\t--nowrap : do not put HTML doc wrapper\n");
1303 printf("\t--valid : validate the document in addition to std well-formed check\n");
1304 printf("\t--postvalid : do a posteriori validation, i.e after parsing\n");
1305 printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n");
1306 printf("\t--timing : print some timings\n");
1307 printf("\t--output file or -o file: save to a given file\n");
1308 printf("\t--repeat : repeat 100 times, for timing or profiling\n");
1309 printf("\t--insert : ad-hoc test for valid insertions\n");
1311 printf("\t--compress : turn on gzip compression of output\n");
1313 #ifdef LIBXML_DOCB_ENABLED
1314 printf("\t--sgml : use the DocBook SGML parser\n");
1316 #ifdef LIBXML_HTML_ENABLED
1317 printf("\t--html : use the HTML parser\n");
1319 printf("\t--push : use the push mode of the parser\n");
1320 #ifdef HAVE_SYS_MMAN_H
1321 printf("\t--memory : parse from memory\n");
1323 printf("\t--nowarning : do not emit warnings from parser/validator\n");
1324 printf("\t--noblanks : drop (ignorable?) blanks spaces\n");
1325 printf("\t--format : reformat/reindent the input\n");
1326 printf("\t--testIO : test user I/O support\n");
1327 printf("\t--encode encoding : output in the given encoding\n");
1328 #ifdef LIBXML_CATALOG_ENABLED
1329 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
1330 printf("\t otherwise XML Catalogs starting from \n");
1331 printf("\t " XML_XML_DEFAULT_CATALOG " are activated by default\n");
1332 printf("\t--nocatalogs: deactivate all catalogs\n");
1334 printf("\t--auto : generate a small doc on the fly\n");
1335 #ifdef LIBXML_XINCLUDE_ENABLED
1336 printf("\t--xinclude : do XInclude processing\n");
1338 printf("\t--loaddtd : fetch external DTD\n");
1339 printf("\t--dtdattr : loaddtd + populate the tree with inherited attributes \n");
1340 printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
1341 printf("\t--stream : use the streaming interface to process very large files\n");
1342 printf("\t--chkregister : verify the node registration code\n");
1343 #ifdef LIBXML_SCHEMAS_ENABLED
1344 printf("\t--relaxng schema : do RelaxNG validation against the schema\n");
1345 printf("\t--schema schema : do validation against the WXS schema\n");
1347 printf("\nLibxml project home page: http://xmlsoft.org/\n");
1348 printf("To report bugs or get some help check: http://xmlsoft.org/bugs.html\n");
1351 static void registerNode(xmlNodePtr node)
1353 node->_private = malloc(sizeof(long));
1354 *(long*)node->_private = (long) 0x81726354;
1357 static void deregisterNode(xmlNodePtr node)
1359 assert(node->_private != NULL);
1360 assert(*(long*)node->_private == (long) 0x81726354);
1361 free(node->_private);
1365 main(int argc, char **argv) {
1376 for (i = 1; i < argc ; i++) {
1377 if (!strcmp(argv[i], "-"))
1380 if (argv[i][0] != '-')
1382 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
1385 #ifdef LIBXML_DEBUG_ENABLED
1386 if ((!strcmp(argv[i], "-shell")) ||
1387 (!strcmp(argv[i], "--shell"))) {
1392 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
1394 else if ((!strcmp(argv[i], "-recover")) ||
1395 (!strcmp(argv[i], "--recover")))
1397 else if ((!strcmp(argv[i], "-noent")) ||
1398 (!strcmp(argv[i], "--noent")))
1400 else if ((!strcmp(argv[i], "-version")) ||
1401 (!strcmp(argv[i], "--version"))) {
1402 showVersion(argv[0]);
1404 } else if ((!strcmp(argv[i], "-noout")) ||
1405 (!strcmp(argv[i], "--noout")))
1407 else if ((!strcmp(argv[i], "-o")) ||
1408 (!strcmp(argv[i], "-output")) ||
1409 (!strcmp(argv[i], "--output"))) {
1413 else if ((!strcmp(argv[i], "-htmlout")) ||
1414 (!strcmp(argv[i], "--htmlout")))
1416 #ifdef LIBXML_DOCB_ENABLED
1417 else if ((!strcmp(argv[i], "-sgml")) ||
1418 (!strcmp(argv[i], "--sgml"))) {
1422 #ifdef LIBXML_HTML_ENABLED
1423 else if ((!strcmp(argv[i], "-html")) ||
1424 (!strcmp(argv[i], "--html"))) {
1427 #endif /* LIBXML_HTML_ENABLED */
1428 else if ((!strcmp(argv[i], "-nowrap")) ||
1429 (!strcmp(argv[i], "--nowrap")))
1431 else if ((!strcmp(argv[i], "-loaddtd")) ||
1432 (!strcmp(argv[i], "--loaddtd")))
1434 else if ((!strcmp(argv[i], "-dtdattr")) ||
1435 (!strcmp(argv[i], "--dtdattr"))) {
1438 } else if ((!strcmp(argv[i], "-valid")) ||
1439 (!strcmp(argv[i], "--valid")))
1441 else if ((!strcmp(argv[i], "-postvalid")) ||
1442 (!strcmp(argv[i], "--postvalid"))) {
1445 } else if ((!strcmp(argv[i], "-dtdvalid")) ||
1446 (!strcmp(argv[i], "--dtdvalid"))) {
1451 else if ((!strcmp(argv[i], "-dropdtd")) ||
1452 (!strcmp(argv[i], "--dropdtd")))
1454 else if ((!strcmp(argv[i], "-insert")) ||
1455 (!strcmp(argv[i], "--insert")))
1457 else if ((!strcmp(argv[i], "-timing")) ||
1458 (!strcmp(argv[i], "--timing")))
1460 else if ((!strcmp(argv[i], "-auto")) ||
1461 (!strcmp(argv[i], "--auto")))
1463 else if ((!strcmp(argv[i], "-repeat")) ||
1464 (!strcmp(argv[i], "--repeat")))
1466 else if ((!strcmp(argv[i], "-push")) ||
1467 (!strcmp(argv[i], "--push")))
1469 #ifdef HAVE_SYS_MMAN_H
1470 else if ((!strcmp(argv[i], "-memory")) ||
1471 (!strcmp(argv[i], "--memory")))
1474 else if ((!strcmp(argv[i], "-testIO")) ||
1475 (!strcmp(argv[i], "--testIO")))
1477 #ifdef LIBXML_XINCLUDE_ENABLED
1478 else if ((!strcmp(argv[i], "-xinclude")) ||
1479 (!strcmp(argv[i], "--xinclude")))
1483 else if ((!strcmp(argv[i], "-compress")) ||
1484 (!strcmp(argv[i], "--compress"))) {
1486 xmlSetCompressMode(9);
1489 else if ((!strcmp(argv[i], "-nowarning")) ||
1490 (!strcmp(argv[i], "--nowarning"))) {
1491 xmlGetWarningsDefaultValue = 0;
1492 xmlPedanticParserDefault(0);
1494 else if ((!strcmp(argv[i], "-pedantic")) ||
1495 (!strcmp(argv[i], "--pedantic"))) {
1496 xmlGetWarningsDefaultValue = 1;
1497 xmlPedanticParserDefault(1);
1499 #ifdef LIBXML_DEBUG_ENABLED
1500 else if ((!strcmp(argv[i], "-debugent")) ||
1501 (!strcmp(argv[i], "--debugent"))) {
1503 xmlParserDebugEntities = 1;
1506 #ifdef LIBXML_CATALOG_ENABLED
1507 else if ((!strcmp(argv[i], "-catalogs")) ||
1508 (!strcmp(argv[i], "--catalogs"))) {
1510 } else if ((!strcmp(argv[i], "-nocatalogs")) ||
1511 (!strcmp(argv[i], "--nocatalogs"))) {
1515 else if ((!strcmp(argv[i], "-encode")) ||
1516 (!strcmp(argv[i], "--encode"))) {
1520 * OK it's for testing purposes
1522 xmlAddEncodingAlias("UTF-8", "DVEnc");
1524 else if ((!strcmp(argv[i], "-noblanks")) ||
1525 (!strcmp(argv[i], "--noblanks"))) {
1527 xmlKeepBlanksDefault(0);
1529 else if ((!strcmp(argv[i], "-format")) ||
1530 (!strcmp(argv[i], "--format"))) {
1533 xmlKeepBlanksDefault(0);
1535 else if ((!strcmp(argv[i], "-stream")) ||
1536 (!strcmp(argv[i], "--stream"))) {
1539 else if ((!strcmp(argv[i], "-chkregister")) ||
1540 (!strcmp(argv[i], "--chkregister"))) {
1542 #ifdef LIBXML_SCHEMAS_ENABLED
1543 } else if ((!strcmp(argv[i], "-relaxng")) ||
1544 (!strcmp(argv[i], "--relaxng"))) {
1548 } else if ((!strcmp(argv[i], "-schema")) ||
1549 (!strcmp(argv[i], "--schema"))) {
1554 } else if ((!strcmp(argv[i], "-nonet")) ||
1555 (!strcmp(argv[i], "--nonet"))) {
1556 xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
1558 fprintf(stderr, "Unknown option %s\n", argv[i]);
1564 #ifdef LIBXML_CATALOG_ENABLED
1565 if (nocatalogs == 0) {
1569 catal = getenv("SGML_CATALOG_FILES");
1570 if (catal != NULL) {
1571 xmlLoadCatalogs(catal);
1573 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
1580 xmlRegisterNodeDefault(registerNode);
1581 xmlDeregisterNodeDefault(deregisterNode);
1584 indent = getenv("XMLLINT_INDENT");
1585 if(indent != NULL) {
1586 xmlTreeIndentString = indent;
1590 xmlLineNumbersDefault(1);
1592 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
1594 xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
1595 if (noent != 0) xmlSubstituteEntitiesDefault(1);
1596 if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
1597 if ((htmlout) && (!nowrap)) {
1598 xmlGenericError(xmlGenericErrorContext,
1599 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n");
1600 xmlGenericError(xmlGenericErrorContext,
1601 "\t\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n");
1602 xmlGenericError(xmlGenericErrorContext,
1603 "<html><head><title>%s output</title></head>\n",
1605 xmlGenericError(xmlGenericErrorContext,
1606 "<body bgcolor=\"#ffffff\"><h1 align=\"center\">%s output</h1>\n",
1610 #ifdef LIBXML_SCHEMAS_ENABLED
1611 if ((relaxng != NULL) && (stream == 0)) {
1612 xmlRelaxNGParserCtxtPtr ctxt;
1614 /* forces loading the DTDs */
1615 xmlLoadExtDtdDefaultValue |= 1;
1619 ctxt = xmlRelaxNGNewParserCtxt(relaxng);
1620 xmlRelaxNGSetParserErrors(ctxt,
1621 (xmlRelaxNGValidityErrorFunc) fprintf,
1622 (xmlRelaxNGValidityWarningFunc) fprintf,
1624 relaxngschemas = xmlRelaxNGParse(ctxt);
1625 if (relaxngschemas == NULL) {
1626 xmlGenericError(xmlGenericErrorContext,
1627 "Relax-NG schema %s failed to compile\n", relaxng);
1630 xmlRelaxNGFreeParserCtxt(ctxt);
1632 endTimer("Compiling the schemas");
1634 } else if ((schema != NULL) && (stream == 0)) {
1635 xmlSchemaParserCtxtPtr ctxt;
1640 ctxt = xmlSchemaNewParserCtxt(schema);
1641 xmlSchemaSetParserErrors(ctxt,
1642 (xmlSchemaValidityErrorFunc) fprintf,
1643 (xmlSchemaValidityWarningFunc) fprintf,
1645 wxschemas = xmlSchemaParse(ctxt);
1646 if (wxschemas == NULL) {
1647 xmlGenericError(xmlGenericErrorContext,
1648 "WXS schema %s failed to compile\n", schema);
1651 xmlSchemaFreeParserCtxt(ctxt);
1653 endTimer("Compiling the schemas");
1657 for (i = 1; i < argc ; i++) {
1658 if ((!strcmp(argv[i], "-encode")) ||
1659 (!strcmp(argv[i], "--encode"))) {
1662 } else if ((!strcmp(argv[i], "-o")) ||
1663 (!strcmp(argv[i], "-output")) ||
1664 (!strcmp(argv[i], "--output"))) {
1668 if ((!strcmp(argv[i], "-dtdvalid")) ||
1669 (!strcmp(argv[i], "--dtdvalid"))) {
1673 if ((!strcmp(argv[i], "-relaxng")) ||
1674 (!strcmp(argv[i], "--relaxng"))) {
1678 if ((!strcmp(argv[i], "-schema")) ||
1679 (!strcmp(argv[i], "--schema"))) {
1683 if ((timing) && (repeat))
1685 /* Remember file names. "-" means stdin. <sven@zen.org> */
1686 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
1688 for (acount = 0;acount < 100 * repeat;acount++)
1690 streamFile(argv[i]);
1692 parseAndPrintFile(argv[i]);
1695 streamFile(argv[i]);
1697 parseAndPrintFile(argv[i]);
1700 if ((timing) && (repeat)) {
1701 endTimer("100 iterations");
1706 parseAndPrintFile(NULL);
1707 if ((htmlout) && (!nowrap)) {
1708 xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
1710 if ((files == 0) && (!generate) && (version == 0)) {
1713 #ifdef LIBXML_SCHEMAS_ENABLED
1714 if (relaxngschemas != NULL)
1715 xmlRelaxNGFree(relaxngschemas);
1716 if (wxschemas != NULL)
1717 xmlSchemaFree(wxschemas);
1718 xmlRelaxNGCleanupTypes();