2 * testDocbook.c : a small tester program for SGML Docbook input.
4 * See Copyright for the status of this software.
11 #ifdef LIBXML_DOCB_ENABLED
18 #ifdef HAVE_SYS_TYPES_H
19 #include <sys/types.h>
21 #ifdef HAVE_SYS_STAT_H
34 #include <libxml/xmlmemory.h>
35 #include <libxml/DOCBparser.h>
36 #include <libxml/tree.h>
37 #include <libxml/debugXML.h>
38 #include <libxml/globals.h>
40 #ifdef LIBXML_DEBUG_ENABLED
45 static int repeat = 0;
49 static char *encoding = NULL;
51 xmlSAXHandler emptySAXHandlerStruct = {
52 NULL, /* internalSubset */
53 NULL, /* isStandalone */
54 NULL, /* hasInternalSubset */
55 NULL, /* hasExternalSubset */
56 NULL, /* resolveEntity */
58 NULL, /* entityDecl */
59 NULL, /* notationDecl */
60 NULL, /* attributeDecl */
61 NULL, /* elementDecl */
62 NULL, /* unparsedEntityDecl */
63 NULL, /* setDocumentLocator */
64 NULL, /* startDocument */
65 NULL, /* endDocument */
66 NULL, /* startElement */
67 NULL, /* endElement */
69 NULL, /* characters */
70 NULL, /* ignorableWhitespace */
71 NULL, /* processingInstruction */
73 NULL, /* xmlParserWarning */
74 NULL, /* xmlParserError */
75 NULL, /* xmlParserError */
76 NULL, /* getParameterEntity */
77 NULL, /* cdataBlock */
78 NULL, /* externalSubset */
82 xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
83 extern xmlSAXHandlerPtr debugSAXHandler;
85 /************************************************************************
89 ************************************************************************/
93 * @ctxt: An XML parser context
95 * Is this document tagged standalone ?
100 isStandaloneDebug(void *ctxt ATTRIBUTE_UNUSED)
102 fprintf(stdout, "SAX.isStandalone()\n");
107 * hasInternalSubsetDebug:
108 * @ctxt: An XML parser context
110 * Does this document has an internal subset
115 hasInternalSubsetDebug(void *ctxt ATTRIBUTE_UNUSED)
117 fprintf(stdout, "SAX.hasInternalSubset()\n");
122 * hasExternalSubsetDebug:
123 * @ctxt: An XML parser context
125 * Does this document has an external subset
130 hasExternalSubsetDebug(void *ctxt ATTRIBUTE_UNUSED)
132 fprintf(stdout, "SAX.hasExternalSubset()\n");
137 * internalSubsetDebug:
138 * @ctxt: An XML parser context
140 * Does this document has an internal subset
143 internalSubsetDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name,
144 const xmlChar *ExternalID, const xmlChar *SystemID)
146 fprintf(stdout, "SAX.internalSubset(%s,", name);
147 if (ExternalID == NULL)
148 fprintf(stdout, " ,");
150 fprintf(stdout, " %s,", ExternalID);
151 if (SystemID == NULL)
152 fprintf(stdout, " )\n");
154 fprintf(stdout, " %s)\n", SystemID);
158 * resolveEntityDebug:
159 * @ctxt: An XML parser context
160 * @publicId: The public ID of the entity
161 * @systemId: The system ID of the entity
163 * Special entity resolver, better left to the parser, it has
164 * more context than the application layer.
165 * The default behaviour is to NOT resolve the entities, in that case
166 * the ENTITY_REF nodes are built in the structure (and the parameter
169 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
171 static xmlParserInputPtr
172 resolveEntityDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
174 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
177 fprintf(stdout, "SAX.resolveEntity(");
178 if (publicId != NULL)
179 fprintf(stdout, "%s", (char *)publicId);
181 fprintf(stdout, " ");
182 if (systemId != NULL)
183 fprintf(stdout, ", %s)\n", (char *)systemId);
185 fprintf(stdout, ", )\n");
187 if (systemId != NULL) {
188 return(xmlNewInputFromFile(ctxt, (char *) systemId));
196 * @ctxt: An XML parser context
197 * @name: The entity name
199 * Get an entity by name
201 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
204 getEntityDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name)
206 fprintf(stdout, "SAX.getEntity(%s)\n", name);
211 * getParameterEntityDebug:
212 * @ctxt: An XML parser context
213 * @name: The entity name
215 * Get a parameter entity by name
217 * Returns the xmlParserInputPtr
220 getParameterEntityDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name)
222 fprintf(stdout, "SAX.getParameterEntity(%s)\n", name);
229 * @ctxt: An XML parser context
230 * @name: the entity name
231 * @type: the entity type
232 * @publicId: The public ID of the entity
233 * @systemId: The system ID of the entity
234 * @content: the entity value (without processing).
236 * An entity definition has been parsed
239 entityDeclDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name, int type,
240 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
242 fprintf(stdout, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
243 name, type, publicId, systemId, content);
247 * attributeDeclDebug:
248 * @ctxt: An XML parser context
249 * @name: the attribute name
250 * @type: the attribute type
252 * An attribute definition has been parsed
255 attributeDeclDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *elem,
256 const xmlChar *name, int type, int def,
257 const xmlChar *defaultValue,
258 xmlEnumerationPtr tree ATTRIBUTE_UNUSED)
260 fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
261 elem, name, type, def, defaultValue);
266 * @ctxt: An XML parser context
267 * @name: the element name
268 * @type: the element type
269 * @content: the element value (without processing).
271 * An element definition has been parsed
274 elementDeclDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name, int type,
275 xmlElementContentPtr content ATTRIBUTE_UNUSED)
277 fprintf(stdout, "SAX.elementDecl(%s, %d, ...)\n",
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
288 * What to do when a notation declaration has been parsed.
291 notationDeclDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name,
292 const xmlChar *publicId, const xmlChar *systemId)
294 fprintf(stdout, "SAX.notationDecl(%s, %s, %s)\n",
295 (char *) name, (char *) publicId, (char *) systemId);
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
306 * What to do when an unparsed entity declaration is parsed
309 unparsedEntityDeclDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name,
310 const xmlChar *publicId, const xmlChar *systemId,
311 const xmlChar *notationName)
313 fprintf(stdout, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
314 (char *) name, (char *) publicId, (char *) systemId,
315 (char *) notationName);
319 * setDocumentLocatorDebug:
320 * @ctxt: An XML parser context
321 * @loc: A SAX Locator
323 * Receive the document locator at startup, actually xmlDefaultSAXLocator
324 * Everything is available on the context, so this is useless in our case.
327 setDocumentLocatorDebug(void *ctxt ATTRIBUTE_UNUSED,
328 xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
330 fprintf(stdout, "SAX.setDocumentLocator()\n");
334 * startDocumentDebug:
335 * @ctxt: An XML parser context
337 * called when the document start being processed.
340 startDocumentDebug(void *ctxt ATTRIBUTE_UNUSED)
342 fprintf(stdout, "SAX.startDocument()\n");
347 * @ctxt: An XML parser context
349 * called when the document end has been detected.
352 endDocumentDebug(void *ctxt ATTRIBUTE_UNUSED)
354 fprintf(stdout, "SAX.endDocument()\n");
359 * @ctxt: An XML parser context
360 * @name: The element name
362 * called when an opening tag has been processed.
365 startElementDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
369 fprintf(stdout, "SAX.startElement(%s", (char *) name);
371 for (i = 0;(atts[i] != NULL);i++) {
372 fprintf(stdout, ", %s", atts[i++]);
373 if (atts[i] != NULL) {
374 unsigned char output[40];
375 const unsigned char *att = atts[i];
377 fprintf(stdout, "='");
378 while ((attlen = strlen((char*)att)) > 0) {
379 outlen = sizeof output - 1;
380 docbEncodeEntities(output, &outlen, att, &attlen, '\'');
381 fprintf(stdout, "%.*s", outlen, output);
384 fprintf(stdout, "'");
388 fprintf(stdout, ")\n");
393 * @ctxt: An XML parser context
394 * @name: The element name
396 * called when the end of an element has been detected.
399 endElementDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name)
401 fprintf(stdout, "SAX.endElement(%s)\n", (char *) name);
406 * @ctxt: An XML parser context
407 * @ch: a xmlChar string
408 * @len: the number of xmlChar
410 * receiving some chars from the parser.
411 * Question: how much at a time ???
414 charactersDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
416 unsigned char output[40];
417 int inlen = len, outlen = 30;
419 docbEncodeEntities(output, &outlen, ch, &inlen, 0);
422 fprintf(stdout, "SAX.characters(%s, %d)\n", output, len);
427 * @ctxt: An XML parser context
428 * @name: The entity name
430 * called when an entity reference is detected.
433 referenceDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name)
435 fprintf(stdout, "SAX.reference(%s)\n", name);
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
445 * receiving some ignorable whitespaces from the parser.
446 * Question: how much at a time ???
449 ignorableWhitespaceDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
454 for (i = 0;(i<len) && (i < 30);i++)
458 fprintf(stdout, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
462 * processingInstructionDebug:
463 * @ctxt: An XML parser context
464 * @target: the target name
465 * @data: the PI data's
466 * @len: the number of xmlChar
468 * A processing instruction has been parsed.
471 processingInstructionDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *target,
474 fprintf(stdout, "SAX.processingInstruction(%s, %s)\n",
475 (char *) target, (char *) data);
480 * @ctxt: An XML parser context
481 * @value: the comment content
483 * A comment has been parsed.
486 commentDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *value)
488 fprintf(stdout, "SAX.comment(%s)\n", value);
493 * @ctx: the user data (XML parser context)
494 * @value: The pcdata content
495 * @len: the block length
497 * called when a pcdata block has been parsed
500 cdataBlockDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *value, int len)
502 fprintf(stdout, "SAX.pcdata(%.20s, %d)\n",
503 (char *) value, len);
507 * externalSubsetDebug:
508 * @ctxt: An XML parser context
510 * Does this document has an external subset
513 externalSubsetDebug(void *ctxt ATTRIBUTE_UNUSED, const xmlChar *name,
514 const xmlChar *ExternalID, const xmlChar *SystemID)
516 fprintf(stdout, "SAX.externalSubset(%s,", name);
517 if (ExternalID == NULL)
518 fprintf(stdout, " ,");
520 fprintf(stdout, " %s,", ExternalID);
521 if (SystemID == NULL)
522 fprintf(stdout, " )\n");
524 fprintf(stdout, " %s)\n", SystemID);
529 * @ctxt: An XML parser context
530 * @msg: the message to display/transmit
531 * @...: extra parameters for the message display
533 * Display and format a warning messages, gives file, line, position and
537 warningDebug(void *ctxt ATTRIBUTE_UNUSED, const char *msg, ...)
542 fprintf(stdout, "SAX.warning: ");
543 vfprintf(stdout, msg, args);
549 * @ctxt: An XML parser context
550 * @msg: the message to display/transmit
551 * @...: extra parameters for the message display
553 * Display and format a error messages, gives file, line, position and
557 errorDebug(void *ctxt ATTRIBUTE_UNUSED, const char *msg, ...)
562 fprintf(stdout, "SAX.error: ");
563 vfprintf(stdout, msg, args);
569 * @ctxt: An XML parser context
570 * @msg: the message to display/transmit
571 * @...: extra parameters for the message display
573 * Display and format a fatalError messages, gives file, line, position and
577 fatalErrorDebug(void *ctxt ATTRIBUTE_UNUSED, const char *msg, ...)
582 fprintf(stdout, "SAX.fatalError: ");
583 vfprintf(stdout, msg, args);
587 xmlSAXHandler debugSAXHandlerStruct = {
590 hasInternalSubsetDebug,
591 hasExternalSubsetDebug,
598 unparsedEntityDeclDebug,
599 setDocumentLocatorDebug,
606 ignorableWhitespaceDebug,
607 processingInstructionDebug,
612 getParameterEntityDebug,
618 xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
619 /************************************************************************
623 ************************************************************************/
626 parseSAXFile(char *filename) {
627 docbDocPtr doc = NULL;
630 * Empty callbacks for checking
635 f = fopen(filename, "r");
639 docbParserCtxtPtr ctxt;
643 res = fread(chars, 1, 4, f);
645 ctxt = docbCreatePushParserCtxt(emptySAXHandler, NULL,
646 chars, res, filename, XML_CHAR_ENCODING_NONE);
647 while ((res = fread(chars, 1, size, f)) > 0) {
648 docbParseChunk(ctxt, chars, res, 0);
650 docbParseChunk(ctxt, chars, 0, 1);
652 docbFreeParserCtxt(ctxt);
655 fprintf(stdout, "sgmlSAXParseFile returned non-NULL\n");
661 f = fopen(filename, "r");
665 docbParserCtxtPtr ctxt;
669 res = fread(chars, 1, 4, f);
671 ctxt = docbCreatePushParserCtxt(debugSAXHandler, NULL,
672 chars, res, filename, XML_CHAR_ENCODING_NONE);
673 while ((res = fread(chars, 1, size, f)) > 0) {
674 docbParseChunk(ctxt, chars, res, 0);
676 docbParseChunk(ctxt, chars, 0, 1);
678 docbFreeParserCtxt(ctxt);
681 fprintf(stdout, "sgmlSAXParseFile returned non-NULL\n");
688 doc = docbSAXParseFile(filename, NULL, emptySAXHandler, NULL);
690 fprintf(stdout, "sgmlSAXParseFile returned non-NULL\n");
698 doc = docbSAXParseFile(filename, NULL, debugSAXHandler, NULL);
700 fprintf(stdout, "sgmlSAXParseFile returned non-NULL\n");
708 parseAndPrintFile(char *filename) {
709 docbDocPtr doc = NULL, tmp;
712 * build an SGML tree from a string;
717 f = fopen(filename, "r");
721 docbParserCtxtPtr ctxt;
725 res = fread(chars, 1, 4, f);
727 ctxt = docbCreatePushParserCtxt(NULL, NULL,
728 chars, res, filename, XML_CHAR_ENCODING_NONE);
729 while ((res = fread(chars, 1, size, f)) > 0) {
730 docbParseChunk(ctxt, chars, res, 0);
732 docbParseChunk(ctxt, chars, 0, 1);
734 docbFreeParserCtxt(ctxt);
739 doc = docbParseFile(filename, NULL);
742 fprintf(stderr, "Could not parse %s\n", filename);
746 * test intermediate copy if needed.
750 doc = xmlCopyDoc(doc, 1);
758 #ifdef LIBXML_DEBUG_ENABLED
761 xmlSaveFileEnc("-", doc, encoding);
763 xmlDocDump(stdout, doc);
765 xmlDebugDumpDocument(stdout, doc);
768 xmlSaveFileEnc("-", doc, encoding);
770 xmlDocDump(stdout, doc);
780 int main(int argc, char **argv) {
784 for (i = 1; i < argc ; i++) {
785 #ifdef LIBXML_DEBUG_ENABLED
786 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
790 if ((!strcmp(argv[i], "-copy")) || (!strcmp(argv[i], "--copy")))
792 else if ((!strcmp(argv[i], "-push")) || (!strcmp(argv[i], "--push")))
794 else if ((!strcmp(argv[i], "-sax")) || (!strcmp(argv[i], "--sax")))
796 else if ((!strcmp(argv[i], "-noent")) || (!strcmp(argv[i], "--noent")))
798 else if ((!strcmp(argv[i], "-noout")) || (!strcmp(argv[i], "--noout")))
800 else if ((!strcmp(argv[i], "-repeat")) ||
801 (!strcmp(argv[i], "--repeat")))
803 else if ((!strcmp(argv[i], "-encode")) ||
804 (!strcmp(argv[i], "--encode"))) {
809 if (noent != 0) xmlSubstituteEntitiesDefault(1);
810 for (i = 1; i < argc ; i++) {
811 if ((!strcmp(argv[i], "-encode")) ||
812 (!strcmp(argv[i], "--encode"))) {
816 if (argv[i][0] != '-') {
818 for (count = 0;count < 100 * repeat;count++) {
820 parseSAXFile(argv[i]);
822 parseAndPrintFile(argv[i]);
826 parseSAXFile(argv[i]);
828 parseAndPrintFile(argv[i]);
834 printf("Usage : %s [--debug] [--copy] [--copy] SGMLfiles ...\n",
836 printf("\tParse the Docbook files and output the result of the parsing\n");
837 #ifdef LIBXML_DEBUG_ENABLED
838 printf("\t--debug : dump a debug tree of the in-memory document\n");
840 printf("\t--copy : used to test the internal copy implementation\n");
841 printf("\t--sax : debug the sequence of SAX callbacks\n");
842 printf("\t--repeat : parse the file 100 times, for timing\n");
843 printf("\t--noout : do not print the result\n");
844 printf("\t--push : use the push mode parser\n");
845 printf("\t--encode encoding : output in the given encoding\n");
852 #else /* !LIBXML_DOCB_ENABLED */
854 int main(int argc, char **argv) {
855 printf("%s : SGML support not compiled in\n", argv[0]);