KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > processor > StylesheetHandler


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: StylesheetHandler.java,v 1.64 2004/02/17 22:10:49 minchau Exp $
18  */

19 package org.apache.xalan.processor;
20
21 import java.util.Stack JavaDoc;
22
23 import javax.xml.transform.ErrorListener JavaDoc;
24 import javax.xml.transform.SourceLocator JavaDoc;
25 import javax.xml.transform.Templates JavaDoc;
26 import javax.xml.transform.TransformerConfigurationException JavaDoc;
27 import javax.xml.transform.TransformerException JavaDoc;
28 import javax.xml.transform.sax.TemplatesHandler JavaDoc;
29
30 import org.apache.xalan.extensions.ExpressionVisitor;
31 import org.apache.xalan.res.XSLMessages;
32 import org.apache.xalan.res.XSLTErrorResources;
33 import org.apache.xalan.templates.Constants;
34 import org.apache.xalan.templates.ElemForEach;
35 import org.apache.xalan.templates.ElemTemplateElement;
36 import org.apache.xalan.templates.Stylesheet;
37 import org.apache.xalan.templates.StylesheetRoot;
38 import org.apache.xml.utils.BoolStack;
39 import org.apache.xml.utils.NamespaceSupport2;
40 import org.apache.xml.utils.NodeConsumer;
41 import org.apache.xml.utils.PrefixResolver;
42 import org.apache.xml.utils.SAXSourceLocator;
43 import org.apache.xml.utils.XMLCharacterRecognizer;
44 import org.apache.xpath.XPath;
45 import org.apache.xpath.compiler.FunctionTable;
46 import org.apache.xpath.functions.Function;
47
48 import org.w3c.dom.Node JavaDoc;
49
50 import org.xml.sax.Attributes JavaDoc;
51 import org.xml.sax.InputSource JavaDoc;
52 import org.xml.sax.Locator JavaDoc;
53 import org.xml.sax.helpers.DefaultHandler JavaDoc;
54 import org.xml.sax.helpers.NamespaceSupport JavaDoc;
55
56 /**
57  * Initializes and processes a stylesheet via SAX events.
58  * This class acts as essentially a state machine, maintaining
59  * a ContentHandler stack, and pushing appropriate content
60  * handlers as parse events occur.
61  * @xsl.usage advanced
62  */

63 public class StylesheetHandler extends DefaultHandler JavaDoc
64         implements TemplatesHandler JavaDoc, PrefixResolver, NodeConsumer
65 {
66
67
68   static {
69       Function func = new org.apache.xalan.templates.FuncDocument();
70
71       FunctionTable.installFunction("document", func);
72
73       // func = new org.apache.xalan.templates.FuncKey();
74
// FunctionTable.installFunction("key", func);
75
func = new org.apache.xalan.templates.FuncFormatNumb();
76
77       FunctionTable.installFunction("format-number", func);
78
79   }
80   /**
81    * Create a StylesheetHandler object, creating a root stylesheet
82    * as the target.
83    *
84    * @param processor non-null reference to the transformer factory that owns this handler.
85    *
86    * @throws TransformerConfigurationException if a StylesheetRoot
87    * can not be constructed for some reason.
88    */

89   public StylesheetHandler(TransformerFactoryImpl processor)
90           throws TransformerConfigurationException JavaDoc
91   {
92
93     // m_schema = new XSLTSchema();
94
init(processor);
95   }
96
97   /**
98    * Do common initialization.
99    *
100    * @param processor non-null reference to the transformer factory that owns this handler.
101    */

102   void init(TransformerFactoryImpl processor)
103   {
104     m_stylesheetProcessor = processor;
105
106     // Set the initial content handler.
107
m_processors.push(m_schema.getElementProcessor());
108     this.pushNewNamespaceSupport();
109
110     // m_includeStack.push(SystemIDResolver.getAbsoluteURI(this.getBaseIdentifier(), null));
111
// initXPath(processor, null);
112
}
113
114   /**
115    * Process an expression string into an XPath.
116    * Must be public for access by the AVT class.
117    *
118    * @param str A non-null reference to a valid or invalid XPath expression string.
119    *
120    * @return A non-null reference to an XPath object that represents the string argument.
121    *
122    * @throws javax.xml.transform.TransformerException if the expression can not be processed.
123    * @see <a HREF="http://www.w3.org/TR/xslt#section-Expressions">Section 4 Expressions in XSLT Specification</a>
124    */

125   public XPath createXPath(String JavaDoc str, ElemTemplateElement owningTemplate)
126           throws javax.xml.transform.TransformerException JavaDoc
127   {
128     ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
129     XPath xpath = new XPath(str, owningTemplate, this, XPath.SELECT, handler);
130     // Visit the expression, registering namespaces for any extension functions it includes.
131
xpath.callVisitors(xpath, new ExpressionVisitor(getStylesheetRoot()));
132     return xpath;
133   }
134
135   /**
136    * Process an expression string into an XPath.
137    *
138    * @param str A non-null reference to a valid or invalid match pattern string.
139    *
140    * @return A non-null reference to an XPath object that represents the string argument.
141    *
142    * @throws javax.xml.transform.TransformerException if the pattern can not be processed.
143    * @see <a HREF="http://www.w3.org/TR/xslt#patterns">Section 5.2 Patterns in XSLT Specification</a>
144    */

145   XPath createMatchPatternXPath(String JavaDoc str, ElemTemplateElement owningTemplate)
146           throws javax.xml.transform.TransformerException JavaDoc
147   {
148     ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
149     XPath xpath = new XPath(str, owningTemplate, this, XPath.MATCH, handler);
150     // Visit the expression, registering namespaces for any extension functions it includes.
151
xpath.callVisitors(xpath, new ExpressionVisitor(getStylesheetRoot()));
152     return xpath;
153   }
154
155   /**
156    * Given a namespace, get the corrisponding prefix from the current
157    * namespace support context.
158    *
159    * @param prefix The prefix to look up, which may be an empty string ("") for the default Namespace.
160    *
161    * @return The associated Namespace URI, or null if the prefix
162    * is undeclared in this context.
163    */

164   public String JavaDoc getNamespaceForPrefix(String JavaDoc prefix)
165   {
166     return this.getNamespaceSupport().getURI(prefix);
167   }
168
169   /**
170    * Given a namespace, get the corrisponding prefix. This is here only
171    * to support the {@link org.apache.xml.utils.PrefixResolver} interface,
172    * and will throw an error if invoked on this object.
173    *
174    * @param prefix The prefix to look up, which may be an empty string ("") for the default Namespace.
175    * @param context The node context from which to look up the URI.
176    *
177    * @return The associated Namespace URI, or null if the prefix
178    * is undeclared in this context.
179    */

180   public String JavaDoc getNamespaceForPrefix(String JavaDoc prefix, org.w3c.dom.Node JavaDoc context)
181   {
182
183     // Don't need to support this here. Return the current URI for the prefix,
184
// ignoring the context.
185
assertion(true, "can't process a context node in StylesheetHandler!");
186
187     return null;
188   }
189
190   /**
191    * Utility function to see if the stack contains the given URL.
192    *
193    * @param stack non-null reference to a Stack.
194    * @param url URL string on which an equality test will be performed.
195    *
196    * @return true if the stack contains the url argument.
197    */

198   private boolean stackContains(Stack JavaDoc stack, String JavaDoc url)
199   {
200
201     int n = stack.size();
202     boolean contains = false;
203
204     for (int i = 0; i < n; i++)
205     {
206       String JavaDoc url2 = (String JavaDoc) stack.elementAt(i);
207
208       if (url2.equals(url))
209       {
210         contains = true;
211
212         break;
213       }
214     }
215
216     return contains;
217   }
218
219   ////////////////////////////////////////////////////////////////////
220
// Implementation of the TRAX TemplatesBuilder interface.
221
////////////////////////////////////////////////////////////////////
222

223   /**
224    * When this object is used as a ContentHandler or ContentHandler, it will
225    * create a Templates object, which the caller can get once
226    * the SAX events have been completed.
227    * @return The stylesheet object that was created during
228    * the SAX event process, or null if no stylesheet has
229    * been created.
230    *
231    * Author <a HREF="mailto:scott_boag@lotus.com">Scott Boag</a>
232    *
233    *
234    */

235   public Templates JavaDoc getTemplates()
236   {
237     return getStylesheetRoot();
238   }
239
240   /**
241    * Set the base ID (URL or system ID) for the stylesheet
242    * created by this builder. This must be set in order to
243    * resolve relative URLs in the stylesheet.
244    *
245    * @param baseID Base URL for this stylesheet.
246    */

247   public void setSystemId(String JavaDoc baseID)
248   {
249     pushBaseIndentifier(baseID);
250   }
251
252   /**
253    * Get the base ID (URI or system ID) from where relative
254    * URLs will be resolved.
255    *
256    * @return The systemID that was set with {@link #setSystemId}.
257    */

258   public String JavaDoc getSystemId()
259   {
260     return this.getBaseIdentifier();
261   }
262
263   ////////////////////////////////////////////////////////////////////
264
// Implementation of the EntityResolver interface.
265
////////////////////////////////////////////////////////////////////
266

267   /**
268    * Resolve an external entity.
269    *
270    * @param publicId The public identifer, or null if none is
271    * available.
272    * @param systemId The system identifier provided in the XML
273    * document.
274    * @return The new input source, or null to require the
275    * default behaviour.
276    *
277    * @throws org.xml.sax.SAXException if the entity can not be resolved.
278    */

279   public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
280           throws org.xml.sax.SAXException JavaDoc
281   {
282     return getCurrentProcessor().resolveEntity(this, publicId, systemId);
283   }
284
285   ////////////////////////////////////////////////////////////////////
286
// Implementation of DTDHandler interface.
287
////////////////////////////////////////////////////////////////////
288

289   /**
290    * Receive notification of a notation declaration.
291    *
292    * <p>By default, do nothing. Application writers may override this
293    * method in a subclass if they wish to keep track of the notations
294    * declared in a document.</p>
295    *
296    * @param name The notation name.
297    * @param publicId The notation public identifier, or null if not
298    * available.
299    * @param systemId The notation system identifier.
300    * @see org.xml.sax.DTDHandler#notationDecl
301    */

302   public void notationDecl(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
303   {
304     getCurrentProcessor().notationDecl(this, name, publicId, systemId);
305   }
306
307   /**
308    * Receive notification of an unparsed entity declaration.
309    *
310    * @param name The entity name.
311    * @param publicId The entity public identifier, or null if not
312    * available.
313    * @param systemId The entity system identifier.
314    * @param notationName The name of the associated notation.
315    * @see org.xml.sax.DTDHandler#unparsedEntityDecl
316    */

317   public void unparsedEntityDecl(String JavaDoc name, String JavaDoc publicId,
318                                  String JavaDoc systemId, String JavaDoc notationName)
319   {
320     getCurrentProcessor().unparsedEntityDecl(this, name, publicId, systemId,
321                                              notationName);
322   }
323
324   /**
325    * Given a namespace URI, and a local name or a node type, get the processor
326    * for the element, or return null if not allowed.
327    *
328    * @param uri The Namespace URI, or an empty string.
329    * @param localName The local name (without prefix), or empty string if not namespace processing.
330    * @param rawName The qualified name (with prefix).
331    *
332    * @return A non-null reference to a element processor.
333    *
334    * @throws org.xml.sax.SAXException if the element is not allowed in the
335    * found position in the stylesheet.
336    */

337   XSLTElementProcessor getProcessorFor(
338           String JavaDoc uri, String JavaDoc localName, String JavaDoc rawName)
339             throws org.xml.sax.SAXException JavaDoc
340   {
341
342     XSLTElementProcessor currentProcessor = getCurrentProcessor();
343     XSLTElementDef def = currentProcessor.getElemDef();
344     XSLTElementProcessor elemProcessor = def.getProcessorFor(uri, localName);
345
346     if (null == elemProcessor
347             && !(currentProcessor instanceof ProcessorStylesheetDoc)
348             && ((null == getStylesheet()
349                 || Double.valueOf(getStylesheet().getVersion()).doubleValue()
350                    > Constants.XSLTVERSUPPORTED)
351                 ||(!uri.equals(Constants.S_XSLNAMESPACEURL) &&
352                             currentProcessor instanceof ProcessorStylesheetElement)
353                 || getElemVersion() > Constants.XSLTVERSUPPORTED
354         ))
355     {
356       elemProcessor = def.getProcessorForUnknown(uri, localName);
357     }
358
359     if (null == elemProcessor)
360       error(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_ALLOWED_IN_POSITION, new Object JavaDoc[]{rawName}),null);//rawName + " is not allowed in this position in the stylesheet!",
361

362                 
363     return elemProcessor;
364   }
365
366   ////////////////////////////////////////////////////////////////////
367
// Implementation of ContentHandler interface.
368
////////////////////////////////////////////////////////////////////
369

370   /**
371    * Receive a Locator object for document events.
372    * This is called by the parser to push a locator for the
373    * stylesheet being parsed. The stack needs to be popped
374    * after the stylesheet has been parsed. We pop in
375    * popStylesheet.
376    *
377    * @param locator A locator for all SAX document events.
378    * @see org.xml.sax.ContentHandler#setDocumentLocator
379    * @see org.xml.sax.Locator
380    */

381   public void setDocumentLocator(Locator JavaDoc locator)
382   {
383
384     // System.out.println("pushing locator for: "+locator.getSystemId());
385
m_stylesheetLocatorStack.push(new SAXSourceLocator(locator));
386   }
387
388   /**
389    * The level of the stylesheet we are at.
390    */

391   private int m_stylesheetLevel = -1;
392
393   /**
394    * Receive notification of the beginning of the document.
395    *
396    * @see org.xml.sax.ContentHandler#startDocument
397    *
398    * @throws org.xml.sax.SAXException Any SAX exception, possibly
399    * wrapping another exception.
400    */

401   public void startDocument() throws org.xml.sax.SAXException JavaDoc
402   {
403     m_stylesheetLevel++;
404     pushSpaceHandling(false);
405   }
406
407   /** m_parsingComplete becomes true when the top-level stylesheet and all
408    * its included/imported stylesheets have been been fully parsed, as an
409    * indication that composition/optimization/compilation can begin.
410    * @see isStylesheetParsingComplete */

411   private boolean m_parsingComplete = false;
412
413   /**
414    * Test whether the _last_ endDocument() has been processed.
415    * This is needed as guidance for stylesheet optimization
416    * and compilation engines, which generally don't want to start
417    * until all included and imported stylesheets have been fully
418    * parsed.
419    *
420    * @return true iff the complete stylesheet tree has been built.
421    */

422   public boolean isStylesheetParsingComplete()
423   {
424     return m_parsingComplete;
425   }
426
427   /**
428    * Receive notification of the end of the document.
429    *
430    * @see org.xml.sax.ContentHandler#endDocument
431    *
432    * @throws org.xml.sax.SAXException Any SAX exception, possibly
433    * wrapping another exception.
434    */

435   public void endDocument() throws org.xml.sax.SAXException JavaDoc
436   {
437
438     try
439     {
440       if (null != getStylesheetRoot())
441       {
442         if (0 == m_stylesheetLevel)
443           getStylesheetRoot().recompose();
444       }
445       else
446         throw new TransformerException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_NO_STYLESHEETROOT, null)); //"Did not find the stylesheet root!");
447

448       XSLTElementProcessor elemProcessor = getCurrentProcessor();
449
450       if (null != elemProcessor)
451         elemProcessor.startNonText(this);
452
453       m_stylesheetLevel--;
454       
455       popSpaceHandling();
456
457       // WARNING: This test works only as long as stylesheets are parsed
458
// more or less recursively. If we switch to an iterative "work-list"
459
// model, this will become true prematurely. In that case,
460
// isStylesheetParsingComplete() will have to be adjusted to be aware
461
// of the worklist.
462
m_parsingComplete = (m_stylesheetLevel < 0);
463     }
464     catch (TransformerException JavaDoc te)
465     {
466       throw new org.xml.sax.SAXException JavaDoc(te);
467     }
468   }
469   
470   private java.util.Vector JavaDoc m_prefixMappings = new java.util.Vector JavaDoc();
471
472   /**
473    * Receive notification of the start of a Namespace mapping.
474    *
475    * <p>By default, do nothing. Application writers may override this
476    * method in a subclass to take specific actions at the start of
477    * each element (such as allocating a new tree node or writing
478    * output to a file).</p>
479    *
480    * @param prefix The Namespace prefix being declared.
481    * @param uri The Namespace URI mapped to the prefix.
482    * @see org.xml.sax.ContentHandler#startPrefixMapping
483    *
484    * @throws org.xml.sax.SAXException Any SAX exception, possibly
485    * wrapping another exception.
486    */

