KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xsl > Generator


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.xsl;
30
31 import com.caucho.java.JavaWriter;
32 import com.caucho.java.LineMap;
33 import com.caucho.log.Log;
34 import com.caucho.util.CharBuffer;
35 import com.caucho.util.CharScanner;
36 import com.caucho.util.IntArray;
37 import com.caucho.util.IntMap;
38 import com.caucho.util.L10N;
39 import com.caucho.util.StringCharCursor;
40 import com.caucho.vfs.Path;
41 import com.caucho.vfs.ReadStream;
42 import com.caucho.xml.CauchoDocument;
43 import com.caucho.xml.QAbstractNode;
44 import com.caucho.xml.QElement;
45 import com.caucho.xml.QName;
46 import com.caucho.xml.Xml;
47 import com.caucho.xml.XmlChar;
48 import com.caucho.xpath.Expr;
49 import com.caucho.xpath.NamespaceContext;
50 import com.caucho.xpath.XPath;
51 import com.caucho.xpath.pattern.AbstractPattern;
52 import com.caucho.xpath.pattern.UnionPattern;
53 import com.caucho.xsl.fun.FormatNumberFun;
54 import com.caucho.xsl.fun.KeyFun;
55 import com.caucho.xsl.java.XslAttributeSet;
56 import com.caucho.xsl.java.XslNode;
57 import com.caucho.xsl.java.XslStylesheet;
58 import com.caucho.xsl.java.XslTemplate;
59
60 import org.w3c.dom.Attr JavaDoc;
61 import org.w3c.dom.Document JavaDoc;
62 import org.w3c.dom.DocumentType JavaDoc;
63 import org.w3c.dom.Element JavaDoc;
64 import org.w3c.dom.Node JavaDoc;
65 import org.w3c.dom.Text JavaDoc;
66
67 import java.io.FileNotFoundException JavaDoc;
68 import java.io.IOException JavaDoc;
69 import java.text.DecimalFormatSymbols JavaDoc;
70 import java.util.ArrayList JavaDoc;
71 import java.util.HashMap JavaDoc;
72 import java.util.Iterator JavaDoc;
73 import java.util.logging.Level JavaDoc;
74 import java.util.logging.Logger JavaDoc;
75
76 /**
77  * Base class for generating code from an XSL tree. JavaGenerator and
78  * JavaScriptGenerator extend this class for language-specific code
79  * generation.
80  */

