KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > StyleSheet


1 package com.icl.saxon;
2 import com.icl.saxon.tree.TreeBuilder;
3 import com.icl.saxon.tinytree.TinyBuilder;
4 import com.icl.saxon.om.Builder;
5 import com.icl.saxon.om.Navigator;
6 import com.icl.saxon.om.DocumentInfo;
7 import com.icl.saxon.om.Namespace;
8 import com.icl.saxon.om.NamePool;
9 import com.icl.saxon.expr.*;
10 import com.icl.saxon.style.*;
11 import com.icl.saxon.output.*;
12 import com.icl.saxon.trace.*;
13 import com.icl.saxon.style.TerminationException;
14
15 import org.xml.sax.SAXException JavaDoc;
16 import org.xml.sax.helpers.AttributesImpl JavaDoc;
17 import org.xml.sax.*;
18
19 import org.w3c.dom.Node JavaDoc;
20 import org.w3c.dom.Document JavaDoc;
21
22 import java.util.*;
23 import java.io.*;
24 import java.net.URL JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26
27 import javax.xml.transform.*;
28 import javax.xml.transform.sax.*;
29 import javax.xml.transform.stream.*;
30
31 /**
32   * This <B>StyleSheet</B> class is the entry point to the Saxon XSLT Processor. This
33   * class is provided to control the processor from the command line.<p>
34   *
35   * The XSLT syntax supported conforms to the W3C XSLT 1.0 and XPath 1.0 recommendation.
36   * Only the transformation language is implemented (not the formatting objects).
37   * Saxon extensions are documented in the file extensions.html
38   *
39   * @author M.H.Kay (mhkay@iclway.co.uk)
40   */