487   public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
488           throws org.xml.sax.SAXException JavaDoc
489   {
490
491     // m_nsSupport.pushContext();
492
// this.getNamespaceSupport().declarePrefix(prefix, uri);
493
//m_prefixMappings.add(prefix); // JDK 1.2+ only -sc
494
//m_prefixMappings.add(uri); // JDK 1.2+ only -sc
495
m_prefixMappings.addElement(prefix); // JDK 1.1.x compat -sc
496
m_prefixMappings.addElement(uri); // JDK 1.1.x compat -sc
497
}
498
499   /**
500    * Receive notification of the end of a Namespace mapping.
501    *
502    * <p>By default, do nothing. Application writers may override this
503    * method in a subclass to take specific actions at the start of
504    * each element (such as allocating a new tree node or writing
505    * output to a file).</p>
506    *
507    * @param prefix The Namespace prefix being declared.
508    * @see org.xml.sax.ContentHandler#endPrefixMapping
509    *
510    * @throws org.xml.sax.SAXException Any SAX exception, possibly
511    * wrapping another exception.
512    */

513   public void endPrefixMapping(String JavaDoc prefix) throws org.xml.sax.SAXException JavaDoc
514   {
515
516     // m_nsSupport.popContext();
517
}
518
519   /**
520    * Flush the characters buffer.
521    *
522    * @throws org.xml.sax.SAXException
523    */

524   private void flushCharacters() throws org.xml.sax.SAXException JavaDoc
525   {
526
527     XSLTElementProcessor elemProcessor = getCurrentProcessor();
528
529     if (null != elemProcessor)
530       elemProcessor.startNonText(this);
531   }
532
533   /**
534    * Receive notification of the start of an element.
535    *
536    * @param name The element type name.
537    *
538    * @param uri The Namespace URI, or an empty string.
539    * @param localName The local name (without prefix), or empty string if not namespace processing.
540    * @param rawName The qualified name (with prefix).
541    * @param attributes The specified or defaulted attributes.
542    *
543    * @throws org.xml.sax.SAXException
544    */

545   public void startElement(
546           String JavaDoc uri, String JavaDoc localName, String JavaDoc rawName, Attributes JavaDoc attributes)
547             throws org.xml.sax.SAXException JavaDoc
548   {
549     NamespaceSupport JavaDoc nssupport = this.getNamespaceSupport();
550     nssupport.pushContext();
551     
552     int n = m_prefixMappings.size();
553
554     for (int i = 0; i < n; i++)
555     {
556       String JavaDoc prefix = (String JavaDoc)m_prefixMappings.elementAt(i++);
557       String JavaDoc nsURI = (String JavaDoc)m_prefixMappings.elementAt(i);
558       nssupport.declarePrefix(prefix, nsURI);
559     }
560     //m_prefixMappings.clear(); // JDK 1.2+ only -sc
561
m_prefixMappings.removeAllElements(); // JDK 1.1.x compat -sc
562

563     m_elementID++;
564
565     // This check is currently done for all elements. We should possibly consider
566
// limiting this check to xsl:stylesheet elements only since that is all it really
567
// applies to. Also, it could be bypassed if m_shouldProcess is already true.
568
// In other words, the next two statements could instead look something like this:
569
// if (!m_shouldProcess)
570
// {
571
// if (localName.equals(Constants.ELEMNAME_STYLESHEET_STRING) &&
572
// url.equals(Constants.S_XSLNAMESPACEURL))
573
// {
574
// checkForFragmentID(attributes);
575
// if (!m_shouldProcess)
576
// return;
577
// }
578
// else
579
// return;
580
// }
581
// I didn't include this code statement at this time because in practice
582
// it is a small performance hit and I was waiting to see if its absence
583
// caused a problem. - GLP
584

585     checkForFragmentID(attributes);
586
587     if (!m_shouldProcess)
588       return;
589
590     flushCharacters();
591     
592     pushSpaceHandling(attributes);
593
594     XSLTElementProcessor elemProcessor = getProcessorFor(uri, localName,
595                                            rawName);
596
597     if(null != elemProcessor) // defensive, for better multiple error reporting. -sb
598
{
599       this.pushProcessor(elemProcessor);
600       elemProcessor.startElement(this, uri, localName, rawName, attributes);
601     }
602     else
603     {
604       m_shouldProcess = false;
605       popSpaceHandling();
606     }
607                 
608   }
609
610   /**
611    * Receive notification of the end of an element.
612    *
613    * @param name The element type name.
614    * @param attributes The specified or defaulted attributes.
615    *
616    * @param uri The Namespace URI, or an empty string.
617    * @param localName The local name (without prefix), or empty string if not namespace processing.
618    * @param rawName The qualified name (with prefix).
619    * @see org.xml.sax.ContentHandler#endElement
620    *
621    * @throws org.xml.sax.SAXException Any SAX exception, possibly
622    * wrapping another exception.
623    */