81 abstract class Generator {
82   private static final Logger JavaDoc log = Log.open(Generator.class);
83   protected static final L10N L = new L10N(Generator.class);
84
85   public static final String JavaDoc XSLNS = "http://www.w3.org/1999/XSL/Transform";
86   public static final String JavaDoc XTPNS = "http://www.caucho.com/XTP/1.0";
87
88   private static final int STYLESHEET = 0;
89   private static final int OUTPUT = STYLESHEET + 1;
90   private static final int IMPORT = OUTPUT + 1;
91   private static final int INCLUDE = IMPORT + 1;
92   private static final int TEMPLATE = INCLUDE + 1;
93   private static final int STRIP_SPACE = TEMPLATE + 1;
94   private static final int PRESERVE_SPACE = STRIP_SPACE + 1;
95   private static final int KEY = PRESERVE_SPACE + 1;
96   private static final int LOCALE = KEY + 1;
97   private static final int ATTRIBUTE_SET = LOCALE + 1;
98   private static final int NAMESPACE_ALIAS = ATTRIBUTE_SET + 1;
99
100   private static final int APPLY_TEMPLATES = NAMESPACE_ALIAS + 1;
101   private static final int APPLY_IMPORTS = APPLY_TEMPLATES + 1;
102   private static final int CALL_TEMPLATE = APPLY_IMPORTS + 1;
103   private static final int PARAM = CALL_TEMPLATE + 1;
104   private static final int VARIABLE = PARAM + 1;
105   private static final int VALUE_OF = VARIABLE + 1;
106   private static final int COPY_OF = VALUE_OF + 1;
107   private static final int FOR_EACH = COPY_OF + 1;
108   private static final int IF = FOR_EACH + 1;
109   private static final int CHOOSE = IF + 1;
110
111   private static final int TEXT = CHOOSE + 1;
112   private static final int XSL_TEXT = TEXT + 1;
113   private static final int NUMBER = XSL_TEXT + 1;
114   private static final int COPY = NUMBER + 1;
115   private static final int COPY_ELEMENT = COPY + 1;
116   private static final int ELEMENT = COPY_ELEMENT + 1;
117   private static final int ATTRIBUTE = ELEMENT + 1;
118   private static final int PI = ATTRIBUTE + 1;
119   private static final int COMMENT = PI + 1;
120
121   private static final int MESSAGE = COMMENT + 1;
122
123   private static final int EXPRESSION = MESSAGE + 1;
124   private static final int SCRIPTLET = EXPRESSION + 1;
125   private static final int DECLARATION = SCRIPTLET + 1;
126   private static final int DIRECTIVE_CACHE = DECLARATION + 1;
127   private static final int DIRECTIVE_PAGE = DIRECTIVE_CACHE + 1;
128   private static final int WHILE = DIRECTIVE_PAGE + 1;
129
130   private static final int ASSIGN = WHILE + 1;
131   private static final int IGNORE = ASSIGN + 1;
132
133   // xslt 2.0
134
private static final int RESULT_DOCUMENT = IGNORE + 1;
135
136   private static IntMap _tags;
137   private static IntMap _xtpTags;
138   private String JavaDoc _version = "1.0";
139
140   String JavaDoc _xslName;
141   // the root context
142
Path _topContext;
143   // the pwd for the file
144
Path _baseURL;
145   Path _context;
146   CharBuffer _text;
147   HashMap JavaDoc<String JavaDoc,String JavaDoc> _names = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
148   int _loopDepth;
149   Path _workPath;
150   int _uniqueId;
151
152   protected HashMap JavaDoc<String JavaDoc,String JavaDoc> _preserve = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
153   protected HashMap JavaDoc<String JavaDoc,String JavaDoc> _strip = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
154
155   HashMap JavaDoc<String JavaDoc,XslAttributeSet> _attributeSets =
156     new HashMap JavaDoc<String JavaDoc,XslAttributeSet>();
157
158   protected HashMap JavaDoc<String JavaDoc,String JavaDoc[]> _namespaceAliases =
159     new HashMap JavaDoc<String JavaDoc,String JavaDoc[]>();
160   protected HashMap JavaDoc<String JavaDoc,String JavaDoc> _excludedNamespaces =
161     new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
162   protected KeyFun _keyFun;
163   protected FormatNumberFun _formatNumberFun;
164
165   protected NamespaceContext _namespace;
166   protected ArrayList JavaDoc _globalActions = new ArrayList JavaDoc();
167   protected ArrayList JavaDoc<String JavaDoc> _globalParameters =
168     new ArrayList JavaDoc<String JavaDoc>();
169
170   protected Document _doc;
171   protected CauchoDocument _qDoc;
172
173   protected Path _path;
174
175   boolean _lineContent;
176   int _lineWs;
177   String JavaDoc _systemId;
178   String JavaDoc _filename;
179   int _line;
180   protected LineMap _lineMap;
181   private ArrayList JavaDoc _frags;
182   protected int _destLine = 1;
183   boolean _defaultCacheable = true;
184   boolean _isCacheable;
185   protected String JavaDoc _encoding;
186
187   HashMap JavaDoc<String JavaDoc,ArrayList JavaDoc<Template>> _templates = new HashMap JavaDoc<String JavaDoc,ArrayList JavaDoc<Template>>();
188   int _minImportance; // for included files, the minimum importance
189
int _importance;
190   int _templateCount;
191   private IntArray _vars = new IntArray();
192   private ArrayList JavaDoc<XslNode> _inits = new ArrayList JavaDoc<XslNode>();
193   protected ArrayList JavaDoc<Path> _depends = new ArrayList JavaDoc<Path>();
194   protected ArrayList JavaDoc<String JavaDoc> _cacheDepends = new ArrayList JavaDoc<String JavaDoc>();
195
196   private boolean _isCauchoXsl;
197   protected boolean _isRawText;
198   protected String JavaDoc _errorPage;
199   boolean _hasSession;
200   protected AbstractPattern _nodeListContext;
201   private boolean _isTop;
202   private ClassLoader JavaDoc _loader;
203
204   protected boolean _isSpecial;
205   protected boolean _isStyleScript;
206
207   HashMap JavaDoc<String JavaDoc,String JavaDoc> _outputAttributes = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
208   HashMap JavaDoc<String JavaDoc,String JavaDoc> _macros;
209   HashMap JavaDoc<String JavaDoc,Document> _files;
210   
211   protected AbstractStylesheetFactory _xslGenerator;
212
213   protected ArrayList JavaDoc<String JavaDoc> _imports = new ArrayList JavaDoc<String JavaDoc>();
214
215   Generator(AbstractStylesheetFactory xslGenerator)
216   {
217     _xslGenerator = xslGenerator;
218     
219     _workPath = xslGenerator.getWorkPath();
220
221     Path path = xslGenerator.getStylePath();
222
223     _context = path;
224     _topContext = _context;
225     _loader = xslGenerator.getClassLoader();
226     if (_loader == null)
227       _loader = Thread.currentThread().getContextClassLoader();
228     
229     _text = new CharBuffer();
230     _frags = new ArrayList JavaDoc();
231     _macros = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
232
233     _keyFun = new KeyFun();
234     _formatNumberFun = new FormatNumberFun();
235   }
236
237   void init(String JavaDoc filename)
238   {
239     _lineMap = new LineMap(filename);
240   }
241   
242   public void setErrorPage(String JavaDoc errorPage)
243   {
244     _errorPage = errorPage;
245   }
246
247   public void setStyleScript(boolean stylescript)
248   {
249     _isStyleScript = stylescript;
250   }
251
252   /**
253    * Adds a Java import to the generated stylesheet.
254    */

255   public void addImport(String JavaDoc pkg)
256   {
257     if (! _imports.contains(pkg))
258       _imports.add(pkg);
259   }
260   
261   public void setContentType(String JavaDoc type)
262   {
263     // contentType = type;
264
}
265
266   void setPath(Path path)
267   {
268     _path = path;
269     _context = path;
270   }
271
272   void setWorkPath(Path path)
273   {
274     _workPath = path;
275   }
276
277   public int getMinImportance()
278   {
279     return _minImportance;
280   }
281
282   public int getMaxImportance()
283   {
284     return _importance;
285   }
286
287   public NamespaceContext getNamespace()
288   {
289     return _namespace;
290   }
291
292   public AbstractPattern getNodeListContext()
293   {
294     return _nodeListContext;
295   }
296
297   public void addLocale(String JavaDoc name, DecimalFormatSymbols JavaDoc format)
298   {
299     _formatNumberFun.addLocale(name, format);
300   }
301
302   /**
303    * Generates a uniqueId
304    */

305   public int uniqueId()
306   {
307     return _uniqueId++;
308   }
309
310   /**
311    * Starts the generation from the top of the document.
312    *
313    * @param xsl the stylesheet document.
314    */

315   public StylesheetImpl generate(Node node) throws Exception JavaDoc
316   {
317     Document xsl = node.getOwnerDocument();
318     if (xsl == null)
319       xsl = (Document) node;
320
321     DocumentType JavaDoc dtd = xsl.getDoctype();
322
323     if (dtd != null) {
324       _context = _path.lookup(xsl.getDoctype().getSystemId());
325       _topContext = _context;
326     }
327     
328     Element top = (Element) xsl.getDocumentElement();
329
330     if (top == null)
331       throw error(xsl, L.l("xsl:stylesheet must be top element."));
332
333     _doc = xsl;
334     if (_doc instanceof CauchoDocument)
335       _qDoc = (CauchoDocument) _doc;
336
337     QElement qTop = null;
338     if (top instanceof QElement)
339       qTop = (QElement) top;
340
341     /*
342     if (qTop != null && qTop.getFilename() != null)
343       context = topContext.lookup(qTop.getFilename()).getParent();
344     */

345     
346     _isTop = true;
347     _files = new HashMap JavaDoc<String JavaDoc,Document>();
348     scanFiles(top);
349
350     if (_qDoc != null) {
351       ArrayList JavaDoc depends = (ArrayList JavaDoc) _qDoc.getProperty(CauchoDocument.DEPENDS);
352       for (int i = 0; depends != null && i < depends.size(); i++) {
353         Path path = (Path) depends.get(i);
354         addDepend(path);
355       }
356     }
357     else {
358       addDepend(_path);
359     }
360
361     if ("stylesheet".equals(getXslLocal(top)) ||
362     "transform".equals(getXslLocal(top))) {
363       generateStylesheet(top, true);
364     }
365     else {
366       // literal result element
367
printHeader();
368       boolean oldCacheable = _isCacheable;
369       boolean oldDefaultCacheable = _defaultCacheable;
370       _isCacheable = true;
371     
372       XslNode literal = createChild(top);
373
374       XslTemplate template = new XslTemplate();
375       template.setGenerator((JavaGenerator) this);
376       template.addAttribute(new QName("match"), "/");
377       template.addChild(literal);
378
379       template.generateDeclaration(getOut());
380     
381       template.generate(getOut());
382
383       // printTemplate(top, null, "/", null, 0.0/0.0);
384

385       _isCacheable = oldCacheable;
386       _defaultCacheable = oldDefaultCacheable;
387     }
388
389     addNamespace(top);
390     StylesheetImpl stylesheet = completeGenerate(_inits, _globalActions);
391
392     return stylesheet;
393   }
394
395   private static CharScanner commaDelimScanner = new CharScanner(" \t\n\r,");
396
397   /**
398    * Scan the stylesheet for imported packages and files. The imported
399    * stylesheets will be read and stored in the 'files' HashMap for when
400    * they're actually needed.
401    */

402   private void scanFiles(Element top)
403     throws XslParseException, IOException JavaDoc
404   {
405     _isCauchoXsl = ! top.getAttribute("xsl-caucho").equals("");
406
407     Iterator JavaDoc iter;
408     try {
409       iter = XPath.select("//xtp:directive.page/@*", top);
410     } catch (Exception JavaDoc e) {
411       throw new XslParseException(e);
412     }
413     while (iter.hasNext()) {
414       Attr JavaDoc attr = (Attr JavaDoc) iter.next();
415       String JavaDoc name = attr.getNodeName();
416       String JavaDoc value = attr.getNodeValue();
417
418       if (name.equals("import")) {
419         StringCharCursor cursor = new StringCharCursor(value);
420         CharBuffer cb = new CharBuffer();
421         while (cursor.current() != cursor.DONE) {
422           char ch;
423           commaDelimScanner.skip(cursor);
424
425           cb.clear();
426           ch = commaDelimScanner.scan(cursor, cb);
427
428           if (cb.length() != 0) {
429             addImport(cb.toString());
430           }
431           else if (ch != cursor.DONE)
432             throw new IOException JavaDoc(L.l("illegal `import' directive"));
433         }
434       }
435     }
436
437     try {
438       iter = XPath.select("//xsl:import|xsl:include", top);
439     } catch (Exception JavaDoc e) {
440       throw new XslParseException(e);
441     }
442     while (iter.hasNext()) {
443       Element elt = (Element) iter.next();
444       String JavaDoc href = elt.getAttribute("href");
445
446       ReadStream rs;
447
448       try {
449         rs = _xslGenerator.openPath(href, _context.getURL());
450       } catch (Exception JavaDoc e) {
451         throw new XslParseException(e);
452       }
453
454       Path path = rs.getPath();
455       
456       Document xsl = readXsl(rs);
457       Element subtop = xsl.getDocumentElement();
458
459       if (subtop == null)
460         throw error(elt, L.l("xsl:import file {0} is empty", path.getFullPath()));
461       
462       Path oldContext = _context;
463
464       Path virtualPath = _context.getParent().lookup(href);
465       _context = virtualPath;
466
467       _files.put(virtualPath.getPath(), xsl);
468       
469       scanFiles(subtop);
470       _context = oldContext;
471     }
472   }
473
474   public void addImportList(String JavaDoc value)
475     throws XslParseException
476   {
477     StringCharCursor cursor = new StringCharCursor(value);
478     CharBuffer cb = new CharBuffer();
479     while (cursor.current() != cursor.DONE) {
480       char ch;
481       commaDelimScanner.skip(cursor);
482
483       cb.clear();
484       ch = commaDelimScanner.scan(cursor, cb);
485
486       if (cb.length() != 0) {
487     addImport(cb.toString());
488       }
489       else if (ch != cursor.DONE)
490     throw error(L.l("illegal `import' directive"));
491     }
492   }
493
494   /**
495    * Read in an imported or included XSL file.
496    *
497    * @param path Path to the include files.
498    *
499    * @return XML tree describing the XSL.
500    */

501   Document readXsl(Path path)
502     throws IOException JavaDoc, XslParseException
503   {
504     return readXsl(path.openRead());
505   }
506
507   /**
508    * Read in an imported or included XSL file.
509    *
510    * @param path Path to the include files.
511    *
512    * @return XML tree describing the XSL.
513    */

514   Document readXsl(ReadStream file)
515     throws IOException JavaDoc, XslParseException
516   {
517     try {
518       addDepend(file.getPath());
519       
520       if (_isStyleScript) {
521     XslParser parser = new XslParser();
522     
523     return parser.parse(file);
524       }
525       else
526     return new Xml().parseDocument(file);
527     } catch (org.xml.sax.SAXException JavaDoc e) {
528       throw new XslParseException(e);
529     } finally {
530       file.close();
531     }
532   }
533
534   /**
535    * Start the top-level stylesheet generation.
536    */

537   private void generateStylesheet(Element elt, boolean isTop)
538     throws Exception JavaDoc
539   {
540     QElement element = (QElement) elt;
541     _isCauchoXsl = ! element.getAttribute("xsl-caucho").equals("");
542
543     String JavaDoc systemId = element.getBaseURI();
544     Path oldContext = _context;
545
546     if (systemId != null)
547       _context = _context.lookup(systemId);
548     
549     XslNode stylesheet = createChild(element);
550
551     addNamespace(element);
552     
553     if (isTop)
554       printHeader();
555
556     stylesheet.generateDeclaration(getOut());
557     
558     stylesheet.generate(getOut());
559
560     _context = oldContext;
561
562     /*
563     _version = element.getAttribute("version");
564     if (_version.equals(""))
565       _version = "1.0";
566     
567     // generateAttributeSets(element);
568
569     excludeNamespaces(element);
570
571     String xslSpace = element.getAttribute("xsl-space");
572     ArrayList<XslNode> children = new ArrayList<XslNode>();
573     for (Node child = element.getFirstChild();
574      child != null;
575      child = child.getNextSibling()) {
576       if (! (child instanceof Element))
577         continue;
578       
579       int code = -1;
580       String name = getXslLocal(child);
581       if (name != null)
582     code = _tags.get(name);
583       else if ((name = getXtpLocal(child)) != null)
584     code = _xtpTags.get(name);
585       else {
586         String childName = child.getNodeName();
587         
588         if (childName.startsWith("jsp:directive.") ||
589             childName.equals("jsp:declaration") ||
590             childName.equals("jsp:scriptlet"))
591           addGlobalAction((Element) child);
592     continue;
593       }
594
595       NamespaceContext oldNamespace = addNamespace((Element) child);
596       // generateTopLevelNode(code, (Element) child);
597       XslNode node = createChild(child);
598
599       children.add(node);
600       _namespace = oldNamespace;
601     }
602
603     for (int i = 0; i < children.size(); i++) {
604       XslNode node = children.get(i);
605       
606       node.generate(getOut());
607     }
608     */

609   }
610
611   abstract protected JavaWriter getOut();
612
613   abstract protected XslNode createChild(Node child)
614     throws Exception JavaDoc;
615   
616   abstract protected XslNode createChild(XslNode parent, Node child)
617     throws Exception JavaDoc;
618        
619   private void addGlobalAction(Element elt)
620   {
621     _globalActions.add(elt);
622   }
623
624   /**
625    * Converts the exclude-result-prefixes into the "excludedNamespaces"
626    * hashMap for later use.
627    */

628   private void excludeNamespaces(Element element)
629     throws Exception JavaDoc
630   {
631     if (! (element instanceof QElement))
632       return;
633     
634     QElement elt = (QElement) element;
635     String JavaDoc excludeNamespace;
636     excludeNamespace = element.getAttribute("exclude-result-prefixes");
637     if (! excludeNamespace.equals("")) {
638       for (String JavaDoc prefix : excludeNamespace.split("[,\\s]+")) {
639
640     String JavaDoc ns = elt.getNamespace(prefix);
641     if (ns == null)
642       throw error(elt, L.l("`{0}' must be a namespace prefix",
643                                prefix));
644     _excludedNamespaces.put(ns, "");
645       }
646     }
647   }
648
649   public void addExcludedNamespace(String JavaDoc ns)
650   {
651     _excludedNamespaces.put(ns, "");
652   }
653
654   public void addInit(XslNode node)
655   {
656     _inits.add(node);
657   }
658
659   public void addGlobalParameter(String JavaDoc param)
660   {
661     _globalParameters.add(param);
662   }
663
664   /**
665    * Adds a file dependency for cacheable references to the output of
666    * the stylesheet.
667    */

668   private void addCacheDepends(String JavaDoc attr)
669   {
670     if (attr.equals(""))
671       return;
672
673     int i = 0;
674     int ch = 0;
675     int len = attr.length();
676     for (;
677      i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ',';
678      i++) {
679     }
680     CharBuffer cb = new CharBuffer();
681     while (i < len) {
682       cb.clear();
683       for (;
684        i < len && ! XmlChar.isWhitespace((ch = attr.charAt(i))) &&
685          ch != ',';
686        i++) {
687     cb.append((char) ch);
688       }
689
690       _cacheDepends.add(cb.toString());
691
692       for (;
693        i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ',';
694        i++) {
695       }
696     }
697   }
698
699   private void generateCacheDepends(String JavaDoc attr)
700     throws Exception JavaDoc
701   {
702     if (attr.equals(""))
703       return;
704
705     int i = 0;
706     int ch = 0;
707     int len = attr.length();
708     for (;
709      i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ',';
710      i++) {
711     }
712     CharBuffer cb = new CharBuffer();
713     while (i < len) {
714       cb.clear();
715       for (;
716        i < len && ! XmlChar.isWhitespace((ch = attr.charAt(i))) &&
717          ch != ',';
718        i++) {
719     cb.append((char) ch);
720       }
721
722       printCacheDepends(cb.toString());
723
724       for (;
725        i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ',';
726        i++) {
727       }
728     }
729   }
730
731   /**
732    * Generate code for xsl:template
733    */

734   void generateTemplate(Element element)
735     throws Exception JavaDoc
736   {
737     String JavaDoc name = element.getAttribute("name");
738     String JavaDoc patternString = element.getAttribute("match");
739     String JavaDoc mode = element.getAttribute("mode");
740     String JavaDoc priority = element.getAttribute("priority");
741     double dPriority = 0.0/0.0;
742
743     if (! name.equals(""))
744       _macros.put(name, name);
745
746     if (name.equals("") && patternString.equals(""))
747       throw error("xsl:template expects a `name' or a `match' attribute.");
748
749     if (! priority.equals("")) {
750       try {
751     dPriority = Double.valueOf(priority).doubleValue();
752       } catch (Exception JavaDoc e) {
753     throw error("xsl:template expects `priority' must be a double.");
754       }
755     }
756
757     boolean oldCacheable = _isCacheable;
758     boolean oldDefaultCacheable = _defaultCacheable;
759     AbstractPattern oldNodeListContext = _nodeListContext;
760     if (! patternString.equals(""))
761       _nodeListContext = parseMatch(patternString);
762
763     _isCacheable = true;
764     printTemplate(element, name, patternString, mode, dPriority);
765     _nodeListContext = oldNodeListContext;
766     _isCacheable = oldCacheable;
767     _defaultCacheable = oldDefaultCacheable;
768   }
769
770   public XslNode generateImport(String JavaDoc href)
771     throws Exception JavaDoc
772   {
773     Path path = lookupPath(href);
774
775     if (_files.get(path.getPath()) != null)
776       return null;
777
778     Document xsl = readFile(href, path);
779     
780     if (xsl == null)
781       throw new FileNotFoundException JavaDoc(href);
782
783     QElement top = (QElement) xsl.getDocumentElement();
784     if (top == null ||
785     ! "stylesheet".equals(getXslLocal(top)) &&
786     ! "transform".equals(getXslLocal(top))) {
787       throw error("imported stylesheet `" + href +
788           "' missing xsl:stylesheet.");
789     }
790
791     int oldMinImportance = _minImportance;
792     Path oldContext = _context;
793     Path virtualPath = _context.getParent().lookup(href);
794     _context = virtualPath;
795     _minImportance = _importance;
796     boolean oldTop = _isTop;
797     boolean oldRaw = _isRawText;
798     _isTop = false;
799     _isRawText = false;
800     
801     String JavaDoc systemId = top.getBaseURI();
802
803     if (systemId != null)
804       _context = _context.lookup(systemId);
805     
806     XslStylesheet stylesheet = (XslStylesheet) createChild(top);
807
808     _isRawText = oldRaw;
809     _isTop = oldTop;
810     _minImportance = oldMinImportance;
811     _context = oldContext;
812
813     incrementImportance();
814
815     return stylesheet;
816   }
817
818   /**
819    * Generates code for xsl:include. The included file has the same
820    * importance as the containing file.
821    */

822   void generateInclude(Element element)
823     throws Exception JavaDoc
824   {
825     String JavaDoc href = element.getAttribute("href");
826     if (href.equals(""))
827       throw error("xsl:include expects `href' attribute.");
828     
829     if (element.getFirstChild() != null)
830       throw error("xsl:include must be empty");
831   }
832
833   public void generateInclude(XslNode parent, String JavaDoc href)
834     throws Exception JavaDoc
835   {
836     Path path = lookupPath(href);
837
838     if (_files.get(path.getPath()) != null)
839       return;
840     
841     Document xsl = readFile(href, path);
842     
843     Element top = (Element) xsl.getDocumentElement();
844     if (top == null ||
845     ! "stylesheet".equals(getXslLocal(top)) &&
846     ! "transform".equals(getXslLocal(top))) {
847       throw error("imported stylesheet `" + href +
848           "' missing xsl:stylesheet.");
849     }
850
851     Path oldContext = _context;
852     _context = path;
853
854     for (Node node = top.getFirstChild();
855      node != null;
856      node = node.getNextSibling()) {
857       XslNode child = createChild(parent, node);
858
859       if (child != null)
860     parent.addChild(child);
861     }
862     
863     // generateStylesheet(top, false);
864

865     _context = oldContext;
866   }
867
868   /**
869    * Returns the actual path for the relative href.
870    */

871   private Path lookupPath(String JavaDoc href)
872   {
873     return _context.getParent().lookup(href);
874   }
875
876   private Document readFile(String JavaDoc href, Path virtualPath)
877     throws Exception JavaDoc
878   {
879     Document xsl = (Document) _files.get(virtualPath.getPath());
880
881     if (xsl != null)
882       throw new IllegalStateException JavaDoc(L.l("'{0}' is a duplicated path",
883                       virtualPath.getPath()));
884     
885     ReadStream rs;
886
887     try {
888       rs = _xslGenerator.openPath(href, _context.getURL());
889     } catch (Exception JavaDoc e) {
890       throw new XslParseException(e);
891     }
892
893     Path path = rs.getPath();
894       
895     xsl = readXsl(rs);
896     Element subtop = xsl.getDocumentElement();
897
898     if (subtop == null)
899       throw error(L.l("xsl:import file {0} is empty", path.getFullPath()));
900       
901     Path oldContext = _context;
902
903     _context = virtualPath;
904
905     _files.put(virtualPath.getPath(), xsl);
906       
907     _context = oldContext;
908
909     return xsl;
910   }
911
912   void generateKey(Element element)
913     throws Exception JavaDoc
914   {
915     String JavaDoc name = element.getAttribute("name");
916     if (name.equals(""))
917       throw error("xsl:key expects `name' attribute.");
918     String JavaDoc match = element.getAttribute("match");
919     if (match.equals(""))
920       throw error("xsl:key expects `match' attribute.");
921     String JavaDoc use = element.getAttribute("use");
922     if (use.equals(""))
923       throw error("xsl:key expects `use' attribute.");
924     
925     if (element.getFirstChild() != null)
926       throw error("xsl:key must be empty");
927
928     _keyFun.add(name, parseMatch(match), parseExpr(use));
929   }
930
931   public void addKey(String JavaDoc name, AbstractPattern match, Expr use)
932   {
933     _keyFun.add(name, match, use);
934   }
935
936   void generateLocale(Element element)
937     throws Exception JavaDoc
938   {
939     String JavaDoc name = element.getAttribute("name");
940     if (name.equals(""))
941       name = "*";
942
943     DecimalFormatSymbols JavaDoc format = new DecimalFormatSymbols JavaDoc();
944
945     String JavaDoc value = element.getAttribute("decimal-separator");
946     if (value.length() > 0)
947       format.setDecimalSeparator(value.charAt(0));
948
949     value = element.getAttribute("grouping-separator");
950     if (value.length() > 0)
951       format.setGroupingSeparator(value.charAt(0));
952
953     value = element.getAttribute("infinity");
954     if (! value.equals(""))
955       format.setInfinity(value);
956
957     value = element.getAttribute("minus-sign");
958     if (value.length() > 0)
959       format.setMinusSign(value.charAt(0));
960
961     value = element.getAttribute("NaN");
962     if (! value.equals(""))
963       format.setNaN(value);
964
965     value = element.getAttribute("percent");
966     if (value.length() > 0)
967       format.setPercent(value.charAt(0));
968
969     value = element.getAttribute("per-mille");
970     if (value.length() > 0)
971       format.setPerMill(value.charAt(0));
972
973     value = element.getAttribute("zero-digit");
974     if (value.length() > 0)
975       format.setZeroDigit(value.charAt(0));
976
977     value = element.getAttribute("digit");
978     if (value.length() > 0)
979       format.setDigit(value.charAt(0));
980
981     value = element.getAttribute("pattern-separator");
982     if (value.length() > 0)
983       format.setPatternSeparator(value.charAt(0));
984
985     _formatNumberFun.addLocale(name, format);
986   }
987
988   void generateNamespaceAlias(Element element)
989     throws Exception JavaDoc
990   {
991     if (! (element instanceof QElement))
992       return;
993     
994     QElement elt = (QElement) element;
995     String JavaDoc stylesheetPrefix;
996     String JavaDoc resultPrefix;
997
998     stylesheetPrefix = (String JavaDoc) element.getAttribute("stylesheet-prefix");
999     resultPrefix = (String JavaDoc) element.getAttribute("result-prefix");
1000
1001    if (stylesheetPrefix.equals(""))
1002      throw error(element, "xsl:namespace-alias needs `stylesheet-prefix'");
1003    if (resultPrefix.equals(""))
1004      throw error(element, "xsl:namespace-alias needs `result-prefix'");
1005  }
1006
1007  public void addNamespaceAlias(String JavaDoc stylesheetPrefix,
1008                String JavaDoc resultPrefix)
1009  {
1010    /*
1011    String stylesheetNs = getNamespace(stylesheetPrefix);
1012    if (stylesheetPrefix.equals("#default"))
1013      stylesheetNs = "";
1014    else if (stylesheetNs.equals(""))
1015      throw error("`" + stylesheetPrefix + "' is not a valid namespace prefix");
1016    String resultNs = getNamespace(resultPrefix);
1017    if (resultPrefix.equals("#default")) {
1018      resultPrefix = "";
1019      resultNs = "";
1020    }
1021    else if (resultNs.equals(""))
1022      throw error("`" + resultPrefix + "' is not a valid namespace prefix");
1023    
1024    String result[] = new String[] { resultPrefix, resultNs };
1025    _namespaceAliases.put(stylesheetNs, result);
1026    */

1027  }
1028
1029  public void addNamespaceAlias(String JavaDoc namespace, String JavaDoc []result)
1030  {
1031    _namespaceAliases.put(namespace, result);
1032  }
1033
1034  public String JavaDoc []getNamespaceAlias(String JavaDoc namespace)
1035  {
1036    return _namespaceAliases.get(namespace);
1037  }
1038
1039  /**
1040   * Scans through the stylesheet, grabbing the attribute set
1041   * definitions.
1042   *
1043   * @param element the current nost
1044   */

1045  /*
1046  void generateAttributeSets(Element element)
1047    throws Exception
1048  {
1049    Node child = element.getFirstChild();
1050
1051    for (; child != null; child = child.getNextSibling()) {
1052      if (! "attribute-set".equals(getXslLocal(child)))
1053    continue;
1054
1055      QElement elt = (QElement) child;
1056      String name = elt.getAttribute("name");
1057      if (name.equals(""))
1058    throw error(L.l("xsl:attribute-set expects `name' attribute."));
1059
1060      generateAttributeSet(element, name);
1061    }
1062  }
1063  */

1064
1065  /**
1066   * Scans through the stylesheet, grabbing the attribute set
1067   * definitions.
1068   *
1069   * @param element the current node
1070   */

1071  /*
1072  HashMap<String,String> generateAttributeSet(Element element, String setName)
1073    throws Exception
1074  {
1075    Node child = element.getFirstChild();
1076
1077    for (; child != null; child = child.getNextSibling()) {
1078      if (! "attribute-set".equals(getXslLocal(child)))
1079    continue;
1080
1081      QElement elt = (QElement) child;
1082      String name = elt.getAttribute("name");
1083      if (name.equals(""))
1084    throw error(L.l("xsl:attribute-set expects `name' attribute."));
1085
1086      if (! name.equals(setName))
1087        continue;
1088
1089      HashMap<String,String> set = _attributeSets.get(name);
1090      if (set != null)
1091        return set;
1092
1093      set = new HashMap<String,String>();
1094      _attributeSets.put(name, set);
1095
1096      // add any attributes from use-attribute-sets
1097      for (Node attr = elt.getFirstAttribute();
1098       attr != null;
1099       attr = attr.getNextSibling()) {
1100    if (attr.getNodeName().equals("use-attribute-sets")) {
1101      HashMap<String,String> subset = generateAttributeSet(element, attr.getNodeValue());
1102          
1103      if (subset == null)
1104        throw error(elt, L.l("Unknown attribute-set `{0}'. Each use-attribute-sets needs a matching xsl:attribute-set.", attr.getNodeValue()));
1105      Iterator<String> iter = subset.keySet().iterator();
1106      while (iter.hasNext()) {
1107        String key = iter.next();
1108        set.put(key, subset.get(key));
1109      }
1110    }
1111      }
1112
1113      for (Node attr = elt.getFirstChild();
1114       attr != null;
1115       attr = attr.getNextSibling()) {
1116    if (! "attribute".equals(getXslLocal(attr)))
1117      continue;
1118    Element attrElt = (Element) attr;
1119    String attrName = attrElt.getAttribute("name");
1120    if (attrName.equals(""))
1121      throw error(L.l("xsl:attribute expects `name' attribute."));
1122
1123    set.put(attrName, ((QElement) attr).getTextValue());
1124      }
1125
1126      for (Attr attr = ((QElement) elt).getFirstAttribute();
1127       attr != null;
1128       attr = (Attr) attr.getNextSibling()) {
1129    if (attr.getNodeName().equals("name") ||
1130        attr.getNodeName().equals("use-attribute-sets"))
1131      continue;
1132
1133    set.put(attr.getNodeName(), attr.getNodeValue());
1134      }
1135
1136      return set;
1137    }
1138
1139    return null;
1140  }
1141  */

1142
1143  public void addAttributeSet(String JavaDoc name, XslAttributeSet attributeSet)
1144  {
1145    _attributeSets.put(name, attributeSet);
1146  }
1147
1148  /*
1149  public XslAttributeSet getAttributeSet(String name)
1150  {
1151    return _attributeSets.get(name);
1152  }
1153  */

1154
1155  public void setDisableOutputEscaping(boolean disable)
1156  {
1157    _isRawText = disable;
1158  }
1159
1160  public boolean getDisableOutputEscaping()
1161  {
1162    return _isRawText;
1163  }
1164  
1165  private void generateOutput(Element element)
1166    throws Exception JavaDoc
1167  {
1168    Node attr = ((QElement) element).getFirstAttribute();
1169
1170    if (element.getFirstChild() != null)
1171      throw error("xsl:output must be empty");
1172
1173    String JavaDoc disableEscaping;
1174    disableEscaping = element.getAttribute("resin:disable-output-escaping");
1175    if (disableEscaping.equals(""))
1176      disableEscaping = element.getAttribute("disable-output-escaping");
1177    if (disableEscaping.equals("no") ||
1178        disableEscaping.equals("false"))
1179      _isRawText = false;
1180    else if (! disableEscaping.equals(""))
1181      _isRawText = true;
1182
1183    // Only top-level xsl:output matters (XXX: spec?)
1184
if (! _isTop)
1185      return;
1186
1187    if (_outputAttributes == null)
1188      _outputAttributes = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
1189
1190    for (; attr != null; attr = attr.getNextSibling()) {
1191      _outputAttributes.put(attr.getNodeName(), attr.getNodeValue());
1192    }
1193  }
1194
1195  public void setOutputAttribute(String JavaDoc name, String JavaDoc value)
1196  {
1197    _outputAttributes.put(name, value);
1198  }
1199
1200  private void generatePreserveSpace(Element element)
1201    throws Exception JavaDoc
1202  {
1203    String JavaDoc elements = element.getAttribute("elements");
1204    if (elements.equals(""))
1205      throw error("xsl:preserve-space expects `elements' attribute.");
1206    
1207    if (element.getFirstChild() != null)
1208      throw error("xsl:preserve-space must be empty");
1209    
1210    int i = 0;
1211    int len = elements.length();
1212    for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) {
1213    }
1214    CharBuffer cb = new CharBuffer();
1215    while (i < len) {
1216      cb.clear();
1217
1218      for (; i < len && ! XmlChar.isWhitespace(elements.charAt(i)); i++)
1219    cb.append(elements.charAt(i));
1220
1221      _preserve.put(cb.toString(), "true");
1222
1223      for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) {
1224      }
1225    }
1226  }
1227
1228  private void generateStripSpace(Element element)
1229    throws Exception JavaDoc
1230  {
1231    throw new UnsupportedOperationException JavaDoc();
1232    /*
1233    String elements = element.getAttribute("elements");
1234    if (elements.equals(""))
1235      throw error("xsl:strip-space expects `elements' attribute.");
1236    
1237    if (element.getFirstChild() != null)
1238      throw error("xsl:strip-space must be empty");
1239    */

1240  }
1241
1242  public void addStripSpace(String JavaDoc elements)
1243  {
1244    int i = 0;
1245    int len = elements.length();
1246    for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) {
1247    }
1248    CharBuffer cb = new CharBuffer();
1249    while (i < len) {
1250      cb.clear();
1251
1252      for (; i < len && ! XmlChar.isWhitespace(elements.charAt(i)); i++) {
1253    cb.append(elements.charAt(i));
1254      }
1255
1256      _strip.put(cb.toString(), "true");
1257
1258      for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) {
1259      }
1260    }
1261  }
1262
1263  public void addPreserveSpace(String JavaDoc elements)
1264  {
1265    int i = 0;
1266    int len = elements.length();
1267    for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) {
1268    }
1269    CharBuffer cb = new CharBuffer();
1270    while (i < len) {
1271      cb.clear();
1272
1273      for (; i < len && ! XmlChar.isWhitespace(elements.charAt(i)); i++) {
1274    cb.append(elements.charAt(i));
1275      }
1276
1277      _preserve.put(cb.toString(), "true");
1278
1279      for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) {
1280      }
1281    }
1282  }
1283
1284  protected void generateChildren(Node node)
1285    throws Exception JavaDoc
1286  {
1287    _vars.add(0);
1288    for (Node child = node.getFirstChild();
1289         child != null;
1290     child = child.getNextSibling()) {
1291      generateChild(child);
1292    }
1293    int count = _vars.pop();
1294    if (count > 0 && _vars.size() > 0)
1295      printPopScope(count);
1296  }
1297  
1298  protected void generateChild(Node child)
1299    throws Exception JavaDoc
1300  {
1301    generateChildImpl(child);
1302  }
1303
1304  public void generateChildImpl(Node child)
1305    throws Exception JavaDoc
1306  {
1307    String JavaDoc nodeName = getXslLocal(child);
1308    int code = -1;
1309    if (nodeName != null)
1310      code = _tags.get(nodeName);
1311    else if ((nodeName = getXtpLocal(child)) != null)
1312      code = _xtpTags.get(nodeName);
1313    /* XXX: xsl/04al
1314    else if (macros.get(child.getNodeName()) != null) {
1315      generateMacro((Element) child);
1316      return;
1317    }
1318    */

1319
1320    if (nodeName == null) {
1321      if (child.getNodeType() == child.TEXT_NODE)
1322        generateText(child);
1323      else if (child.getNodeType() == child.ELEMENT_NODE) {
1324        NamespaceContext oldNamespace = addNamespace((Element) child);
1325        printElement((Element) child);
1326        _namespace = oldNamespace;
1327      }
1328      return;
1329    }
1330
1331    if (child instanceof QElement) {
1332      NamespaceContext oldNamespace = addNamespace((QElement) child);
1333      generateChild(child, code);
1334      _namespace = oldNamespace;
1335    }
1336    else
1337      generateChild(child, code);
1338  }
1339  
1340  public void generateChild(Node child, int code)
1341    throws Exception JavaDoc
1342  {
1343    if (child instanceof QAbstractNode) {
1344      QAbstractNode qChild = (QAbstractNode) child;
1345      setLocation(qChild.getBaseURI(), qChild.getFilename(), qChild.getLine());
1346    }
1347
1348    switch (code) {
1349    case TEXT:
1350      generateText(child);
1351      break;
1352
1353    case XSL_TEXT:
1354      generateXslText((Element) child);
1355      break;
1356
1357    case APPLY_TEMPLATES:
1358      generateApplyTemplates((Element) child);
1359      break;
1360
1361    case APPLY_IMPORTS:
1362      generateApplyImports((Element) child);
1363      break;
1364
1365    case CALL_TEMPLATE:
1366      generateCallTemplate((Element) child);
1367      break;
1368
1369    case PARAM:
1370      generateParamVariable((Element) child);
1371      break;
1372
1373    case VARIABLE:
1374      generateVariable((Element) child);
1375      break;
1376
1377    case VALUE_OF:
1378      generateValueOf((Element) child);
1379      break;
1380
1381    case COPY_OF:
1382      generateCopyOf((Element) child);
1383      break;
1384
1385    case FOR_EACH:
1386      generateForEach((Element) child);
1387      break;
1388
1389    case IF:
1390      generateIf((Element) child);
1391      break;
1392
1393    case CHOOSE:
1394      generateChoose((Element) child);
1395      break;
1396
1397    case NUMBER:
1398      generateNumber((Element) child);
1399      break;
1400
1401    case COPY:
1402      printCopy((Element) child);
1403      break;
1404
1405    case COPY_ELEMENT:
1406      printCopyElement((Element) child);
1407      break;
1408
1409    case ELEMENT:
1410      generateElement((Element) child);
1411      break;
1412
1413    case ATTRIBUTE:
1414      generateAttribute((Element) child);
1415      break;
1416
1417    case PI:
1418      printPi((Element) child);
1419      break;
1420
1421    case COMMENT:
1422      printComment((Element) child);
1423      break;
1424
1425    case MESSAGE:
1426      printMessage((Element) child);
1427      break;
1428
1429    case EXPRESSION:
1430      if (! _defaultCacheable)
1431    _isCacheable = false;
1432      printExpression((Element) child);
1433      break;
1434
1435    case SCRIPTLET:
1436      if (! _defaultCacheable)
1437    _isCacheable = false;
1438      printScriptlet((Element) child);
1439      break;
1440
1441    case DIRECTIVE_CACHE:
1442      generateCacheDepends(((Element) child).getAttribute("file"));
1443      if (! ((Element) child).getAttribute("no-cache").equals("")) {
1444    _isCacheable = false;
1445    _defaultCacheable = false;
1446      }
1447      else
1448    _defaultCacheable = true;
1449      break;
1450
1451    case WHILE:
1452      generateWhile((Element) child);
1453      break;
1454
1455    case ASSIGN:
1456      generateAssign((Element) child);
1457      break;
1458
1459    case RESULT_DOCUMENT:
1460      generateResultDocument((Element) child);
1461      break;
1462
1463    case IGNORE:
1464      break;
1465
1466    default:
1467      if (child instanceof QElement &&
1468          XSLNS.equals(((QElement) child).getNamespaceURI()) &&
1469      _version != null && _version.equals("1.0"))
1470    throw error(child, "unknown XSL element `" +
1471            child.getNodeName() + "'");
1472      else {
1473    Node subchild = child.getFirstChild();
1474    boolean hasFallback = false;
1475    for (; subchild != null; subchild = subchild.getNextSibling()) {
1476      String JavaDoc local = getXslLocal(subchild);
1477      if (local != null && local.equals("fallback")) {
1478        hasFallback = true;
1479        generateChildren(subchild);
1480      }
1481    }
1482    if (! hasFallback) // && child.getNamespace().equals(XSLNS))
1483
printError(L.l("expected xsl tag at `{0}'",
1484                         child.getNodeName()));
1485      }
1486      break;
1487    }
1488  }
1489
1490  private void generateText(Node node)
1491    throws Exception JavaDoc
1492  {
1493    String JavaDoc data = node.getNodeValue();
1494    int length = data.length();
1495
1496    if (length == 0)
1497      return;
1498
1499    int i = 0;
1500    for (; i < length && XmlChar.isWhitespace(data.charAt(i)); i++) {
1501    }
1502
1503    if (i == length && stripNode(node))
1504      return;
1505
1506    if (data != null && data.length() > 0 && node instanceof QAbstractNode) {
1507      setLocation(node);
1508      writeText(data);
1509    }
1510  }
1511
1512  private boolean stripNode(Node node)
1513  {
1514    for (node = node.getParentNode();
1515     node != null;
1516     node = node.getParentNode()) {
1517      if (node instanceof Element) {
1518    Element elt = (Element) node;
1519    String JavaDoc space = elt.getAttribute("xml:space");
1520    if (! space.equals(""))
1521      return ! space.equals("preserve");
1522      }
1523    }
1524
1525    return true;
1526  }
1527
1528  void generateXslText(Element element)
1529    throws Exception JavaDoc
1530  {
1531    _text.clear();
1532    for (Node child = element.getFirstChild();
1533     child != null;
1534     child = child.getNextSibling()) {
1535      if (! (child instanceof Text JavaDoc))
1536    continue;
1537
1538      String JavaDoc data = child.getNodeValue();
1539      int length = data.length();
1540      
1541      _text.append(data);
1542    }
1543
1544    String JavaDoc disableEscaping = element.getAttribute("disable-output-escaping");
1545    if (disableEscaping.equals(""))
1546      disableEscaping = "no";
1547
1548    if (_text.length() <= 0) {
1549    }
1550    else if (! disableEscaping.equals("yes") &&
1551             ! disableEscaping.equals("true"))
1552      writeText(_text.toString());
1553    else {
1554      startDisableEscaping();
1555      writeText(_text.toString());
1556      endDisableEscaping();
1557    }
1558  }
1559
1560  private void generateApplyTemplates(Node node)
1561    throws Exception JavaDoc
1562  {
1563    QElement element = (QElement) node;
1564    String JavaDoc select = element.getAttribute("select");
1565    String JavaDoc mode = element.getAttribute("mode");
1566    AbstractPattern selectPattern = null;
1567    if (! select.equals(""))
1568      selectPattern = parseSelect(select, node);
1569
1570    Sort []sort = generateSort(node);
1571
1572    if (sort != null && selectPattern == null)
1573      selectPattern = parseSelect("*", node);
1574
1575    pushCall();
1576    generateArgs(element);
1577    printApplyTemplates(selectPattern, mode, sort);
1578    popCall();
1579  }
1580
1581  private void generateApplyImports(Node node)
1582    throws Exception JavaDoc
1583  {
1584    QElement element = (QElement) node;
1585    String JavaDoc mode = element.getAttribute("mode");
1586
1587    if (element.getFirstChild() != null)
1588      throw error(L.l("xsl:apply-imports must be empty"));
1589
1590    pushCall();
1591    generateArgs(element);
1592    printApplyImports(mode, _minImportance, _importance);
1593    popCall();
1594  }
1595
1596  private void generateCallTemplate(Element element)
1597    throws Exception JavaDoc
1598  {
1599    String JavaDoc name = element.getAttribute("name");
1600    String JavaDoc mode = element.getAttribute("mode");
1601
1602    if (name.equals(""))
1603      throw error(L.l("{0} expects `{1}' attribute",
1604                      "xsl:call-template", "name"));
1605
1606    if (findMacro(name) == null)
1607      throw error(element, L.l("`{0}' is an unknown macro for xsl:call-template. All macros must be defined in an <xsl:template name='...'> element.", name));
1608
1609    pushCall();
1610    generateArgs(element);
1611    printCallTemplate(name, mode);
1612    popCall();
1613  }
1614
1615  private Element findMacro(String JavaDoc name)
1616    throws Exception JavaDoc
1617  {
1618    Element template = findMacroInDocument(_doc, name);
1619    if (template != null)
1620      return template;
1621    
1622    Iterator JavaDoc iter = _files.values().iterator();
1623    while (iter.hasNext()) {
1624      Document doc = (Document) iter.next();
1625
1626      template = findMacroInDocument(doc, name);
1627
1628      if (template != null)
1629        return template;
1630    }
1631
1632    return null;
1633  }
1634
1635  private Element findMacroInDocument(Document doc, String JavaDoc name)
1636  {
1637    Element elt = doc.getDocumentElement();
1638
1639    for (Node child = elt.getFirstChild();
1640         child != null;
1641         child = child.getNextSibling()) {
1642      if (! child.getNodeName().equals("xsl:template"))
1643        continue;
1644
1645      Element template = (Element) child;
1646
1647      if (template.getAttribute("name").equals(name))
1648        return template;
1649    }
1650
1651    return null;
1652  }
1653
1654  private void generateMacro(Element element)
1655    throws Exception JavaDoc
1656  {
1657    QElement elt = (QElement) element;
1658
1659    String JavaDoc name = element.getNodeName();
1660    String JavaDoc mode = element.getAttribute("mode");
1661
1662    pushCall();
1663    for (Node node = elt.getFirstAttribute();
1664     node != null;
1665     node = node.getNextSibling()) {
1666      String JavaDoc argName = node.getNodeName();
1667      String JavaDoc argValue = node.getNodeValue();
1668
1669      printParam(argName, argValue, elt);
1670    }
1671    printParam("contents", elt);
1672    printCallTemplate(name, mode);
1673    popCall();
1674  }
1675
1676  private void generateArgs(Element element)
1677    throws Exception JavaDoc
1678  {
1679    for (Node node = element.getFirstChild(); node != null;
1680     node = node.getNextSibling()) {
1681      String JavaDoc localName = getXslLocal(node);
1682
1683      if ("with-param".equals(localName)) {
1684    String JavaDoc key = ((Element) node).getAttribute("name");
1685    String JavaDoc expr = ((Element) node).getAttribute("select");
1686    if (key.equals(""))
1687      throw error(L.l("{0} requires `{1}' attribute",
1688                          "xsl:with-param", "name"));
1689
1690    if (! expr.equals(""))
1691      printParam(key, parseExpr(expr));
1692    else
1693      printParam(key, node);
1694      }
1695    }
1696  }
1697
1698  private void generateParamVariable(Element element)
1699    throws Exception JavaDoc
1700  {
1701    int i = _vars.size() - 1;
1702    _vars.set(i, _vars.get(i) + 1);
1703    
1704    String JavaDoc name = element.getAttribute("name");
1705    String JavaDoc expr = element.getAttribute("select");
1706    if (name.equals(""))
1707      throw error(L.l("{0} expects `{1}' attribute",
1708                      "xsl:param", "name"));
1709
1710    if (! expr.equals(""))
1711      printParamVariable(name, parseExpr(expr));
1712    else
1713      printParamVariable(name, element);
1714  }
1715
1716  private void generateVariable(Element element)
1717    throws Exception JavaDoc
1718  {
1719    int i = _vars.size() - 1;
1720    _vars.set(i, _vars.get(i) + 1);
1721
1722    String JavaDoc name = element.getAttribute("name");
1723    String JavaDoc expr = element.getAttribute("select");
1724    if (name.equals(""))
1725      throw error(L.l("{0} expects `{1}' attribute.",
1726                      "xsl:variable", "name"));
1727
1728    if (! expr.equals(""))
1729      printVariable(name, parseExpr(expr));
1730    else
1731      printVariable(name, element);
1732  }
1733
1734  private void generateAssign(Element element)
1735    throws Exception JavaDoc
1736  {
1737    String JavaDoc name = element.getAttribute("name");
1738    String JavaDoc expr = element.getAttribute("select");
1739    if (name.equals(""))
1740      throw error(L.l("{0} expects `{1}' attribute.",
1741                      "xtp:assign", "name"));
1742
1743    if (! expr.equals(""))
1744      printAssign(name, parseExpr(expr));
1745    else
1746      printAssign(name, element);
1747  }
1748
1749  private void generateResultDocument(Element element)
1750    throws Exception JavaDoc
1751  {
1752    String JavaDoc href = element.getAttribute("href");
1753    String JavaDoc format = element.getAttribute("format");
1754    if (href.equals(""))
1755      throw error(L.l("{0} expects `{1}' attribute.",
1756                      "xtp:result-document", "href"));
1757
1758    printResultDocument(element, href, format);
1759  }
1760
1761  private void generateValueOf(Element element)
1762    throws Exception JavaDoc
1763  {
1764    String JavaDoc select = element.getAttribute("select");
1765    if (select.equals(""))
1766      throw error(L.l("{0} expects `{1}' attribute.",
1767                      "xsl:value-of", "select"));
1768    
1769    if (element.getFirstChild() != null)
1770      throw error(L.l("{0} must be empty", "xsl:value-of"));
1771
1772    String JavaDoc disable = element.getAttribute("disable-output-escaping");
1773    boolean isDisabled = disable.equals("yes");
1774    if (isDisabled)
1775      startDisableEscaping();
1776
1777    printSelectValue(select, element);
1778
1779    if (isDisabled)
1780      endDisableEscaping();
1781  }
1782
1783  private void generateCopyOf(Element element)
1784    throws Exception JavaDoc
1785  {
1786    String JavaDoc select = element.getAttribute("select");
1787    if (select.equals(""))
1788      throw error(L.l("{0} expects `{1}' attribute",
1789                      "xsl:copy-of", "select"));
1790
1791    if (element.getFirstChild() != null)
1792      throw error(L.l("{0} must be empty", "xsl:copy-of"));
1793    
1794    printCopyOf(select, element);
1795  }
1796
1797  /**
1798   * Generates code for the xsl:for-each element
1799   */

