All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.xml.serializer.ToTextStream Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: ToTextStream.java 468654 2006-10-28 07:09:23Z minchau $
 */
package org.apache.xml.serializer;

import java.io.IOException;

import org.apache.xml.serializer.utils.MsgKey;
import org.apache.xml.serializer.utils.Utils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * This class is not a public API.
 * It is only public because it is used in other packages. 
 * This class converts SAX or SAX-like calls to a 
 * serialized document for xsl:output method of "text".
 * @xsl.usage internal
 */
public class ToTextStream extends ToStream 
{ 

       
  /**
   * Default constructor.
   */
  public ToTextStream()
  {
    super();
  }

 
 
  /**
   * Receive notification of the beginning of a document.
   *
   * 

The SAX parser will invoke this method only once, before any * other methods in this interface or in DTDHandler (except for * setDocumentLocator).

* * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException */ protected void startDocumentInternal() throws org.xml.sax.SAXException { super.startDocumentInternal(); m_needToCallStartDocument = false; // No action for the moment. } /** * Receive notification of the end of a document. * *

The SAX parser will invoke this method only once, and it will * be the last method invoked during the parse. The parser shall * not invoke this method until it has either abandoned parsing * (because of an unrecoverable error) or reached the end of * input.

* * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException */ public void endDocument() throws org.xml.sax.SAXException { flushPending(); flushWriter(); if (m_tracer != null) super.fireEndDoc(); } /** * Receive notification of the beginning of an element. * *

The Parser will invoke this method at the beginning of every * element in the XML document; there will be a corresponding * endElement() event for every startElement() event (even when the * element is empty). All of the element's content will be * reported, in order, before the corresponding endElement() * event.

* *

If the element name has a namespace prefix, the prefix will * still be attached. Note that the attribute list provided will * contain only attributes with explicit values (specified or * defaulted): #IMPLIED attributes will be omitted.

* * * @param namespaceURI The Namespace URI, or the empty string if the * element has no Namespace URI or if Namespace * processing is not being performed. * @param localName The local name (without prefix), or the * empty string if Namespace processing is not being * performed. * @param name The qualified name (with prefix), or the * empty string if qualified names are not available. * @param atts The attributes attached to the element, if any. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see #endElement * @see org.xml.sax.AttributeList * * @throws org.xml.sax.SAXException */ public void startElement( String namespaceURI, String localName, String name, Attributes atts) throws org.xml.sax.SAXException { // time to fire off startElement event if (m_tracer != null) { super.fireStartElem(name); this.firePseudoAttributes(); } return; } /** * Receive notification of the end of an element. * *

The SAX parser will invoke this method at the end of every * element in the XML document; there will be a corresponding * startElement() event for every endElement() event (even when the * element is empty).

* *

If the element name has a namespace prefix, the prefix will * still be attached to the name.

* * * @param namespaceURI The Namespace URI, or the empty string if the * element has no Namespace URI or if Namespace * processing is not being performed. * @param localName The local name (without prefix), or the * empty string if Namespace processing is not being * performed. * @param name The qualified name (with prefix), or the * empty string if qualified names are not available. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException */ public void endElement(String namespaceURI, String localName, String name) throws org.xml.sax.SAXException { if (m_tracer != null) super.fireEndElem(name); } /** * Receive notification of character data. * *

The Parser will call this method to report each chunk of * character data. SAX parsers may return all contiguous character * data in a single chunk, or they may split it into several * chunks; however, all of the characters in any single event * must come from the same external entity, so that the Locator * provides useful information.

* *

The application must not attempt to read from the array * outside of the specified range.

* *

Note that some parsers will report whitespace using the * ignorableWhitespace() method rather than this one (validating * parsers must do so).

* * @param ch The characters from the XML document. * @param start The start position in the array. * @param length The number of characters to read from the array. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see #ignorableWhitespace * @see org.xml.sax.Locator */ public void characters(char ch[], int start, int length) throws org.xml.sax.SAXException { flushPending(); try { if (inTemporaryOutputState()) { /* leave characters un-processed as we are * creating temporary output, the output generated by * this serializer will be input to a final serializer * later on and it will do the processing in final * output state (not temporary output state). * * A "temporary" ToTextStream serializer is used to * evaluate attribute value templates (for example), * and the result of evaluating such a thing * is fed into a final serializer later on. */ m_writer.write(ch, start, length); } else { // In final output state we do process the characters! writeNormalizedChars(ch, start, length, m_lineSepUse); } if (m_tracer != null) super.fireCharEvent(ch, start, length); } catch(IOException ioe) { throw new SAXException(ioe); } } /** * If available, when the disable-output-escaping attribute is used, * output raw text without escaping. * * @param ch The characters from the XML document. * @param start The start position in the array. * @param length The number of characters to read from the array. * * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. */ public void charactersRaw(char ch[], int start, int length) throws org.xml.sax.SAXException { try { writeNormalizedChars(ch, start, length, m_lineSepUse); } catch(IOException ioe) { throw new SAXException(ioe); } } /** * Normalize the characters, but don't escape. Different from * SerializerToXML#writeNormalizedChars because it does not attempt to do * XML escaping at all. * * @param ch The characters from the XML document. * @param start The start position in the array. * @param length The number of characters to read from the array. * @param useLineSep true if the operating systems * end-of-line separator should be output rather than a new-line character. * * @throws IOException * @throws org.xml.sax.SAXException */ void writeNormalizedChars( final char ch[], final int start, final int length, final boolean useLineSep) throws IOException, org.xml.sax.SAXException { final String encoding = getEncoding(); final java.io.Writer writer = m_writer; final int end = start + length; /* copy a few "constants" before the loop for performance */ final char S_LINEFEED = CharInfo.S_LINEFEED; // This for() loop always increments i by one at the end // of the loop. Additional increments of i adjust for when // two input characters (a high/low UTF16 surrogate pair) // are processed. for (int i = start; i < end; i++) { final char c = ch[i]; if (S_LINEFEED == c && useLineSep) { writer.write(m_lineSep, 0, m_lineSepLen); // one input char processed } else if (m_encodingInfo.isInEncoding(c)) { writer.write(c); // one input char processed } else if (Encodings.isHighUTF16Surrogate(c)) { final int codePoint = writeUTF16Surrogate(c, ch, i, end); if (codePoint != 0) { // I think we can just emit the message, // not crash and burn. final String integralValue = Integer.toString(codePoint); final String msg = Utils.messages.createMessage( MsgKey.ER_ILLEGAL_CHARACTER, new Object[] { integralValue, encoding }); //Older behavior was to throw the message, //but newer gentler behavior is to write a message to System.err //throw new SAXException(msg); System.err.println(msg); } i++; // two input chars processed } else { // Don't know what to do with this char, it is // not in the encoding and not a high char in // a surrogate pair, so write out as an entity ref if (encoding != null) { /* The output encoding is known, * so somthing is wrong. */ // not in the encoding, so write out a character reference writer.write('&'); writer.write('#'); writer.write(Integer.toString(c)); writer.write(';'); // I think we can just emit the message, // not crash and burn. final String integralValue = Integer.toString(c); final String msg = Utils.messages.createMessage( MsgKey.ER_ILLEGAL_CHARACTER, new Object[] { integralValue, encoding }); //Older behavior was to throw the message, //but newer gentler behavior is to write a message to System.err //throw new SAXException(msg); System.err.println(msg); } else { /* The output encoding is not known, * so just write it out as-is. */ writer.write(c); } // one input char was processed } } } /** * Receive notification of cdata. * *

The Parser will call this method to report each chunk of * character data. SAX parsers may return all contiguous character * data in a single chunk, or they may split it into several * chunks; however, all of the characters in any single event * must come from the same external entity, so that the Locator * provides useful information.

* *

The application must not attempt to read from the array * outside of the specified range.

* *

Note that some parsers will report whitespace using the * ignorableWhitespace() method rather than this one (validating * parsers must do so).

* * @param ch The characters from the XML document. * @param start The start position in the array. * @param length The number of characters to read from the array. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see #ignorableWhitespace * @see org.xml.sax.Locator */ public void cdata(char ch[], int start, int length) throws org.xml.sax.SAXException { try { writeNormalizedChars(ch, start, length, m_lineSepUse); if (m_tracer != null) super.fireCDATAEvent(ch, start, length); } catch(IOException ioe) { throw new SAXException(ioe); } } /** * Receive notification of ignorable whitespace in element content. * *

Validating Parsers must use this method to report each chunk * of ignorable whitespace (see the W3C XML 1.0 recommendation, * section 2.10): non-validating parsers may also use this method * if they are capable of parsing and using content models.

* *

SAX parsers may return all contiguous whitespace in a single * chunk, or they may split it into several chunks; however, all of * the characters in any single event must come from the same * external entity, so that the Locator provides useful * information.

* *

The application must not attempt to read from the array * outside of the specified range.

* * @param ch The characters from the XML document. * @param start The start position in the array. * @param length The number of characters to read from the array. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * @see #characters * * @throws org.xml.sax.SAXException */ public void ignorableWhitespace(char ch[], int start, int length) throws org.xml.sax.SAXException { try { writeNormalizedChars(ch, start, length, m_lineSepUse); } catch(IOException ioe) { throw new SAXException(ioe); } } /** * Receive notification of a processing instruction. * *

The Parser will invoke this method once for each processing * instruction found: note that processing instructions may occur * before or after the main document element.

* *

A SAX parser should never report an XML declaration (XML 1.0, * section 2.8) or a text declaration (XML 1.0, section 4.3.1) * using this method.

* * @param target The processing instruction target. * @param data The processing instruction data, or null if * none was supplied. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. * * @throws org.xml.sax.SAXException */ public void processingInstruction(String target, String data) throws org.xml.sax.SAXException { // flush anything pending first flushPending(); if (m_tracer != null) super.fireEscapingEvent(target, data); } /** * Called when a Comment is to be constructed. * Note that Xalan will normally invoke the other version of this method. * %REVIEW% In fact, is this one ever needed, or was it a mistake? * * @param data The comment data. * @throws org.xml.sax.SAXException Any SAX exception, possibly * wrapping another exception. */ public void comment(String data) throws org.xml.sax.SAXException { final int length = data.length(); if (length > m_charsBuff.length) { m_charsBuff = new char[length*2 + 1]; } data.getChars(0, length, m_charsBuff, 0); comment(m_charsBuff, 0, length); } /** * Report an XML comment anywhere in the document. * * This callback will be used for comments inside or outside the * document element, including comments in the external DTD * subset (if read). * * @param ch An array holding the characters in the comment. * @param start The starting position in the array. * @param length The number of characters to use from the array. * @throws org.xml.sax.SAXException The application may raise an exception. */ public void comment(char ch[], int start, int length) throws org.xml.sax.SAXException { flushPending(); if (m_tracer != null) super.fireCommentEvent(ch, start, length); } /** * Receive notivication of a entityReference. * * @param name non-null reference to the name of the entity. * * @throws org.xml.sax.SAXException */ public void entityReference(String name) throws org.xml.sax.SAXException { if (m_tracer != null) super.fireEntityReference(name); } /** * @see ExtendedContentHandler#addAttribute(String, String, String, String, String) */ public void addAttribute( String uri, String localName, String rawName, String type, String value, boolean XSLAttribute) { // do nothing, just forget all about the attribute } /** * @see org.xml.sax.ext.LexicalHandler#endCDATA() */ public void endCDATA() throws SAXException { // do nothing } /** * @see ExtendedContentHandler#endElement(String) */ public void endElement(String elemName) throws SAXException { if (m_tracer != null) super.fireEndElem(elemName); } /** * From XSLTC */ public void startElement( String elementNamespaceURI, String elementLocalName, String elementName) throws SAXException { if (m_needToCallStartDocument) startDocumentInternal(); // time to fire off startlement event. if (m_tracer != null) { super.fireStartElem(elementName); this.firePseudoAttributes(); } return; } /** * From XSLTC */ public void characters(String characters) throws SAXException { final int length = characters.length(); if (length > m_charsBuff.length) { m_charsBuff = new char[length*2 + 1]; } characters.getChars(0, length, m_charsBuff, 0); characters(m_charsBuff, 0, length); } /** * From XSLTC */ public void addAttribute(String name, String value) { // do nothing, forget about the attribute } /** * Add a unique attribute */ public void addUniqueAttribute(String qName, String value, int flags) throws SAXException { // do nothing, forget about the attribute } public boolean startPrefixMapping( String prefix, String uri, boolean shouldFlush) throws SAXException { // no namespace support for HTML return false; } public void startPrefixMapping(String prefix, String uri) throws org.xml.sax.SAXException { // no namespace support for HTML } public void namespaceAfterStartElement( final String prefix, final String uri) throws SAXException { // no namespace support for HTML } public void flushPending() throws org.xml.sax.SAXException { if (m_needToCallStartDocument) { startDocumentInternal(); m_needToCallStartDocument = false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy