001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: ProcessorCharacters.java 468640 2006-10-28 06:53:53Z minchau $
020 */
021 package org.apache.xalan.processor;
022
023 import javax.xml.transform.TransformerException;
024
025 import org.apache.xalan.templates.ElemTemplateElement;
026 import org.apache.xalan.templates.ElemText;
027 import org.apache.xalan.templates.ElemTextLiteral;
028 import org.apache.xml.utils.XMLCharacterRecognizer;
029
030 import org.w3c.dom.Node;
031
032 /**
033 * This class processes character events for a XSLT template element.
034 * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
035 * @see <a href="http://www.w3.org/TR/xslt#section-Creating-the-Result-Tree">section-Creating-the-Result-Tree in XSLT Specification</a>
036 */
037 public class ProcessorCharacters extends XSLTElementProcessor
038 {
039 static final long serialVersionUID = 8632900007814162650L;
040
041 /**
042 * Receive notification of the start of the non-text event. This
043 * is sent to the current processor when any non-text event occurs.
044 *
045 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
046 */
047 public void startNonText(StylesheetHandler handler) throws org.xml.sax.SAXException
048 {
049 if (this == handler.getCurrentProcessor())
050 {
051 handler.popProcessor();
052 }
053
054 int nChars = m_accumulator.length();
055
056 if ((nChars > 0)
057 && ((null != m_xslTextElement)
058 ||!XMLCharacterRecognizer.isWhiteSpace(m_accumulator))
059 || handler.isSpacePreserve())
060 {
061 ElemTextLiteral elem = new ElemTextLiteral();
062
063 elem.setDOMBackPointer(m_firstBackPointer);
064 elem.setLocaterInfo(handler.getLocator());
065 try
066 {
067 elem.setPrefixes(handler.getNamespaceSupport());
068 }
069 catch(TransformerException te)
070 {
071 throw new org.xml.sax.SAXException(te);
072 }
073
074 boolean doe = (null != m_xslTextElement)
075 ? m_xslTextElement.getDisableOutputEscaping() : false;
076
077 elem.setDisableOutputEscaping(doe);
078 elem.setPreserveSpace(true);
079
080 char[] chars = new char[nChars];
081
082 m_accumulator.getChars(0, nChars, chars, 0);
083 elem.setChars(chars);
084
085 ElemTemplateElement parent = handler.getElemTemplateElement();
086
087 parent.appendChild(elem);
088 }
089
090 m_accumulator.setLength(0);
091 m_firstBackPointer = null;
092 }
093
094 protected Node m_firstBackPointer = null;
095
096 /**
097 * Receive notification of character data inside an element.
098 *
099 *
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 */
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 */
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 */
175 void setXslTextElement(ElemText xslTextElement)
176 {
177 m_xslTextElement = xslTextElement;
178 }
179 }