1800  void generateForEach(Element element)
1801    throws Exception JavaDoc
1802  {
1803    String JavaDoc select = element.getAttribute("select");
1804    if (select.equals(""))
1805      throw error(L.l("{0} expects `{1}' attribute",
1806                      "xsl:for-each", "select"));
1807
1808    Sort []sort = generateSort(element);
1809
1810    if (sort != null)
1811      printForEach(element, select, sort);
1812    else
1813      printForEach(element, select);
1814  }
1815
1816  private Sort []generateSort(Node node)
1817    throws XslParseException, IOException JavaDoc
1818  {
1819    ArrayList JavaDoc<Sort> sorts = new ArrayList JavaDoc<Sort>();
1820  sort:
1821    for (Node child = node.getFirstChild();
1822     child != null;
1823     child = child.getNextSibling()) {
1824      if (child.getNodeType() == child.TEXT_NODE) {
1825    String JavaDoc data = child.getNodeValue();
1826    for (int i = 0; i < data.length(); i++) {
1827      if (! XmlChar.isWhitespace(data.charAt(i)))
1828        break sort;
1829    }
1830    continue;
1831      }
1832      else if (child.getNodeType() == child.COMMENT_NODE ||
1833               child.getNodeType() == child.PROCESSING_INSTRUCTION_NODE)
1834        continue;
1835
1836      String JavaDoc name = getXslLocal(child);
1837      if (! "sort".equals(name))
1838    break;
1839
1840      Element elt = (Element) child;
1841      String JavaDoc select = elt.getAttribute("select");
1842      if (select.equals(""))
1843    throw error(L.l("{0} expects attribute `{1}'",
1844                        "xsl:sort", "select"));
1845
1846      Expr expr = parseExpr(select);
1847      String JavaDoc order = elt.getAttribute("order");
1848      Expr isAscending = null;
1849      if (order.equals("")) {
1850        isAscending = parseExpr("true()");
1851      }
1852      else if (order.startsWith("{") && order.endsWith("}")) {
1853        order = order.substring(1, order.length() - 1);
1854        
1855        isAscending = parseExpr(order + " = 'ascending'");
1856      }
1857      else if (order.equals("ascending"))
1858        isAscending = parseExpr("true()");
1859      else
1860        isAscending = parseExpr("false()");
1861      
1862      String JavaDoc dataType = elt.getAttribute("data-type");
1863      boolean isText = true;
1864      if (dataType.equals("number"))
1865    isText = false;
1866
1867      String JavaDoc lang = elt.getAttribute("lang");
1868      if (lang.equals("")) {
1869        sorts.add(Sort.create(expr, isAscending, isText));
1870      }
1871      else {
1872    if (lang.startsWith("{") && lang.endsWith("}"))
1873      lang = lang.substring(1, lang.length() - 1);
1874    else
1875      lang = "'" + lang + "'";
1876
1877        sorts.add(Sort.create(expr, isAscending, parseExpr(lang)));
1878    /*
1879        int p = lang.indexOf('-');
1880        Locale locale = null;
1881
1882        if (p < 0) {
1883          locale = new Locale(lang, "");
1884        }
1885        else {
1886          String language = lang.substring(0, p);
1887          
1888          int q = lang.indexOf(p + 1, '-');
1889
1890          if (q < 0) {
1891            String country = lang.substring(p + 1);
1892
1893            locale = new Locale(language, country);
1894          }
1895          else {
1896            String country = lang.substring(p + 1, q);
1897            String variant = lang.substring(q);
1898
1899            locale = new Locale(language, country, variant);
1900          }
1901        }
1902
1903        sorts.add(Sort.create(expr, isAscending, lang));
1904    */

1905      }
1906    }
1907
1908    if (sorts.size() > 0)
1909      return (Sort []) sorts.toArray(new Sort[sorts.size()]);
1910    else
1911      return null;
1912  }
1913
1914  void generateIf(Element element)
1915    throws Exception JavaDoc
1916  {
1917    String JavaDoc test = (String JavaDoc) element.getAttribute("test");
1918    if (test.equals(""))
1919      throw error(L.l("{0} expects `{1}' attribute", "xsl:if", "test"));
1920
1921    printIf(element, parseExpr(test));
1922  }
1923
1924  void generateWhile(Element element)
1925    throws Exception JavaDoc
1926  {
1927    String JavaDoc test = (String JavaDoc) element.getAttribute("test");
1928    if (test.equals(""))
1929      throw error(L.l("{0} expects `{1}' attribute", "xsl:while", "test"));
1930
1931    printWhile(element, parseExpr(test));
1932  }
1933
1934  void generateChoose(Element element)
1935    throws Exception JavaDoc
1936  {
1937    boolean first = true;
1938    for (Node child = element.getFirstChild();
1939     child != null;
1940     child = child.getNextSibling()) {
1941      if (! (child instanceof Element))
1942    continue;
1943      
1944      String JavaDoc name = getXslLocal(child);
1945
1946      if ("when".equals(name)) {
1947    Element elt = (Element) child;
1948    String JavaDoc test = elt.getAttribute("test");
1949    if (test.equals(""))
1950      throw error(L.l("{0} expects `{1}' attribute", "xsl:when", "test"));
1951
1952    printChoose(elt, parseExpr(test), first);
1953    first = false;
1954      }
1955      else if ("otherwise".equals(name)) {
1956    printOtherwise((Element) child, first);
1957      }
1958      else
1959    throw error(L.l("xsl:choose expects `xsl:when' or `xsl:otherwise' at `{0}'",
1960                        child.getNodeName()));
1961    }
1962  }
1963
1964  void generateElement(Element element)
1965    throws Exception JavaDoc
1966  {
1967    String JavaDoc name = (String JavaDoc) element.getAttribute("name");
1968    if (name.equals(""))
1969      throw error(L.l("{0} expects `{1}' attribute.", "xsl:element", "name"));
1970    Attr JavaDoc nsAttr = element.getAttributeNode("namespace");
1971
1972    if (nsAttr == null)
1973      printElement(element, name);
1974    else
1975      printElement(element, name, nsAttr.getNodeValue());
1976  }
1977
1978  void generateAttribute(Element element)
1979    throws Exception JavaDoc
1980  {
1981    String JavaDoc name = (String JavaDoc) element.getAttribute("name");
1982    if (name.equals(""))
1983      throw error(L.l("{0} expects `{1}' attribute",
1984                      "xsl:attribute", "name"));
1985    Attr JavaDoc nsAttr = element.getAttributeNode("namespace");
1986
1987    boolean oldSpecial = _isSpecial;
1988    _isSpecial = true;
1989    
1990    if (nsAttr == null)
1991      printAttribute(element, name);
1992    else
1993      printAttribute(element, name, nsAttr.getNodeValue());
1994
1995    _isSpecial = oldSpecial;
1996  }
1997
1998  void generateNumber(Element element)
1999    throws Exception JavaDoc
2000  {
2001    String JavaDoc value = element.getAttribute("value");
2002    String JavaDoc count = element.getAttribute("count");
2003    String JavaDoc from = element.getAttribute("from");
2004    String JavaDoc level = element.getAttribute("level");
2005    String JavaDoc format = element.getAttribute("format");
2006    String JavaDoc letter = element.getAttribute("letter-value");
2007    String JavaDoc separator = element.getAttribute("grouping-separator");
2008    String JavaDoc lang = element.getAttribute("lang");
2009    String JavaDoc size_name = element.getAttribute("grouping-size");
2010
2011    int size = 0;
2012    for (int i = 0; i < size_name.length(); i++) {
2013    char ch = size_name.charAt(i);
2014    if (ch >= '0' && ch <= '9')
2015        size = 10 * size + ch - '0';
2016    }
2017
2018    boolean isAlphabetic = true;
2019    if (! letter.equals("alphabetic"))
2020      isAlphabetic = false;
2021
2022    AbstractPattern countPattern = null;
2023    if (! count.equals(""))
2024      countPattern = parseMatch(count);
2025
2026    AbstractPattern fromPattern = null;
2027    if (! from.equals(""))
2028      fromPattern = parseMatch(from);
2029
2030    if (level.equals("") || level.equals("single"))
2031      level = "single";
2032    else if (level.equals("multiple")) {
2033    }
2034    else if (level.equals("any")) {
2035    }
2036    else
2037      throw error(L.l("xsl:number can't understand level=`{0}'",
2038                      level));
2039
2040    XslNumberFormat xslFormat;
2041    xslFormat = new XslNumberFormat(format, lang, isAlphabetic,
2042                                    separator, size);
2043
2044    if (! value.equals(""))
2045      printNumber(parseExpr(value), xslFormat);
2046    else
2047      printNumber(level, countPattern, fromPattern, xslFormat);
2048  }
2049
2050  void printNumber(Expr expr, XslNumberFormat format)
2051    throws Exception JavaDoc
2052  {
2053    
2054  }
2055
2056  void printNumber(String JavaDoc level,
2057                   AbstractPattern countPattern,
2058                   AbstractPattern fromPattern,
2059           XslNumberFormat format)
2060    throws Exception JavaDoc
2061  {
2062    
2063  }
2064
2065  /**
2066   * Sets location code for the node.
2067   */

