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/exsltconfig.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$" },
111 { 169, "\\copyright" },
118 { 176, "$^{\\circ}$" },
130 { 188, "$\\frac{1}{4}$" },
131 { 189, "$\\frac{1}{2}$" },
132 { 190, "$\\frac{3}{4}$" },
157 { 215, "$\\times$" },
205 { 915, "$\\Gamma$" },
206 { 916, "$\\Delta$" },
210 { 920, "$\\Theta$" },
213 { 923, "$\\Lambda$" },
220 { 931, "$\\Sigma$" },
222 { 933, "$\\Upsilon$" },
226 { 937, "$\\Omega$" },
227 { 945, "$\\alpha$" },
229 { 947, "$\\gamma$" },
230 { 948, "$\\delta$" },
231 { 949, "$\\epsilon$" },
234 { 952, "$\\theta$" },
236 { 954, "$\\kappa$" },
237 { 955, "$\\lambda$" },
244 { 962, "$\\varsigma$" },
245 { 963, "$\\sigma$" },
247 { 965, "$\\upsilon$" },
251 { 969, "$\\omega$" },
254 { 8226, "$\\bullet$" },
255 { 8230, "$\\ldots$" },
256 { 8242, "$\\prime$" },
257 { 8243, "$\\prime\\prime$" },
264 { 8501, "$\\aleph$" },
265 { 8592, "$\\leftarrow$" },
266 { 8593, "$\\uparrow$" },
267 { 8594, "$\\rightarrow$" },
268 { 8595, "$\\downarrow$" },
269 { 8596, "$\\leftrightarrow$" },
270 { 8629, "$\\hookleftarrow$"},
271 { 8656, "$\\Leftarrow$" },
272 { 8657, "$\\Uparrow$" },
273 { 8658, "$\\Rightarrow$" },
274 { 8659, "$\\Downarrow$" },
275 { 8660, "$\\Leftrightarrow$" },
276 { 8704, "$\\forall$" },
277 { 8706, "$\\partial$" },
278 { 8707, "$\\exists$" },
279 { 8709, "$\\emptyset$" },
280 { 8711, "$\\nabla$" },
284 { 8719, "$\\prod$" },
288 { 8730, "$\\surd$" },
289 { 8733, "$\\propto$" },
290 { 8734, "$\\infty$" },
291 { 8736, "$\\angle$" },
292 { 8743, "$\\wedge$" },
297 { 8756, "$\\leadsto$" },
299 { 8773, "$\\cong$" },
300 { 8776, "$\\approx$" },
302 { 8801, "$\\equiv$" },
305 { 8834, "$\\subset$" },
306 { 8835, "$\\supset$" },
308 { 8838, "$\\subseteq$" },
309 { 8839, "$\\supseteq$" },
310 { 8853, "$\\oplus$" },
311 { 8855, "$\\otimes$" },
312 { 8869, "$\\perp$" },
313 { 8901, "$\\cdot$" },
314 { 8968, "$\\lceil$" },
315 { 8969, "$\\rceil$" },
316 { 8970, "$\\lfloor$" },
317 { 8971, "$\\rfloor$" },
318 { 9001, "$\\langle$" },
319 { 9002, "$\\rangle$" },
320 { 9674, "$\\Diamond$" },
321 { 9824, "$\\spadesuit$" },
322 { 9827, "$\\clubsuit$" },
323 { 9829, "$\\heartsuit$" },
324 { 9830, "$\\diamondsuit$" },
327 unsigned char *latex_translate(int code)
334 for (i = 0; translation == 0 && textab[i].unicode <= code
335 && i < sizeof(textab) / sizeof(textab[0]); i++)
337 if (textab[i].unicode == code)
339 translation = textab[i].sequence;
341 fprintf(stderr, "\n*** translation for 0x%04x is %s\n", code, translation);
349 xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) {
352 xmlXIncludeProcessFlags(doc, XSLT_PARSE_OPTIONS);
355 xmlDebugDumpDocument(stdout, doc);
360 LatexEscape(xmlDocGetRootElement(doc));
363 if (output == NULL) {
364 res = xsltApplyStylesheet(cur, doc, params);
368 fprintf(stderr, "no result for %s\n", filename);
375 #ifdef LIBXML_DEBUG_ENABLED
377 xmlDebugDumpDocument(stdout, res);
380 if (cur->methodURI == NULL) {
381 xsltSaveResultToFile(stdout, res, cur);
384 (cur->method, (const xmlChar *) "xhtml")) {
385 fprintf(stderr, "non standard output xhtml\n");
386 xsltSaveResultToFile(stdout, res, cur);
389 "Unsupported non standard output %s\n",
391 xsltSaveResultToFile(stdout, res, cur);
394 #ifdef LIBXML_DEBUG_ENABLED
400 xsltRunStylesheet(cur, doc, params, output, NULL, NULL);
406 void LatexEscape(xmlNodePtr node)
409 xmlAttrPtr attribute;
413 unsigned char *translation, *replacement;
418 fprintf(stderr, "\n-------- Node type %d\n", node->type);
420 if (xmlNodeIsText(node))
423 fprintf(stderr, "\n-------- Text node at %p (%d bytes):\n%s",
424 node, strlen(node->content), node->content);
427 textlen = strlen(node->content);
432 replacement = malloc(textlen);
435 for (byte = node->content; *byte != '\0'; byte++)
437 /* transform from utf-8 to unicode */
439 if ((*byte & 0x80) == 0)
443 else if ((*byte & 0xe0) == 0xc0)
446 fprintf(stderr, "2-byte unicode: 0x%02x, 0x%02x\n",byte[0], byte[1]);
448 unicode = (*byte & 0x1f) << 6;
450 unicode |= *byte & 0x3f;
452 fprintf(stderr, "Unicode = 0x%04x\n", unicode);
455 else if ((*byte & 0xf0) == 0xe0)
459 unicode = (*byte & 0x0f) << 12;
461 unicode |= (*byte & 0x3f) << 6;
463 unicode |= *byte & 0x3f;
467 fprintf(stderr, "More than 3 bytes utf-8 is not supported.\n");
470 translation = latex_translate(unicode);
472 /* Append the original byte or the translation to the replacment text */
474 if (translation == 0)
476 if (i + 1 >= textlen)
479 replacement = realloc(replacement, textlen);
481 replacement[i++] = *byte;
487 if (i + strlen(translation) + 1 >= textlen)
490 replacement = realloc(replacement, textlen);
492 for (j = 0; translation[j]; j++)
494 replacement[i++] = translation[j];
498 replacement[i] = '\0';
499 xmlNodeSetContent(node, replacement);
501 fprintf(stderr, "\n-------- Replacement text:\n%s", replacement);
507 for (attribute = node->properties; attribute != 0; attribute = attribute->next)
509 LatexEscape(attribute->children);
511 for (child = node->children; child != 0; child = child->next)
513 if (strcmp(child->name, "verbatim") != 0 )
521 static void usage(const char *name)
523 printf("Usage: %s [options] stylesheet file [file ...]\n", name);
524 printf(" Options:\n");
525 printf("\t--version or -V: show the version of libxml and libxslt used\n");
526 printf("\t--verbose or -v: show logs of what's happening\n");
527 printf("\t--output file or -o file: save to a given file\n");
528 printf("\t--debug: dump the tree of the result instead\n");
529 printf("\t--latex: transform special characters for latex\n");
530 printf("\t--novalid: skip the Dtd loading phase\n");
531 printf("\t--noout: do not dump the result\n");
532 printf("\t--maxdepth val : increase the maximum depth\n");
533 #ifdef LIBXML_HTML_ENABLED
534 printf("\t--html: the input document is(are) an HTML file(s)\n");
536 #ifdef LIBXML_DOCB_ENABLED
537 printf("\t--docbook: the input document is SGML docbook\n");
539 printf("\t--param name value : pass a (parameter,value) pair\n");
540 printf("\t string values must be quoted like \"'string'\"\n");
541 printf("\t--nonet refuse to fetch DTDs or entities over network\n");
542 #ifdef LIBXML_CATALOG_ENABLED
543 printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
544 printf("\t otherwise XML Catalogs starting from \n");
545 printf("\t file:///etc/xml/catalog are activated by default\n");
550 main(int argc, char **argv)
553 xsltStylesheetPtr cur = NULL;
554 xmlDocPtr doc, style;
565 xmlLineNumbersDefault(1);
568 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
570 xmlLoadExtDtdDefaultValue = 0;
571 for (i = 1; i < argc; i++) {
572 if (!strcmp(argv[i], "-"))
575 if (argv[i][0] != '-')
577 #ifdef LIBXML_DEBUG_ENABLED
578 if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
582 if ((!strcmp(argv[i], "-v")) ||
583 (!strcmp(argv[i], "-verbose")) ||
584 (!strcmp(argv[i], "--verbose"))) {
585 xsltSetGenericDebugFunc(stderr, NULL);
586 } else if ((!strcmp(argv[i], "-o")) ||
587 (!strcmp(argv[i], "-output")) ||
588 (!strcmp(argv[i], "--output"))) {
591 } else if ((!strcmp(argv[i], "-V")) ||
592 (!strcmp(argv[i], "-version")) ||
593 (!strcmp(argv[i], "--version")))
596 } else if ((!strcmp(argv[i], "-novalid")) ||
597 (!strcmp(argv[i], "--novalid"))) {
599 } else if ((!strcmp(argv[i], "-latex")) ||
600 (!strcmp(argv[i], "--latex"))) {
602 } else if ((!strcmp(argv[i], "-noout")) ||
603 (!strcmp(argv[i], "--noout"))) {
605 #ifdef LIBXML_HTML_ENABLED
606 } else if ((!strcmp(argv[i], "-html")) ||
607 (!strcmp(argv[i], "--html"))) {
610 } else if ((!strcmp(argv[i], "-nonet")) ||
611 (!strcmp(argv[i], "--nonet"))) {
612 xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
613 #ifdef LIBXML_CATALOG_ENABLED
614 } else if ((!strcmp(argv[i], "-catalogs")) ||
615 (!strcmp(argv[i], "--catalogs"))) {
616 const char *catalogs;
618 catalogs = getenv("SGML_CATALOG_FILES");
619 if (catalogs == NULL) {
620 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
622 xmlLoadCatalogs(catalogs);
625 } else if ((!strcmp(argv[i], "-param")) ||
626 (!strcmp(argv[i], "--param"))) {
628 params[nbparams++] = argv[i++];
629 params[nbparams++] = argv[i];
630 if (nbparams >= 16) {
631 fprintf(stderr, "too many params\n");
634 } else if ((!strcmp(argv[i], "-maxdepth")) ||
635 (!strcmp(argv[i], "--maxdepth"))) {
639 if (sscanf(argv[i], "%d", &value) == 1) {
641 xsltMaxDepth = value;
644 fprintf(stderr, "Unknown option %s\n", argv[i]);
649 params[nbparams] = NULL;
651 xsltSetXIncludeDefault(1);
653 * Replace entities with their content.
655 xmlSubstituteEntitiesDefault(1);
658 * Register the EXSLT extensions and the test module
661 //xsltRegisterTestModule();
663 for (i = 1; i < argc; i++) {
664 if ((!strcmp(argv[i], "-maxdepth")) ||
665 (!strcmp(argv[i], "--maxdepth"))) {
668 } else if ((!strcmp(argv[i], "-o")) ||
669 (!strcmp(argv[i], "-output")) ||
670 (!strcmp(argv[i], "--output"))) {
674 if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) {
678 if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
679 style = xmlParseFile((const char *) argv[i]);
681 fprintf(stderr, "cannot parse %s\n", argv[i]);
684 cur = xsltLoadStylesheetPI(style);
686 /* it is an embedded stylesheet */
687 xsltProcess(style, cur, argv[i]);
688 xsltFreeStylesheet(cur);
691 cur = xsltParseStylesheetDoc(style);
693 if (cur->indent == 1)
694 xmlIndentTreeOutput = 1;
696 xmlIndentTreeOutput = 0;
709 * disable CDATA from being built in the document tree
711 xmlDefaultSAXHandlerInit();
712 xmlDefaultSAXHandler.cdataBlock = NULL;
714 if ((cur != NULL) && (cur->errors == 0)) {
715 for (; i < argc; i++) {
717 #ifdef LIBXML_HTML_ENABLED
719 doc = htmlParseFile(argv[i], NULL);
722 doc = xmlParseFile(argv[i]);
724 fprintf(stderr, "unable to parse %s\n", argv[i]);
727 xsltProcess(doc, cur, argv[i]);
731 xsltFreeStylesheet(cur);
733 //xsltCleanupGlobals();