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 }