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