2068  void setLocation(Node node)
2069    throws Exception JavaDoc
2070  {
2071    if (node instanceof QAbstractNode) {
2072      setLocation(((QAbstractNode) node).getBaseURI(),
2073          ((QAbstractNode) node).getFilename(),
2074                  ((QAbstractNode) node).getLine());
2075    }
2076  }
2077
2078  public void setLocation(String JavaDoc systemId, String JavaDoc filename, int line)
2079    throws XslParseException, IOException JavaDoc
2080  {
2081    if (filename != null) {
2082      _systemId = systemId;
2083      _filename = filename;
2084      _line = line;
2085      // _lineMap.add(filename, line, getOut().getDestLine());
2086
}
2087  }
2088
2089  int getTextLength()
2090  {
2091    return _text.length();
2092  }
2093
2094  protected void printHeader()
2095    throws XslParseException, IOException JavaDoc
2096  {
2097  }
2098  
2099  abstract protected void startDisableEscaping()
2100    throws Exception JavaDoc;
2101   
2102  abstract protected void endDisableEscaping()
2103    throws Exception JavaDoc;
2104
2105  abstract protected void writeText(String JavaDoc text)
2106    throws Exception JavaDoc;
2107
2108  abstract protected void printTemplate(Element node,
2109                    String JavaDoc name, String JavaDoc pattern,
2110                    String JavaDoc mode, double priority)
2111    throws Exception JavaDoc;
2112
2113
2114  /**
2115   * Prints location code for the node.
2116   */