41   
42 public class StyleSheet {
43
44     protected TransformerFactoryImpl factory = new TransformerFactoryImpl();
45     
46     protected NamePool namePool = NamePool.getDefaultNamePool();
47     boolean showTime = false;
48     int repeat = 1;
49         
50     /**
51     * Main program, can be used directly from the command line.
52     * <p>The format is:</P>
53     * <p>java com.icl.saxon.StyleSheet [options] <I>source-file</I> <I>style-file</I> &gt;<I>output-file</I></P>
54     * <p>followed by any number of parameters in the form {keyword=value}... which can be
55     * referenced from within the stylesheet.</p>
56     * <p>This program applies the XSL style sheet in style-file to the source XML document in source-file.</p>
57     */

58     
59     public static void main (String JavaDoc args[])
60         throws java.lang.Exception JavaDoc
61     {
62         // the real work is delegated to another routine so that it can be used in a subclass
63
(new StyleSheet()).doMain(args, new StyleSheet(), " java com.icl.saxon.StyleSheet");
64     }
65
66     /**
67     * Support method for main program. This support method can also be invoked from subclasses
68     * that support the same command line interface
69     * @param args the command-line arguments
70     * @param app instance of the StyleSheet class (or a subclass) to be invoked
71     * @param name name of the class, to be used in error messages
72     */

73
74     protected void doMain(String JavaDoc args[], StyleSheet app, String JavaDoc name) {
75         
76         
77         String JavaDoc sourceFileName = null;
78         String JavaDoc styleFileName = null;
79         File sourceFile = null;
80         File styleFile = null;
81         File outputFile = null;
82         boolean useURLs = false;
83         ParameterSet params = new ParameterSet();
84         Properties outputProperties = new Properties();
85         String JavaDoc outputFileName = null;
86         boolean useAssociatedStylesheet = false;
87         boolean wholeDirectory = false;
88         
89                 // Check the command-line arguments.
90

91         try {
92             int i = 0;
93             while (true) {
94                 if (i>=args.length) badUsage(name, "No source file name");
95
96                 if (args[i].charAt(0)=='-') {
97
98                     if (args[i].equals("-a")) {
99                         useAssociatedStylesheet = true;
100                         i++;
101                     }
102
103                     else if (args[i].equals("-ds")) {
104                         factory.setAttribute(
105                             FeatureKeys.TREE_MODEL,
106                             new Integer JavaDoc(Builder.STANDARD_TREE));
107                         i++;
108                     }
109
110                     else if (args[i].equals("-dt")) {
111                         factory.setAttribute(
112                             FeatureKeys.TREE_MODEL,
113                             new Integer JavaDoc(Builder.TINY_TREE));
114                         i++;
115                     }
116
117
118                     else if (args[i].equals("-l")) {
119                         factory.setAttribute(
120                             FeatureKeys.LINE_NUMBERING,
121                             new Boolean JavaDoc(true));
122                         i++;
123                     }
124
125                     else if (args[i].equals("-u")) {
126                         useURLs = true;
127                         i++;
128                     }
129         
130                     else if (args[i].equals("-t")) {
131                         System.err.println(Version.getProductName());
132                         System.err.println("Java version " + System.getProperty("java.version"));
133                         factory.setAttribute(
134                             FeatureKeys.TIMING,
135                             new Boolean JavaDoc(true));
136
137                         Loader.setTracing(true);
138                         showTime = true;
139                         i++;
140                     }
141
142                     else if (args[i].equals("-3")) { // undocumented option: do it thrice
143
i++;
144                         repeat = 3;
145                     }
146
147                     else if (args[i].equals("-9")) { // undocumented option: do it nine times
148
i++;
149                         repeat = 9;
150                     }
151         
152                     else if (args[i].equals("-o")) {
153                         i++;
154                         if (args.length < i+2) badUsage(name, "No output file name");
155                         outputFileName = args[i++];
156                     }
157
158                     else if (args[i].equals("-x")) {
159                         i++;
160                         if (args.length < i+2) badUsage(name, "No source parser class");
161                         String JavaDoc sourceParserName = args[i++];
162                         factory.setAttribute(
163                                 FeatureKeys.SOURCE_PARSER_CLASS,
164                                 sourceParserName);
165                     }
166
167                     else if (args[i].equals("-y")) {
168                         i++;
169                         if (args.length < i+2) badUsage(name, "No style parser class");
170                         String JavaDoc styleParserName = args[i++];
171                         factory.setAttribute(
172                                 FeatureKeys.STYLE_PARSER_CLASS,
173                                 styleParserName);
174                     }
175
176                     else if (args[i].equals("-r")) {
177                         i++;
178                         if (args.length < i+2) badUsage(name, "No URIResolver class");
179                         String JavaDoc r = args[i++];
180                         factory.setURIResolver(makeURIResolver(r));
181                     }
182
183                     else if (args[i].equals("-T")) {
184                         i++;
185                         TraceListener traceListener = new com.icl.saxon.trace.SimpleTraceListener();
186                         factory.setAttribute(
187                                 FeatureKeys.TRACE_LISTENER,
188                                 traceListener);
189                         factory.setAttribute(
190                                 FeatureKeys.LINE_NUMBERING,
191                                 Boolean.TRUE);
192                     }
193
194                     else if (args[i].equals("-TL")) {
195                         i++;
196                         if (args.length < i+2) badUsage(name, "No TraceListener class");
197                         TraceListener traceListener = makeTraceListener(args[i++]);
198                         factory.setAttribute(
199                                 FeatureKeys.TRACE_LISTENER,
200                                 traceListener);
201                         factory.setAttribute(
202                                 FeatureKeys.LINE_NUMBERING,
203                                 Boolean.TRUE);
204                     }
205
206                     else if (args[i].equals("-w0")) {
207                         i++;
208                         factory.setAttribute(
209                                 FeatureKeys.RECOVERY_POLICY,
210                                 new Integer JavaDoc(Controller.RECOVER_SILENTLY));
211                     }
212                     else if (args[i].equals("-w1")) {
213                         i++;
214                         factory.setAttribute(
215                                 FeatureKeys.RECOVERY_POLICY,
216                                 new Integer JavaDoc(Controller.RECOVER_WITH_WARNINGS));
217                     }
218                     else if (args[i].equals("-w2")) {
219                         i++;
220                         factory.setAttribute(
221                                 FeatureKeys.RECOVERY_POLICY,
222                                 new Integer JavaDoc(Controller.DO_NOT_RECOVER));
223                     }
224                     
225                     else if (args[i].equals("-m")) {
226                         i++;
227                         if (args.length < i+2) badUsage(name, "No message Emitter class");
228                         factory.setAttribute(
229                                 FeatureKeys.MESSAGE_EMITTER_CLASS,
230                                 args[i++]);
231                     }
232
233                     else if (args[i].equals("-noext")) {
234                         i++;
235                         factory.setAttribute(
236                                 FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS,
237                                 new Boolean JavaDoc(false));
238                     }
239
240                     else badUsage(name, "Unknown option " + args[i]);
241                 }
242             
243                 else break;
244             }
245
246             if (args.length < i+1 ) badUsage(name, "No source file name");
247             sourceFileName = args[i++];
248
249             if (!useAssociatedStylesheet) {
250                 if (args.length < i+1 ) badUsage(name, "No stylesheet file name");
251                 styleFileName = args[i++];
252             }
253         
254             for (int p=i; p<args.length; p++) {
255                 String JavaDoc arg = args[p];
256                 int eq = arg.indexOf("=");
257                 if (eq<1 || eq>=arg.length()-1) badUsage(name, "Bad param=value pair on command line");
258                 String JavaDoc argname = arg.substring(0,eq);
259                 int argcode = namePool.allocate("", "", argname);
260                 params.put(argcode, new StringValue(arg.substring(eq+1)));
261             }
262
263             Source sourceInput = null;
264
265             if (useURLs || sourceFileName.startsWith("http:") || sourceFileName.startsWith("file:")) {
266                 sourceInput = factory.getURIResolver().resolve(sourceFileName, null);
267
268             } else {
269                 sourceFile = new File(sourceFileName);
270                 if (!sourceFile.exists()) {
271                     quit("Source file " + sourceFile + " does not exist", 2);
272                 }
273                 if (sourceFile.isDirectory()) {
274                     wholeDirectory = true;
275                     if (outputFileName==null) {
276                         quit("To process a directory, -o must be specified", 2);
277                     } else if (outputFileName.equals(sourceFileName)) {
278                         quit("Output directory must be different from input", 2);
279                     } else {
280                         outputFile = new File(outputFileName);
281                         if (!outputFile.isDirectory()) {
282                             quit("Input is a directory, but output is not", 2);
283                         }
284                     }
285                 } else {
286                     ExtendedInputSource eis = new ExtendedInputSource(sourceFile);
287                     sourceInput = new SAXSource(factory.getSourceParser(), eis);
288                     eis.setEstimatedLength((int)sourceFile.length());
289                 }
290             }
291
292             if (outputFileName!=null && !wholeDirectory) {
293                  outputFile = new File(outputFileName);
294                  if (outputFile.isDirectory()) {
295                             quit("Output is a directory, but input is not", 2);
296                  }
297             }
298
299             if (useAssociatedStylesheet) {
300                 if (wholeDirectory) {
301                     processDirectoryAssoc(sourceFile, outputFile, params);
302                 } else {
303                     processFileAssoc(sourceInput, null, outputFile, params);
304                 }
305             } else {
306                 
307                 long startTime = (new Date()).getTime();
308
309                 Source styleSource;
310                 if (useURLs || styleFileName.startsWith("http:")
311                                  || styleFileName.startsWith("file:")) {
312                     styleSource = factory.getURIResolver().resolve(styleFileName, null);
313                     
314                 } else {
315                     File sheetFile = new File(styleFileName);
316                     if (!sheetFile.exists()) {
317                         quit("Stylesheet file " + sheetFile + " does not exist", 2);
318                     }
319                     ExtendedInputSource eis = new ExtendedInputSource(sheetFile);
320                     styleSource = new SAXSource(factory.getStyleParser(), eis);
321                 }
322                     
323                 if (styleSource==null) {
324                     quit("URIResolver for stylesheet file must return a Source", 2);
325                 }
326
327                 Templates sheet = factory.newTemplates(styleSource);
328
329                 if (showTime) {
330                     long endTime = (new Date()).getTime();
331                     System.err.println("Preparation time: " + (endTime-startTime) + " milliseconds");
332                     startTime = endTime;
333                 }
334                 
335                 if (wholeDirectory) {
336                     processDirectory(sourceFile, sheet, outputFile, params);
337                 } else {
338                     processFile(sourceInput, sheet, outputFile, params);
339                 }
340             }
341         } catch (TerminationException err) {
342             quit(err.getMessage(), 1);
343         } catch (TransformerException err) {
344             quit("Transformation failed: " + err.getMessage(), 2);
345         } catch (Exception JavaDoc err2) {
346             err2.printStackTrace();
347         }
348         
349
350         //System.exit(0);
351
}
352
353     /**
354     * Exit with a message
355     */

356
357     protected static void quit(String JavaDoc message, int code) {
358         System.err.println(message);
359         System.exit(code);
360     }
361
362     /**
363     * Process each file in the source directory using its own associated stylesheet
364     */

365
366     public void processDirectoryAssoc(
367         File sourceDir, File outputDir, ParameterSet params)
368         throws Exception JavaDoc {
369
370         String JavaDoc[] files = sourceDir.list();
371         int failures = 0;
372         for (int f=0; f<files.length; f++) {
373             File file = new File(sourceDir, files[f]);
374             if (!file.isDirectory()) {
375                 String JavaDoc localName = file.getName();
376                 try {
377                     ExtendedInputSource eis = new ExtendedInputSource(file);
378                     SAXSource source = new SAXSource(factory.getSourceParser(), eis);
379                     processFileAssoc(source, localName, outputDir, params);
380                 } catch (TransformerException err) {
381                     failures++;
382                     System.err.println("While processing " + localName +
383                          ": " + err.getMessage() + "\n");
384                 }
385             }
386         }
387         if (failures>0) {
388             throw new TransformerException(failures + " transformation" +
389                  (failures==1?"":"s") + " failed");
390         }
391     }
392
393     /**
394     * Make an output file in the output directory, with filename extension derived from the
395     * media-type produced by the stylesheet
396     */

397
398     private File makeOutputFile(File directory, String JavaDoc localName,
399                                  Templates sheet) {
400         String JavaDoc mediaType = sheet.getOutputProperties().getProperty(
401                                     OutputKeys.MEDIA_TYPE);
402         String JavaDoc suffix = ".xml";
403         if ("text/html".equals(mediaType)) {
404             suffix = ".html";
405         } else if ("text/plain".equals(mediaType)) {
406             suffix = ".txt";
407         }
408         String JavaDoc prefix = localName;
409         if (localName.endsWith(".xml") || localName.endsWith(".XML")) {
410             prefix = localName.substring(0, localName.length()-4);
411         }
412         return new File(directory, prefix+suffix);
413     }
414             
415
416     /**
417     * Process a single source file using its associated stylesheet(s)
418     */

419
420     public void processFileAssoc(
421         Source sourceInput, String JavaDoc localName, File outputFile, ParameterSet params)
422         throws TransformerException
423     {
424         if (showTime) {
425             System.err.println("Processing " + sourceInput.getSystemId() + " using associated stylesheet");
426         }
427         long startTime = (new Date()).getTime();
428
429         Source style = factory.getAssociatedStylesheet(sourceInput, null, null, null);
430         Templates sheet = factory.newTemplates(style);
431         if (showTime) {
432             System.err.println("Prepared associated stylesheet " + style.getSystemId());
433         }
434         Transformer instance = sheet.newTransformer();
435         ((Controller)instance).setParams(params);
436         
437         File outFile = outputFile;
438     
439         if (outFile!=null && outFile.isDirectory()) {
440             outFile = makeOutputFile(outFile, localName, sheet);
441         }
442
443         StreamResult result =
444             (outFile==null ? new StreamResult(System.out) : new StreamResult(outFile));
445         
446         try {
447             instance.transform(sourceInput, result);
448         } catch (TerminationException err) {
449             throw err;
450         } catch (TransformerException err) {
451             // The error message will already have been displayed; don't do it twice
452
throw new TransformerException("Run-time errors were reported");
453         }
454     
455         if (showTime) {
456             long endTime = (new Date()).getTime();
457             System.err.println("Execution time: " + (endTime-startTime) + " milliseconds");
458             startTime = endTime;
459         }
460     }
461
462     /**
463     * Process each file in the source directory using the same supplied stylesheet
464     */

465
466     public void processDirectory(
467         File sourceDir, Templates sheet, File outputDir, ParameterSet params)
468         throws TransformerException
469     {
470             
471         String JavaDoc[] files = sourceDir.list();
472         int failures = 0;
473         for (int f=0; f<files.length; f++) {
474             File file = new File(sourceDir, files[f]);
475             String JavaDoc localName = file.getName();
476             try {
477                 if (!file.isDirectory()) {
478                     File outputFile = makeOutputFile(outputDir, localName, sheet);
479                     ExtendedInputSource eis = new ExtendedInputSource(file);
480                     Source source = new SAXSource(factory.getSourceParser(), eis);
481                     processFile(source, sheet, outputFile, params);
482                 }
483             } catch (TransformerException err) {
484                 failures++;
485                 System.err.println("While processing " + localName + ": " + err.getMessage() + "\n");
486             }
487         }
488         if (failures>0) {
489             throw new TransformerException(failures + " transformation" +
490                  (failures==1?"":"s") + " failed");
491         }
492     }
493
494     /**
495     * Process a single file using a supplied stylesheet
496     */

497
498     public void processFile(
499         Source source, Templates sheet, File outputFile, ParameterSet params)
500         throws TransformerException {
501
502         for (int r=0; r<repeat; r++) { // repeat is for internal testing/timing
503
if (showTime) {
504                 System.err.println("Processing " + source.getSystemId());
505             }
506             long startTime = (new Date()).getTime();
507             Transformer instance = sheet.newTransformer();
508             ((Controller)instance).setParams(params);
509
510             Result result =
511                 (outputFile==null ?
512                     new StreamResult(System.out) :
513                     new StreamResult(outputFile));
514
515             try {
516                 instance.transform(source, result);
517             } catch (TerminationException err) {
518                 throw err;
519             } catch (TransformerException err) {
520                 // The message will already have been displayed; don't do it twice
521
throw new TransformerException("Run-time errors were reported");
522             }
523
524             if (showTime) {
525                 long endTime = (new Date()).getTime();
526                 System.err.println("Execution time: " + (endTime-startTime) + " milliseconds");
527                 startTime = endTime;
528             }
529         }
530     }
531
532     protected void badUsage(String JavaDoc name, String JavaDoc message) {
533         System.err.println(message);
534         System.err.println(Version.getProductName());
535         System.err.println("Usage: " + name + " [options] source-doc style-doc {param=value}...");
536         System.err.println("Options: ");
537         System.err.println(" -a Use xml-stylesheet PI, not style-doc argument ");
538         System.err.println(" -ds Use standard tree data structure ");
539         System.err.println(" -dt Use tinytree data structure (default)");
540         System.err.println(" -o filename Send output to named file or directory ");
541         System.err.println(" -m classname Use specified Emitter class for xsl:message output ");
542         System.err.println(" -r classname Use specified URIResolver class ");
543         System.err.println(" -t Display version and timing information ");
544         System.err.println(" -T Set standard TraceListener");
545         System.err.println(" -TL classname Set a specific TraceListener");
546         System.err.println(" -u Names are URLs not filenames ");
547         System.err.println(" -w0 Recover silently from recoverable errors ");
548         System.err.println(" -w1 Report recoverable errors and continue (default)");
549         System.err.println(" -w2 Treat recoverable errors as fatal");
550         System.err.println(" -x classname Use specified SAX parser for source file ");
551         System.err.println(" -y classname Use specified SAX parser for stylesheet ");
552         System.err.println(" -? Display this message ");
553         System.exit(2);
554     }
555
556     public static URIResolver makeURIResolver (String JavaDoc className)
557     throws TransformerException
558     {
559         Object JavaDoc obj = Loader.getInstance(className);
560         if (obj instanceof URIResolver) {
561             return (URIResolver)obj;
562         }
563         throw new TransformerException("Class " + className + " is not a URIResolver");
564     }
565
566     public static TraceListener makeTraceListener (String JavaDoc className)
567     throws TransformerException
568     {
569         Object JavaDoc obj = Loader.getInstance(className);
570         if (obj instanceof TraceListener) {
571             return (TraceListener)obj;
572         }
573         throw new TransformerException("Class " + className + " is not a TraceListener");
574     }
575
576 }
577
578 //
579
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
580
// you may not use this file except in compliance with the License. You may obtain a copy of the
581
// License at http://www.mozilla.org/MPL/
582
//
583
// Software distributed under the License is distributed on an "AS IS" basis,
584
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
585
// See the License for the specific language governing rights and limitations under the License.
586
//
587
// The Original Code is: all this file.
588
//
589
// The Initial Developer of the Original Code is
590
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
591
//
592
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
593
//
594
// Contributor(s): none.
595
//
596
Popular Tags