624   public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc rawName)
625           throws org.xml.sax.SAXException JavaDoc
626   {
627
628     m_elementID--;
629
630     if (!m_shouldProcess)
631       return;
632
633     if ((m_elementID + 1) == m_fragmentID)
634       m_shouldProcess = false;
635
636     flushCharacters();
637     
638     popSpaceHandling();
639
640     XSLTElementProcessor p = getCurrentProcessor();
641
642     p.endElement(this, uri, localName, rawName);
643     this.popProcessor();
644     this.getNamespaceSupport().popContext();
645   }
646
647   /**
648    * Receive notification of character data inside an element.
649    *
650    * @param ch The characters.
651    * @param start The start position in the character array.
652    * @param length The number of characters to use from the
653    * character array.
654    * @see org.xml.sax.ContentHandler#characters
655    *
656    * @throws org.xml.sax.SAXException Any SAX exception, possibly
657    * wrapping another exception.
658    */

659   public void characters(char ch[], int start, int length)
660           throws org.xml.sax.SAXException JavaDoc
661   {
662
663     if (!m_shouldProcess)
664       return;
665
666     XSLTElementProcessor elemProcessor = getCurrentProcessor();
667     XSLTElementDef def = elemProcessor.getElemDef();
668
669     if (def.getType() != XSLTElementDef.T_PCDATA)
670       elemProcessor = def.getProcessorFor(null, "text()");
671
672     if (null == elemProcessor)
673     {
674
675       // If it's whitespace, just ignore it, otherwise flag an error.
676
if (!XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
677         error(
678           XSLMessages.createMessage(XSLTErrorResources.ER_NONWHITESPACE_NOT_ALLOWED_IN_POSITION, null),null);//"Non-whitespace text is not allowed in this position in the stylesheet!",
679

680     }
681     else
682       elemProcessor.characters(this, ch, start, length);
683   }
684
685   /**
686    * Receive notification of ignorable whitespace in element content.
687    *
688    * @param ch The whitespace characters.
689    * @param start The start position in the character array.
690    * @param length The number of characters to use from the
691    * character array.
692    * @see org.xml.sax.ContentHandler#ignorableWhitespace
693    *
694    * @throws org.xml.sax.SAXException Any SAX exception, possibly
695    * wrapping another exception.
696    */

697   public void ignorableWhitespace(char ch[], int start, int length)
698           throws org.xml.sax.SAXException JavaDoc
699   {
700
701     if (!m_shouldProcess)
702       return;
703
704     getCurrentProcessor().ignorableWhitespace(this, ch, start, length);
705   }
706
707   /**
708    * Receive notification of a processing instruction.
709    *
710    * <p>The Parser will invoke this method once for each processing
711    * instruction found: note that processing instructions may occur
712    * before or after the main document element.</p>
713    *
714    * <p>A SAX parser should never report an XML declaration (XML 1.0,
715    * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
716    * using this method.</p>
717    *
718    * <p>By default, do nothing. Application writers may override this
719    * method in a subclass to take specific actions for each
720    * processing instruction, such as setting status variables or
721    * invoking other methods.</p>
722    *
723    * @param target The processing instruction target.
724    * @param data The processing instruction data, or null if
725    * none is supplied.
726    * @see org.xml.sax.ContentHandler#processingInstruction
727    *
728    * @throws org.xml.sax.SAXException Any SAX exception, possibly
729    * wrapping another exception.
730    */

731   public void processingInstruction(String JavaDoc target, String JavaDoc data)
732           throws org.xml.sax.SAXException JavaDoc
733   {
734     if (!m_shouldProcess)
735       return;
736
737     // Recreating Scott's kluge:
738
// A xsl:for-each or xsl:apply-templates may have a special
739
// PI that tells us not to cache the document. This PI
740
// should really be namespaced.
741
// String localName = getLocalName(target);
742
// String ns = m_stylesheet.getNamespaceFromStack(target);
743
//
744
// %REVIEW%: We need a better PI architecture
745

746     String JavaDoc prefix="",ns="", localName=target;
747     int colon=target.indexOf(':');
748     if(colon>=0)
749     {
750       ns=getNamespaceForPrefix(prefix=target.substring(0,colon));
751       localName=target.substring(colon+1);
752     }
753
754     try
755     {
756       // A xsl:for-each or xsl:apply-templates may have a special
757
// PI that tells us not to cache the document. This PI
758
// should really be namespaced... but since the XML Namespaces
759
// spec never defined namespaces as applying to PI's, and since
760
// the testcase we're trying to support is inconsistant in whether
761
// it binds the prefix, I'm going to make this sloppy for
762
// testing purposes.
763
if(
764         "xalan-doc-cache-off".equals(target) ||
765         "xalan:doc-cache-off".equals(target) ||
766        ("doc-cache-off".equals(localName) &&
767         ns.equals("org.apache.xalan.xslt.extensions.Redirect") )
768      )
769       {
770     if(!(m_elems.peek() instanceof ElemForEach))
771           throw new TransformerException JavaDoc
772         ("xalan:doc-cache-off not allowed here!",
773          getLocator());
774         ElemForEach elem = (ElemForEach)m_elems.peek();
775
776         elem.m_doc_cache_off = true;
777
778     //System.out.println("JJK***** Recognized <? {"+ns+"}"+prefix+":"+localName+" "+data+"?>");
779
}
780     }
781     catch(Exception JavaDoc e)
782     {
783       // JJK: Officially, unknown PIs can just be ignored.
784
// Do we want to issue a warning?
785
}
786
787
788     flushCharacters();
789     getCurrentProcessor().processingInstruction(this, target, data);
790   }
791
792   /**
793    * Receive notification of a skipped entity.
794    *
795    * <p>By default, do nothing. Application writers may override this
796    * method in a subclass to take specific actions for each
797    * processing instruction, such as setting status variables or
798    * invoking other methods.</p>
799    *
800    * @param name The name of the skipped entity.
801    * @see org.xml.sax.ContentHandler#processingInstruction
802    *
803    * @throws org.xml.sax.SAXException Any SAX exception, possibly
804    * wrapping another exception.
805    */

806   public void skippedEntity(String JavaDoc name) throws org.xml.sax.SAXException JavaDoc
807   {
808
809     if (!m_shouldProcess)
810       return;
811
812     getCurrentProcessor().skippedEntity(this, name);
813   }
814
815   /**
816    * Warn the user of an problem.
817    *
818    * @param msg An key into the {@link org.apache.xalan.res.XSLTErrorResources}
819    * table, that is one of the WG_ prefixed definitions.
820    * @param args An array of arguments for the given warning.
821    *
822    * @throws org.xml.sax.SAXException that wraps a
823    * {@link javax.xml.transform.TransformerException} if the current
824    * {@link javax.xml.transform.ErrorListener#warning}
825    * method chooses to flag this condition as an error.
826    * @xsl.usage internal
827    */

828   public void warn(String JavaDoc msg, Object JavaDoc args[]) throws org.xml.sax.SAXException JavaDoc
829   {
830
831     String JavaDoc formattedMsg = XSLMessages.createWarning(msg, args);
832     SAXSourceLocator locator = getLocator();
833     ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
834
835     try
836     {
837       if (null != handler)
838         handler.warning(new TransformerException JavaDoc(formattedMsg, locator));
839     }
840     catch (TransformerException JavaDoc te)
841     {
842       throw new org.xml.sax.SAXException JavaDoc(te);
843     }
844   }
845
846   /**
847    * Assert that a condition is true. If it is not true, throw an error.
848    *
849    * @param condition false if an error should not be thrown, otherwise true.
850    * @param msg Error message to be passed to the RuntimeException as an
851    * argument.
852    * @throws RuntimeException if the condition is not true.
853    * @xsl.usage internal
854    */

855   private void assertion(boolean condition, String JavaDoc msg) throws RuntimeException JavaDoc
856   {
857     if (!condition)
858       throw new RuntimeException JavaDoc(msg);
859   }
860
861   /**
862    * Tell the user of an error, and probably throw an
863    * exception.
864    *
865    * @param msg An error message.
866    * @param e An error which the SAXException should wrap.
867    *
868    * @throws org.xml.sax.SAXException that wraps a
869    * {@link javax.xml.transform.TransformerException} if the current
870    * {@link javax.xml.transform.ErrorListener#error}
871    * method chooses to flag this condition as an error.
872    * @xsl.usage internal
873    */

874   protected void error(String JavaDoc msg, Exception JavaDoc e)
875           throws org.xml.sax.SAXException JavaDoc
876   {
877
878     SAXSourceLocator locator = getLocator();
879     ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
880     TransformerException JavaDoc pe;
881
882     if (!(e instanceof TransformerException JavaDoc))
883     {
884       pe = (null == e)
885            ? new TransformerException JavaDoc(msg, locator)
886            : new TransformerException JavaDoc(msg, locator, e);
887     }
888     else
889       pe = (TransformerException JavaDoc) e;
890
891     if (null != handler)
892     {
893       try
894       {
895         handler.error(pe);
896       }
897       catch (TransformerException JavaDoc te)
898       {
899         throw new org.xml.sax.SAXException JavaDoc(te);
900       }
901     }
902     else
903       throw new org.xml.sax.SAXException JavaDoc(pe);
904   }
905
906   /**
907    * Tell the user of an error, and probably throw an
908    * exception.
909    *
910    * @param msg A key into the {@link org.apache.xalan.res.XSLTErrorResources}
911    * table, that is one of the WG_ prefixed definitions.
912    * @param args An array of arguments for the given warning.
913    * @param e An error which the SAXException should wrap.
914    *
915    * @throws org.xml.sax.SAXException that wraps a
916    * {@link javax.xml.transform.TransformerException} if the current
917    * {@link javax.xml.transform.ErrorListener#error}
918    * method chooses to flag this condition as an error.
919    * @xsl.usage internal
920    */

921   protected void error(String JavaDoc msg, Object JavaDoc args[], Exception JavaDoc e)
922           throws org.xml.sax.SAXException JavaDoc
923   {
924
925     String JavaDoc formattedMsg = XSLMessages.createMessage(msg, args);
926
927     error(formattedMsg, e);
928   }
929
930   /**
931    * Receive notification of a XSLT processing warning.
932    *
933    * @param e The warning information encoded as an exception.
934    *
935    * @throws org.xml.sax.SAXException that wraps a
936    * {@link javax.xml.transform.TransformerException} if the current
937    * {@link javax.xml.transform.ErrorListener#warning}
938    * method chooses to flag this condition as an error.
939    */

940   public void warning(org.xml.sax.SAXParseException JavaDoc e)
941           throws org.xml.sax.SAXException JavaDoc
942   {
943
944     String JavaDoc formattedMsg = e.getMessage();
945     SAXSourceLocator locator = getLocator();
946     ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
947
948     try
949     {
950       handler.warning(new TransformerException JavaDoc(formattedMsg, locator));
951     }
952     catch (TransformerException JavaDoc te)
953     {
954       throw new org.xml.sax.SAXException JavaDoc(te);
955     }
956   }
957
958   /**
959    * Receive notification of a recoverable XSLT processing error.
960    *
961    * @param e The error information encoded as an exception.
962    *
963    * @throws org.xml.sax.SAXException that wraps a
964    * {@link javax.xml.transform.TransformerException} if the current
965    * {@link javax.xml.transform.ErrorListener#error}
966    * method chooses to flag this condition as an error.
967    */

968   public void error(org.xml.sax.SAXParseException JavaDoc e)
969           throws org.xml.sax.SAXException JavaDoc
970   {
971
972     String JavaDoc formattedMsg = e.getMessage();
973     SAXSourceLocator locator = getLocator();
974     ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
975
976     try
977     {
978       handler.error(new TransformerException JavaDoc(formattedMsg, locator));
979     }
980     catch (TransformerException JavaDoc te)
981     {
982       throw new org.xml.sax.SAXException JavaDoc(te);
983     }
984   }
985
986   /**
987    * Report a fatal XSLT processing error.
988    *
989    * @param e The error information encoded as an exception.
990    *
991    * @throws org.xml.sax.SAXException that wraps a
992    * {@link javax.xml.transform.TransformerException} if the current
993    * {@link javax.xml.transform.ErrorListener#fatalError}
994    * method chooses to flag this condition as an error.
995    */

996   public void fatalError(org.xml.sax.SAXParseException JavaDoc e)
997           throws org.xml.sax.SAXException JavaDoc
998   {
999
1000    String JavaDoc formattedMsg = e.getMessage();
1001    SAXSourceLocator locator = getLocator();
1002    ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
1003
1004    try
1005    {
1006      handler.fatalError(new TransformerException JavaDoc(formattedMsg, locator));
1007    }
1008    catch (TransformerException JavaDoc te)
1009    {
1010      throw new org.xml.sax.SAXException JavaDoc(te);
1011    }
1012  }
1013
1014  /**
1015   * If we have a URL to a XML fragment, this is set
1016   * to false until the ID is found.
1017   * (warning: I worry that this should be in a stack).
1018   */

1019  private boolean m_shouldProcess = true;
1020
1021  /**
1022   * If we have a URL to a XML fragment, the value is stored
1023   * in this string, and the m_shouldProcess flag is set to
1024   * false until we match an ID with this string.
1025   * (warning: I worry that this should be in a stack).
1026   */

1027  private String JavaDoc m_fragmentIDString;
1028
1029  /**
1030   * Keep track of the elementID, so we can tell when
1031   * is has completed. This isn't a real ID, but rather
1032   * a nesting level. However, it's good enough for
1033   * our purposes.
1034   * (warning: I worry that this should be in a stack).
1035   */

1036  private int m_elementID = 0;
1037
1038  /**
1039   * The ID of the fragment that has been found
1040   * (warning: I worry that this should be in a stack).
1041   */

1042  private int m_fragmentID = 0;
1043
1044  /**
1045   * Check to see if an ID attribute matched the #id, called
1046   * from startElement.
1047   *
1048   * @param attributes The specified or defaulted attributes.
1049   */

1050  private void checkForFragmentID(Attributes JavaDoc attributes)
1051  {
1052
1053    if (!m_shouldProcess)
1054    {
1055      if ((null != attributes) && (null != m_fragmentIDString))
1056      {
1057        int n = attributes.getLength();
1058
1059        for (int i = 0; i < n; i++)
1060        {
1061          String JavaDoc name = attributes.getQName(i);
1062
1063          if (name.equals(Constants.ATTRNAME_ID))
1064          {
1065            String JavaDoc val = attributes.getValue(i);
1066
1067            if (val.equalsIgnoreCase(m_fragmentIDString))
1068            {
1069              m_shouldProcess = true;
1070              m_fragmentID = m_elementID;
1071            }
1072          }
1073        }
1074      }
1075    }
1076  }
1077
1078  /**
1079   * The XSLT TransformerFactory for needed services.
1080   */

1081  private TransformerFactoryImpl m_stylesheetProcessor;
1082
1083  /**
1084   * Get the XSLT TransformerFactoryImpl for needed services.
1085   * TODO: This method should be renamed.
1086   *
1087   * @return The TransformerFactoryImpl that owns this handler.
1088   */

1089  TransformerFactoryImpl getStylesheetProcessor()
1090  {
1091    return m_stylesheetProcessor;
1092  }
1093
1094  /**
1095   * If {@link #getStylesheetType} returns this value, the current stylesheet
1096   * is a root stylesheet.
1097   */

1098  static final int STYPE_ROOT = 1;
1099
1100  /**
1101   * If {@link #getStylesheetType} returns this value, the current stylesheet
1102   * is an included stylesheet.
1103   */

1104  static final int STYPE_INCLUDE = 2;
1105
1106  /**
1107   * If {@link #getStylesheetType} returns this value, the current stylesheet
1108   * is an imported stylesheet.
1109   */

1110  static final int STYPE_IMPORT = 3;
1111
1112  /** The current stylesheet type. */
1113  private int m_stylesheetType = STYPE_ROOT;
1114
1115  /**
1116   * Get the type of stylesheet that should be built
1117   * or is being processed.
1118   *
1119   * @return one of STYPE_ROOT, STYPE_INCLUDE, or STYPE_IMPORT.
1120   */

1121  int getStylesheetType()
1122  {
1123    return m_stylesheetType;
1124  }
1125
1126  /**
1127   * Set the type of stylesheet that should be built
1128   * or is being processed.
1129   *
1130   * @param type Must be one of STYPE_ROOT, STYPE_INCLUDE, or STYPE_IMPORT.
1131   */

1132  void setStylesheetType(int type)
1133  {
1134    m_stylesheetType = type;
1135  }
1136
1137  /**
1138   * The stack of stylesheets being processed.
1139   */

1140  private Stack JavaDoc m_stylesheets = new Stack JavaDoc();
1141
1142  /**
1143   * Return the stylesheet that this handler is constructing.
1144   *
1145   * @return The current stylesheet that is on top of the stylesheets stack,
1146   * or null if no stylesheet is on the stylesheets stack.
1147   */

1148  Stylesheet getStylesheet()
1149  {
1150    return (m_stylesheets.size() == 0)
1151           ? null : (Stylesheet) m_stylesheets.peek();
1152  }
1153
1154  /**
1155   * Return the last stylesheet that was popped off the stylesheets stack.
1156   *
1157   * @return The last popped stylesheet, or null.
1158   */

1159  Stylesheet getLastPoppedStylesheet()
1160  {
1161    return m_lastPoppedStylesheet;
1162  }
1163
1164  /**
1165   * Return the stylesheet root that this handler is constructing.
1166   *
1167   * @return The root stylesheet of the stylesheets tree.
1168   */

1169  public StylesheetRoot getStylesheetRoot()
1170  {
1171    return m_stylesheetRoot;
1172  }
1173
1174  /** The root stylesheet of the stylesheets tree. */
1175  StylesheetRoot m_stylesheetRoot;
1176        
1177        /** The last stylesheet that was popped off the stylesheets stack. */
1178  Stylesheet m_lastPoppedStylesheet;
1179
1180  /**
1181   * Push the current stylesheet being constructed. If no other stylesheets
1182   * have been pushed onto the stack, assume the argument is a stylesheet
1183   * root, and also set the stylesheet root member.
1184   *
1185   * @param s non-null reference to a stylesheet.
1186   */

1187  public void pushStylesheet(Stylesheet s)
1188  {
1189
1190    if (m_stylesheets.size() == 0)
1191      m_stylesheetRoot = (StylesheetRoot) s;
1192
1193    m_stylesheets.push(s);
1194  }
1195
1196  /**
1197   * Pop the last stylesheet pushed, and return the stylesheet that this
1198   * handler is constructing, and set the last popped stylesheet member.
1199   * Also pop the stylesheet locator stack.
1200   *
1201   * @return The stylesheet popped off the stack, or the last popped stylesheet.
1202   */

1203  Stylesheet popStylesheet()
1204  {
1205
1206    // The stylesheetLocatorStack needs to be popped because
1207
// a locator was pushed in for this stylesheet by the SAXparser by calling
1208
// setDocumentLocator().
1209
if (!m_stylesheetLocatorStack.isEmpty())
1210      m_stylesheetLocatorStack.pop();
1211
1212    if (!m_stylesheets.isEmpty())
1213      m_lastPoppedStylesheet = (Stylesheet) m_stylesheets.pop();
1214
1215    // Shouldn't this be null if stylesheets is empty? -sb
1216
return m_lastPoppedStylesheet;
1217  }
1218
1219  /**
1220   * The stack of current processors.
1221   */

1222  private Stack JavaDoc m_processors = new Stack JavaDoc();
1223
1224  /**
1225   * Get the current XSLTElementProcessor at the top of the stack.
1226   *
1227   * @return Valid XSLTElementProcessor, which should never be null.
1228   */

1229  XSLTElementProcessor getCurrentProcessor()
1230  {
1231    return (XSLTElementProcessor) m_processors.peek();
1232  }
1233
1234  /**
1235   * Push the current XSLTElementProcessor onto the top of the stack.
1236   *
1237   * @param processor non-null reference to the current element processor.
1238   */

1239  void pushProcessor(XSLTElementProcessor processor)
1240  {
1241    m_processors.push(processor);
1242  }
1243
1244  /**
1245   * Pop the current XSLTElementProcessor from the top of the stack.
1246   * @return the XSLTElementProcessor which was popped.
1247   */

1248  XSLTElementProcessor popProcessor()
1249  {
1250    return (XSLTElementProcessor) m_processors.pop();
1251  }
1252
1253  /**
1254   * The root of the XSLT Schema, which tells us how to
1255   * transition content handlers, create elements, etc.
1256   * For the moment at least, this can't be static, since
1257   * the processors store state.
1258   */

1259  private XSLTSchema m_schema = new XSLTSchema();
1260
1261  /**
1262   * Get the root of the XSLT Schema, which tells us how to
1263   * transition content handlers, create elements, etc.
1264   *
1265   * @return The root XSLT Schema, which should never be null.
1266   */

1267  XSLTSchema getSchema()
1268  {
1269    return m_schema;
1270  }
1271
1272  /**
1273   * The stack of elements, pushed and popped as events occur.
1274   */

1275  private Stack JavaDoc m_elems = new Stack JavaDoc();
1276
1277  /**
1278   * Get the current ElemTemplateElement at the top of the stack.
1279   * @return Valid ElemTemplateElement, which may be null.
1280   */

1281  ElemTemplateElement getElemTemplateElement()
1282  {
1283
1284    try
1285    {
1286      return (ElemTemplateElement) m_elems.peek();
1287    }
1288    catch (java.util.EmptyStackException JavaDoc ese)
1289    {
1290      return null;
1291    }
1292  }
1293
1294  /** An increasing number that is used to indicate the order in which this element
1295   * was encountered during the parse of the XSLT tree.
1296   */

1297  private int m_docOrderCount = 0;
1298
1299  /**
1300   * Returns the next m_docOrderCount number and increments the number for future use.
1301   */

1302  int nextUid()
1303  {
1304    return m_docOrderCount++;
1305  }
1306
1307  /**
1308   * Push the current XSLTElementProcessor to the top of the stack. As a
1309   * side-effect, set the document order index (simply because this is a
1310   * convenient place to set it).
1311   *
1312   * @param elem Should be a non-null reference to the intended current
1313   * template element.
1314   */

1315  void pushElemTemplateElement(ElemTemplateElement elem)
1316  {
1317
1318    if (elem.getUid() == -1)
1319      elem.setUid(nextUid());
1320
1321    m_elems.push(elem);
1322  }
1323
1324  /**
1325   * Get the current XSLTElementProcessor from the top of the stack.
1326   * @return the ElemTemplateElement which was popped.
1327   */

1328  ElemTemplateElement popElemTemplateElement()
1329  {
1330    return (ElemTemplateElement) m_elems.pop();
1331  }
1332
1333  /**
1334   * This will act as a stack to keep track of the
1335   * current include base.
1336   */

1337  Stack JavaDoc m_baseIdentifiers = new Stack JavaDoc();
1338
1339  /**
1340   * Push a base identifier onto the base URI stack.
1341   *
1342   * @param baseID The current base identifier for this position in the
1343   * stylesheet, which may be a fragment identifier, or which may be null.
1344   * @see <a HREF="http://www.w3.org/TR/xslt#base-uri">
1345   * Section 3.2 Base URI of XSLT specification.</a>
1346   */

1347  void pushBaseIndentifier(String JavaDoc baseID)
1348  {
1349
1350    if (null != baseID)
1351    {
1352      int posOfHash = baseID.indexOf('#');
1353
1354      if (posOfHash > -1)
1355      {
1356        m_fragmentIDString = baseID.substring(posOfHash + 1);
1357        m_shouldProcess = false;
1358      }
1359      else
1360        m_shouldProcess = true;
1361    }
1362    else
1363      m_shouldProcess = true;
1364
1365    m_baseIdentifiers.push(baseID);
1366  }
1367
1368  /**
1369   * Pop a base URI from the stack.
1370   * @return baseIdentifier.
1371   */

1372  String JavaDoc popBaseIndentifier()
1373  {
1374    return (String JavaDoc) m_baseIdentifiers.pop();
1375  }
1376
1377  /**
1378   * Return the base identifier.
1379   *
1380   * @return The base identifier of the current stylesheet.
1381   */

1382  public String JavaDoc getBaseIdentifier()
1383  {
1384
1385    // Try to get the baseIdentifier from the baseIdentifier's stack,
1386
// which may not be the same thing as the value found in the
1387
// SourceLocators stack.
1388
String JavaDoc base = (String JavaDoc) (m_baseIdentifiers.isEmpty()
1389                            ? null : m_baseIdentifiers.peek());
1390
1391    // Otherwise try the stylesheet.
1392
if (null == base)
1393    {
1394      SourceLocator JavaDoc locator = getLocator();
1395
1396      base = (null == locator) ? "" : locator.getSystemId();
1397    }
1398
1399    return base;
1400  }
1401
1402  /**
1403   * The top of this stack should contain the currently processed
1404   * stylesheet SAX locator object.
1405   */

1406  private Stack JavaDoc m_stylesheetLocatorStack = new Stack JavaDoc();
1407
1408  /**
1409   * Get the current stylesheet Locator object.
1410   *
1411   * @return non-null reference to the current locator object.
1412   */

1413  public SAXSourceLocator getLocator()
1414  {
1415
1416    if (m_stylesheetLocatorStack.isEmpty())
1417    {
1418      SAXSourceLocator locator = new SAXSourceLocator();
1419
1420      locator.setSystemId(this.getStylesheetProcessor().getDOMsystemID());
1421
1422      return locator;
1423
1424      // m_stylesheetLocatorStack.push(locator);
1425
}
1426
1427    return ((SAXSourceLocator) m_stylesheetLocatorStack.peek());
1428  }
1429
1430  /**
1431   * A stack of URL hrefs for imported stylesheets. This is
1432   * used to diagnose circular imports.
1433   */

1434  private Stack JavaDoc m_importStack = new Stack JavaDoc();
1435
1436  /**
1437   * Push an import href onto the stylesheet stack.
1438   *
1439   * @param hrefUrl non-null reference to the URL for the current imported
1440   * stylesheet.
1441   */

1442  void pushImportURL(String JavaDoc hrefUrl)
1443  {
1444    m_importStack.push(hrefUrl);
1445  }
1446
1447  /**
1448   * See if the imported stylesheet stack already contains
1449   * the given URL. Used to test for recursive imports.
1450   *
1451   * @param hrefUrl non-null reference to a URL string.
1452   *
1453   * @return true if the URL is on the import stack.
1454   */

1455  boolean importStackContains(String JavaDoc hrefUrl)
1456  {
1457    return stackContains(m_importStack, hrefUrl);
1458  }
1459
1460  /**
1461   * Pop an import href from the stylesheet stack.
1462   *
1463   * @return non-null reference to the import URL that was popped.
1464   */

1465  String JavaDoc popImportURL()
1466  {
1467    return (String JavaDoc) m_importStack.pop();
1468  }
1469
1470  /**
1471   * If this is set to true, we've already warned about using the
1472   * older XSLT namespace URL.
1473   */

1474  private boolean warnedAboutOldXSLTNamespace = false;
1475
1476  /** Stack of NamespaceSupport objects. */
1477  Stack JavaDoc m_nsSupportStack = new Stack JavaDoc();
1478
1479  /**
1480   * Push a new NamespaceSupport instance.
1481   */

1482  void pushNewNamespaceSupport()
1483  {
1484    m_nsSupportStack.push(new NamespaceSupport2());
1485  }
1486
1487  /**
1488   * Pop the current NamespaceSupport object.
1489   *
1490   */

1491  void popNamespaceSupport()
1492  {
1493    m_nsSupportStack.pop();
1494  }
1495
1496  /**
1497   * Get the current NamespaceSupport object.
1498   *
1499   * @return a non-null reference to the current NamespaceSupport object,
1500   * which is the top of the namespace support stack.
1501   */

1502  NamespaceSupport JavaDoc getNamespaceSupport()
1503  {
1504    return (NamespaceSupport JavaDoc) m_nsSupportStack.peek();
1505  }
1506
1507  /**
1508   * The originating node if the current stylesheet is being created
1509   * from a DOM.
1510   * @see org.apache.xml.utils.NodeConsumer
1511   */

1512  private Node JavaDoc m_originatingNode;
1513
1514  /**
1515   * Set the node that is originating the SAX event.
1516   *
1517   * @param n Reference to node that originated the current event.
1518   * @see org.apache.xml.utils.NodeConsumer
1519   */

1520  public void setOriginatingNode(Node JavaDoc n)
1521  {
1522    m_originatingNode = n;
1523  }
1524
1525  /**
1526   * Set the node that is originating the SAX event.
1527   *
1528   * @return Reference to node that originated the current event.
1529   * @see org.apache.xml.utils.NodeConsumer
1530   */

1531  public Node JavaDoc getOriginatingNode()
1532  {
1533    return m_originatingNode;
1534  }
1535  
1536  /**
1537   * Stack of booleans that are pushed and popped in start/endElement depending
1538   * on the value of xml:space=default/preserve.
1539   */

1540  private BoolStack m_spacePreserveStack = new BoolStack();
1541  
1542  /**
1543   * Return boolean value from the spacePreserve stack depending on the value
1544   * of xml:space=default/preserve.
1545   *
1546   * @return true if space should be preserved, false otherwise.
1547   */

1548  boolean isSpacePreserve()
1549  {
1550    return m_spacePreserveStack.peek();
1551  }
1552  
1553  /**
1554   * Pop boolean value from the spacePreserve stack.
1555   */

1556  void popSpaceHandling()
1557  {
1558    m_spacePreserveStack.pop();
1559  }
1560  
1561  /**
1562   * Push boolean value on to the spacePreserve stack.
1563   *
1564   * @param b true if space should be preserved, false otherwise.
1565   */

1566  void pushSpaceHandling(boolean b)
1567    throws org.xml.sax.SAXParseException JavaDoc
1568  {
1569    m_spacePreserveStack.push(b);
1570  }
1571  
1572  /**
1573   * Push boolean value on to the spacePreserve stack depending on the value
1574   * of xml:space=default/preserve.
1575   *
1576   * @param attrs list of attributes that were passed to startElement.
1577   */

1578  void pushSpaceHandling(Attributes JavaDoc attrs)
1579    throws org.xml.sax.SAXParseException JavaDoc
1580  {
1581    String JavaDoc value = attrs.getValue("xml:space");
1582    if(null == value)
1583    {
1584      m_spacePreserveStack.push(m_spacePreserveStack.peekOrFalse());
1585    }
1586    else if(value.equals("preserve"))
1587    {
1588      m_spacePreserveStack.push(true);
1589    }
1590    else if(value.equals("default"))
1591    {
1592      m_spacePreserveStack.push(false);
1593    }
1594    else
1595    {
1596      SAXSourceLocator locator = getLocator();
1597      ErrorListener JavaDoc handler = m_stylesheetProcessor.getErrorListener();
1598  
1599      try
1600      {
1601        handler.error(new TransformerException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_ILLEGAL_XMLSPACE_VALUE, null), locator)); //"Illegal value for xml:space", locator));
1602
}
1603      catch (TransformerException JavaDoc te)
1604      {
1605        throw new org.xml.sax.SAXParseException JavaDoc(te.getMessage(), locator, te);
1606      }
1607      m_spacePreserveStack.push(m_spacePreserveStack.peek());
1608    }
1609  }
1610  
1611  private double getElemVersion()
1612  {
1613    ElemTemplateElement elem = getElemTemplateElement();
1614    double version = -1;
1615    while ((version == -1 || version == Constants.XSLTVERSUPPORTED) && elem != null)
1616    {
1617      try{
1618      version = Double.valueOf(elem.getVersion()).doubleValue();
1619      }
1620      catch (Exception JavaDoc ex)
1621      {
1622        version = -1;
1623      }
1624      elem = elem.getParentElem();
1625      }
1626    return (version == -1)? Constants.XSLTVERSUPPORTED : version;
1627  }
1628    /**
1629     * @see PrefixResolver#handlesNullPrefixes()
1630     */

1631    public boolean handlesNullPrefixes() {
1632        return false;
1633    }
1634
1635}
1636
1637
1638
1639
Popular Tags