2117  void printLocation(Node node)
2118    throws Exception JavaDoc
2119  {
2120    if (node instanceof QAbstractNode) {
2121      printLocation(((QAbstractNode) node).getBaseURI(),
2122            ((QAbstractNode) node).getFilename(),
2123                    ((QAbstractNode) node).getLine());
2124    }
2125  }
2126
2127  abstract protected void printLocation(String JavaDoc systemId, String JavaDoc filename, int line)
2128    throws Exception JavaDoc;
2129  
2130  abstract protected void printElement(Node node)
2131    throws Exception JavaDoc;
2132
2133  abstract protected void
2134    printApplyTemplates(AbstractPattern select, String JavaDoc mode, Sort []sort)
2135    throws Exception JavaDoc;
2136
2137  abstract protected void
2138    printApplyImports(String JavaDoc mode, int min, int max)
2139    throws Exception JavaDoc;
2140  
2141  abstract protected void
2142    printCallTemplate(String JavaDoc name, String JavaDoc mode)
2143    throws Exception JavaDoc;
2144  
2145  abstract protected void pushCall()
2146    throws Exception JavaDoc;
2147  
2148  abstract protected void popCall()
2149    throws Exception JavaDoc;
2150  
2151  abstract protected void printParam(String JavaDoc name, Object JavaDoc value)
2152    throws Exception JavaDoc;
2153
2154  abstract protected void printParam(String JavaDoc name, String JavaDoc value, Element elt)
2155    throws Exception JavaDoc;
2156    
2157  abstract protected void printParamVariable(String JavaDoc name, Expr expr)
2158    throws Exception JavaDoc;
2159  
2160  abstract protected void printParamVariable(String JavaDoc name, Element elt)
2161    throws Exception JavaDoc;
2162  
2163  abstract protected void printVariable(String JavaDoc name, Object JavaDoc value)
2164    throws Exception JavaDoc;
2165  
2166  protected void printAssign(String JavaDoc name, Object JavaDoc value)
2167    throws Exception JavaDoc
2168  {
2169    printVariable(name, value);
2170  }
2171  
2172  abstract protected void printPopScope(int count)
2173    throws Exception JavaDoc;
2174  
2175  abstract protected void printCopyOf(String JavaDoc select, Element element)
2176    throws Exception JavaDoc;
2177
2178  abstract protected void printSelectValue(String JavaDoc select, Element element)
2179    throws Exception JavaDoc;
2180
2181  abstract protected void printForEach(Element element, String JavaDoc select)
2182    throws Exception JavaDoc;
2183
2184  abstract protected void printForEach(Element element, String JavaDoc select,
2185                       Sort []sort)
2186    throws Exception JavaDoc;
2187
2188  protected void printIf(Element element, Expr expr)
2189    throws Exception JavaDoc
2190  {
2191  }
2192
2193  protected void printChoose(Element element, Expr expr, boolean first)
2194    throws Exception JavaDoc
2195  {
2196  }
2197
2198  protected void printOtherwise(Element element, boolean first)
2199    throws Exception JavaDoc
2200  {
2201  }
2202
2203  protected void printCopy(Element element)
2204    throws Exception JavaDoc
2205  {
2206  }
2207
2208  protected void printCopyElement(Element element)
2209    throws Exception JavaDoc
2210  {
2211  }
2212
2213  protected void printElement(Element element, String JavaDoc name)
2214    throws Exception JavaDoc
2215  {
2216  }
2217
2218  protected void printElement(Element element, String JavaDoc name, String JavaDoc namespace)
2219    throws Exception JavaDoc
2220  {
2221  }
2222
2223  protected void printAttribute(Element node, String JavaDoc name)
2224    throws Exception JavaDoc
2225  {
2226  }
2227
2228  protected void printAttribute(Element node, String JavaDoc name, String JavaDoc namespace)
2229    throws Exception JavaDoc
2230  {
2231  }
2232
2233  protected void printPi(Element node)
2234    throws Exception JavaDoc
2235  {
2236  }
2237
2238  protected void printComment(Element node)
2239    throws Exception JavaDoc
2240  {
2241  }
2242
2243  protected void printError(String JavaDoc msg)
2244    throws Exception JavaDoc
2245  {
2246  }
2247
2248  protected void printMessage(Element node)
2249    throws Exception JavaDoc
2250  {
2251  }
2252
2253  // extension
2254

