/* $Id: trans.c,v 1.19 2004/11/22 02:28:21 mgrouch Exp $ */ #include "config.h" #include "trans.h" /* * This code is based on xsltproc by Daniel Veillard (daniel@veillard.com) * (see also http://xmlsoft.org/) */ /* TODO: 1. preloading entities */ xmlChar *paths[MAX_PATHS + 1]; int nbpaths = 0; const char *output = NULL; /* file name to save output */ int errorno = 0; xmlExternalEntityLoader defaultEntityLoader = NULL; /** * Initialize global command line options */ void xsltInitOptions(xsltOptionsPtr ops) { ops->noval = 1; ops->nonet = 1; ops->omit_decl = 0; ops->show_extensions = 0; ops->noblanks = 0; ops->embed = 0; #ifdef LIBXML_XINCLUDE_ENABLED ops->xinclude = 0; #endif #ifdef LIBXML_HTML_ENABLED ops->html = 0; #endif #ifdef LIBXML_CATALOG_ENABLED ops->catalogs = 0; #endif } /** * Initialize LibXML */ void xsltInitLibXml(xsltOptionsPtr ops) { /* * Initialize library memory */ xmlInitMemory(); LIBXML_TEST_VERSION /* * Store line numbers in the document tree */ xmlLineNumbersDefault(1); /* * Register the EXSLT extensions */ exsltRegisterAll(); /* * Register the test module */ xsltRegisterTestModule(); if (ops->show_extensions) { xsltDebugDumpExtensions(stderr); exit(0); } /* * Replace entities with their content. */ xmlSubstituteEntitiesDefault(1); /* * Register entity loader */ defaultEntityLoader = xmlGetExternalEntityLoader(); xmlSetExternalEntityLoader(xsltExternalEntityLoader); if (ops->nonet) { defaultEntityLoader = xmlNoNetExternalEntityLoader; } xmlKeepBlanksDefault(1); if (ops->noblanks) xmlKeepBlanksDefault(0); xmlPedanticParserDefault(0); xmlGetWarningsDefaultValue = 1; /*xmlDoValidityCheckingDefaultValue = 0;*/ xmlLoadExtDtdDefaultValue = 1; /* * DTD validation options */ if (ops->noval == 0) { xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; } else { xmlLoadExtDtdDefaultValue = 0; } #ifdef LIBXML_XINCLUDE_ENABLED /* * enable XInclude */ if (ops->xinclude) xsltSetXIncludeDefault(1); #endif #ifdef LIBXML_CATALOG_ENABLED /* * enable SGML catalogs */ if (ops->catalogs) { char *catalogs = getenv("SGML_CATALOG_FILES"); if (catalogs == NULL) fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n"); else xmlLoadCatalogs(catalogs); } #endif } /** * Entity loader */ xmlParserInputPtr xsltExternalEntityLoader(const char *URL, const char *ID, xmlParserCtxtPtr ctxt) { xmlParserInputPtr ret; warningSAXFunc warning = NULL; int i; if ((ctxt != NULL) && (ctxt->sax != NULL)) { warning = ctxt->sax->warning; ctxt->sax->warning = NULL; } if (defaultEntityLoader != NULL) { ret = defaultEntityLoader(URL, ID, ctxt); if (ret != NULL) { if (warning != NULL) ctxt->sax->warning = warning; return(ret); } } /* preload resources */ /* TODO 1. preloading entities */ for (i = 0; i < nbpaths; i++) { xmlChar *newURL; int len; len = xmlStrlen(paths[i]) + xmlStrlen(BAD_CAST URL) + 5; newURL = xmlMalloc(len); if (newURL != NULL) { sprintf((char *) newURL, "%s/%s", paths[i], URL); ret = defaultEntityLoader((const char *)newURL, ID, ctxt); xmlFree(newURL); if (ret != NULL) { if (warning != NULL) ctxt->sax->warning = warning; return(ret); } } } if (warning != NULL) { ctxt->sax->warning = warning; if (URL != NULL) warning(ctxt, "failed to load external entity \"%s\"\n", URL); else if (ID != NULL) warning(ctxt, "failed to load external entity \"%s\"\n", ID); } return(NULL); } /** * Run stylesheet on XML document */ void xsltProcess(xsltOptionsPtr ops, xmlDocPtr doc, const char** params, xsltStylesheetPtr cur, const char *filename) { xmlDocPtr res; xsltTransformContextPtr ctxt; if (ops->omit_decl) { cur->omitXmlDeclaration = 1; } #ifdef LIBXML_XINCLUDE_ENABLED if (ops->xinclude) xmlXIncludeProcess(doc); #endif if (output == NULL) { ctxt = xsltNewTransformContext(cur, doc); if (ctxt == NULL) return; res = xsltApplyStylesheetUser(cur, doc, params, NULL, NULL, ctxt); if (ctxt->state == XSLT_STATE_ERROR) errorno = 9; if (ctxt->state == XSLT_STATE_STOPPED) errorno = 10; xsltFreeTransformContext(ctxt); xmlFreeDoc(doc); if (res == NULL) { fprintf(stderr, "no result for %s\n", filename); return; } if (cur->methodURI == NULL) { xsltSaveResultToFile(stdout, res, cur); } else { if (xmlStrEqual(cur->method, (const xmlChar *) "xhtml")) { fprintf(stderr, "non standard output xhtml\n"); xsltSaveResultToFile(stdout, res, cur); } else { fprintf(stderr, "unsupported non standard output %s\n", cur->method); errorno = 7; } } xmlFreeDoc(res); } else { int ret; ctxt = xsltNewTransformContext(cur, doc); if (ctxt == NULL) return; ret = xsltRunStylesheet(cur, doc, params, output, NULL, NULL); if (ctxt->state == XSLT_STATE_ERROR) errorno = 9; xsltFreeTransformContext(ctxt); xmlFreeDoc(doc); } } /** * run XSLT on documents */ int xsltRun(xsltOptionsPtr ops, char* xsl, const char** params, int count, char **docs) { xsltStylesheetPtr cur = NULL; xmlDocPtr doc, style; int i, options = 0; options = XML_PARSE_DTDATTR; /* * Compile XSLT Sylesheet */ style = xmlReadFile((const char *) xsl, NULL, options); if (style == NULL) { fprintf(stderr, "cannot parse %s\n", xsl); cur = NULL; errorno = 4; } else { if (ops->embed) { cur = xsltLoadStylesheetPI(style); if (cur != NULL) { /* it is an embedded stylesheet */ xsltProcess(ops, style, params, cur, xsl); xsltFreeStylesheet(cur); cur = NULL; } for (i=0; ierrors != 0) { errorno = 5; goto done; } if (cur->indent == 1) xmlIndentTreeOutput = 1; else xmlIndentTreeOutput = 0; } else { xmlFreeDoc(style); errorno = 5; goto done; } } /* * disable CDATA from being built in the document tree */ xmlDefaultSAXHandlerInit(); xmlDefaultSAXHandler.cdataBlock = NULL; /* * run XSLT */ if ((cur != NULL) && (cur->errors == 0)) { for (i=0; ihtml) doc = htmlParseFile(docs[i], NULL); else #endif { doc = xmlReadFile((const char *) docs[i], NULL, options); } if (doc == NULL) { fprintf(stderr, "unable to parse %s\n", docs[i]); errorno = 6; continue; } xsltProcess(ops, doc, params, cur, docs[i]); } if (count == 0) { /* stdin */ doc = NULL; #ifdef LIBXML_HTML_ENABLED if (ops->html) doc = htmlParseFile("-", NULL); else #endif doc = xmlReadFile("-", NULL, options); xsltProcess(ops, doc, params, cur, "-"); } } done: /* * Clean up */ if (cur != NULL) xsltFreeStylesheet(cur); return(errorno); }