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