2255  protected void printExpression(Element node)
2256    throws Exception JavaDoc
2257  {
2258  }
2259
2260  protected void printScriptlet(Element node)
2261    throws Exception JavaDoc
2262  {
2263  }
2264
2265  protected void printDeclaration(Element node)
2266    throws Exception JavaDoc
2267  {
2268  }
2269
2270  protected void printCacheDepends(String JavaDoc path)
2271    throws Exception JavaDoc
2272  {
2273  }
2274
2275  protected void printWhile(Element element, Expr expr)
2276    throws Exception JavaDoc
2277  {
2278  }
2279
2280  protected void printResultDocument(Element element, String JavaDoc href,
2281                                     String JavaDoc format)
2282    throws Exception JavaDoc
2283  {
2284  }
2285
2286  public int getImportance()
2287  {
2288    return _importance;
2289  }
2290
2291  public void setMinImportance(int importance)
2292  {
2293    _minImportance = importance;
2294  }
2295  
2296  public void incrementImportance()
2297  {
2298    _importance++;
2299  }
2300
2301  /**
2302   * Adds a new template pattern.
2303   *
2304   * @param pattern the match pattern.
2305   * @param mode the template mode.
2306   * @param priority the template priority.
2307   * @param function the associated function name.
2308   * @param funId the function id.
2309   */

