testSAX.c revision dd6b36766fb1cc83020cc12f226452ba2d640e35
1/* 2 * tester.c : a small tester program for parsing using the SAX API. 3 * 4 * See Copyright for the status of this software. 5 * 6 * Daniel.Veillard@w3.org 7 */ 8 9#ifdef WIN32 10#define HAVE_FCNTL_H 11#include <io.h> 12#else 13#include "config.h" 14#endif 15 16#include <stdio.h> 17#include <string.h> 18#include <stdarg.h> 19 20#ifdef HAVE_SYS_TYPES_H 21#include <sys/types.h> 22#endif 23#ifdef HAVE_SYS_STAT_H 24#include <sys/stat.h> 25#endif 26#ifdef HAVE_FCNTL_H 27#include <fcntl.h> 28#endif 29#ifdef HAVE_UNISTD_H 30#include <unistd.h> 31#endif 32#ifdef HAVE_STDLIB_H 33#include <stdlib.h> 34#endif 35 36 37#include "parser.h" 38#include "parserInternals.h" /* only for xmlNewInputFromFile() */ 39#include "tree.h" 40#include "debugXML.h" 41 42static int debug = 0; 43static int copy = 0; 44static int recovery = 0; 45 46xmlSAXHandler emptySAXHandlerStruct = { 47 NULL, /* internalSubset */ 48 NULL, /* isStandalone */ 49 NULL, /* hasInternalSubset */ 50 NULL, /* hasExternalSubset */ 51 NULL, /* resolveEntity */ 52 NULL, /* getEntity */ 53 NULL, /* entityDecl */ 54 NULL, /* notationDecl */ 55 NULL, /* attributeDecl */ 56 NULL, /* elementDecl */ 57 NULL, /* unparsedEntityDecl */ 58 NULL, /* setDocumentLocator */ 59 NULL, /* startDocument */ 60 NULL, /* endDocument */ 61 NULL, /* startElement */ 62 NULL, /* endElement */ 63 NULL, /* reference */ 64 NULL, /* characters */ 65 NULL, /* ignorableWhitespace */ 66 NULL, /* processingInstruction */ 67 NULL, /* comment */ 68 NULL, /* xmlParserWarning */ 69 NULL, /* xmlParserError */ 70 NULL, /* xmlParserError */ 71 NULL, /* getParameterEntity */ 72}; 73 74xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct; 75extern xmlSAXHandlerPtr debugSAXHandler; 76 77/* 78 * Note: there is a couple of errors introduced on purpose. 79 */ 80static xmlChar buffer[] = 81"<?xml version=\"1.0\"?>\n\ 82<?xml:namespace ns = \"http://www.ietf.org/standards/dav/\" prefix = \"D\"?>\n\ 83<?xml:namespace ns = \"http://www.w3.com/standards/z39.50/\" prefix = \"Z\"?>\n\ 84<D:propertyupdate>\n\ 85<D:set a=\"'toto'\" b>\n\ 86 <D:prop>\n\ 87 <Z:authors>\n\ 88 <Z:Author>Jim Whitehead</Z:Author>\n\ 89 <Z:Author>Roy Fielding</Z:Author>\n\ 90 </Z:authors>\n\ 91 </D:prop>\n\ 92 </D:set>\n\ 93 <D:remove>\n\ 94 <D:prop><Z:Copyright-Owner/></D:prop>\n\ 95 </D:remove>\n\ 96</D:propertyupdate>\n\ 97\n\ 98"; 99 100/************************************************************************ 101 * * 102 * Debug Handlers * 103 * * 104 ************************************************************************/ 105 106/** 107 * isStandaloneDebug: 108 * @ctxt: An XML parser context 109 * 110 * Is this document tagged standalone ? 111 * 112 * Returns 1 if true 113 */ 114int 115isStandaloneDebug(void *ctx) 116{ 117 fprintf(stdout, "SAX.isStandalone()\n"); 118 return(0); 119} 120 121/** 122 * hasInternalSubsetDebug: 123 * @ctxt: An XML parser context 124 * 125 * Does this document has an internal subset 126 * 127 * Returns 1 if true 128 */ 129int 130hasInternalSubsetDebug(void *ctx) 131{ 132 fprintf(stdout, "SAX.hasInternalSubset()\n"); 133 return(0); 134} 135 136/** 137 * hasExternalSubsetDebug: 138 * @ctxt: An XML parser context 139 * 140 * Does this document has an external subset 141 * 142 * Returns 1 if true 143 */ 144int 145hasExternalSubsetDebug(void *ctx) 146{ 147 fprintf(stdout, "SAX.hasExternalSubset()\n"); 148 return(0); 149} 150 151/** 152 * hasInternalSubsetDebug: 153 * @ctxt: An XML parser context 154 * 155 * Does this document has an internal subset 156 */ 157void 158internalSubsetDebug(void *ctx, const xmlChar *name, 159 const xmlChar *ExternalID, const xmlChar *SystemID) 160{ 161 xmlDtdPtr externalSubset; 162 163 fprintf(stdout, "SAX.internalSubset(%s, %s, %s)\n", 164 name, ExternalID, SystemID); 165 166 if ((ExternalID != NULL) || (SystemID != NULL)) { 167 externalSubset = xmlParseDTD(ExternalID, SystemID); 168 if (externalSubset != NULL) { 169 xmlFreeDtd(externalSubset); 170 } 171 } 172} 173 174/** 175 * resolveEntityDebug: 176 * @ctxt: An XML parser context 177 * @publicId: The public ID of the entity 178 * @systemId: The system ID of the entity 179 * 180 * Special entity resolver, better left to the parser, it has 181 * more context than the application layer. 182 * The default behaviour is to NOT resolve the entities, in that case 183 * the ENTITY_REF nodes are built in the structure (and the parameter 184 * values). 185 * 186 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 187 */ 188xmlParserInputPtr 189resolveEntityDebug(void *ctx, const xmlChar *publicId, const xmlChar *systemId) 190{ 191 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; 192 193 194 fprintf(stdout, "SAX.resolveEntity("); 195 if (publicId != NULL) 196 fprintf(stdout, "%s", (char *)publicId); 197 else 198 fprintf(stdout, " "); 199 if (systemId != NULL) 200 fprintf(stdout, ", %s)\n", (char *)systemId); 201 else 202 fprintf(stdout, ", )\n"); 203 if (systemId != NULL) { 204 return(xmlNewInputFromFile(ctxt, (char *) systemId)); 205 } 206 return(NULL); 207} 208 209/** 210 * getEntityDebug: 211 * @ctxt: An XML parser context 212 * @name: The entity name 213 * 214 * Get an entity by name 215 * 216 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. 217 */ 218xmlEntityPtr 219getEntityDebug(void *ctx, const xmlChar *name) 220{ 221 fprintf(stdout, "SAX.getEntity(%s)\n", name); 222 return(NULL); 223} 224 225/** 226 * getParameterEntityDebug: 227 * @ctxt: An XML parser context 228 * @name: The entity name 229 * 230 * Get a parameter entity by name 231 * 232 * Returns the xmlParserInputPtr 233 */ 234xmlEntityPtr 235getParameterEntityDebug(void *ctx, const xmlChar *name) 236{ 237 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name); 238 return(NULL); 239} 240 241 242/** 243 * entityDeclDebug: 244 * @ctxt: An XML parser context 245 * @name: the entity name 246 * @type: the entity type 247 * @publicId: The public ID of the entity 248 * @systemId: The system ID of the entity 249 * @content: the entity value (without processing). 250 * 251 * An entity definition has been parsed 252 */ 253void 254entityDeclDebug(void *ctx, const xmlChar *name, int type, 255 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 256{ 257 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n", 258 name, type, publicId, systemId, content); 259} 260 261/** 262 * attributeDeclDebug: 263 * @ctxt: An XML parser context 264 * @name: the attribute name 265 * @type: the attribute type 266 * 267 * An attribute definition has been parsed 268 */ 269void 270attributeDeclDebug(void *ctx, const xmlChar *elem, const xmlChar *name, 271 int type, int def, const xmlChar *defaultValue, 272 xmlEnumerationPtr tree) 273{ 274 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n", 275 elem, name, type, def, defaultValue); 276} 277 278/** 279 * elementDeclDebug: 280 * @ctxt: An XML parser context 281 * @name: the element name 282 * @type: the element type 283 * @content: the element value (without processing). 284 * 285 * An element definition has been parsed 286 */ 287void 288elementDeclDebug(void *ctx, const xmlChar *name, int type, 289 xmlElementContentPtr content) 290{ 291 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n", 292 name, type); 293} 294 295/** 296 * notationDeclDebug: 297 * @ctxt: An XML parser context 298 * @name: The name of the notation 299 * @publicId: The public ID of the entity 300 * @systemId: The system ID of the entity 301 * 302 * What to do when a notation declaration has been parsed. 303 */ 304void 305notationDeclDebug(void *ctx, const xmlChar *name, 306 const xmlChar *publicId, const xmlChar *systemId) 307{ 308 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n", 309 (char *) name, (char *) publicId, (char *) systemId); 310} 311 312/** 313 * unparsedEntityDeclDebug: 314 * @ctxt: An XML parser context 315 * @name: The name of the entity 316 * @publicId: The public ID of the entity 317 * @systemId: The system ID of the entity 318 * @notationName: the name of the notation 319 * 320 * What to do when an unparsed entity declaration is parsed 321 */ 322void 323unparsedEntityDeclDebug(void *ctx, const xmlChar *name, 324 const xmlChar *publicId, const xmlChar *systemId, 325 const xmlChar *notationName) 326{ 327 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n", 328 (char *) name, (char *) publicId, (char *) systemId, 329 (char *) notationName); 330} 331 332/** 333 * setDocumentLocatorDebug: 334 * @ctxt: An XML parser context 335 * @loc: A SAX Locator 336 * 337 * Receive the document locator at startup, actually xmlDefaultSAXLocator 338 * Everything is available on the context, so this is useless in our case. 339 */ 340void 341setDocumentLocatorDebug(void *ctx, xmlSAXLocatorPtr loc) 342{ 343 fprintf(stdout, "SAX.setDocumentLocator()\n"); 344} 345 346/** 347 * startDocumentDebug: 348 * @ctxt: An XML parser context 349 * 350 * called when the document start being processed. 351 */ 352void 353startDocumentDebug(void *ctx) 354{ 355 fprintf(stdout, "SAX.startDocument()\n"); 356} 357 358/** 359 * endDocumentDebug: 360 * @ctxt: An XML parser context 361 * 362 * called when the document end has been detected. 363 */ 364void 365endDocumentDebug(void *ctx) 366{ 367 fprintf(stdout, "SAX.endDocument()\n"); 368} 369 370/** 371 * startElementDebug: 372 * @ctxt: An XML parser context 373 * @name: The element name 374 * 375 * called when an opening tag has been processed. 376 */ 377void 378startElementDebug(void *ctx, const xmlChar *name, const xmlChar **atts) 379{ 380 int i; 381 382 fprintf(stdout, "SAX.startElement(%s", (char *) name); 383 if (atts != NULL) { 384 for (i = 0;(atts[i] != NULL);i++) { 385 fprintf(stdout, ", %s='", atts[i++]); 386 fprintf(stdout, "%s'", atts[i]); 387 } 388 } 389 fprintf(stdout, ")\n"); 390} 391 392/** 393 * endElementDebug: 394 * @ctxt: An XML parser context 395 * @name: The element name 396 * 397 * called when the end of an element has been detected. 398 */ 399void 400endElementDebug(void *ctx, const xmlChar *name) 401{ 402 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name); 403} 404 405/** 406 * charactersDebug: 407 * @ctxt: An XML parser context 408 * @ch: a xmlChar string 409 * @len: the number of xmlChar 410 * 411 * receiving some chars from the parser. 412 * Question: how much at a time ??? 413 */ 414void 415charactersDebug(void *ctx, const xmlChar *ch, int len) 416{ 417 int i; 418 419 fprintf(stdout, "SAX.characters("); 420 for (i = 0;(i < len) && (i < 30);i++) 421 fprintf(stdout, "%c", ch[i]); 422 fprintf(stdout, ", %d)\n", len); 423} 424 425/** 426 * referenceDebug: 427 * @ctxt: An XML parser context 428 * @name: The entity name 429 * 430 * called when an entity reference is detected. 431 */ 432void 433referenceDebug(void *ctx, const xmlChar *name) 434{ 435 fprintf(stdout, "SAX.reference(%s)\n", name); 436} 437 438/** 439 * ignorableWhitespaceDebug: 440 * @ctxt: An XML parser context 441 * @ch: a xmlChar string 442 * @start: the first char in the string 443 * @len: the number of xmlChar 444 * 445 * receiving some ignorable whitespaces from the parser. 446 * Question: how much at a time ??? 447 */ 448void 449ignorableWhitespaceDebug(void *ctx, const xmlChar *ch, int len) 450{ 451 fprintf(stdout, "SAX.ignorableWhitespace(%.30s, %d)\n", 452 (char *) ch, len); 453} 454 455/** 456 * processingInstructionDebug: 457 * @ctxt: An XML parser context 458 * @target: the target name 459 * @data: the PI data's 460 * @len: the number of xmlChar 461 * 462 * A processing instruction has been parsed. 463 */ 464void 465processingInstructionDebug(void *ctx, const xmlChar *target, 466 const xmlChar *data) 467{ 468 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n", 469 (char *) target, (char *) data); 470} 471 472/** 473 * commentDebug: 474 * @ctxt: An XML parser context 475 * @value: the comment content 476 * 477 * A comment has been parsed. 478 */ 479void 480commentDebug(void *ctx, const xmlChar *value) 481{ 482 fprintf(stdout, "SAX.comment(%s)\n", value); 483} 484 485/** 486 * warningDebug: 487 * @ctxt: An XML parser context 488 * @msg: the message to display/transmit 489 * @...: extra parameters for the message display 490 * 491 * Display and format a warning messages, gives file, line, position and 492 * extra parameters. 493 */ 494void 495warningDebug(void *ctx, const char *msg, ...) 496{ 497 va_list args; 498 499 va_start(args, msg); 500 fprintf(stdout, "SAX.warning: "); 501 vfprintf(stdout, msg, args); 502 va_end(args); 503} 504 505/** 506 * errorDebug: 507 * @ctxt: An XML parser context 508 * @msg: the message to display/transmit 509 * @...: extra parameters for the message display 510 * 511 * Display and format a error messages, gives file, line, position and 512 * extra parameters. 513 */ 514void 515errorDebug(void *ctx, const char *msg, ...) 516{ 517 va_list args; 518 519 va_start(args, msg); 520 fprintf(stdout, "SAX.error: "); 521 vfprintf(stdout, msg, args); 522 va_end(args); 523} 524 525/** 526 * fatalErrorDebug: 527 * @ctxt: An XML parser context 528 * @msg: the message to display/transmit 529 * @...: extra parameters for the message display 530 * 531 * Display and format a fatalError messages, gives file, line, position and 532 * extra parameters. 533 */ 534void 535fatalErrorDebug(void *ctx, const char *msg, ...) 536{ 537 va_list args; 538 539 va_start(args, msg); 540 fprintf(stdout, "SAX.fatalError: "); 541 vfprintf(stdout, msg, args); 542 va_end(args); 543} 544 545xmlSAXHandler debugSAXHandlerStruct = { 546 internalSubsetDebug, 547 isStandaloneDebug, 548 hasInternalSubsetDebug, 549 hasExternalSubsetDebug, 550 resolveEntityDebug, 551 getEntityDebug, 552 entityDeclDebug, 553 notationDeclDebug, 554 attributeDeclDebug, 555 elementDeclDebug, 556 unparsedEntityDeclDebug, 557 setDocumentLocatorDebug, 558 startDocumentDebug, 559 endDocumentDebug, 560 startElementDebug, 561 endElementDebug, 562 referenceDebug, 563 charactersDebug, 564 ignorableWhitespaceDebug, 565 processingInstructionDebug, 566 commentDebug, 567 warningDebug, 568 errorDebug, 569 fatalErrorDebug, 570 getParameterEntityDebug, 571}; 572 573xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct; 574 575/************************************************************************ 576 * * 577 * Debug * 578 * * 579 ************************************************************************/ 580 581void parseAndPrintFile(char *filename) { 582 xmlDocPtr doc; 583 584 /* 585 * Empty callbacks for checking 586 */ 587 doc = xmlSAXParseFile(emptySAXHandler, filename, 0); 588 if (doc != NULL) { 589 fprintf(stdout, "xmlSAXParseFile returned non-NULL\n"); 590 xmlDocDump(stdout, doc); 591 } 592 593 /* 594 * Debug callback 595 */ 596 doc = xmlSAXParseFile(debugSAXHandler, filename, 0); 597 if (doc != NULL) { 598 fprintf(stderr, "xmlSAXParseFile returned non-NULL\n"); 599 xmlDocDump(stdout, doc); 600 } 601} 602 603void parseAndPrintBuffer(xmlChar *buf) { 604 xmlDocPtr doc; 605 606 /* 607 * Empty callbacks for checking 608 */ 609 doc = xmlSAXParseDoc(emptySAXHandler, buf, 0); 610 if (doc != NULL) { 611 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n"); 612 xmlDocDump(stdout, doc); 613 } 614 615 /* 616 * Debug callback 617 */ 618 doc = xmlSAXParseDoc(debugSAXHandler, buf, 0); 619 if (doc != NULL) { 620 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n"); 621 xmlDocDump(stdout, doc); 622 } 623} 624 625int main(int argc, char **argv) { 626 int i; 627 int files = 0; 628 629 for (i = 1; i < argc ; i++) { 630 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) 631 debug++; 632 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy"))) 633 copy++; 634 else if ((!strcmp(argv[i], "-recover")) || 635 (!strcmp(argv[i], "--recover"))) 636 recovery++; 637 } 638 for (i = 1; i < argc ; i++) { 639 if (argv[i][0] != '-') { 640 parseAndPrintFile(argv[i]); 641 files ++; 642 } 643 } 644 if (files == 0) { 645 printf("\nFirst test for the parser, with errors\n"); 646 parseAndPrintBuffer(buffer); 647 } 648 649 return(0); 650} 651