XMLEventListener.java |
/* * $Id: XMLEventListener.java,v 1.9 2005/09/12 08:40:02 znerd Exp $ */ package org.znerd.xmlenc; import java.io.IOException; import java.io.UnsupportedEncodingException; /** * Interface for XML event listeners. * * <h3>State transitions</h3> * * XML event sources must obey a state model when calling * <code>XMLEventListener</code>s. However, an <code>XMLEventListener</code> * is not required to check that this state model is actually respected. If it * does, then it will throw an {@link IllegalStateException} if the state * model is violated. * * <p>Stateful <code>XMLEventListener</code> implementations should * implement the {@link StatefulXMLEventListener} interface instead of * implementing <code>XMLEventListener</code> directly. * * <p>Initially the state of an uninitialized <code>XMLEventListener</code> is * {@link #UNINITIALIZED UNINITIALIZED}. * * <p>The following table defines how the state changes when a certain * method is called in a certain state. Horizontally are the current states, * vertically the notification methods. The cells self contain the * new state. * * <p><table class="states"> * <tr> * <th></th> * <th><acronym title="BEFORE_XML_DECLARATION">S0</acronym></th> * <th><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></th> * <th><acronym title="BEFORE_ROOT_ELEMENT">S2</acronym></th> * <th><acronym title="START_TAG_OPEN">S3</acronym></th> * <th><acronym title="WITHIN_ELEMENT">S4</acronym></th> * <th><acronym title="AFTER_ROOT_ELEMENT">S5</acronym></th> * <th><acronym title="DOCUMENT_ENDED">S6</acronym></th> * </tr> * <tr> * <th>{@link #declaration()}</th> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #dtd(String,String,String)}</th> * <td><acronym title="BEFORE_ROOT_ELEMENT">S2</acronym></td> * <td><acronym title="BEFORE_ROOT_ELEMENT">S2</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #startTag(String)}</th> * <td><acronym title="START_TAG_OPEN">S3</acronym></td> * <td><acronym title="START_TAG_OPEN">S3</acronym></td> * <td><acronym title="START_TAG_OPEN">S3</acronym></td> * <td><acronym title="START_TAG_OPEN">S3</acronym></td> * <td><acronym title="START_TAG_OPEN">S3</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #attribute(String,String)}</th> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td><acronym title="START_TAG_OPEN">S3</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #endTag()}</th> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym>/<acronym title="AFTER_ROOT_ELEMENT">S5</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym>/<acronym title="AFTER_ROOT_ELEMENT">S5</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #pcdata(String)}</th> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #pcdata(char[],int,int)}</th> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #cdata(String)}</th> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #whitespace(String)}</th> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_ROOT_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="AFTER_ROOT_ELEMENT">S5</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #whitespace(char[],int,int)}</th> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_ROOT_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="AFTER_ROOT_ELEMENT">S5</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #comment(String)}</th> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_ROOT_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="AFTER_ROOT_ELEMENT">S5</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #pi(String,String)}</th> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_DTD_DECLARATION">S1</acronym></td> * <td><acronym title="BEFORE_ROOT_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="WITHIN_ELEMENT">S4</acronym></td> * <td><acronym title="AFTER_ROOT_ELEMENT">S5</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * <tr> * <th>{@link #endDocument()}</th> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * <td><acronym title="DOCUMENT_ENDED">S6</acronym></td> * <td><acronym title="DOCUMENT_ENDED">S6</acronym></td> * <td><acronym title="DOCUMENT_ENDED">S6</acronym></td> * <td class="err"><acronym title="IllegalStateException">ISE</acronym></td> * </tr> * </table> * * <p>List of states as used in the table: * * <ul> * <li>S0: {@link #BEFORE_XML_DECLARATION BEFORE_XML_DECLARATION}</li> * <li>S1: {@link #BEFORE_DTD_DECLARATION BEFORE_DTD_DECLARATION}</li> * <li>S2: {@link #BEFORE_ROOT_ELEMENT BEFORE_ROOT_ELEMENT}</li> * <li>S3: {@link #START_TAG_OPEN START_TAG_OPEN}</li> * <li>S4: {@link #WITHIN_ELEMENT WITHIN_ELEMENT}</li> * <li>S5: {@link #AFTER_ROOT_ELEMENT AFTER_ROOT_ELEMENT}</li> * <li>S6: {@link #DOCUMENT_ENDED DOCUMENT_ENDED}</li> * </ul> * * @version $Revision: 1.9 $ $Date: 2005/09/12 08:40:02 $ * @author Ernst de Haan (<a href="mailto:wfe.dehaan@gmail.com">wfe.dehaan@gmail.com</a>) * * @since xmlenc 0.30 */ public interface XMLEventListener extends XMLEventListenerStates { /** * Resets this XML event listener. The state will be set to * {@link #UNINITIALIZED UNINITIALIZED}. */ void reset(); /** * Returns the current state of this outputter. * * @return * the current state, cannot be <code>null</code>. * * @throws UnsupportedOperationException * if this is not a stateful XML event listener. */ XMLEventListenerState getState() throws UnsupportedOperationException; /** * Sets the state of this XML event listener. Normally, it is not necessary * to call this method and it should be used with great care. * * <p>Calling this method with {@link #UNINITIALIZED UNINITIALIZED} as * the state is equivalent to calling {@link #reset()}. * * @param newState * the new state, not <code>null</code>. * * @param newElementStack * the new element stack, if <code>newState == {@link #START_TAG_OPEN START_TAG_OPEN} * || newState == {@link #WITHIN_ELEMENT WITHIN_ELEMENT}</code> then it should be * non-<code>null</code> and containing no <code>null</code> elements, * otherwise it must be <code>null</code>. * * @throws IllegalArgumentException * if <code>newState == null * || (newState == {@link #START_TAG_OPEN START_TAG_OPEN} && newElementStack == null) * || (newState == {@link #WITHIN_ELEMENT WITHIN_ELEMENT} && newElementStack == null) * || (newState != {@link #START_TAG_OPEN START_TAG_OPEN} && newState != {@link #WITHIN_ELEMENT WITHIN_ELEMENT} && newElementStack != null) * || newElementStack[<i>n</i>] == null</code> (where <code>0 <= <i>n</i> < newElementStack.length</code>). */ void setState(XMLEventListenerState newState, String[] newElementStack) throws IllegalArgumentException; /** * Notification of an XML declaration. No encoding is explicitly specified. * * @throws IllegalStateException * if <code>getState() != BEFORE_XML_DECLARATION</code>. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE ERROR_STATE}. */ void declaration() throws IllegalStateException, IOException; /** * Notification of a document type declaration. * * <p>An external subset can be specified using either a * <em>system identifier</em> (alone), or using both a * <em>public identifier</em> and a <em>system identifier</em>. It can * never be specified using a <em>public identifier</em> alone. * * <p>For example, for XHTML 1.0 the public identifier is: * * <blockquote><code>-//W3C//DTD XHTML 1.0 Transitional//EN</code></blockquote> * * <p>while the system identifier is: * * <blockquote><code>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</code></blockquote> * * <p>The output is typically similar to this: * * <blockquote><code><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></code></blockquote> * * or alternatively, if only the <em>system identifier</em> is specified: * * <blockquote><code><!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></code></blockquote> * * @param name * the name of the document type, not <code>null</code>. * * @param publicID * the public identifier, can be <code>null</code>. * * @param systemID * the system identifier, can be <code>null</code>, but otherwise * it should be a properly formatted URL, see * <a href="http://www.w3.org/TR/2000/REC-xml-20001006#sec-external-ent">section 4.2.2 External Entities</a> * in the XML 1.0 Specification. * * @throws IllegalStateException * if <code>getState() != {@link #BEFORE_XML_DECLARATION BEFORE_XML_DECLARATION}&& * getState() != {@link #BEFORE_DTD_DECLARATION BEFORE_DTD_DECLARATION}</code>. * * @throws IllegalArgumentException * if <code>name == null || * (publicID != null && systemID == null)</code>. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void dtd(String name, String publicID, String systemID) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of an element start tag. * * @param type * the type of the tag to start, not <code>null</code>. * * @throws IllegalStateException * if <code>getState() != {@link #BEFORE_XML_DECLARATION BEFORE_XML_DECLARATION} && * getState() != {@link #BEFORE_DTD_DECLARATION BEFORE_DTD_DECLARATION} && * getState() != {@link #BEFORE_ROOT_ELEMENT BEFORE_ROOT_ELEMENT} && * getState() != {@link #START_TAG_OPEN START_TAG_OPEN} && * getState() != {@link #WITHIN_ELEMENT WITHIN_ELEMENT}</code>. * * * @throws IllegalArgumentException * if <code>type == null</code>. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE ERROR_STATE}. */ void startTag(String type) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Adds an attribute to the current element. There must currently be an * open element. * * <p>The attribute value is surrounded by single quotes. * * @param name * the name of the attribute, not <code>null</code>. * * @param value * the value of the attribute, not <code>null</code>. * * @throws IllegalStateException * if <code>getState() != {@link #START_TAG_OPEN}</code>. * * @throws IllegalArgumentException * if <code>name == null || value == null</code>. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void attribute(String name, String value) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of an element end tag. * * @throws IllegalStateException * if <code>getState() != START_TAG_OPEN && * getState() != WITHIN_ELEMENT</code> * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void endTag() throws IllegalStateException, IOException; /** * Notification of a PCDATA section (as a <code>String</code>). * * @param text * the PCDATA section contents, not <code>null</code>. * * @throws IllegalStateException * if <code>getState() != START_TAG_OPEN && * getState() != WITHIN_ELEMENT</code> * * @throws IllegalArgumentException * if <code>text == null</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void pcdata(String text) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of a PCDATA section (as a <code>char</code> array). * * @param ch * the character array containing the PCDATA section contents, not * <code>null</code>. * * @param start * the start index in the array, must be >= 0 and it must be < * <code>ch.length</code>. * * @param length * the number of characters to read from the array, must be > 0. * * @throws IllegalStateException * if <code>getState() != START_TAG_OPEN && * getState() != WITHIN_ELEMENT</code> * * @throws IllegalArgumentException * if <code>ch == null * || start < 0 * || start >= ch.length * || length < 0</code>. * * @throws IndexOutOfBoundsException * if <code>start + length > ch.length</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void pcdata(char[] ch, int start, int length) throws IllegalStateException, IllegalArgumentException, IndexOutOfBoundsException, InvalidXMLException, IOException; /** * Notification of a CDATA section. * * <p>A CDATA section can contain any string, except * <code>"]]>"</code>. This will, however, not be checked by this * method. * * <p>Left angle brackets and ampersands will be output in their literal * form; they need not (and cannot) be escaped using * <code>"&lt;"</code> and <code>"&amp;"</code>. * * <p>If the specified string is empty (i.e. * <code>"".equals(text)</code>, then nothing will be output. * * <p>If the specified string contains characters that cannot be printed * in this encoding, then the result is undefined. * * @param text * the contents of the CDATA section, not <code>null</code>. * * @throws IllegalStateException * if <code>getState() != START_TAG_OPEN && * getState() != WITHIN_ELEMENT</code> * * @throws IllegalArgumentException * if <code>text == null</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void cdata(String text) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of ignorable whitespace (as a <code>String</code>). * Ignorable whitespace can be found anywhere in an XML document, * except above the XML declaration. * * <p>This method does not check if the string actually contains * whitespace. * * <p>If the state equals {@link #BEFORE_XML_DECLARATION}, then it will be set to * {@link #BEFORE_DTD_DECLARATION}, otherwise if the state is * {@link #START_TAG_OPEN} then it will be set to {@link #WITHIN_ELEMENT}, * otherwise the state will not be changed. * * @param whitespace * the ignorable whitespace to be written, not <code>null</code>. * * @throws IllegalStateException * if <code>getState() == ERROR_STATE</code>. * * @throws IllegalArgumentException * if <code>whitespace == null</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void whitespace(String whitespace) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of ignorable whitespace (as a <code>String</code>). * Ignorable whitespace can be found anywhere in an XML document, * except above the XML declaration. * * <p>This method does not check if the string actually contains * whitespace. * * <p>If the state equals {@link #BEFORE_XML_DECLARATION}, then it will be set to * {@link #BEFORE_DTD_DECLARATION}, otherwise if the state is * {@link #START_TAG_OPEN} then it will be set to {@link #WITHIN_ELEMENT}, * otherwise the state will not be changed. * * @param ch * the character array containing the text to be written, not * <code>null</code>. * * @param start * the start index in the array, must be >= 0 and it must be < * <code>ch.length</code>. * * @param length * the number of characters to read from the array, must be > 0. * * @throws IllegalStateException * if <code>getState() == ERROR_STATE</code>. * * @throws IllegalArgumentException * if <code>ch == null * || start < 0 * || start >= ch.length * || length < 0</code>. * * @throws IndexOutOfBoundsException * if <code>start + length > ch.length</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void whitespace(char[] ch, int start, int length) throws IllegalStateException, IllegalArgumentException, IndexOutOfBoundsException, InvalidXMLException, IOException; /** * Notification of a comment. The comment should not contain the string * <code>"--"</code>. * * <p>If the state equals {@link #BEFORE_XML_DECLARATION}, then it will be set to * {@link #BEFORE_DTD_DECLARATION}, otherwise if the state is * {@link #START_TAG_OPEN} then it will be set to {@link #WITHIN_ELEMENT}, * otherwise the state will not be changed. * * @param text * the text for the comment be written, not <code>null</code>. * * @throws IllegalStateException * if <code>getState() == ERROR_STATE</code>. * * @throws IllegalArgumentException * if <code>text == null</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void comment(String text) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of a processing instruction. A target and an optional * instruction should be specified. * * <p>A processing instruction can appear above and below the root * element, and between elements. It cannot appear inside an element start * or end tag, nor inside a comment. Processing instructions cannot be * nested. * * <p>If the state equals {@link #BEFORE_XML_DECLARATION}, then it will be set to * {@link #BEFORE_DTD_DECLARATION}, otherwise the state will not be * changed. * * @param target * an identification of the application at which the instruction is * targeted, not <code>null</code>. * * @param instruction * the instruction, can be <code>null</code>, which is equivalent to an * empty string. * * @throws IllegalStateException * if <code>getState() == ERROR_STATE</code>. * * @throws IllegalArgumentException * if <code>target == null</code>. * * @throws InvalidXMLException * if the specified text contains an invalid character. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void pi(String target, String instruction) throws IllegalStateException, IllegalArgumentException, InvalidXMLException, IOException; /** * Notification of the end of the document. After calling this method, none * of the other notification methods can be called until {@link #reset()} * is called. * * @throws IllegalStateException * if <code>getState() == UNINITIALIZED * || getState() == DOCUMENT_ENDED</code>. * * @throws IOException * if an I/O error occurs; this will set the state to * {@link #ERROR_STATE}. */ void endDocument() throws IllegalStateException, IOException; }