summaryrefslogtreecommitdiff
path: root/xsltproc/xsltproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'xsltproc/xsltproc.c')
-rw-r--r--xsltproc/xsltproc.c510
1 files changed, 510 insertions, 0 deletions
diff --git a/xsltproc/xsltproc.c b/xsltproc/xsltproc.c
new file mode 100644
index 00000000..290743d3
--- /dev/null
+++ b/xsltproc/xsltproc.c
@@ -0,0 +1,510 @@
+/*
+ * xsltproc.c: user program for the XSL Transformation 1.0 engine
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#include "libxslt/libxslt.h"
+#include "libexslt/exslt.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#ifdef LIBXML_DOCB_ENABLED
+#include <libxml/DOCBparser.h>
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/extensions.h>
+#include <libexslt/exsltconfig.h>
+
+#ifdef WIN32
+#ifdef _MSC_VER
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define gettimeofday(p1,p2)
+#endif /* _MS_VER */
+#else /* WIN32 */
+#include <sys/time.h>
+#endif /* WIN32 */
+
+extern int xmlLoadExtDtdDefaultValue;
+
+static int debug = 0;
+static int repeat = 0;
+static int timing = 0;
+static int novalid = 0;
+static int noout = 0;
+#ifdef LIBXML_DOCB_ENABLED
+static int docbook = 0;
+#endif
+#ifdef LIBXML_HTML_ENABLED
+static int html = 0;
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+static int xinclude = 0;
+#endif
+static int profile = 0;
+static int nonet;
+static xmlExternalEntityLoader defaultLoader = NULL;
+
+static struct timeval begin, end;
+static const char *params[16 + 1];
+static int nbparams = 0;
+static const char *output = NULL;
+
+static xmlParserInputPtr
+xsltNoNetExternalEntityLoader(const char *URL, const char *ID,
+ xmlParserCtxtPtr ctxt) {
+ if (URL != NULL) {
+ if ((!xmlStrncasecmp((const xmlChar *) URL,
+ (const xmlChar *) "ftp://", 6)) ||
+ (!xmlStrncasecmp((const xmlChar *) URL,
+ (const xmlChar *) "http://", 7))) {
+ fprintf(stderr, "Attempt to load network entity %s \n", URL);
+ if (nonet)
+ return(NULL);
+ }
+ }
+ if (defaultLoader != NULL) {
+ return(defaultLoader(URL, ID, ctxt));
+ }
+ return(NULL);
+}
+
+static void
+xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) {
+ xmlDocPtr res;
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+ if (xinclude) {
+ if (timing)
+ gettimeofday(&begin, NULL);
+ xmlXIncludeProcess(doc);
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec += (end.tv_usec - begin.tv_usec) / 1000;
+ fprintf(stderr, "XInclude processing %s took %ld ms\n",
+ filename, msec);
+ }
+ }
+#endif
+ if (timing)
+ gettimeofday(&begin, NULL);
+ if (output == NULL) {
+ if (repeat) {
+ int j;
+
+ for (j = 1; j < repeat; j++) {
+ res = xsltApplyStylesheet(cur, doc, params);
+ xmlFreeDoc(res);
+ xmlFreeDoc(doc);
+#ifdef LIBXML_HTML_ENABLED
+ if (html)
+ doc = htmlParseFile(filename, NULL);
+ else
+#endif
+#ifdef LIBXML_DOCB_ENABLED
+ if (docbook)
+ doc = docbParseFile(filename, NULL);
+ else
+#endif
+ doc = xmlParseFile(filename);
+ }
+ }
+ if (profile) {
+ res = xsltProfileStylesheet(cur, doc, params, stderr);
+ } else {
+ res = xsltApplyStylesheet(cur, doc, params);
+ }
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec += (end.tv_usec - begin.tv_usec) / 1000;
+ if (repeat)
+ fprintf(stderr,
+ "Applying stylesheet %d times took %ld ms\n",
+ repeat, msec);
+ else
+ fprintf(stderr,
+ "Applying stylesheet took %ld ms\n", msec);
+ }
+ xmlFreeDoc(doc);
+ if (res == NULL) {
+ fprintf(stderr, "no result for %s\n", filename);
+ return;
+ }
+ if (noout) {
+ xmlFreeDoc(res);
+ return;
+ }
+#ifdef LIBXML_DEBUG_ENABLED
+ if (debug)
+ xmlDebugDumpDocument(stdout, res);
+ else {
+#endif
+ if (cur->methodURI == NULL) {
+ if (timing)
+ gettimeofday(&begin, NULL);
+ xsltSaveResultToFile(stdout, res, cur);
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec += (end.tv_usec - begin.tv_usec) / 1000;
+ fprintf(stderr, "Saving result took %ld ms\n",
+ msec);
+ }
+ } else {
+ if (xmlStrEqual
+ (cur->method, (const xmlChar *) "xhtml")) {
+ fprintf(stderr, "non standard output xhtml\n");
+ if (timing)
+ gettimeofday(&begin, NULL);
+ xsltSaveResultToFile(stdout, res, cur);
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec +=
+ (end.tv_usec - begin.tv_usec) / 1000;
+ fprintf(stderr,
+ "Saving result took %ld ms\n",
+ msec);
+ }
+ } else {
+ fprintf(stderr,
+ "Unsupported non standard output %s\n",
+ cur->method);
+ }
+ }
+#ifdef LIBXML_DEBUG_ENABLED
+ }
+#endif
+
+ xmlFreeDoc(res);
+ } else {
+ xsltRunStylesheet(cur, doc, params, output, NULL, NULL);
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec += (end.tv_usec - begin.tv_usec) / 1000;
+ fprintf(stderr,
+ "Running stylesheet and saving result took %ld ms\n",
+ msec);
+ }
+ xmlFreeDoc(doc);
+ }
+}
+
+static void usage(const char *name) {
+ printf("Usage: %s [options] stylesheet file [file ...]\n", name);
+ printf(" Options:\n");
+ printf(" --version or -V: show the version of libxml and libxslt used\n");
+ printf(" --verbose or -v: show logs of what's happening\n");
+ printf(" --output file or -o file: save to a given file\n");
+ printf(" --timing: display the time used\n");
+ printf(" --repeat: run the transformation 20 times\n");
+ printf(" --debug: dump the tree of the result instead\n");
+ printf(" --novalid: skip the Dtd loading phase\n");
+ printf(" --noout: do not dump the result\n");
+ printf(" --maxdepth val : increase the maximum depth\n");
+#ifdef LIBXML_HTML_ENABLED
+ printf(" --html: the input document is(are) an HTML file(s)\n");
+#endif
+#ifdef LIBXML_DOCB_ENABLED
+ printf(" --docbook: the input document is SGML docbook\n");
+#endif
+ printf(" --param name value : pass a (parameter,value) pair\n");
+ printf(" --nonet refuse to fetch DTDs or entities over network\n");
+ printf(" --warnnet warn against fetching over the network\n");
+#ifdef LIBXML_CATALOG_ENABLED
+ printf(" --catalogs : use the catalogs from $SGML_CATALOG_FILES\n");
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+ printf(" --xinclude : do XInclude processing on document intput\n");
+#endif
+ printf(" --profile or --norman : dump profiling informations \n");
+}
+
+int
+main(int argc, char **argv)
+{
+ int i;
+ xsltStylesheetPtr cur = NULL;
+ xmlDocPtr doc, style;
+
+ if (argc <= 1) {
+ usage(argv[0]);
+ return (1);
+ }
+
+ xmlInitMemory();
+
+ LIBXML_TEST_VERSION
+
+ defaultLoader = xmlGetExternalEntityLoader();
+ if (novalid == 0) /* TODO XML_DETECT_IDS | XML_COMPLETE_ATTRS */
+ xmlLoadExtDtdDefaultValue = 6;
+ else
+ xmlLoadExtDtdDefaultValue = 0;
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-"))
+ break;
+
+ if (argv[i][0] != '-')
+ continue;
+#ifdef LIBXML_DEBUG_ENABLED
+ if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
+ debug++;
+ } else
+#endif
+ if ((!strcmp(argv[i], "-v")) ||
+ (!strcmp(argv[i], "-verbose")) ||
+ (!strcmp(argv[i], "--verbose"))) {
+ xsltSetGenericDebugFunc(stderr, NULL);
+ } else if ((!strcmp(argv[i], "-o")) ||
+ (!strcmp(argv[i], "-output")) ||
+ (!strcmp(argv[i], "--output"))) {
+ i++;
+ output = argv[i++];
+ } else if ((!strcmp(argv[i], "-V")) ||
+ (!strcmp(argv[i], "-version")) ||
+ (!strcmp(argv[i], "--version"))) {
+ printf("Using libxml %s, libxslt %s and libexslt %s\n",
+ xmlParserVersion, xsltEngineVersion, exsltLibraryVersion);
+ printf
+ ("xsltproc was compiled against libxml %d, libxslt %d and libexslt %d\n",
+ LIBXML_VERSION, LIBXSLT_VERSION, LIBEXSLT_VERSION);
+ printf("libxslt %d was compiled against libxml %d\n",
+ xsltLibxsltVersion, xsltLibxmlVersion);
+ printf("libexslt %d was compiled against libxml %d\n",
+ exsltLibexsltVersion, exsltLibxmlVersion);
+ } else if ((!strcmp(argv[i], "-repeat"))
+ || (!strcmp(argv[i], "--repeat"))) {
+ if (repeat == 0)
+ repeat = 20;
+ else
+ repeat = 100;
+ } else if ((!strcmp(argv[i], "-novalid")) ||
+ (!strcmp(argv[i], "--novalid"))) {
+ novalid++;
+ } else if ((!strcmp(argv[i], "-noout")) ||
+ (!strcmp(argv[i], "--noout"))) {
+ noout++;
+#ifdef LIBXML_DOCB_ENABLED
+ } else if ((!strcmp(argv[i], "-docbook")) ||
+ (!strcmp(argv[i], "--docbook"))) {
+ docbook++;
+#endif
+#ifdef LIBXML_HTML_ENABLED
+ } else if ((!strcmp(argv[i], "-html")) ||
+ (!strcmp(argv[i], "--html"))) {
+ html++;
+#endif
+ } else if ((!strcmp(argv[i], "-timing")) ||
+ (!strcmp(argv[i], "--timing"))) {
+ timing++;
+ } else if ((!strcmp(argv[i], "-profile")) ||
+ (!strcmp(argv[i], "--profile"))) {
+ profile++;
+ } else if ((!strcmp(argv[i], "-norman")) ||
+ (!strcmp(argv[i], "--norman"))) {
+ profile++;
+ } else if ((!strcmp(argv[i], "-warnnet")) ||
+ (!strcmp(argv[i], "--warnnet"))) {
+ xmlSetExternalEntityLoader(xsltNoNetExternalEntityLoader);
+ } else if ((!strcmp(argv[i], "-nonet")) ||
+ (!strcmp(argv[i], "--nonet"))) {
+ xmlSetExternalEntityLoader(xsltNoNetExternalEntityLoader);
+ nonet = 1;
+#ifdef LIBXML_CATALOG_ENABLED
+ } else if ((!strcmp(argv[i], "-catalogs")) ||
+ (!strcmp(argv[i], "--catalogs"))) {
+ const char *catalogs;
+
+ catalogs = getenv("SGML_CATALOG_FILES");
+ if (catalogs == NULL) {
+ fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
+ } else {
+ xmlLoadCatalogs(catalogs);
+ }
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+ } else if ((!strcmp(argv[i], "-xinclude")) ||
+ (!strcmp(argv[i], "--xinclude"))) {
+ xinclude++;
+ xsltSetXIncludeDefault(1);
+#endif
+ } else if ((!strcmp(argv[i], "-param")) ||
+ (!strcmp(argv[i], "--param"))) {
+ i++;
+ params[nbparams++] = argv[i++];
+ params[nbparams++] = argv[i];
+ if (nbparams >= 16) {
+ fprintf(stderr, "too many params\n");
+ return (1);
+ }
+ } else if ((!strcmp(argv[i], "-maxdepth")) ||
+ (!strcmp(argv[i], "--maxdepth"))) {
+ int value;
+
+ i++;
+ if (sscanf(argv[i], "%d", &value) == 1) {
+ if (value > 0)
+ xsltMaxDepth = value;
+ }
+ } else {
+ fprintf(stderr, "Unknown option %s\n", argv[i]);
+ usage(argv[0]);
+ return (1);
+ }
+ }
+ params[nbparams] = NULL;
+
+ /*
+ * Replace entities with their content.
+ */
+ xmlSubstituteEntitiesDefault(1);
+
+ /*
+ * Register the EXSLT extensions
+ */
+ exslRegisterAll();
+
+ for (i = 1; i < argc; i++) {
+ if ((!strcmp(argv[i], "-maxdepth")) ||
+ (!strcmp(argv[i], "--maxdepth"))) {
+ i++;
+ continue;
+ } else if ((!strcmp(argv[i], "-o")) ||
+ (!strcmp(argv[i], "-output")) ||
+ (!strcmp(argv[i], "--output"))) {
+ i++;
+ continue;
+ }
+ if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) {
+ i += 2;
+ continue;
+ }
+ if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
+ if (timing)
+ gettimeofday(&begin, NULL);
+ style = xmlParseFile((const char *) argv[i]);
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec += (end.tv_usec - begin.tv_usec) / 1000;
+ fprintf(stderr, "Parsing stylesheet %s took %ld ms\n",
+ argv[i], msec);
+ }
+ if (style == NULL) {
+ fprintf(stderr, "cannot parse %s\n", argv[i]);
+ cur = NULL;
+ } else {
+ cur = xsltLoadStylesheetPI(style);
+ if (cur != NULL) {
+ /* it is an embedded stylesheet */
+ xsltProcess(style, cur, argv[i]);
+ xsltFreeStylesheet(cur);
+ exit(0);
+ }
+ cur = xsltParseStylesheetDoc(style);
+ if (cur != NULL) {
+ if (cur->indent == 1)
+ xmlIndentTreeOutput = 1;
+ else
+ xmlIndentTreeOutput = 0;
+ i++;
+ }
+ }
+ break;
+
+ }
+ }
+
+ /*
+ * disable CDATA from being built in the document tree
+ */
+ xmlDefaultSAXHandlerInit();
+ xmlDefaultSAXHandler.cdataBlock = NULL;
+
+ if ((cur != NULL) && (cur->errors == 0)) {
+ for (; i < argc; i++) {
+ doc = NULL;
+ if (timing)
+ gettimeofday(&begin, NULL);
+#ifdef LIBXML_HTML_ENABLED
+ if (html)
+ doc = htmlParseFile(argv[i], NULL);
+ else
+#endif
+#ifdef LIBXML_DOCB_ENABLED
+ if (docbook)
+ doc = docbParseFile(argv[i], NULL);
+ else
+#endif
+ doc = xmlParseFile(argv[i]);
+ if (doc == NULL) {
+ fprintf(stderr, "unable to parse %s\n", argv[i]);
+ continue;
+ }
+ if (timing) {
+ long msec;
+
+ gettimeofday(&end, NULL);
+ msec = end.tv_sec - begin.tv_sec;
+ msec *= 1000;
+ msec += (end.tv_usec - begin.tv_usec) / 1000;
+ fprintf(stderr, "Parsing document %s took %ld ms\n",
+ argv[i], msec);
+ }
+ xsltProcess(doc, cur, argv[i]);
+ }
+ xsltFreeStylesheet(cur);
+ }
+ xsltUnregisterAllExtModules();
+ xmlCleanupParser();
+ xmlMemoryDump();
+ return (0);
+}
+