blob: 1e7acb1b4714b3c5a04cbd86cb6a18e4527af60e [file] [log] [blame]
Daniel Veillard5099ae81999-04-21 20:12:07 +00001/*
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#include <sys/types.h>
16#ifdef HAVE_SYS_STAT_H
17#include <sys/stat.h>
18#endif
19#ifdef HAVE_FCNTL_H
20#include <fcntl.h>
21#endif
22#ifdef HAVE_UNISTD_H
23#include <unistd.h>
24#endif
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28#include <stdarg.h>
29
30#include "parser.h"
Daniel Veillard011b63c1999-06-02 17:44:04 +000031#include "parserInternals.h" /* only for xmlNewInputFromFile() */
Daniel Veillard5099ae81999-04-21 20:12:07 +000032#include "tree.h"
33#include "debugXML.h"
34
35static int debug = 0;
36static int copy = 0;
37static int recovery = 0;
38
39xmlSAXHandler emptySAXHandlerStruct = {
40 NULL, /* internalSubset */
41 NULL, /* isStandalone */
42 NULL, /* hasInternalSubset */
43 NULL, /* hasExternalSubset */
44 NULL, /* resolveEntity */
45 NULL, /* getEntity */
46 NULL, /* entityDecl */
47 NULL, /* notationDecl */
48 NULL, /* attributeDecl */
49 NULL, /* elementDecl */
50 NULL, /* unparsedEntityDecl */
51 NULL, /* setDocumentLocator */
52 NULL, /* startDocument */
53 NULL, /* endDocument */
54 NULL, /* startElement */
55 NULL, /* endElement */
56 NULL, /* reference */
57 NULL, /* characters */
58 NULL, /* ignorableWhitespace */
59 NULL, /* processingInstruction */
60 NULL, /* comment */
61 NULL, /* xmlParserWarning */
62 NULL, /* xmlParserError */
63 NULL, /* xmlParserError */
64};
65
66xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
Daniel Veillard011b63c1999-06-02 17:44:04 +000067extern xmlSAXHandlerPtr debugSAXHandler;
Daniel Veillard5099ae81999-04-21 20:12:07 +000068
69/*
70 * Note: there is a couple of errors introduced on purpose.
71 */
72static CHAR buffer[] =
73"<?xml version=\"1.0\"?>\n\
74<?xml:namespace ns = \"http://www.ietf.org/standards/dav/\" prefix = \"D\"?>\n\
75<?xml:namespace ns = \"http://www.w3.com/standards/z39.50/\" prefix = \"Z\"?>\n\
76<D:propertyupdate>\n\
77<D:set a=\"'toto'\" b>\n\
78 <D:prop>\n\
79 <Z:authors>\n\
80 <Z:Author>Jim Whitehead</Z:Author>\n\
81 <Z:Author>Roy Fielding</Z:Author>\n\
82 </Z:authors>\n\
83 </D:prop>\n\
84 </D:set>\n\
85 <D:remove>\n\
86 <D:prop><Z:Copyright-Owner/></D:prop>\n\
87 </D:remove>\n\
88</D:propertyupdate>\n\
89\n\
90";
91
92/************************************************************************
93 * *
94 * Debug Handlers *
95 * *
96 ************************************************************************/
97
98/**
99 * isStandaloneDebug:
100 * @ctxt: An XML parser context
101 *
102 * Is this document tagged standalone ?
103 *
104 * Returns 1 if true
105 */
106int
107isStandaloneDebug(xmlParserCtxtPtr ctxt)
108{
Daniel Veillard27d88741999-05-29 11:51:49 +0000109 fprintf(stdout, "SAX.isStandalone()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000110 return(0);
111}
112
113/**
114 * hasInternalSubsetDebug:
115 * @ctxt: An XML parser context
116 *
117 * Does this document has an internal subset
118 *
119 * Returns 1 if true
120 */
121int
122hasInternalSubsetDebug(xmlParserCtxtPtr ctxt)
123{
Daniel Veillard27d88741999-05-29 11:51:49 +0000124 fprintf(stdout, "SAX.hasInternalSubset()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000125 return(0);
126}
127
128/**
129 * hasExternalSubsetDebug:
130 * @ctxt: An XML parser context
131 *
132 * Does this document has an external subset
133 *
134 * Returns 1 if true
135 */
136int
137hasExternalSubsetDebug(xmlParserCtxtPtr ctxt)
138{
Daniel Veillard27d88741999-05-29 11:51:49 +0000139 fprintf(stdout, "SAX.hasExternalSubset()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000140 return(0);
141}
142
143/**
144 * hasInternalSubsetDebug:
145 * @ctxt: An XML parser context
146 *
147 * Does this document has an internal subset
148 */
149void
150internalSubsetDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
151 const CHAR *ExternalID, const CHAR *SystemID)
152{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000153 xmlDtdPtr externalSubset;
154
Daniel Veillard27d88741999-05-29 11:51:49 +0000155 fprintf(stdout, "SAX.internalSubset(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000156 name, ExternalID, SystemID);
Daniel Veillard011b63c1999-06-02 17:44:04 +0000157
158 if ((ExternalID != NULL) || (SystemID != NULL)) {
159 externalSubset = xmlSAXParseDTD(debugSAXHandler, ExternalID, SystemID);
160 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000161}
162
163/**
164 * resolveEntityDebug:
165 * @ctxt: An XML parser context
166 * @publicId: The public ID of the entity
167 * @systemId: The system ID of the entity
168 *
169 * Special entity resolver, better left to the parser, it has
170 * more context than the application layer.
171 * The default behaviour is to NOT resolve the entities, in that case
172 * the ENTITY_REF nodes are built in the structure (and the parameter
173 * values).
174 *
175 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
176 */
177xmlParserInputPtr
178resolveEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId)
179{
Daniel Veillard14fff061999-06-22 21:49:07 +0000180
181 fprintf(stdout, "SAX.resolveEntity(");
182 if (publicId != NULL)
183 fprintf(stdout, "%s", (char *)publicId);
184 else
185 fprintf(stdout, " ");
186 if (systemId != NULL)
187 fprintf(stdout, ", %s)\n", (char *)systemId);
188 else
189 fprintf(stdout, ", )\n");
Daniel Veillard011b63c1999-06-02 17:44:04 +0000190 if (systemId != NULL) {
191 return(xmlNewInputFromFile(ctxt, systemId));
192 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000193 return(NULL);
194}
195
196/**
197 * getEntityDebug:
198 * @ctxt: An XML parser context
199 * @name: The entity name
200 *
201 * Get an entity by name
202 *
203 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
204 */
205xmlEntityPtr
206getEntityDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
207{
Daniel Veillard27d88741999-05-29 11:51:49 +0000208 fprintf(stdout, "SAX.getEntity(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000209 return(NULL);
210}
211
212
213/**
214 * entityDeclDebug:
215 * @ctxt: An XML parser context
216 * @name: the entity name
217 * @type: the entity type
218 * @publicId: The public ID of the entity
219 * @systemId: The system ID of the entity
220 * @content: the entity value (without processing).
221 *
222 * An entity definition has been parsed
223 */
224void
225entityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
226 const CHAR *publicId, const CHAR *systemId, CHAR *content)
227{
Daniel Veillard27d88741999-05-29 11:51:49 +0000228 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000229 name, type, publicId, systemId, content);
230}
231
232/**
233 * attributeDeclDebug:
234 * @ctxt: An XML parser context
235 * @name: the attribute name
236 * @type: the attribute type
237 *
238 * An attribute definition has been parsed
239 */
240void
241attributeDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *elem, const CHAR *name,
242 int type, int def, const CHAR *defaultValue,
243 xmlEnumerationPtr tree)
244{
Daniel Veillard27d88741999-05-29 11:51:49 +0000245 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000246 elem, name, type, def, defaultValue);
247}
248
249/**
250 * elementDeclDebug:
251 * @ctxt: An XML parser context
252 * @name: the element name
253 * @type: the element type
254 * @content: the element value (without processing).
255 *
256 * An element definition has been parsed
257 */
258void
259elementDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
260 xmlElementContentPtr content)
261{
Daniel Veillard27d88741999-05-29 11:51:49 +0000262 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000263 name, type);
264}
265
266/**
267 * notationDeclDebug:
268 * @ctxt: An XML parser context
269 * @name: The name of the notation
270 * @publicId: The public ID of the entity
271 * @systemId: The system ID of the entity
272 *
273 * What to do when a notation declaration has been parsed.
274 * TODO Not handled currently.
275 */
276void
277notationDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
278 const CHAR *publicId, const CHAR *systemId)
279{
Daniel Veillard27d88741999-05-29 11:51:49 +0000280 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000281 (char *) name, (char *) publicId, (char *) systemId);
282}
283
284/**
285 * unparsedEntityDeclDebug:
286 * @ctxt: An XML parser context
287 * @name: The name of the entity
288 * @publicId: The public ID of the entity
289 * @systemId: The system ID of the entity
290 * @notationName: the name of the notation
291 *
292 * What to do when an unparsed entity declaration is parsed
293 * TODO Create an Entity node.
294 */
295void
296unparsedEntityDeclDebug(xmlParserCtxtPtr ctxt, const CHAR *name,
297 const CHAR *publicId, const CHAR *systemId,
298 const CHAR *notationName)
299{
Daniel Veillard27d88741999-05-29 11:51:49 +0000300 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000301 (char *) name, (char *) publicId, (char *) systemId,
302 (char *) notationName);
303}
304
305/**
306 * setDocumentLocatorDebug:
307 * @ctxt: An XML parser context
308 * @loc: A SAX Locator
309 *
310 * Receive the document locator at startup, actually xmlDefaultSAXLocator
311 * Everything is available on the context, so this is useless in our case.
312 */
313void
314setDocumentLocatorDebug(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
315{
Daniel Veillard27d88741999-05-29 11:51:49 +0000316 fprintf(stdout, "SAX.setDocumentLocator()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000317}
318
319/**
320 * startDocumentDebug:
321 * @ctxt: An XML parser context
322 *
323 * called when the document start being processed.
324 */
325void
326startDocumentDebug(xmlParserCtxtPtr ctxt)
327{
Daniel Veillard27d88741999-05-29 11:51:49 +0000328 fprintf(stdout, "SAX.startDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000329}
330
331/**
332 * endDocumentDebug:
333 * @ctxt: An XML parser context
334 *
335 * called when the document end has been detected.
336 */
337void
338endDocumentDebug(xmlParserCtxtPtr ctxt)
339{
Daniel Veillard27d88741999-05-29 11:51:49 +0000340 fprintf(stdout, "SAX.endDocument()\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000341}
342
343/**
344 * startElementDebug:
345 * @ctxt: An XML parser context
346 * @name: The element name
347 *
348 * called when an opening tag has been processed.
349 * TODO We currently have a small pblm with the arguments ...
350 */
351void
352startElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR **atts)
353{
354 int i;
355
Daniel Veillard27d88741999-05-29 11:51:49 +0000356 fprintf(stdout, "SAX.startElement(%s", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000357 if (atts != NULL) {
358 for (i = 0;(atts[i] != NULL);i++) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000359 fprintf(stdout, ", %s='", atts[i++]);
360 fprintf(stdout, "%s'", atts[i]);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000361 }
362 }
Daniel Veillard27d88741999-05-29 11:51:49 +0000363 fprintf(stdout, ")\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000364}
365
366/**
367 * endElementDebug:
368 * @ctxt: An XML parser context
369 * @name: The element name
370 *
371 * called when the end of an element has been detected.
372 */
373void
374endElementDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
375{
Daniel Veillard27d88741999-05-29 11:51:49 +0000376 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000377}
378
379/**
380 * charactersDebug:
381 * @ctxt: An XML parser context
382 * @ch: a CHAR string
383 * @len: the number of CHAR
384 *
385 * receiving some chars from the parser.
386 * Question: how much at a time ???
387 */
388void
389charactersDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
390{
Daniel Veillard27d88741999-05-29 11:51:49 +0000391 fprintf(stdout, "SAX.characters(%.30s, %d)\n", (char *) ch, len);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000392}
393
394/**
395 * referenceDebug:
396 * @ctxt: An XML parser context
397 * @name: The entity name
398 *
399 * called when an entity reference is detected.
400 */
401void
402referenceDebug(xmlParserCtxtPtr ctxt, const CHAR *name)
403{
Daniel Veillard27d88741999-05-29 11:51:49 +0000404 fprintf(stdout, "SAX.reference(%s)\n", name);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000405}
406
407/**
408 * ignorableWhitespaceDebug:
409 * @ctxt: An XML parser context
410 * @ch: a CHAR string
411 * @start: the first char in the string
412 * @len: the number of CHAR
413 *
414 * receiving some ignorable whitespaces from the parser.
415 * Question: how much at a time ???
416 */
417void
418ignorableWhitespaceDebug(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
419{
Daniel Veillard27d88741999-05-29 11:51:49 +0000420 fprintf(stdout, "SAX.ignorableWhitespace(%.30s, %d)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000421 (char *) ch, len);
422}
423
424/**
425 * processingInstructionDebug:
426 * @ctxt: An XML parser context
427 * @target: the target name
428 * @data: the PI data's
429 * @len: the number of CHAR
430 *
431 * A processing instruction has been parsed.
432 */
433void
434processingInstructionDebug(xmlParserCtxtPtr ctxt, const CHAR *target,
435 const CHAR *data)
436{
Daniel Veillard27d88741999-05-29 11:51:49 +0000437 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
Daniel Veillard5099ae81999-04-21 20:12:07 +0000438 (char *) target, (char *) data);
439}
440
441/**
442 * commentDebug:
443 * @ctxt: An XML parser context
444 * @value: the comment content
445 *
446 * A comment has been parsed.
447 */
448void
449commentDebug(xmlParserCtxtPtr ctxt, const CHAR *value)
450{
Daniel Veillard27d88741999-05-29 11:51:49 +0000451 fprintf(stdout, "SAX.comment(%s)\n", value);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000452}
453
454/**
455 * warningDebug:
456 * @ctxt: An XML parser context
457 * @msg: the message to display/transmit
458 * @...: extra parameters for the message display
459 *
460 * Display and format a warning messages, gives file, line, position and
461 * extra parameters.
462 */
463void
464warningDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
465{
466 va_list args;
467
468 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000469 fprintf(stdout, "SAX.warning: ");
470 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000471 va_end(args);
472}
473
474/**
475 * errorDebug:
476 * @ctxt: An XML parser context
477 * @msg: the message to display/transmit
478 * @...: extra parameters for the message display
479 *
480 * Display and format a error messages, gives file, line, position and
481 * extra parameters.
482 */
483void
484errorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
485{
486 va_list args;
487
488 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000489 fprintf(stdout, "SAX.error: ");
490 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000491 va_end(args);
492}
493
494/**
495 * fatalErrorDebug:
496 * @ctxt: An XML parser context
497 * @msg: the message to display/transmit
498 * @...: extra parameters for the message display
499 *
500 * Display and format a fatalError messages, gives file, line, position and
501 * extra parameters.
502 */
503void
504fatalErrorDebug(xmlParserCtxtPtr ctxt, const char *msg, ...)
505{
506 va_list args;
507
508 va_start(args, msg);
Daniel Veillard27d88741999-05-29 11:51:49 +0000509 fprintf(stdout, "SAX.fatalError: ");
510 vfprintf(stdout, msg, args);
Daniel Veillard5099ae81999-04-21 20:12:07 +0000511 va_end(args);
512}
513
514xmlSAXHandler debugSAXHandlerStruct = {
515 internalSubsetDebug,
516 isStandaloneDebug,
517 hasInternalSubsetDebug,
518 hasExternalSubsetDebug,
519 resolveEntityDebug,
520 getEntityDebug,
521 entityDeclDebug,
522 notationDeclDebug,
523 attributeDeclDebug,
524 elementDeclDebug,
525 unparsedEntityDeclDebug,
526 setDocumentLocatorDebug,
527 startDocumentDebug,
528 endDocumentDebug,
529 startElementDebug,
530 endElementDebug,
531 referenceDebug,
532 charactersDebug,
533 ignorableWhitespaceDebug,
534 processingInstructionDebug,
535 commentDebug,
536 warningDebug,
537 errorDebug,
538 fatalErrorDebug,
539};
540
541xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
542
543/************************************************************************
544 * *
545 * Debug *
546 * *
547 ************************************************************************/
548
549void parseAndPrintFile(char *filename) {
550 xmlDocPtr doc;
551
552 /*
553 * Empty callbacks for checking
554 */
555 doc = xmlSAXParseFile(emptySAXHandler, filename, 0);
556 if (doc != NULL) {
Daniel Veillard27d88741999-05-29 11:51:49 +0000557 fprintf(stdout, "xmlSAXParseFile returned non-NULL\n");
Daniel Veillard5099ae81999-04-21 20:12:07 +0000558 xmlDocDump(stdout, doc);
559 }
560
561 /*
562 * Debug callback
563 */
564 doc = xmlSAXParseFile(debugSAXHandler, filename, 0);
565 if (doc != NULL) {
566 fprintf(stderr, "xmlSAXParseFile returned non-NULL\n");
567 xmlDocDump(stdout, doc);
568 }
569}
570
571void parseAndPrintBuffer(CHAR *buf) {
572 xmlDocPtr doc;
573
574 /*
575 * Empty callbacks for checking
576 */
577 doc = xmlSAXParseDoc(emptySAXHandler, buf, 0);
578 if (doc != NULL) {
579 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
580 xmlDocDump(stdout, doc);
581 }
582
583 /*
584 * Debug callback
585 */
586 doc = xmlSAXParseDoc(debugSAXHandler, buf, 0);
587 if (doc != NULL) {
588 fprintf(stderr, "xmlSAXParseDoc returned non-NULL\n");
589 xmlDocDump(stdout, doc);
590 }
591}
592
593int main(int argc, char **argv) {
594 int i;
595 int files = 0;
596
597 for (i = 1; i < argc ; i++) {
598 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
599 debug++;
600 else if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
601 copy++;
602 else if ((!strcmp(argv[i], "-recover")) ||
603 (!strcmp(argv[i], "--recover")))
604 recovery++;
605 }
606 for (i = 1; i < argc ; i++) {
607 if (argv[i][0] != '-') {
608 parseAndPrintFile(argv[i]);
609 files ++;
610 }
611 }
612 if (files == 0) {
613 printf("\nFirst test for the parser, with errors\n");
614 parseAndPrintBuffer(buffer);
615 }
616
617 return(0);
618}