2 * xsltproc.c: user program for the XSL Transformation 1.0 engine
4 * See Copyright for the status of this software.
9 //#include <libxslt/libxslt.h>
10 //#include <libexslt/exslt.h>
12 #ifdef HAVE_SYS_STAT_H
22 #include <libxml/xmlmemory.h>
23 #include <libxml/debugXML.h>
24 #include <libxml/HTMLtree.h>
25 #include <libxml/xmlIO.h>
26 #ifdef LIBXML_XINCLUDE_ENABLED
27 #include <libxml/xinclude.h>
29 #ifdef LIBXML_CATALOG_ENABLED
30 #include <libxml/catalog.h>
32 #include <libxml/parserInternals.h>
34 #include <libxslt/xslt.h>
35 #include <libxslt/xsltInternals.h>
36 #include <libxslt/transform.h>
37 #include <libxslt/xsltutils.h>
38 #include <libxslt/extensions.h>
40 #include <libexslt/exslt.h>
45 /* MS C library seems to define stat and _stat. The definition
46 * is identical. Still, mapping them to each other causes a warning. */
48 # define stat(x,y) _stat(x,y)
54 xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL,
56 xmlParserCtxtPtr ctxt);
58 #define LIBXML_DEBUG_ENABLED
62 static int novalid = 0;
65 #ifdef LIBXML_DOCB_ENABLED
66 static int docbook = 0;
68 #ifdef LIBXML_HTML_ENABLED
72 static const char *params[16 + 1];
73 static int nbparams = 0;
74 static const char *output = NULL;
76 void LatexEscape(xmlNodePtr node);
79 * The LaTeX translation table. Translate unicodes to LaTeX escape sequences.
87 unsigned char *sequence;
96 { '\\', "$\\backslash$" },
112 { 169, "\\copyright" },
119 { 176, "$^{\\circ}$" },
131 { 188, "$\\frac{1}{4}$" },
132 { 189, "$\\frac{1}{2}$" },
133 { 190, "$\\frac{3}{4}$" },
158 { 215, "$\\times$" },
206 { 915, "$\\Gamma$" },
207 { 916, "$\\Delta$" },
211 { 920, "$\\Theta$" },
214 { 923, "$\\Lambda$" },
221 { 931, "$\\Sigma$" },
223 { 933, "$\\Upsilon$" },
227 { 937, "$\\Omega$" },
228 { 945, "$\\alpha$" },
230 { 947, "$\\gamma$" },
231 { 948, "$\\delta$" },
232 { 949, "$\\epsilon$" },
235 { 952, "$\\theta$" },
237 { 954, "$\\kappa$" },
238 { 955, "$\\lambda$" },
245 { 962, "$\\varsigma$" },
246 { 963, "$\\sigma$" },
248 { 965, "$\\upsilon$" },
252 { 969, "$\\omega$" },
255 { 8226, "$\\bullet$" },
256 { 8230, "$\\ldots$" },
257 { 8242, "$\\prime$" },
258 { 8243, "$\\prime\\prime$" },
265 { 8501, "$\\aleph$" },
266 { 8592, "$\\leftarrow$" },
267 { 8593, "$\\uparrow$" },
268 { 8594, "$\\rightarrow$" },
269 { 8595, "$\\downarrow$" },
270 { 8596, "$\\leftrightarrow$" },
271 { 8629, "$\\hookleftarrow$"},
272 { 8656, "$\\Leftarrow$" },
273 { 8657, "$\\Uparrow$" },
274 { 8658, "$\\Rightarrow$" },
275 { 8659, "$\\Downarrow$" },
276 { 8660, "$\\Leftrightarrow$" },
277 { 8704, "$\\forall$" },
278 { 8706, "$\\partial$" },
279 { 8707, "$\\exists$" },
280 { 8709, "$\\emptyset$" },
281 { 8711, "$\\nabla$" },
285 { 8719, "$\\prod$" },
289 { 8730, "$\\surd$" },
290 { 8733, "$\\propto$" },
291 { 8734, "$\\infty$" },
292 { 8736, "$\\angle$" },
293 { 8743, "$\\wedge$" },
298 { 8756, "$\\leadsto$" },
300 { 8773, "$\\cong$" },
301 { 8776, "$\\approx$" },
303 { 8801, "$\\equiv$" },
306 { 8834, "$\\subset$" },
307 { 8835, "$\\supset$" },
309 { 8838, "$\\subseteq$" },
310 { 8839, "$\\supseteq$" },
311 { 8853, "$\\oplus$" },
312 { 8855, "$\\otimes$" },
313 { 8869, "$\\perp$" },
314 { 8901, "$\\cdot$" },
315 { 8968, "$\\lceil$" },
316 { 8969, "$\\rceil$" },
317 { 8970, "$\\lfloor$" },
318 { 8971, "$\\rfloor$" },
319 { 9001, "$\\langle$" },
320 { 9002, "$\\rangle$" },
321 { 9674, "$\\Diamond$" },
322 { 9824, "$\\spadesuit$" },
323 { 9827, "$\\clubsuit$" },
324 { 9829, "$\\heartsuit$" },
325 { 9830, "$\\diamondsuit$" },
328 unsigned char *latex_translate(int code)
335 for (i = 0; translation == 0 && textab[i].unicode <= code
336 && i < sizeof(textab) / sizeof(textab[0]); i++)
338 if (textab[i].unicode == code)
340 translation = textab[i].sequence;
342 fprintf(stderr, "\n*** translation for 0x%04x is %s\n", code, translation);
350 xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) {
353 xmlXIncludeProcessFlags(doc, XSLT_PARSE_OPTIONS);
356 xmlDebugDumpDocument(stdout, doc);
361 LatexEscape(xmlDocGetRootElement(doc));
364 if (output == NULL) {
365 res = xsltApplyStylesheet(cur, doc, params);
369 fprintf(stderr, "no result for %s\n", filename);
376 #ifdef LIBXML_DEBUG_ENABLED
378 xmlDebugDumpDocument(stdout, res);
381 if (cur->methodURI == NULL) {
382 xsltSaveResultToFile(stdout, res, cur);
385 (cur->method, (const xmlChar *) "xhtml")) {
386 fprintf(stderr, "non standard output xhtml\n");
387 xsltSaveResultToFile(stdout, res, cur);
390 "Unsupported non standard output %s\n",
392 xsltSaveResultToFile(stdout, res, cur);
395 #ifdef LIBXML_DEBUG_ENABLED
401 xsltRunStylesheet(cur, doc, params, output, NULL, NULL);
407 void LatexEscape(xmlNodePtr node)
410 xmlAttrPtr attribute;
414 unsigned char *translation, *replacement;
419 fprintf(stderr, "\n-------- Node type %d\n", node->type);
421 if (xmlNodeIsText(node))
424 fprintf(stderr, "\n-------- Text node at %p (%d bytes):\n%s",
425 node, strlen(node->content), node->content);
428 textlen = strlen(node->content);
433 replacement = malloc(textlen);
436 for (byte = node->content; *byte != '\0'; byte++)
438 /* transform from utf-8 to unicode */
440 if ((*byte & 0x80) == 0)
444 else if ((*byte & 0xe0) == 0xc0)
447 fprintf(stderr, "2-byte unicode: 0x%02x, 0x%02x\n",byte[0], byte[1]);
449 unicode = (*byte & 0x1f) << 6;
451 unicode |= *byte & 0x3f;
453 fprintf(stderr, "Unicode = 0x%04x\n", unicode);
456 else if ((*byte & 0xf0) == 0xe0)
460 unicode = (*byte & 0x0f) << 12;
462 unicode |= (*byte & 0x3f) << 6;
464 unicode |= *byte & 0x3f;
468 fprintf(stderr, "More than 3 bytes utf-8 is not supported.\n");
471 translation = latex_translate(unicode);
473 /* Append the original byte or the translation to the replacment text */
475 if (translation == 0)
477 if (i + 1 >= textlen)
480 replacement = realloc(replacement, textlen);
482 replacement[i++] = *byte;
488 if (i + strlen(translation) + 1 >= textlen)
491 replacement = realloc(replacement, textlen);
493 for (j = 0; translation[j]; j++)
495 replacement[i++] = translation[j];
499 replacement[i] = '\0';
500 xmlNodeSetContent(node, replacement);
502 fprintf(stderr, "\n-------- Replacement text:\n%s", replacement);
508 for (attribute = node->properties; attribute != 0; attribute = attribute->next)
510 LatexEscape(attribute->children);
512 for (child = node->children; child != 0; child = child->next)
514 if (strcmp(child->name, "verbatim") != 0 && strcmp(child->name, "example") != 0)
522 static void usage(const char *name)
524 printf("Usage: %s [options] stylesheet file [file ...]\n", name);
525 printf(" Options:\n");
526 printf("\t--version or -V: show the version of libxml and libxslt used\n");
527 printf("\t--verbose or -v: show logs of what's happening\n");
528 printf("\t--output file or -o file: save to a given file\n");
529 printf("\t--debug: dump the tree of the result instead\n");
530 printf("\t--latex: transform special characters for latex\n");
531 printf("\t--novalid: skip the Dtd loading phase\n");
532 printf("\t--noout: do not dump the result\n");
533 printf("\t--maxdepth val : increase the maximum depth\n");
534 #ifdef LIBXML_HTML_ENABLED
535 printf("\t--html: the input document is(are) an HTML file(s)\n");
537 #ifdef LIBXML_DOCB_ENABLED
538 printf("\t--docbook: the input document is SGML docbook\n");
540 printf("\t--param name value : pass a (parameter,value) pair\n");
541 printf("\t string values must be quoted like \"'string'\"\n");
542 printf("\t--nonet refuse to fetch DTDs or entities over network\n");
543 #ifdef LIBXML_CATALOG_ENABLED
544 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
545 printf("\t otherwise XML Catalogs starting from \n");
546 printf("\t file:///etc/xml/catalog are activated by default\n");
551 main(int argc, char **argv)
554 xsltStylesheetPtr cur = NULL;
555 xmlDocPtr doc, style;
566 xmlLineNumbersDefault(1);
569 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
571 xmlLoadExtDtdDefaultValue = 0;
572 for (i = 1; i < argc; i++) {
573 if (!strcmp(argv[i], "-"))
576 if (argv[i][0] != '-')
578 #ifdef LIBXML_DEBUG_ENABLED
579 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
583 if ((!strcmp(argv[i], "-v")) ||
584 (!strcmp(argv[i], "-verbose")) ||
585 (!strcmp(argv[i], "--verbose"))) {
586 xsltSetGenericDebugFunc(stderr, NULL);
587 } else if ((!strcmp(argv[i], "-o")) ||
588 (!strcmp(argv[i], "-output")) ||
589 (!strcmp(argv[i], "--output"))) {
592 } else if ((!strcmp(argv[i], "-V")) ||
593 (!strcmp(argv[i], "-version")) ||
594 (!strcmp(argv[i], "--version")))
597 } else if ((!strcmp(argv[i], "-novalid")) ||
598 (!strcmp(argv[i], "--novalid"))) {
600 } else if ((!strcmp(argv[i], "-latex")) ||
601 (!strcmp(argv[i], "--latex"))) {
603 } else if ((!strcmp(argv[i], "-noout")) ||
604 (!strcmp(argv[i], "--noout"))) {
606 #ifdef LIBXML_HTML_ENABLED
607 } else if ((!strcmp(argv[i], "-html")) ||
608 (!strcmp(argv[i], "--html"))) {
611 } else if ((!strcmp(argv[i], "-nonet")) ||
612 (!strcmp(argv[i], "--nonet"))) {
613 xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
614 #ifdef LIBXML_CATALOG_ENABLED
615 } else if ((!strcmp(argv[i], "-catalogs")) ||
616 (!strcmp(argv[i], "--catalogs"))) {
617 const char *catalogs;
619 catalogs = getenv("SGML_CATALOG_FILES");
620 if (catalogs == NULL) {
621 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
623 xmlLoadCatalogs(catalogs);
626 } else if ((!strcmp(argv[i], "-param")) ||
627 (!strcmp(argv[i], "--param"))) {
629 params[nbparams++] = argv[i++];
630 params[nbparams++] = argv[i];
631 if (nbparams >= 16) {
632 fprintf(stderr, "too many params\n");
635 } else if ((!strcmp(argv[i], "-maxdepth")) ||
636 (!strcmp(argv[i], "--maxdepth"))) {
640 if (sscanf(argv[i], "%d", &value) == 1) {
642 xsltMaxDepth = value;
645 fprintf(stderr, "Unknown option %s\n", argv[i]);
650 params[nbparams] = NULL;
652 xsltSetXIncludeDefault(1);
654 * Replace entities with their content.
656 xmlSubstituteEntitiesDefault(1);
659 * Register the EXSLT extensions and the test module
662 //xsltRegisterTestModule();
664 for (i = 1; i < argc; i++) {
665 if ((!strcmp(argv[i], "-maxdepth")) ||
666 (!strcmp(argv[i], "--maxdepth"))) {
669 } else if ((!strcmp(argv[i], "-o")) ||
670 (!strcmp(argv[i], "-output")) ||
671 (!strcmp(argv[i], "--output"))) {
675 if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) {
679 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
680 style = xmlParseFile((const char *) argv[i]);
682 fprintf(stderr, "cannot parse %s\n", argv[i]);
685 cur = xsltLoadStylesheetPI(style);
687 /* it is an embedded stylesheet */
688 xsltProcess(style, cur, argv[i]);
689 xsltFreeStylesheet(cur);
692 cur = xsltParseStylesheetDoc(style);
694 if (cur->indent == 1)
695 xmlIndentTreeOutput = 1;
697 xmlIndentTreeOutput = 0;
710 * disable CDATA from being built in the document tree
712 xmlDefaultSAXHandlerInit();
713 xmlDefaultSAXHandler.cdataBlock = NULL;
715 if ((cur != NULL) && (cur->errors == 0)) {
716 for (; i < argc; i++) {
718 #ifdef LIBXML_HTML_ENABLED
720 doc = htmlParseFile(argv[i], NULL);
723 doc = xmlParseFile(argv[i]);
725 fprintf(stderr, "unable to parse %s\n", argv[i]);
728 xsltProcess(doc, cur, argv[i]);
732 xsltFreeStylesheet(cur);
734 //xsltCleanupGlobals();