001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.serialization;
018:
019: import org.apache.avalon.framework.configuration.Configuration;
020: import org.apache.avalon.framework.configuration.ConfigurationException;
021: import org.apache.cocoon.CascadingIOException;
022: import org.apache.cocoon.xml.XMLUtils;
023:
024: import org.xml.sax.SAXException;
025: import org.xml.sax.Attributes;
026:
027: import javax.xml.transform.OutputKeys;
028: import javax.xml.transform.sax.TransformerHandler;
029: import javax.xml.transform.stream.StreamResult;
030: import java.io.IOException;
031: import java.io.OutputStream;
032:
033: /**
034: * Text serializer converts XML into plain text.
035: * It omits all XML tags and writes only character events to the output.
036: * Internally, text serializer uses XML serializer with {@link OutputKeys#METHOD}
037: * set to <code>text</code>.
038: *
039: * <p>Input document must have at least one element - root element - which
040: * should wrap all the text inside it.
041: *
042: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
043: * @version $Id: TextSerializer.java 433543 2006-08-22 06:22:54Z crossley $
044: */
045: public class TextSerializer extends AbstractTextSerializer {
046:
047: /**
048: * Set to true after first XML element
049: */
050: private boolean hasRootElement;
051:
052: /**
053: * Set to true after first XML element
054: */
055: private boolean hadNoRootElement;
056:
057: /**
058: * Set the configurations for this serializer.
059: */
060: public void configure(Configuration conf)
061: throws ConfigurationException {
062: super .configure(conf);
063: this .format.put(OutputKeys.METHOD, "text");
064: }
065:
066: /**
067: * Set the {@link OutputStream} where the requested resource should
068: * be serialized.
069: */
070: public void setOutputStream(OutputStream out) throws IOException {
071: super .setOutputStream(out);
072: try {
073: TransformerHandler handler = this .getTransformerHandler();
074: handler.getTransformer().setOutputProperties(format);
075: handler.setResult(new StreamResult(this .output));
076: this .setContentHandler(handler);
077: this .setLexicalHandler(handler);
078: } catch (Exception e) {
079: final String message = "Cannot set TextSerializer outputstream";
080: throw new CascadingIOException(message, e);
081: }
082: }
083:
084: public void startElement(String uri, String loc, String raw,
085: Attributes a) throws SAXException {
086: this .hasRootElement = true;
087: super .startElement(uri, loc, raw, a);
088: }
089:
090: public void characters(char c[], int start, int len)
091: throws SAXException {
092: if (!this .hasRootElement) {
093: this .hasRootElement = this .hadNoRootElement = true;
094: getLogger()
095: .warn(
096: "Encountered text before root element. Creating <text> wrapper element.");
097: super .startElement("", "text", "text",
098: XMLUtils.EMPTY_ATTRIBUTES);
099: }
100: super .characters(c, start, len);
101: }
102:
103: public void endDocument() throws SAXException {
104: if (this .hadNoRootElement) {
105: super .endElement("", "text", "text");
106: }
107: super .endDocument();
108: }
109:
110: public void recycle() {
111: super .recycle();
112: this .hasRootElement = false;
113: this .hadNoRootElement = false;
114: }
115: }
|