2310  Template addPattern(AbstractPattern pattern, String JavaDoc mode, double priority,
2311                      String JavaDoc function, int funId)
2312  {
2313    if (pattern instanceof UnionPattern) {
2314      UnionPattern union = (UnionPattern) pattern;
2315      addPattern(union.getLeft(), mode, priority, function, funId);
2316      return addPattern(union.getRight(), mode, priority, function, funId);
2317    }
2318
2319    if (Double.isNaN(priority))
2320      priority = pattern.getPriority();
2321
2322    if (log.isLoggable(Level.FINER))
2323      log.finer("add " + pattern.getNodeName() + " " + pattern + " fun:" +
2324                function + " mode:" + mode + " priority:" + priority);
2325
2326    Template template = new Template(pattern, mode,
2327                     _minImportance, _importance,
2328                     priority, _templateCount++,
2329                                     function, funId);
2330
2331    addTemplate(pattern.getNodeName(), template);
2332
2333    return template;
2334  }
2335  
2336  private void addTemplate(String JavaDoc nodeName, Template template)
2337  {
2338    ArrayList JavaDoc<Template> templateList = _templates.get(nodeName);
2339    
2340    if (templateList == null) {
2341      templateList = new ArrayList JavaDoc<Template>();
2342      _templates.put(nodeName, templateList);
2343    }
2344
2345    for (int i = templateList.size() - 1; i >= 0; i--) {
2346      Template item = templateList.get(i);
2347
2348      if (template.compareTo(item) <= 0) {
2349    templateList.add(i + 1, template);
2350    return;
2351      }
2352    }
2353
2354    templateList.add(0, template);
2355  }
2356
2357  public AbstractPattern parseMatch(String JavaDoc pattern)
2358    throws XslParseException, IOException JavaDoc
2359  {
2360    if (true)
2361      throw new RuntimeException JavaDoc();
2362    try {
2363      return XPath.parseMatch(pattern, _namespace).getPattern();
2364    } catch (Exception JavaDoc e) {
2365      throw error(L.l("{0} in pattern `{1}'",
2366                      e.toString(), pattern));
2367    }
2368  }
2369
2370  public AbstractPattern parseSelect(String JavaDoc pattern)
2371    throws IOException JavaDoc, XslParseException
2372  {
2373    if (true)
2374      throw new RuntimeException JavaDoc();
2375    
2376    try {
2377      return XPath.parseSelect(pattern, _namespace).getPattern();
2378    } catch (Exception JavaDoc e) {
2379      throw error(e);
2380    }
2381  }
2382
2383  protected AbstractPattern parseSelect(String JavaDoc pattern, Node node)
2384    throws IOException JavaDoc, XslParseException
2385  {
2386    if (true)
2387      throw new UnsupportedOperationException JavaDoc();
2388    try {
2389      return XPath.parseSelect(pattern, _namespace).getPattern();
2390    } catch (Exception JavaDoc e) {
2391      throw error(node, e);
2392    }
2393  }
2394
2395  public Expr parseExpr(String JavaDoc pattern)
2396    throws XslParseException
2397  {
2398    if (true)
2399      throw new UnsupportedOperationException JavaDoc();
2400    try {
2401      return XPath.parseExpr(pattern, _namespace, _nodeListContext);
2402    } catch (Exception JavaDoc e) {
2403      throw error(e);
2404    }
2405  }
2406
2407  XslParseException error(Exception JavaDoc e)
2408  {
2409    if (e.getMessage() != null)
2410      return error(e.getMessage());
2411    else {
2412      log.log(Level.WARNING, e.toString(), e);
2413      
2414      return error(e.toString());
2415    }
2416  }
2417
2418  XslParseException error(Node node, Exception JavaDoc e)
2419  {
2420    if (e.getMessage() != null)
2421      return error(node, e.getMessage());
2422    else {
2423      log.log(Level.WARNING, e.toString(), e);
2424
2425      return error(e.toString());
2426    }
2427  }
2428  
2429  XslParseException error(String JavaDoc message)
2430  {
2431    return new XslParseException(_filename + ":" + _line + ": " + message);
2432  }
2433
2434  /**
2435   * Creates an error message with filename and line number based on
2436   * the source node.
2437   *
2438   * @param node XML node of the source XSL.
2439   * @param message the error message.
2440   */

