You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Xslt.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. //package org.apache.tools.ant.taskdefs;
  55. import org.apache.tools.ant.Task;
  56. import java.net.*;
  57. import java.io.*;
  58. import java.util.*;
  59. import org.apache.xalan.xslt.*;
  60. /**
  61. * Task to call the XSLT processor Xalan (part of xml.apache.org), which converts xml files
  62. * from a source to an output using a stylesheet file
  63. *
  64. * <p>
  65. * This task can take the following arguments:
  66. * <ul>
  67. * <li>infile
  68. * <li>xsltfile
  69. * <li>outfile
  70. * <li>smart
  71. * <li>dependent
  72. * </ul>
  73. * <p>
  74. * Of these arguments, <b>infile, outfile</b> and <b>xsltfile</b> are required.
  75. * <p>smart defaults to 'no'. The other allowed value is 'yes'. If smart is set to 'yes'
  76. * xalan is only called if either the outfile is older than the infile or the stylesheet
  77. * or the outfile doesn't exist.
  78. * <p>dependent defaults to 'none'. Other possible values: a comma delimited list of file names
  79. * which date is checked against the output file. This way you can name files which, if
  80. * they have been modified, initiate a restart of the xslt process, like external entities etc.
  81. * <p>
  82. * @author Fotis Jannidis <a href="mailto:fotis@jannidis.de">fotis@jannidis.de</a>
  83. */
  84. public class Xslt extends Task {
  85. private String infile, outfile, xsltfile;
  86. private String smart = "no"; //defaults to do conversion everytime task is called
  87. private String dependent = "none"; //defaults to no dependencies
  88. private boolean startXslt = false;
  89. /**
  90. * Sets the input file
  91. *
  92. */
  93. public void setInfile (String infile) {
  94. this.infile = infile;
  95. }
  96. /**
  97. * Sets the stylesheet file
  98. *
  99. */
  100. public void setXsltfile (String xsltfile) {
  101. this.xsltfile = xsltfile;
  102. }
  103. /**
  104. * Sets the output file
  105. *
  106. */
  107. public void setOutfile (String outfile) {
  108. this.outfile = outfile;
  109. }
  110. /**
  111. * Sets the value for smart
  112. *
  113. * @param option valid values:
  114. * <ul>
  115. * <li>yes: check whether output file is older than input or stylesheet
  116. * <li>no: (default) do conversion everytime task is called
  117. * </ul>
  118. */
  119. public void setSmart (String smart) {
  120. this.smart = smart;
  121. }
  122. /**
  123. * Sets the value for dependent
  124. *
  125. * @param option valid values:
  126. * <ul>
  127. * <li>none: (default)
  128. * <li>comma delimited list of files whose existence and date is checked
  129. * against the output file
  130. * </ul>
  131. */
  132. public void setDependent (String dependent) {
  133. this.dependent = dependent;
  134. }
  135. /**
  136. * Calls Xalan and does the transformation
  137. *
  138. */
  139. private void transform(String xmlSourceURL, String xslURL, String outputURL)
  140. throws java.io.IOException,
  141. java.net.MalformedURLException,
  142. org.xml.sax.SAXException
  143. {
  144. // Use XSLTProcessor to instantiate an XSLTProcessor.
  145. org.apache.xalan.xslt.XSLTProcessor processor =
  146. org.apache.xalan.xslt.XSLTProcessorFactory.getProcessor();
  147. // Create the 3 objects the XSLTProcessor needs to perform the transformation.
  148. org.apache.xalan.xslt.XSLTInputSource xmlSource =
  149. new org.apache.xalan.xslt.XSLTInputSource (infile);
  150. org.apache.xalan.xslt.XSLTInputSource xslSheet =
  151. new org.apache.xalan.xslt.XSLTInputSource (xsltfile);
  152. org.apache.xalan.xslt.XSLTResultTarget xmlResult =
  153. new org.apache.xalan.xslt.XSLTResultTarget (outfile);
  154. // Perform the transformation.
  155. System.out.println("============================");
  156. System.out.println("xslt \nin: " + infile + "\nstyle: " + xsltfile + "\nout: " + outfile);
  157. System.out.println("============================");
  158. processor.process(xmlSource, xslSheet, xmlResult);
  159. } //end transform
  160. /**
  161. * Catches the errors transform() can throw and
  162. * returns meaningfull error messages
  163. */
  164. private void startTransform () {
  165. try {
  166. transform (infile,xsltfile,outfile);
  167. } catch (org.xml.sax.SAXException saxerror) {
  168. System.out.println("Task xslt - SAX ERROR:\n " + saxerror);
  169. } catch (MalformedURLException urlerror) {
  170. System.out.println("Task xslt - URL ERROR:\n " + urlerror);
  171. } catch (IOException ioerror) {
  172. System.out.println("Task xslt - IO ERROR:\n " + ioerror);
  173. }
  174. } //end startTransform
  175. /**
  176. * Checks for existence of output file and compares
  177. * dates with input and stylesheet file
  178. */
  179. private boolean smartCheck (File outfileF, long outfileLastModified, File infileF, File xsltfileF) {
  180. if (outfileF.exists()) {
  181. //checks whether output file is older than input file or xslt stylesheet file
  182. if ((outfileLastModified < infileF.lastModified()) |
  183. (outfileLastModified < xsltfileF.lastModified())) {
  184. return true;
  185. }
  186. } else {
  187. //if output file does not exist, start xslt process
  188. return true;
  189. }
  190. return false;
  191. } //end smartCheck
  192. /**
  193. * Checks for existence and date of dependent files
  194. * This could be folded together with smartCheck by using
  195. * a general routine but it wouldn't be as fast as now
  196. */
  197. private boolean dependenciesCheck(File outfileF, long outfileLastModified) {
  198. String dependentFileName;
  199. File dependentFile;
  200. StringTokenizer tokens = new StringTokenizer(dependent,",");
  201. while (tokens.hasMoreTokens()) {
  202. dependentFileName = (String) tokens.nextToken();
  203. dependentFile = new File (dependentFileName);
  204. //check: does dependent file exist
  205. if (dependentFile.exists()) {
  206. //check dates
  207. if ((outfileLastModified < dependentFile.lastModified()) ) {
  208. return true;
  209. }
  210. } else {
  211. System.err.println("Task xslt - ERROR in attribute 'dependent':\n file " + dependentFileName + " does not exist.");
  212. }
  213. }
  214. return false;
  215. } //end dependenciesCheck
  216. /**
  217. * Main method, which is called by ant.
  218. * Checks for the value of smart and calls startTransform accordingly
  219. */
  220. public void execute () throws org.apache.tools.ant.BuildException {
  221. File outfileF = new File (outfile);
  222. File infileF = new File(infile);
  223. File xsltfileF = new File (xsltfile);
  224. long outfileLastModified = outfileF.lastModified();
  225. boolean startFileExist = true;
  226. //checks whether input and stylesheet exist.
  227. //this could be left to the parser, but this solution does make problems if smart is set to yes
  228. if (!infileF.exists()) {
  229. System.err.println("Task xslt - ERROR:\n Input file " + infile + " does not exist!");
  230. startFileExist = false;
  231. } else if (!xsltfileF.exists()) {
  232. System.err.println("Task xslt - ERROR:\n Stylesheet file " + xsltfile + " does not exist!");
  233. startFileExist = false;
  234. }
  235. //checks attribute 'smart'
  236. if (smart.equals("no")) {
  237. startXslt = true;
  238. //if attribute smart = 'yes'
  239. } else if (smart.equals("yes")) {
  240. startXslt = smartCheck (outfileF,outfileLastModified,infileF,xsltfileF);
  241. //checks dependent files against output file, makes only sense if smartCheck returns false
  242. if (!dependent.equals("none") & (startXslt == false)) {
  243. startXslt = dependenciesCheck(outfileF,outfileLastModified);
  244. }
  245. //returns error message, if smart has another value as 'yes' or 'no'
  246. } else {
  247. System.err.println("Task xslt - ERROR: Allowed values for the attribute smart are 'yes' or 'no'");
  248. }
  249. if (startFileExist & startXslt) {
  250. startTransform();
  251. }
  252. } //end execute
  253. //quick access for debugging
  254. //usage XSLT infile xsltfile outfile (smart is 'yes')
  255. /*
  256. public static void main (String args[]) {
  257. Xslt xslt = new Xslt();
  258. xslt.setInfile(args[0]);
  259. xslt.setXsltfile(args[1]);
  260. xslt.setOutfile(args[2]);
  261. xslt.setSmart("yes");
  262. xslt.setDependent("test1,test2");
  263. xslt.execute();
  264. } */
  265. }