%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.commons.jelly.XMLOutput |
|
|
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. |