testHTML.c revision d6d7f7bf96a87688cc4bf756cf98367018e3ef88
1/* 2 * testHTML.c : a small tester program for HTML input. 3 * 4 * See Copyright for the status of this software. 5 * 6 * Daniel.Veillard@w3.org 7 */ 8 9#ifdef WIN32 10#include "win32config.h" 11#else 12#include "config.h" 13#endif 14 15#include <libxml/xmlversion.h> 16#ifdef LIBXML_HTML_ENABLED 17 18#include <stdio.h> 19#include <string.h> 20#include <stdarg.h> 21 22 23#ifdef HAVE_SYS_TYPES_H 24#include <sys/types.h> 25#endif 26#ifdef HAVE_SYS_STAT_H 27#include <sys/stat.h> 28#endif 29#ifdef HAVE_FCNTL_H 30#include <fcntl.h> 31#endif 32#ifdef HAVE_UNISTD_H 33#include <unistd.h> 34#endif 35#ifdef HAVE_STDLIB_H 36#include <stdlib.h> 37#endif 38 39#include <libxml/xmlmemory.h> 40#include <libxml/HTMLparser.h> 41#include <libxml/HTMLtree.h> 42#include <libxml/debugXML.h> 43#include <libxml/xmlerror.h> 44 45#ifdef LIBXML_DEBUG_ENABLED 46static int debug = 0; 47#endif 48static int copy = 0; 49static int sax = 0; 50static int repeat = 0; 51static int noout = 0; 52static int push = 0; 53static char *encoding = NULL; 54 55xmlSAXHandler emptySAXHandlerStruct = { 56 NULL, /* internalSubset */ 57 NULL, /* isStandalone */ 58 NULL, /* hasInternalSubset */ 59 NULL, /* hasExternalSubset */ 60 NULL, /* resolveEntity */ 61 NULL, /* getEntity */ 62 NULL, /* entityDecl */ 63 NULL, /* notationDecl */ 64 NULL, /* attributeDecl */ 65 NULL, /* elementDecl */ 66 NULL, /* unparsedEntityDecl */ 67 NULL, /* setDocumentLocator */ 68 NULL, /* startDocument */ 69 NULL, /* endDocument */ 70 NULL, /* startElement */ 71 NULL, /* endElement */ 72 NULL, /* reference */ 73 NULL, /* characters */ 74 NULL, /* ignorableWhitespace */ 75 NULL, /* processingInstruction */ 76 NULL, /* comment */ 77 NULL, /* xmlParserWarning */ 78 NULL, /* xmlParserError */ 79 NULL, /* xmlParserError */ 80 NULL, /* getParameterEntity */ 81}; 82 83xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct; 84extern xmlSAXHandlerPtr debugSAXHandler; 85 86/************************************************************************ 87 * * 88 * Debug Handlers * 89 * * 90 ************************************************************************/ 91 92/** 93 * isStandaloneDebug: 94 * @ctxt: An XML parser context 95 * 96 * Is this document tagged standalone ? 97 * 98 * Returns 1 if true 99 */ 100int 101isStandaloneDebug(void *ctx) 102{ 103 fprintf(stdout, "SAX.isStandalone()\n"); 104 return(0); 105} 106 107/** 108 * hasInternalSubsetDebug: 109 * @ctxt: An XML parser context 110 * 111 * Does this document has an internal subset 112 * 113 * Returns 1 if true 114 */ 115int 116hasInternalSubsetDebug(void *ctx) 117{ 118 fprintf(stdout, "SAX.hasInternalSubset()\n"); 119 return(0); 120} 121 122/** 123 * hasExternalSubsetDebug: 124 * @ctxt: An XML parser context 125 * 126 * Does this document has an external subset 127 * 128 * Returns 1 if true 129 */ 130int 131hasExternalSubsetDebug(void *ctx) 132{ 133 fprintf(stdout, "SAX.hasExternalSubset()\n"); 134 return(0); 135} 136 137/** 138 * hasInternalSubsetDebug: 139 * @ctxt: An XML parser context 140 * 141 * Does this document has an internal subset 142 */ 143void 144internalSubsetDebug(void *ctx, const xmlChar *name, 145 const xmlChar *ExternalID, const xmlChar *SystemID) 146{ 147 fprintf(stdout, "SAX.internalSubset(%s,", name); 148 if (ExternalID == NULL) 149 fprintf(stdout, " ,"); 150 else 151 fprintf(stdout, " %s,", ExternalID); 152 if (SystemID == NULL) 153 fprintf(stdout, " )\n"); 154 else 155 fprintf(stdout, " %s)\n", SystemID); 156} 157 158/** 159 * resolveEntityDebug: 160 * @ctxt: An XML parser context 161 * @publicId: The public ID of the entity 162 * @systemId: The system ID of the entity 163 * 164 * Special entity resolver, better left to the parser, it has 165 * more context than the application layer. 166 * The default behaviour is to NOT resolve the entities, in that case 167 * the ENTITY_REF nodes are built in the structure (and the parameter 168 * values). 169 * 170 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 171 */ 172xmlParserInputPtr 173resolveEntityDebug(void *ctx, const xmlChar *publicId, const xmlChar *systemId) 174{ 175 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 176 177 178 fprintf(stdout, "SAX.resolveEntity("); 179 if (publicId != NULL) 180 fprintf(stdout, "%s", (char *)publicId); 181 else 182 fprintf(stdout, " "); 183 if (systemId != NULL) 184 fprintf(stdout, ", %s)\n", (char *)systemId); 185 else 186 fprintf(stdout, ", )\n"); 187/********* 188 if (systemId != NULL) { 189 return(xmlNewInputFromFile(ctxt, (char *) systemId)); 190 } 191 *********/ 192 return(NULL); 193} 194 195/** 196 * getEntityDebug: 197 * @ctxt: An XML parser context 198 * @name: The entity name 199 * 200 * Get an entity by name 201 * 202 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 203 */ 204xmlEntityPtr 205getEntityDebug(void *ctx, const xmlChar *name) 206{ 207 fprintf(stdout, "SAX.getEntity(%s)\n", name); 208 return(NULL); 209} 210 211/** 212 * getParameterEntityDebug: 213 * @ctxt: An XML parser context 214 * @name: The entity name 215 * 216 * Get a parameter entity by name 217 * 218 * Returns the xmlParserInputPtr 219 */ 220xmlEntityPtr 221getParameterEntityDebug(void *ctx, const xmlChar *name) 222{ 223 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name); 224 return(NULL); 225} 226 227 228/** 229 * entityDeclDebug: 230 * @ctxt: An XML parser context 231 * @name: the entity name 232 * @type: the entity type 233 * @publicId: The public ID of the entity 234 * @systemId: The system ID of the entity 235 * @content: the entity value (without processing). 236 * 237 * An entity definition has been parsed 238 */ 239void 240entityDeclDebug(void *ctx, const xmlChar *name, int type, 241 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 242{ 243 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n", 244 name, type, publicId, systemId, content); 245} 246 247/** 248 * attributeDeclDebug: 249 * @ctxt: An XML parser context 250 * @name: the attribute name 251 * @type: the attribute type 252 * 253 * An attribute definition has been parsed 254 */ 255void 256attributeDeclDebug(void *ctx, const xmlChar *elem, const xmlChar *name, 257 int type, int def, const xmlChar *defaultValue, 258 xmlEnumerationPtr tree) 259{ 260 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n", 261 elem, name, type, def, defaultValue); 262} 263 264/** 265 * elementDeclDebug: 266 * @ctxt: An XML parser context 267 * @name: the element name 268 * @type: the element type 269 * @content: the element value (without processing). 270 * 271 * An element definition has been parsed 272 */ 273void 274elementDeclDebug(void *ctx, const xmlChar *name, int type, 275 xmlElementContentPtr content) 276{ 277 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n", 278 name, type); 279} 280 281/** 282 * notationDeclDebug: 283 * @ctxt: An XML parser context 284 * @name: The name of the notation 285 * @publicId: The public ID of the entity 286 * @systemId: The system ID of the entity 287 * 288 * What to do when a notation declaration has been parsed. 289 */ 290void 291notationDeclDebug(void *ctx, const xmlChar *name, 292 const xmlChar *publicId, const xmlChar *systemId) 293{ 294 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n", 295 (char *) name, (char *) publicId, (char *) systemId); 296} 297 298/** 299 * unparsedEntityDeclDebug: 300 * @ctxt: An XML parser context 301 * @name: The name of the entity 302 * @publicId: The public ID of the entity 303 * @systemId: The system ID of the entity 304 * @notationName: the name of the notation 305 * 306 * What to do when an unparsed entity declaration is parsed 307 */ 308void 309unparsedEntityDeclDebug(void *ctx, const xmlChar *name, 310 const xmlChar *publicId, const xmlChar *systemId, 311 const xmlChar *notationName) 312{ 313 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n", 314 (char *) name, (char *) publicId, (char *) systemId, 315 (char *) notationName); 316} 317 318/** 319 * setDocumentLocatorDebug: 320 * @ctxt: An XML parser context 321 * @loc: A SAX Locator 322 * 323 * Receive the document locator at startup, actually xmlDefaultSAXLocator 324 * Everything is available on the context, so this is useless in our case. 325 */ 326void 327setDocumentLocatorDebug(void *ctx, xmlSAXLocatorPtr loc) 328{ 329 fprintf(stdout, "SAX.setDocumentLocator()\n"); 330} 331 332/** 333 * startDocumentDebug: 334 * @ctxt: An XML parser context 335 * 336 * called when the document start being processed. 337 */ 338void 339startDocumentDebug(void *ctx) 340{ 341 fprintf(stdout, "SAX.startDocument()\n"); 342} 343 344/** 345 * endDocumentDebug: 346 * @ctxt: An XML parser context 347 * 348 * called when the document end has been detected. 349 */ 350void 351endDocumentDebug(void *ctx) 352{ 353 fprintf(stdout, "SAX.endDocument()\n"); 354} 355 356/** 357 * startElementDebug: 358 * @ctxt: An XML parser context 359 * @name: The element name 360 * 361 * called when an opening tag has been processed. 362 */ 363void 364startElementDebug(void *ctx, const xmlChar *name, const xmlChar **atts) 365{ 366 int i; 367 368 fprintf(stdout, "SAX.startElement(%s", (char *) name); 369 if (atts != NULL) { 370 for (i = 0;(atts[i] != NULL);i++) { 371 fprintf(stdout, ", %s", atts[i++]); 372 if (atts[i] != NULL) { 373 unsigned char output[40]; 374 const unsigned char *att = atts[i]; 375 int outlen, attlen; 376 fprintf(stdout, "='"); 377 while ((attlen = strlen((char*)att)) > 0) { 378 outlen = sizeof output - 1; 379 htmlEncodeEntities(output, &outlen, att, &attlen, '\''); 380 fprintf(stdout, "%.*s", outlen, output); 381 att += attlen; 382 } 383 fprintf(stdout, "'"); 384 } 385 } 386 } 387 fprintf(stdout, ")\n"); 388} 389 390/** 391 * endElementDebug: 392 * @ctxt: An XML parser context 393 * @name: The element name 394 * 395 * called when the end of an element has been detected. 396 */ 397void 398endElementDebug(void *ctx, const xmlChar *name) 399{ 400 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name); 401} 402 403/** 404 * charactersDebug: 405 * @ctxt: An XML parser context 406 * @ch: a xmlChar string 407 * @len: the number of xmlChar 408 * 409 * receiving some chars from the parser. 410 * Question: how much at a time ??? 411 */ 412void 413charactersDebug(void *ctx, const xmlChar *ch, int len) 414{ 415 unsigned char output[40]; 416 int inlen = len, outlen = 30; 417 418 htmlEncodeEntities(output, &outlen, ch, &inlen, 0); 419 output[outlen] = 0; 420 421 fprintf(stdout, "SAX.characters(%s, %d)\n", output, len); 422} 423 424/** 425 * cdataDebug: 426 * @ctxt: An XML parser context 427 * @ch: a xmlChar string 428 * @len: the number of xmlChar 429 * 430 * receiving some cdata chars from the parser. 431 * Question: how much at a time ??? 432 */ 433void 434cdataDebug(void *ctx, const xmlChar *ch, int len) 435{ 436 unsigned char output[40]; 437 int inlen = len, outlen = 30; 438 439 htmlEncodeEntities(output, &outlen, ch, &inlen, 0); 440 output[outlen] = 0; 441 442 fprintf(stdout, "SAX.cdata(%s, %d)\n", output, len); 443} 444 445/** 446 * referenceDebug: 447 * @ctxt: An XML parser context 448 * @name: The entity name 449 * 450 * called when an entity reference is detected. 451 */ 452void 453referenceDebug(void *ctx, const xmlChar *name) 454{ 455 fprintf(stdout, "SAX.reference(%s)\n", name); 456} 457 458/** 459 * ignorableWhitespaceDebug: 460 * @ctxt: An XML parser context 461 * @ch: a xmlChar string 462 * @start: the first char in the string 463 * @len: the number of xmlChar 464 * 465 * receiving some ignorable whitespaces from the parser. 466 * Question: how much at a time ??? 467 */ 468void 469ignorableWhitespaceDebug(void *ctx, const xmlChar *ch, int len) 470{ 471 char output[40]; 472 int i; 473 474 for (i = 0;(i<len) && (i < 30);i++) 475 output[i] = ch[i]; 476 output[i] = 0; 477 478 fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", output, len); 479} 480 481/** 482 * processingInstructionDebug: 483 * @ctxt: An XML parser context 484 * @target: the target name 485 * @data: the PI data's 486 * @len: the number of xmlChar 487 * 488 * A processing instruction has been parsed. 489 */ 490void 491processingInstructionDebug(void *ctx, const xmlChar *target, 492 const xmlChar *data) 493{ 494 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n", 495 (char *) target, (char *) data); 496} 497 498/** 499 * commentDebug: 500 * @ctxt: An XML parser context 501 * @value: the comment content 502 * 503 * A comment has been parsed. 504 */ 505void 506commentDebug(void *ctx, const xmlChar *value) 507{ 508 fprintf(stdout, "SAX.comment(%s)\n", value); 509} 510 511/** 512 * warningDebug: 513 * @ctxt: An XML parser context 514 * @msg: the message to display/transmit 515 * @...: extra parameters for the message display 516 * 517 * Display and format a warning messages, gives file, line, position and 518 * extra parameters. 519 */ 520void 521warningDebug(void *ctx, const char *msg, ...) 522{ 523 va_list args; 524 525 va_start(args, msg); 526 fprintf(stdout, "SAX.warning: "); 527 vfprintf(stdout, msg, args); 528 va_end(args); 529} 530 531/** 532 * errorDebug: 533 * @ctxt: An XML parser context 534 * @msg: the message to display/transmit 535 * @...: extra parameters for the message display 536 * 537 * Display and format a error messages, gives file, line, position and 538 * extra parameters. 539 */ 540void 541errorDebug(void *ctx, const char *msg, ...) 542{ 543 va_list args; 544 545 va_start(args, msg); 546 fprintf(stdout, "SAX.error: "); 547 vfprintf(stdout, msg, args); 548 va_end(args); 549} 550 551/** 552 * fatalErrorDebug: 553 * @ctxt: An XML parser context 554 * @msg: the message to display/transmit 555 * @...: extra parameters for the message display 556 * 557 * Display and format a fatalError messages, gives file, line, position and 558 * extra parameters. 559 */ 560void 561fatalErrorDebug(void *ctx, const char *msg, ...) 562{ 563 va_list args; 564 565 va_start(args, msg); 566 fprintf(stdout, "SAX.fatalError: "); 567 vfprintf(stdout, msg, args); 568 va_end(args); 569} 570 571xmlSAXHandler debugSAXHandlerStruct = { 572 internalSubsetDebug, 573 isStandaloneDebug, 574 hasInternalSubsetDebug, 575 hasExternalSubsetDebug, 576 resolveEntityDebug, 577 getEntityDebug, 578 entityDeclDebug, 579 notationDeclDebug, 580 attributeDeclDebug, 581 elementDeclDebug, 582 unparsedEntityDeclDebug, 583 setDocumentLocatorDebug, 584 startDocumentDebug, 585 endDocumentDebug, 586 startElementDebug, 587 endElementDebug, 588 referenceDebug, 589 charactersDebug, 590 ignorableWhitespaceDebug, 591 processingInstructionDebug, 592 commentDebug, 593 warningDebug, 594 errorDebug, 595 fatalErrorDebug, 596 getParameterEntityDebug, 597 cdataDebug, 598 NULL 599}; 600 601xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct; 602/************************************************************************ 603 * * 604 * Debug * 605 * * 606 ************************************************************************/ 607 608void parseSAXFile(char *filename) { 609 htmlDocPtr doc = NULL; 610 611 /* 612 * Empty callbacks for checking 613 */ 614 if (push) { 615 FILE *f; 616 617 f = fopen(filename, "r"); 618 if (f != NULL) { 619 int res, size = 3; 620 char chars[4096]; 621 htmlParserCtxtPtr ctxt; 622 623 /* if (repeat) */ 624 size = 4096; 625 res = fread(chars, 1, 4, f); 626 if (res > 0) { 627 ctxt = htmlCreatePushParserCtxt(emptySAXHandler, NULL, 628 chars, res, filename, 0); 629 while ((res = fread(chars, 1, size, f)) > 0) { 630 htmlParseChunk(ctxt, chars, res, 0); 631 } 632 htmlParseChunk(ctxt, chars, 0, 1); 633 doc = ctxt->myDoc; 634 htmlFreeParserCtxt(ctxt); 635 } 636 if (doc != NULL) { 637 fprintf(stdout, "htmlSAXParseFile returned non-NULL\n"); 638 xmlFreeDoc(doc); 639 } 640 fclose(f); 641 } 642 if (!noout) { 643 f = fopen(filename, "r"); 644 if (f != NULL) { 645 int res, size = 3; 646 char chars[4096]; 647 htmlParserCtxtPtr ctxt; 648 649 /* if (repeat) */ 650 size = 4096; 651 res = fread(chars, 1, 4, f); 652 if (res > 0) { 653 ctxt = htmlCreatePushParserCtxt(debugSAXHandler, NULL, 654 chars, res, filename, 0); 655 while ((res = fread(chars, 1, size, f)) > 0) { 656 htmlParseChunk(ctxt, chars, res, 0); 657 } 658 htmlParseChunk(ctxt, chars, 0, 1); 659 doc = ctxt->myDoc; 660 htmlFreeParserCtxt(ctxt); 661 } 662 if (doc != NULL) { 663 fprintf(stdout, "htmlSAXParseFile returned non-NULL\n"); 664 xmlFreeDoc(doc); 665 } 666 fclose(f); 667 } 668 } 669 } else { 670 doc = htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL); 671 if (doc != NULL) { 672 fprintf(stdout, "htmlSAXParseFile returned non-NULL\n"); 673 xmlFreeDoc(doc); 674 } 675 676 if (!noout) { 677 /* 678 * Debug callback 679 */ 680 doc = htmlSAXParseFile(filename, NULL, debugSAXHandler, NULL); 681 if (doc != NULL) { 682 fprintf(stdout, "htmlSAXParseFile returned non-NULL\n"); 683 xmlFreeDoc(doc); 684 } 685 } 686 } 687} 688 689void parseAndPrintFile(char *filename) { 690 htmlDocPtr doc = NULL, tmp; 691 692 /* 693 * build an HTML tree from a string; 694 */ 695 if (push) { 696 FILE *f; 697 698 f = fopen(filename, "r"); 699 if (f != NULL) { 700 int res, size = 3; 701 char chars[4096]; 702 htmlParserCtxtPtr ctxt; 703 704 /* if (repeat) */ 705 size = 4096; 706 res = fread(chars, 1, 4, f); 707 if (res > 0) { 708 ctxt = htmlCreatePushParserCtxt(NULL, NULL, 709 chars, res, filename, 0); 710 while ((res = fread(chars, 1, size, f)) > 0) { 711 htmlParseChunk(ctxt, chars, res, 0); 712 } 713 htmlParseChunk(ctxt, chars, 0, 1); 714 doc = ctxt->myDoc; 715 htmlFreeParserCtxt(ctxt); 716 } 717 fclose(f); 718 } 719 } else { 720 doc = htmlParseFile(filename, NULL); 721 } 722 if (doc == NULL) { 723 xmlGenericError(xmlGenericErrorContext, 724 "Could not parse %s\n", filename); 725 } 726 727 /* 728 * test intermediate copy if needed. 729 */ 730 if (copy) { 731 tmp = doc; 732 doc = xmlCopyDoc(doc, 1); 733 xmlFreeDoc(tmp); 734 } 735 736 /* 737 * print it. 738 */ 739 if (!noout) { 740#ifdef LIBXML_DEBUG_ENABLED 741 if (!debug) { 742 if (encoding) 743 htmlSaveFileEnc("-", doc, encoding); 744 else 745 htmlDocDump(stdout, doc); 746 } else 747 xmlDebugDumpDocument(stdout, doc); 748#else 749 if (encoding) 750 htmlSaveFileEnc("-", doc, encoding); 751 else 752 htmlDocDump(stdout, doc); 753#endif 754 } 755 756 /* 757 * free it. 758 */ 759 xmlFreeDoc(doc); 760} 761 762int main(int argc, char **argv) { 763 int i, count; 764 int files = 0; 765 766 for (i = 1; i < argc ; i++) { 767#ifdef LIBXML_DEBUG_ENABLED 768 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) 769 debug++; 770 else 771#endif 772 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy"))) 773 copy++; 774 else if ((!strcmp(argv[i], "-push")) || (!strcmp(argv[i], "--push"))) 775 push++; 776 else if ((!strcmp(argv[i], "-sax")) || (!strcmp(argv[i], "--sax"))) 777 sax++; 778 else if ((!strcmp(argv[i], "-noout")) || (!strcmp(argv[i], "--noout"))) 779 noout++; 780 else if ((!strcmp(argv[i], "-repeat")) || 781 (!strcmp(argv[i], "--repeat"))) 782 repeat++; 783 else if ((!strcmp(argv[i], "-encode")) || 784 (!strcmp(argv[i], "--encode"))) { 785 i++; 786 encoding = argv[i]; 787 } 788 } 789 for (i = 1; i < argc ; i++) { 790 if ((!strcmp(argv[i], "-encode")) || 791 (!strcmp(argv[i], "--encode"))) { 792 i++; 793 continue; 794 } 795 if (argv[i][0] != '-') { 796 if (repeat) { 797 for (count = 0;count < 100 * repeat;count++) { 798 if (sax) 799 parseSAXFile(argv[i]); 800 else 801 parseAndPrintFile(argv[i]); 802 } 803 } else { 804 if (sax) 805 parseSAXFile(argv[i]); 806 else 807 parseAndPrintFile(argv[i]); 808 } 809 files ++; 810 } 811 } 812 if (files == 0) { 813 printf("Usage : %s [--debug] [--copy] [--copy] HTMLfiles ...\n", 814 argv[0]); 815 printf("\tParse the HTML files and output the result of the parsing\n"); 816#ifdef LIBXML_DEBUG_ENABLED 817 printf("\t--debug : dump a debug tree of the in-memory document\n"); 818#endif 819 printf("\t--copy : used to test the internal copy implementation\n"); 820 printf("\t--sax : debug the sequence of SAX callbacks\n"); 821 printf("\t--repeat : parse the file 100 times, for timing\n"); 822 printf("\t--noout : do not print the result\n"); 823 printf("\t--push : use the push mode parser\n"); 824 printf("\t--encode encoding : output in the given encoding\n"); 825 } 826 xmlCleanupParser(); 827 xmlMemoryDump(); 828 829 return(0); 830} 831#else /* !LIBXML_HTML_ENABLED */ 832#include <stdio.h> 833int main(int argc, char **argv) { 834 printf("%s : HTML support not compiled in\n", argv[0]); 835 return(0); 836} 837#endif 838