1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id: ProcessorCharacters.java 468640 2006-10-28 06:53:53Z minchau $
20  */
21 package org.apache.xalan.processor;
22 
23 import javax.xml.transform.TransformerException;
24 
25 import org.apache.xalan.templates.ElemTemplateElement;
26 import org.apache.xalan.templates.ElemText;
27 import org.apache.xalan.templates.ElemTextLiteral;
28 import org.apache.xml.utils.XMLCharacterRecognizer;
29 
30 import org.w3c.dom.Node;
31 
32 /**
33  * This class processes character events for a XSLT template element.
34  * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
35  * @see <a href="http://www.w3.org/TR/xslt#section-Creating-the-Result-Tree">section-Creating-the-Result-Tree in XSLT Specification</a>
36  */
37 public class ProcessorCharacters extends XSLTElementProcessor
38 {
39     static final long serialVersionUID = 8632900007814162650L;
40 
41   /**
42    * Receive notification of the start of the non-text event.  This
43    * is sent to the current processor when any non-text event occurs.
44    *
45    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
46    */
startNonText(StylesheetHandler handler)47   public void startNonText(StylesheetHandler handler) throws org.xml.sax.SAXException
48   {
49     if (this == handler.getCurrentProcessor())
50     {
51       handler.popProcessor();
52     }
53 
54     int nChars = m_accumulator.length();
55 
56     if ((nChars > 0)
57             && ((null != m_xslTextElement)
58                 ||!XMLCharacterRecognizer.isWhiteSpace(m_accumulator))
59                 || handler.isSpacePreserve())
60     {
61       ElemTextLiteral elem = new ElemTextLiteral();
62 
63       elem.setDOMBackPointer(m_firstBackPointer);
64       elem.setLocaterInfo(handler.getLocator());
65       try
66       {
67         elem.setPrefixes(handler.getNamespaceSupport());
68       }
69       catch(TransformerException te)
70       {
71         throw new org.xml.sax.SAXException(te);
72       }
73 
74       boolean doe = (null != m_xslTextElement)
75                     ? m_xslTextElement.getDisableOutputEscaping() : false;
76 
77       elem.setDisableOutputEscaping(doe);
78       elem.setPreserveSpace(true);
79 
80       char[] chars = new char[nChars];
81 
82       m_accumulator.getChars(0, nChars, chars, 0);
83       elem.setChars(chars);
84 
85       ElemTemplateElement parent = handler.getElemTemplateElement();
86 
87       parent.appendChild(elem);
88     }
89 
90     m_accumulator.setLength(0);
91     m_firstBackPointer = null;
92   }
93 
94   protected Node m_firstBackPointer = null;
95 
96   /**
97    * Receive notification of character data inside an element.
98    *
99    *
100    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
101    * @param ch The characters.
102    * @param start The start position in the character array.
103    * @param length The number of characters to use from the
104    *               character array.
105    * @throws org.xml.sax.SAXException Any SAX exception, possibly
106    *            wrapping another exception.
107    * @see org.xml.sax.ContentHandler#characters
108    */
characters( StylesheetHandler handler, char ch[], int start, int length)109   public void characters(
110           StylesheetHandler handler, char ch[], int start, int length)
111             throws org.xml.sax.SAXException
112   {
113 
114     m_accumulator.append(ch, start, length);
115 
116     if(null == m_firstBackPointer)
117       m_firstBackPointer = handler.getOriginatingNode();
118 
119     // Catch all events until a non-character event.
120     if (this != handler.getCurrentProcessor())
121       handler.pushProcessor(this);
122   }
123 
124   /**
125    * Receive notification of the end of an element.
126    *
127    * @param handler The calling StylesheetHandler/TemplatesBuilder.
128    * @param uri The Namespace URI, or the empty string if the
129    *        element has no Namespace URI or if Namespace
130    *        processing is not being performed.
131    * @param localName The local name (without prefix), or the
132    *        empty string if Namespace processing is not being
133    *        performed.
134    * @param rawName The raw XML 1.0 name (with prefix), or the
135    *        empty string if raw names are not available.
136    * @see org.apache.xalan.processor.StylesheetHandler#startElement
137    * @see org.apache.xalan.processor.StylesheetHandler#endElement
138    * @see org.xml.sax.ContentHandler#startElement
139    * @see org.xml.sax.ContentHandler#endElement
140    * @see org.xml.sax.Attributes
141    */
endElement( StylesheetHandler handler, String uri, String localName, String rawName)142   public void endElement(
143           StylesheetHandler handler, String uri, String localName, String rawName)
144             throws org.xml.sax.SAXException
145   {
146 
147     // Since this has been installed as the current processor, we
148     // may get and end element event, in which case, we pop and clear
149     // and then call the real element processor.
150     startNonText(handler);
151     handler.getCurrentProcessor().endElement(handler, uri, localName,
152                                              rawName);
153     handler.popProcessor();
154   }
155 
156   /**
157    * Accumulate characters, until a non-whitespace event has
158    * occured.
159    */
160   private StringBuffer m_accumulator = new StringBuffer();
161 
162   /**
163    * The xsl:text processor will call this to set a
164    * preserve space state.
165    */
166   private ElemText m_xslTextElement;
167 
168   /**
169    * Set the current setXslTextElement. The xsl:text
170    * processor will call this to set a preserve space state.
171    *
172    * @param xslTextElement The current xslTextElement that
173    *                       is preserving state, or null.
174    */
setXslTextElement(ElemText xslTextElement)175   void setXslTextElement(ElemText xslTextElement)
176   {
177     m_xslTextElement = xslTextElement;
178   }
179 }
180