Coverage report

  %line %branch
org.apache.commons.jelly.XMLOutput
48% 
81% 

 1  
 /*
 2  
  * Copyright 2002,2004 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.jelly;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.io.OutputStream;
 21  
 import java.io.UnsupportedEncodingException;
 22  
 import java.io.Writer;
 23  
 
 24  
 import org.apache.commons.logging.Log;
 25  
 import org.apache.commons.logging.LogFactory;
 26  
 import org.dom4j.io.XMLWriter;
 27  
 import org.xml.sax.Attributes;
 28  
 import org.xml.sax.ContentHandler;
 29  
 import org.xml.sax.Locator;
 30  
 import org.xml.sax.SAXException;
 31  
 import org.xml.sax.XMLReader;
 32  
 import org.xml.sax.ext.LexicalHandler;
 33  
 import org.xml.sax.helpers.AttributesImpl;
 34  
 import org.xml.sax.helpers.DefaultHandler;
 35  
 
 36  
 /** <p><code>XMLOutput</code> is used to output XML events
 37  
   * in a SAX-like manner. This also allows pipelining to be done
 38  
   * such as in the <a href="http://xml.apache.org/cocoon/">Cocoon</a> project.</p>
 39  
   *
 40  
   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 41  
   * @version $Revision: 1.18 $
 42  
   */
 43  
 
 44  40
 public class XMLOutput implements ContentHandler, LexicalHandler {
 45  
 
 46  80
     protected static final String[] LEXICAL_HANDLER_NAMES =
 47  
         {
 48  
             "http://xml.org/sax/properties/lexical-handler",
 49  
             "http://xml.org/sax/handlers/LexicalHandler" };
 50  
 
 51  
     /** empty attributes */
 52  40
     private static final Attributes EMPTY_ATTRIBUTES = new AttributesImpl();
 53  
 
 54  
     /** The SAX ContentHandler that output goes to */
 55  
     private ContentHandler contentHandler;
 56  
 
 57  
     /** The SAX LexicalHandler that output goes to */
 58  
     private LexicalHandler lexicalHandler;
 59  
 
 60  
     /** The Log to which logging calls will be made. */
 61  40
     private static final Log log = LogFactory.getLog(XMLOutput.class);
 62  
 
 63  
     /** the default for escaping of text */
 64  
     private static final boolean DEFAULT_ESCAPE_TEXT = false;
 65  
 
 66  114
     public XMLOutput() {
 67  114
     }
 68  
 
 69  132
     public XMLOutput(ContentHandler contentHandler) {
 70  132
         this.contentHandler = contentHandler;
 71  
         // often classes will implement LexicalHandler as well
 72  132
         if (contentHandler instanceof LexicalHandler) {
 73  0
             this.lexicalHandler = (LexicalHandler) contentHandler;
 74  
         }
 75  132
     }
 76  
 
 77  
     public XMLOutput(
 78  
         ContentHandler contentHandler,
 79  4
         LexicalHandler lexicalHandler) {
 80  4
         this.contentHandler = contentHandler;
 81  4
         this.lexicalHandler = lexicalHandler;
 82  4
     }
 83  
 
 84  
     public String toString() {
 85  0
         return super.toString()
 86  
             + "[contentHandler="
 87  
             + contentHandler
 88  
             + ";lexicalHandler="
 89  
             + lexicalHandler
 90  
             + "]";
 91  
     }
 92  
 
 93  
     /**
 94  
      * Provides a useful hook that implementations can use to close the
 95  
      * underlying OutputStream or Writer
 96  
      */
 97  
     public void close() throws IOException {
 98  0
     }
 99  
 
 100  
     public void flush() throws IOException {
 101  4
         if( contentHandler instanceof XMLWriter )
 102  
         {
 103  4
             ((XMLWriter)contentHandler).flush();
 104  
         }
 105  4
     }
 106  
 
 107  
     // Static helper methods
 108  
     //-------------------------------------------------------------------------
 109  
 
 110  
     /**
 111  
      * Creates an XMLOutput from an existing SAX XMLReader
 112  
      */
 113  
     public static XMLOutput createXMLOutput(XMLReader xmlReader) {
 114  0
         XMLOutput output = new XMLOutput(xmlReader.getContentHandler());
 115  
 
 116  
         // isn't it lovely what we've got to do to find the LexicalHandler... ;-)
 117  0
         for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
 118  
             try {
 119  0
                 Object value = xmlReader.getProperty(LEXICAL_HANDLER_NAMES[i]);
 120  0
                 if (value instanceof LexicalHandler) {
 121  0
                     output.setLexicalHandler((LexicalHandler) value);
 122  0
                     break;
 123  
                 }
 124  0
             }
 125  
             catch (Exception e) {
 126  
                 // ignore any unsupported-operation exceptions
 127  0
                 if (log.isDebugEnabled()) log.debug("error setting lexical handler properties", e);
 128  
             }
 129  
         }
 130  0
         return output;
 131  
     }
 132  
 
 133  
     /**
 134  
      * Creates a text based XMLOutput which converts all XML events into
 135  
      * text and writes to the underlying Writer.
 136  
      */
 137  
     public static XMLOutput createXMLOutput(Writer writer) {
 138  26
         return createXMLOutput(writer, DEFAULT_ESCAPE_TEXT);
 139  
     }
 140  
 
 141  
     /**
 142  
      * Creates a text based XMLOutput which converts all XML events into
 143  
      * text and writes to the underlying Writer.
 144  
      *
 145  
      * @param writer is the writer to output to
 146  
      * @param escapeText is whether or not text output will be escaped. This must be true
 147  
      * if the underlying output is XML or could be false if the underlying output is textual.
 148  
      */
 149  
     public static XMLOutput createXMLOutput(Writer writer, boolean escapeText)
 150  
     {
 151  106
         XMLWriter xmlWriter = new XMLWriter(writer);
 152  106
         xmlWriter.setEscapeText(escapeText);
 153  106
         return createXMLOutput(xmlWriter);
 154  
     }
 155  
 
 156  
     /**
 157  
      * Creates a text based XMLOutput which converts all XML events into
 158  
      * text and writes to the underlying OutputStream.
 159  
      */
 160  
     public static XMLOutput createXMLOutput(OutputStream out) throws UnsupportedEncodingException {
 161  2
         return createXMLOutput(out, DEFAULT_ESCAPE_TEXT);
 162  
     }
 163  
 
 164  
     /**
 165  
      * Creates a text based XMLOutput which converts all XML events into
 166  
      * text and writes to the underlying OutputStream.
 167  
      *
 168  
      * @param out is the output stream to write
 169  
      * @param escapeText is whether or not text output will be escaped. This must be true
 170  
      * if the underlying output is XML or could be false if the underlying output is textual.
 171  
      */
 172  
     public static XMLOutput createXMLOutput(OutputStream out, boolean escapeText) throws UnsupportedEncodingException {
 173  2
         XMLWriter xmlWriter = new XMLWriter(out);
 174  2
         xmlWriter.setEscapeText(escapeText);
 175  2
         return createXMLOutput(xmlWriter);
 176  
     }
 177  
 
 178  
     /**
 179  
      * returns an XMLOutput object that will discard all
 180  
      * tag-generated XML events.  Useful when tag output is not expected
 181  
      * or not significant.
 182  
      *
 183  
      * @return a no-op XMLOutput
 184  
      */
 185  
     public static XMLOutput createDummyXMLOutput() {
 186  130
         return new XMLOutput(class="keyword">new DefaultHandler());
 187  
     }
 188  
 
 189  
     // Extra helper methods provided for tag authors
 190  
     //-------------------------------------------------------------------------
 191  
 
 192  
     /**
 193  
      * Outputs the given String as a piece of valid text in the
 194  
      * XML event stream.
 195  
      * Any special XML characters should be properly escaped.
 196  
      */
 197  
     public void write(String text) throws SAXException {
 198  144
         char[] ch = text.toCharArray();
 199  144
         characters(ch, 0, ch.length);
 200  144
     }
 201  
 
 202  
     /**
 203  
      * Outputs the given String as a piece of CDATA in the
 204  
      * XML event stream.
 205  
      */
 206  
     public void writeCDATA(String text) throws SAXException {
 207  0
         startCDATA();
 208  0
         char[] ch = text.toCharArray();
 209  0
         characters(ch, 0, ch.length);
 210  0
         endCDATA();
 211  0
     }
 212  
 
 213  
     /**
 214  
      * Outputs a comment to the XML stream
 215  
      */
 216  
     public void writeComment(String text) throws SAXException {
 217  0
         char[] ch = text.toCharArray();
 218  0
         comment(ch, 0, ch.length);
 219  0
     }
 220  
 
 221  
     /**
 222  
      * Helper method for outputting a start element event for an element in no namespace
 223  
      */
 224  
     public void startElement(String localName) throws SAXException {
 225  0
         startElement("", localName, localName, EMPTY_ATTRIBUTES);
 226  0
     }
 227  
 
 228  
     /**
 229  
      * Helper method for outputting a start element event for an element in no namespace
 230  
      */
 231  
     public void startElement(String localName, Attributes attributes) throws SAXException {
 232  0
         startElement("", localName, localName, attributes);
 233  0
     }
 234  
 
 235  
     /**
 236  
      * Helper method for outputting an end element event for an element in no namespace
 237  
      */
 238  
     public void endElement(String localName) throws SAXException {
 239  0
         endElement("", localName, localName);
 240  0
     }
 241  
 
 242  
 
 243  
     // ContentHandler interface
 244  
     //-------------------------------------------------------------------------
 245  
 
 246  
     /**
 247  
      * Receive an object for locating the origin of SAX document events.
 248  
      *
 249  
      * <p>SAX parsers are strongly encouraged (though not absolutely
 250  
      * required) to supply a locator: if it does so, it must supply
 251  
      * the locator to the application by invoking this method before
 252  
      * invoking any of the other methods in the ContentHandler
 253  
      * interface.</p>
 254  
      *
 255  
      * <p>The locator allows the application to determine the end
 256  
      * position of any document-related event, even if the parser is
 257  
      * not reporting an error.  Typically, the application will
 258  
      * use this information for reporting its own errors (such as
 259  
      * character content that does not match an application's
 260  
      * business rules).  The information returned by the locator
 261  
      * is probably not sufficient for use with a search engine.</p>
 262  
      *
 263  
      * <p>Note that the locator will return correct information only
 264  
      * during the invocation of the events in this interface.  The
 265  
      * application should not attempt to use it at any other time.</p>
 266  
      *
 267  
      * @param locator An object that can return the location of
 268  
      *                any SAX document event.
 269  
      * @see org.xml.sax.Locator
 270  
      */
 271  
     public void setDocumentLocator(Locator locator) {
 272  0
         contentHandler.setDocumentLocator(locator);
 273  0
     }
 274  
 
 275  
     /**
 276  
      * Receive notification of the beginning of a document.
 277  
      *
 278  
      * <p>The SAX parser will invoke this method only once, before any
 279  
      * other event callbacks (except for {@link #setDocumentLocator
 280  
      * setDocumentLocator}).</p>
 281  
      *
 282  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 283  
      *            wrapping another exception.
 284  
      * @see #endDocument
 285  
      */
 286  
     public void startDocument() throws SAXException {
 287  10
         contentHandler.startDocument();
 288  10
     }
 289  
 
 290  
     /**
 291  
      * Receive notification of the end of a document.
 292  
      *
 293  
      * <p>The SAX parser will invoke this method only once, and it will
 294  
      * be the last method invoked during the parse.  The parser shall
 295  
      * not invoke this method until it has either abandoned parsing
 296  
      * (because of an unrecoverable error) or reached the end of
 297  
      * input.</p>
 298  
      *
 299  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 300  
      *            wrapping another exception.
 301  
      * @see #startDocument
 302  
      */
 303  
     public void endDocument() throws SAXException {
 304  10
         contentHandler.endDocument();
 305  10
     }
 306  
 
 307  
     /**
 308  
      * Begin the scope of a prefix-URI Namespace mapping.
 309  
      *
 310  
      * <p>The information from this event is not necessary for
 311  
      * normal Namespace processing: the SAX XML reader will
 312  
      * automatically replace prefixes for element and attribute
 313  
      * names when the <code>http://xml.org/sax/features/namespaces</code>
 314  
      * feature is <var>true</var> (the default).</p>
 315  
      *
 316  
      * <p>There are cases, however, when applications need to
 317  
      * use prefixes in character data or in attribute values,
 318  
      * where they cannot safely be expanded automatically; the
 319  
      * start/endPrefixMapping event supplies the information
 320  
      * to the application to expand prefixes in those contexts
 321  
      * itself, if necessary.</p>
 322  
      *
 323  
      * <p>Note that start/endPrefixMapping events are not
 324  
      * guaranteed to be properly nested relative to each other:
 325  
      * all startPrefixMapping events will occur immediately before the
 326  
      * corresponding {@link #startElement startElement} event,
 327  
      * and all {@link #endPrefixMapping endPrefixMapping}
 328  
      * events will occur immediately after the corresponding
 329  
      * {@link #endElement endElement} event,
 330  
      * but their order is not otherwise
 331  
      * guaranteed.</p>
 332  
      *
 333  
      * <p>There should never be start/endPrefixMapping events for the
 334  
      * "xml" prefix, since it is predeclared and immutable.</p>
 335  
      *
 336  
      * @param prefix The Namespace prefix being declared.
 337  
      *  An empty string is used for the default element namespace,
 338  
      *  which has no prefix.
 339  
      * @param uri The Namespace URI the prefix is mapped to.
 340  
      * @exception org.xml.sax.SAXException The client may throw
 341  
      *            an exception during processing.
 342  
      * @see #endPrefixMapping
 343  
      * @see #startElement
 344  
      */
 345  
     public void startPrefixMapping(String prefix, String uri) throws SAXException {
 346  2
         contentHandler.startPrefixMapping(prefix, uri);
 347  2
     }
 348  
 
 349  
     /**
 350  
      * End the scope of a prefix-URI mapping.
 351  
      *
 352  
      * <p>See {@link #startPrefixMapping startPrefixMapping} for
 353  
      * details.  These events will always occur immediately after the
 354  
      * corresponding {@link #endElement endElement} event, but the order of
 355  
      * {@link #endPrefixMapping endPrefixMapping} events is not otherwise
 356  
      * guaranteed.</p>
 357  
      *
 358  
      * @param prefix The prefix that was being mapped.
 359  
      *  This is the empty string when a default mapping scope ends.
 360  
      * @exception org.xml.sax.SAXException The client may throw
 361  
      *            an exception during processing.
 362  
      * @see #startPrefixMapping
 363  
      * @see #endElement
 364  
      */
 365  
     public void endPrefixMapping(String prefix) throws SAXException {
 366  2
         contentHandler.endPrefixMapping(prefix);
 367  2
     }
 368  
 
 369  
     /**
 370  
      * Receive notification of the beginning of an element.
 371  
      *
 372  
      * <p>The Parser will invoke this method at the beginning of every
 373  
      * element in the XML document; there will be a corresponding
 374  
      * {@link #endElement endElement} event for every startElement event
 375  
      * (even when the element is empty). All of the element's content will be
 376  
      * reported, in order, before the corresponding endElement
 377  
      * event.</p>
 378  
      *
 379  
      * <p>This event allows up to three name components for each
 380  
      * element:</p>
 381  
      *
 382  
      * <ol>
 383  
      * <li>the Namespace URI;</li>
 384  
      * <li>the local name; and</li>
 385  
      * <li>the qualified (prefixed) name.</li>
 386  
      * </ol>
 387  
      *
 388  
      * <p>Any or all of these may be provided, depending on the
 389  
      * values of the <var>http://xml.org/sax/features/namespaces</var>
 390  
      * and the <var>http://xml.org/sax/features/namespace-prefixes</var>
 391  
      * properties:</p>
 392  
      *
 393  
      * <ul>
 394  
      * <li>the Namespace URI and local name are required when
 395  
      * the namespaces property is <var>true</var> (the default), and are
 396  
      * optional when the namespaces property is <var>false</var> (if one is
 397  
      * specified, both must be);</li>
 398  
      * <li>the qualified name is required when the namespace-prefixes property
 399  
      * is <var>true</var>, and is optional when the namespace-prefixes property
 400  
      * is <var>false</var> (the default).</li>
 401  
      * </ul>
 402  
      *
 403  
      * <p>Note that the attribute list provided will contain only
 404  
      * attributes with explicit values (specified or defaulted):
 405  
      * #IMPLIED attributes will be omitted.  The attribute list
 406  
      * will contain attributes used for Namespace declarations
 407  
      * (xmlns* attributes) only if the
 408  
      * <code>http://xml.org/sax/features/namespace-prefixes</code>
 409  
      * property is true (it is false by default, and support for a
 410  
      * true value is optional).</p>
 411  
      *
 412  
      * <p>Like {@link #characters characters()}, attribute values may have
 413  
      * characters that need more than one <code>char</code> value.  </p>
 414  
      *
 415  
      * @param uri The Namespace URI, or the empty string if the
 416  
      *        element has no Namespace URI or if Namespace
 417  
      *        processing is not being performed.
 418  
      * @param localName The local name (without prefix), or the
 419  
      *        empty string if Namespace processing is not being
 420  
      *        performed.
 421  
      * @param qName The qualified name (with prefix), or the
 422  
      *        empty string if qualified names are not available.
 423  
      * @param atts The attributes attached to the element.  If
 424  
      *        there are no attributes, it shall be an empty
 425  
      *        Attributes object.
 426  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 427  
      *            wrapping another exception.
 428  
      * @see #endElement
 429  
      * @see org.xml.sax.Attributes
 430  
      */
 431  
     public void startElement(
 432  
         String uri,
 433  
         String localName,
 434  
         String qName,
 435  
         Attributes atts)
 436  
         throws SAXException {
 437  26
         contentHandler.startElement(uri, localName, qName, atts);
 438  26
     }
 439  
 
 440  
     /**
 441  
      * Receive notification of the end of an element.
 442  
      *
 443  
      * <p>The SAX parser will invoke this method at the end of every
 444  
      * element in the XML document; there will be a corresponding
 445  
      * {@link #startElement startElement} event for every endElement
 446  
      * event (even when the element is empty).</p>
 447  
      *
 448  
      * <p>For information on the names, see startElement.</p>
 449  
      *
 450  
      * @param uri The Namespace URI, or the empty string if the
 451  
      *        element has no Namespace URI or if Namespace
 452  
      *        processing is not being performed.
 453  
      * @param localName The local name (without prefix), or the
 454  
      *        empty string if Namespace processing is not being
 455  
      *        performed.
 456  
      * @param qName The qualified XML 1.0 name (with prefix), or the
 457  
      *        empty string if qualified names are not available.
 458  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 459  
      *            wrapping another exception.
 460  
      */
 461  
     public void endElement(String uri, String localName, String qName)
 462  
         throws SAXException {
 463  26
         contentHandler.endElement(uri, localName, qName);
 464  26
     }
 465  
 
 466  
     /**
 467  
      * Receive notification of character data.
 468  
      *
 469  
      * <p>The Parser will call this method to report each chunk of
 470  
      * character data.  SAX parsers may return all contiguous character
 471  
      * data in a single chunk, or they may split it into several
 472  
      * chunks; however, all of the characters in any single event
 473  
      * must come from the same external entity so that the Locator
 474  
      * provides useful information.</p>
 475  
      *
 476  
      * <p>The application must not attempt to read from the array
 477  
      * outside of the specified range.</p>
 478  
      *
 479  
      * <p>Individual characters may consist of more than one Java
 480  
      * <code>char</code> value.  There are two important cases where this
 481  
      * happens, because characters can't be represented in just sixteen bits.
 482  
      * In one case, characters are represented in a <em>Surrogate Pair</em>,
 483  
      * using two special Unicode values. Such characters are in the so-called
 484  
      * "Astral Planes", with a code point above U+FFFF.  A second case involves
 485  
      * composite characters, such as a base character combining with one or
 486  
      * more accent characters. </p>
 487  
      *
 488  
      * <p> Your code should not assume that algorithms using
 489  
      * <code>char</code>-at-a-time idioms will be working in character
 490  
      * units; in some cases they will split characters.  This is relevant
 491  
      * wherever XML permits arbitrary characters, such as attribute values,
 492  
      * processing instruction data, and comments as well as in data reported
 493  
      * from this method.  It's also generally relevant whenever Java code
 494  
      * manipulates internationalized text; the issue isn't unique to XML.</p>
 495  
      *
 496  
      * <p>Note that some parsers will report whitespace in element
 497  
      * content using the {@link #ignorableWhitespace ignorableWhitespace}
 498  
      * method rather than this one (validating parsers <em>must</em>
 499  
      * do so).</p>
 500  
      *
 501  
      * @param ch The characters from the XML document.
 502  
      * @param start The start position in the array.
 503  
      * @param length The number of characters to read from the array.
 504  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 505  
      *            wrapping another exception.
 506  
      * @see #ignorableWhitespace
 507  
      * @see org.xml.sax.Locator
 508  
      */
 509  
     public void characters(char ch[], int start, class="keyword">int length) throws SAXException {
 510  144
         contentHandler.characters(ch, start, length);
 511  144
     }
 512  
 
 513  
     /**
 514  
      * Receive notification of ignorable whitespace in element content.
 515  
      *
 516  
      * <p>Validating Parsers must use this method to report each chunk
 517  
      * of whitespace in element content (see the W3C XML 1.0 recommendation,
 518  
      * section 2.10): non-validating parsers may also use this method
 519  
      * if they are capable of parsing and using content models.</p>
 520  
      *
 521  
      * <p>SAX parsers may return all contiguous whitespace in a single
 522  
      * chunk, or they may split it into several chunks; however, all of
 523  
      * the characters in any single event must come from the same
 524  
      * external entity, so that the Locator provides useful
 525  
      * information.</p>
 526  
      *
 527  
      * <p>The application must not attempt to read from the array
 528  
      * outside of the specified range.</p>
 529  
      *
 530  
      * @param ch The characters from the XML document.
 531  
      * @param start The start position in the array.
 532  
      * @param length The number of characters to read from the array.
 533  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 534  
      *            wrapping another exception.
 535  
      * @see #characters
 536  
      */
 537  
     public void ignorableWhitespace(char ch[], int start, class="keyword">int length)
 538  
         throws SAXException {
 539  0
         contentHandler.ignorableWhitespace(ch, start, length);
 540  0
     }
 541  
 
 542  
     /**
 543  
      * Receive notification of a processing instruction.
 544  
      *
 545  
      * <p>The Parser will invoke this method once for each processing
 546  
      * instruction found: note that processing instructions may occur
 547  
      * before or after the main document element.</p>
 548  
      *
 549  
      * <p>A SAX parser must never report an XML declaration (XML 1.0,
 550  
      * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
 551  
      * using this method.</p>
 552  
      *
 553  
      * <p>Like {@link #characters characters()}, processing instruction
 554  
      * data may have characters that need more than one <code>char</code>
 555  
      * value. </p>
 556  
      *
 557  
      * @param target The processing instruction target.
 558  
      * @param data The processing instruction data, or null if
 559  
      *        none was supplied.  The data does not include any
 560  
      *        whitespace separating it from the target.
 561  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 562  
      *            wrapping another exception.
 563  
      */
 564  
     public void processingInstruction(String target, String data)
 565  
         throws SAXException {
 566  0
         contentHandler.processingInstruction(target, data);
 567  0
     }
 568  
 
 569  
     /**
 570  
      * Receive notification of a skipped entity.
 571  
      * This is not called for entity references within markup constructs
 572  
      * such as element start tags or markup declarations.  (The XML
 573  
      * recommendation requires reporting skipped external entities.
 574  
      * SAX also reports internal entity expansion/non-expansion, except
 575  
      * within markup constructs.)
 576  
      *
 577  
      * <p>The Parser will invoke this method each time the entity is
 578  
      * skipped.  Non-validating processors may skip entities if they
 579  
      * have not seen the declarations (because, for example, the
 580  
      * entity was declared in an external DTD subset).  All processors
 581  
      * may skip external entities, depending on the values of the
 582  
      * <code>http://xml.org/sax/features/external-general-entities</code>
 583  
      * and the
 584  
      * <code>http://xml.org/sax/features/external-parameter-entities</code>
 585  
      * properties.</p>
 586  
      *
 587  
      * @param name The name of the skipped entity.  If it is a
 588  
      *        parameter entity, the name will begin with '%', and if
 589  
      *        it is the external DTD subset, it will be the string
 590  
      *        "[dtd]".
 591  
      * @exception org.xml.sax.SAXException Any SAX exception, possibly
 592  
      *            wrapping another exception.
 593  
      */
 594  
     public void skippedEntity(String name) throws SAXException {
 595  0
         contentHandler.skippedEntity(name);
 596  0
     }
 597  
 
 598  
 
 599  
     // Lexical Handler interface
 600  
     //-------------------------------------------------------------------------
 601  
 
 602  
     /**
 603  
      * Report the start of DTD declarations, if any.
 604  
      *
 605  
      * <p>This method is intended to report the beginning of the
 606  
      * DOCTYPE declaration; if the document has no DOCTYPE declaration,
 607  
      * this method will not be invoked.</p>
 608  
      *
 609  
      * <p>All declarations reported through
 610  
      * {@link org.xml.sax.DTDHandler DTDHandler} or
 611  
      * {@link org.xml.sax.ext.DeclHandler DeclHandler} events must appear
 612  
      * between the startDTD and {@link #endDTD endDTD} events.
 613  
      * Declarations are assumed to belong to the internal DTD subset
 614  
      * unless they appear between {@link #startEntity startEntity}
 615  
      * and {@link #endEntity endEntity} events.  Comments and
 616  
      * processing instructions from the DTD should also be reported
 617  
      * between the startDTD and endDTD events, in their original
 618  
      * order of (logical) occurrence; they are not required to
 619  
      * appear in their correct locations relative to DTDHandler
 620  
      * or DeclHandler events, however.</p>
 621  
      *
 622  
      * <p>Note that the start/endDTD events will appear within
 623  
      * the start/endDocument events from ContentHandler and
 624  
      * before the first
 625  
      * {@link org.xml.sax.ContentHandler#startElement startElement}
 626  
      * event.</p>
 627  
      *
 628  
      * @param name The document type name.
 629  
      * @param publicId The declared public identifier for the
 630  
      *        external DTD subset, or null if none was declared.
 631  
      * @param systemId The declared system identifier for the
 632  
      *        external DTD subset, or null if none was declared.
 633  
      *        (Note that this is not resolved against the document
 634  
      *        base URI.)
 635  
      * @exception SAXException The application may raise an
 636  
      *            exception.
 637  
      * @see #endDTD
 638  
      * @see #startEntity
 639  
      */
 640  
     public void startDTD(String name, String class="keyword">publicId, String systemId)
 641  
         throws SAXException {
 642  0
         if (lexicalHandler != null) {
 643  0
             lexicalHandler.startDTD(name, publicId, systemId);
 644  
         }
 645  0
     }
 646  
 
 647  
     /**
 648  
      * Report the end of DTD declarations.
 649  
      *
 650  
      * <p>This method is intended to report the end of the
 651  
      * DOCTYPE declaration; if the document has no DOCTYPE declaration,
 652  
      * this method will not be invoked.</p>
 653  
      *
 654  
      * @exception SAXException The application may raise an exception.
 655  
      * @see #startDTD
 656  
      */
 657  
     public void endDTD() throws SAXException {
 658  0
         if (lexicalHandler != null) {
 659  0
             lexicalHandler.endDTD();
 660  
         }
 661  0
     }
 662  
 
 663  
     /**
 664  
      * Report the beginning of some internal and external XML entities.
 665  
      *
 666  
      * <p>The reporting of parameter entities (including
 667  
      * the external DTD subset) is optional, and SAX2 drivers that
 668  
      * report LexicalHandler events may not implement it; you can use the
 669  
      * <code
 670  
      * >http://xml.org/sax/features/lexical-handler/parameter-entities</code>
 671  
      * feature to query or control the reporting of parameter entities.</p>
 672  
      *
 673  
      * <p>General entities are reported with their regular names,
 674  
      * parameter entities have '%' prepended to their names, and
 675  
      * the external DTD subset has the pseudo-entity name "[dtd]".</p>
 676  
      *
 677  
      * <p>When a SAX2 driver is providing these events, all other
 678  
      * events must be properly nested within start/end entity
 679  
      * events.  There is no additional requirement that events from
 680  
      * {@link org.xml.sax.ext.DeclHandler DeclHandler} or
 681  
      * {@link org.xml.sax.DTDHandler DTDHandler} be properly ordered.</p>
 682  
      *
 683  
      * <p>Note that skipped entities will be reported through the
 684  
      * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
 685  
      * event, which is part of the ContentHandler interface.</p>
 686  
      *
 687  
      * <p>Because of the streaming event model that SAX uses, some
 688  
      * entity boundaries cannot be reported under any
 689  
      * circumstances:</p>
 690  
      *
 691  
      * <ul>
 692  
      * <li>general entities within attribute values</li>
 693  
      * <li>parameter entities within declarations</li>
 694  
      * </ul>
 695  
      *
 696  
      * <p>These will be silently expanded, with no indication of where
 697  
      * the original entity boundaries were.</p>
 698  
      *
 699  
      * <p>Note also that the boundaries of character references (which
 700  
      * are not really entities anyway) are not reported.</p>
 701  
      *
 702  
      * <p>All start/endEntity events must be properly nested.
 703  
      *
 704  
      * @param name The name of the entity.  If it is a parameter
 705  
      *        entity, the name will begin with '%', and if it is the
 706  
      *        external DTD subset, it will be "[dtd]".
 707  
      * @exception SAXException The application may raise an exception.
 708  
      * @see #endEntity
 709  
      * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
 710  
      * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
 711  
      */
 712  
     public void startEntity(String name) throws SAXException {
 713  0
         if (lexicalHandler != null) {
 714  0
             lexicalHandler.startEntity(name);
 715  
         }
 716  0
     }
 717  
 
 718  
     /**
 719  
      * Report the end of an entity.
 720  
      *
 721  
      * @param name The name of the entity that is ending.
 722  
      * @exception SAXException The application may raise an exception.
 723  
      * @see #startEntity
 724  
      */
 725  
     public void endEntity(String name) throws SAXException {
 726  0
         if (lexicalHandler != null) {
 727  0
             lexicalHandler.endEntity(name);
 728  
         }
 729  0
     }
 730  
 
 731  
     /**
 732  
      * Report the start of a CDATA section.
 733  
      *
 734  
      * <p>The contents of the CDATA section will be reported through
 735  
      * the regular {@link org.xml.sax.ContentHandler#characters
 736  
      * characters} event; this event is intended only to report
 737  
      * the boundary.</p>
 738  
      *
 739  
      * @exception SAXException The application may raise an exception.
 740  
      * @see #endCDATA
 741  
      */
 742  
     public void startCDATA() throws SAXException {
 743  0
         if (lexicalHandler != null) {
 744  0
             lexicalHandler.startCDATA();
 745  
         }
 746  0
     }
 747  
 
 748  
     /**
 749  
      * Report the end of a CDATA section.
 750  
      *
 751  
      * @exception SAXException The application may raise an exception.
 752  
      * @see #startCDATA
 753  
      */
 754  
     public void endCDATA() throws SAXException {
 755  0
         if (lexicalHandler != null) {
 756  0
             lexicalHandler.endCDATA();
 757  
         }
 758  0
     }
 759  
 
 760  
     /**
 761  
      * Report an XML comment anywhere in the document.
 762  
      *
 763  
      * <p>This callback will be used for comments inside or outside the
 764  
      * document element, including comments in the external DTD
 765  
      * subset (if read).  Comments in the DTD must be properly
 766  
      * nested inside start/endDTD and start/endEntity events (if
 767  
      * used).</p>
 768  
      *
 769  
      * @param ch An array holding the characters in the comment.
 770  
      * @param start The starting position in the array.
 771  
      * @param length The number of characters to use from the array.
 772  
      * @exception SAXException The application may raise an exception.
 773  
      */
 774  
     public void comment(char ch[], int start, class="keyword">int length) throws SAXException {
 775  0
         if (lexicalHandler != null) {
 776  0
             lexicalHandler.comment(ch, start, length);
 777  
         }
 778  0
     }
 779  
 
 780  
     // Properties
 781  
     //-------------------------------------------------------------------------
 782  
     /**
 783  
      * @return the SAX ContentHandler to use to pipe SAX events into
 784  
      */
 785  
     public ContentHandler getContentHandler() {
 786  6
         return contentHandler;
 787  
     }
 788  
 
 789  
     /**
 790  
      * Sets the SAX ContentHandler to pipe SAX events into
 791  
      *
 792  
      * @param contentHandler is the new ContentHandler to use.
 793  
      *      This value cannot be null.
 794  
      */
 795  
     public void setContentHandler(ContentHandler contentHandler) {
 796  120
         if (contentHandler == null) {
 797  0
             throw new NullPointerException("ContentHandler cannot be null!");
 798  
         }
 799  120
         this.contentHandler = contentHandler;
 800  120
     }
 801  
 
 802  
     /**
 803  
      * @return the SAX LexicalHandler to use to pipe SAX events into
 804  
      */
 805  
     public LexicalHandler getLexicalHandler() {
 806  0
         return lexicalHandler;
 807  
     }
 808  
 
 809  
     /**
 810  
      * Sets the SAX LexicalHandler to pipe SAX events into
 811  
      *
 812  
      * @param lexicalHandler is the new LexicalHandler to use.
 813  
      *      This value can be null.
 814  
      */
 815  
     public void setLexicalHandler(LexicalHandler lexicalHandler) {
 816  114
         this.lexicalHandler = lexicalHandler;
 817  114
     }
 818  
 
 819  
     // Implementation methods
 820  
     //-------------------------------------------------------------------------
 821  
     /**
 822  
      * Factory method to create a new XMLOutput from an XMLWriter
 823  
      */
 824  
     protected static XMLOutput createXMLOutput(final XMLWriter xmlWriter) {
 825  108
         XMLOutput answer = new XMLOutput() {
 826  
             public void close() throws IOException {
 827  
                 xmlWriter.close();
 828  
             }
 829  
         };
 830  108
         answer.setContentHandler(xmlWriter);
 831  108
         answer.setLexicalHandler(xmlWriter);
 832  108
         return answer;
 833  
     }
 834  
 
 835  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.