2441  XslParseException error(Node node, String JavaDoc message)
2442  {
2443    if (! (node instanceof QAbstractNode))
2444      return error(message);
2445    
2446    QAbstractNode qnode = (QAbstractNode) node;
2447
2448    String JavaDoc filename = qnode.getFilename();
2449    int line = qnode.getLine();
2450    
2451    if (filename != null)
2452      return new XslParseException(filename + ":" +
2453                   line + ": " +
2454                   message);
2455    else
2456      return error(message);
2457  }
2458
2459  /**
2460   * Returns the local name of an XSL element. Non-XSL elements return
2461   * null. So xsl:copy will return "copy", while "foo:bar" returns null.
2462   *
2463   * @param node the XSL source node
2464   * @return the local part of the XSL name.
2465   */

2466  protected String JavaDoc getXslLocal(Node node)
2467  {
2468    if (! (node instanceof Element))
2469      return null;
2470
2471    QElement elt = (QElement) node;
2472
2473    String JavaDoc ns = elt.getNamespaceURI();
2474    String JavaDoc prefix = elt.getPrefix();
2475
2476    if (ns == null || ns.equals("")) {
2477      return (elt.getNodeName().startsWith("xsl:") ?
2478          elt.getNodeName().substring(4) :
2479          null);
2480    }
2481    else if (ns.startsWith(XSLNS) &&
2482             (ns.length() == XSLNS.length() || ns.charAt(XSLNS.length()) == '/'))
2483      return elt.getLocalName();
2484    else
2485      return null;
2486  }
2487
2488  protected String JavaDoc getXtpLocal(Node node)
2489  {
2490    if (! (node instanceof Element))
2491      return null;
2492
2493    QElement elt = (QElement) node;
2494
2495    String JavaDoc ns = elt.getNamespaceURI();
2496    String JavaDoc prefix = elt.getPrefix();
2497
2498    if (ns == null || ns.equals("")) {
2499      return (elt.getNodeName().startsWith("xtp:") ?
2500          elt.getNodeName().substring(4) :
2501          null);
2502    }
2503    else if (ns.startsWith(XTPNS))
2504      return elt.getLocalName();
2505    else
2506      return null;
2507  }
2508
2509  /**
2510   * Parses an expression in a context
2511   */

2512  private Expr parseExpr(Node node, String JavaDoc expr)
2513    throws Exception JavaDoc
2514  {
2515    try {
2516      return XPath.parseExpr(expr, _namespace, _nodeListContext);
2517    } catch (Exception JavaDoc e) {
2518      throw error(node, e.getMessage());
2519    }
2520  }
2521
2522  /**
2523   * Adds the namespaces in the element to the current NamespaceContext.
2524   * The XPath pattern parsing uses NamespaceContext to associate the right
2525   * context with element patterns.
2526   *
2527   * @param elt the XSL element being processed.
2528   *
2529   * @return the old namespace context
2530   */

2531  protected NamespaceContext addNamespace(Element elt)
2532  {
2533    NamespaceContext oldNamespace = _namespace;
2534
2535    Node attr = ((QElement) elt).getFirstAttribute();
2536    for (; attr != null; attr = attr.getNextSibling()) {
2537      String JavaDoc name = attr.getNodeName();
2538
2539      if (name.startsWith("xmlns:"))
2540    name = name.substring(6);
2541      else if (name.equals("xmlns"))
2542    name = "";
2543      else
2544        continue;
2545
2546      // Note: according to the spec, the default namespace is not used
2547

2548      String JavaDoc url = attr.getNodeValue();
2549      if (url.equals(XSLNS) || url.equals(XTPNS))
2550        continue;
2551
2552      if (url.startsWith("quote:"))
2553    url = url.substring(6);
2554
2555      _namespace = new NamespaceContext(_namespace, name, url);
2556    }
2557
2558    return oldNamespace;
2559  }
2560
2561  void addDepend(Path depend)
2562  {
2563    if (depend != null)
2564      _depends.add(depend);
2565  }
2566
2567  abstract protected StylesheetImpl completeGenerate(ArrayList JavaDoc<XslNode> inits,
2568                                                     ArrayList JavaDoc globals)
2569    throws Exception JavaDoc;
2570
2571  /**
2572   * Close call when an error occurs.
2573   */

2574  public void close()
2575    throws IOException JavaDoc, XslParseException
2576  {
2577  }
2578
2579  static {
2580    _tags = new IntMap();
2581    _tags.put("stylesheet", STYLESHEET);
2582    _tags.put("transform", STYLESHEET);
2583    _tags.put("output", OUTPUT);
2584    _tags.put("template", TEMPLATE);
2585    _tags.put("preserve-space", PRESERVE_SPACE);
2586    _tags.put("strip-space", STRIP_SPACE);
2587    _tags.put("import", IMPORT);
2588    _tags.put("include", INCLUDE);
2589    _tags.put("key", KEY);
2590    _tags.put("decimal-format", LOCALE);
2591    _tags.put("attribute-set", ATTRIBUTE_SET);
2592    _tags.put("namespace-alias", NAMESPACE_ALIAS);
2593
2594    _tags.put("apply-templates", APPLY_TEMPLATES);
2595    _tags.put("apply-imports", APPLY_IMPORTS);
2596    _tags.put("call-template", CALL_TEMPLATE);
2597    _tags.put("param", PARAM);
2598    _tags.put("variable", VARIABLE);
2599    _tags.put("for-each", FOR_EACH);
2600    _tags.put("if", IF);
2601    _tags.put("choose", CHOOSE);
2602
2603    _tags.put("value-of", VALUE_OF);
2604    _tags.put("copy-of", COPY_OF);
2605    _tags.put("text", XSL_TEXT);
2606    _tags.put("#text", TEXT);
2607    _tags.put("number", NUMBER);
2608    _tags.put("copy", COPY);
2609    _tags.put("element", ELEMENT);
2610    _tags.put("attribute", ATTRIBUTE);
2611    _tags.put("pi", PI);
2612    _tags.put("processing-instruction", PI);
2613    _tags.put("comment", COMMENT);
2614
2615    _tags.put("message", MESSAGE);
2616
2617    _tags.put("sort", IGNORE);
2618    _tags.put("fallback", IGNORE);
2619    // xslt 2.0
2620
_tags.put("result-document", RESULT_DOCUMENT);
2621
2622    _xtpTags = new IntMap();
2623    _xtpTags.put("expression", EXPRESSION);
2624    _xtpTags.put("expr", EXPRESSION);
2625    _xtpTags.put("eval", EXPRESSION);
2626    _xtpTags.put("scriptlet", SCRIPTLET);
2627    _xtpTags.put("script", SCRIPTLET);
2628    _xtpTags.put("decl", DECLARATION);
2629    _xtpTags.put("declaration", DECLARATION);
2630    _xtpTags.put("directive.cache", DIRECTIVE_CACHE);
2631    _xtpTags.put("while", WHILE);
2632    _xtpTags.put("assign", ASSIGN);
2633  }
2634}
2635
Popular Tags