Mercurial > repos > pfrommolt > ngsrich
comparison NGSrich_0.5.5/src/org/jdom/output/SAXOutputter.java @ 0:89ad0a9cca52 default tip
Uploaded
author | pfrommolt |
---|---|
date | Mon, 21 Nov 2011 08:12:19 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:89ad0a9cca52 |
---|---|
1 /*-- | |
2 | |
3 $Id: SAXOutputter.java,v 1.40 2007/11/10 05:29:01 jhunter Exp $ | |
4 | |
5 Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin. | |
6 All rights reserved. | |
7 | |
8 Redistribution and use in source and binary forms, with or without | |
9 modification, are permitted provided that the following conditions | |
10 are met: | |
11 | |
12 1. Redistributions of source code must retain the above copyright | |
13 notice, this list of conditions, and the following disclaimer. | |
14 | |
15 2. Redistributions in binary form must reproduce the above copyright | |
16 notice, this list of conditions, and the disclaimer that follows | |
17 these conditions in the documentation and/or other materials | |
18 provided with the distribution. | |
19 | |
20 3. The name "JDOM" must not be used to endorse or promote products | |
21 derived from this software without prior written permission. For | |
22 written permission, please contact <request_AT_jdom_DOT_org>. | |
23 | |
24 4. Products derived from this software may not be called "JDOM", nor | |
25 may "JDOM" appear in their name, without prior written permission | |
26 from the JDOM Project Management <request_AT_jdom_DOT_org>. | |
27 | |
28 In addition, we request (but do not require) that you include in the | |
29 end-user documentation provided with the redistribution and/or in the | |
30 software itself an acknowledgement equivalent to the following: | |
31 "This product includes software developed by the | |
32 JDOM Project (http://www.jdom.org/)." | |
33 Alternatively, the acknowledgment may be graphical using the logos | |
34 available at http://www.jdom.org/images/logos. | |
35 | |
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT | |
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
47 SUCH DAMAGE. | |
48 | |
49 This software consists of voluntary contributions made by many | |
50 individuals on behalf of the JDOM Project and was originally | |
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and | |
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information | |
53 on the JDOM Project, please see <http://www.jdom.org/>. | |
54 | |
55 */ | |
56 | |
57 package org.jdom.output; | |
58 | |
59 import java.io.*; | |
60 import java.lang.reflect.*; | |
61 import java.util.*; | |
62 | |
63 import org.jdom.*; | |
64 import org.xml.sax.*; | |
65 import org.xml.sax.ext.*; | |
66 import org.xml.sax.helpers.*; | |
67 | |
68 /** | |
69 * Outputs a JDOM document as a stream of SAX2 events. | |
70 * <p> | |
71 * Most ContentHandler callbacks are supported. Both | |
72 * <code>ignorableWhitespace()</code> and <code>skippedEntity()</code> have not | |
73 * been implemented. The <code>{@link JDOMLocator}</code> class returned by | |
74 * <code>{@link #getLocator}</code> exposes the current node being operated | |
75 * upon. | |
76 * <p> | |
77 * At this time, it is not possible to access notations and unparsed entity | |
78 * references in a DTD from JDOM. Therefore, <code>DTDHandler</code> callbacks | |
79 * have not been implemented yet. | |
80 * <p> | |
81 * The <code>ErrorHandler</code> callbacks have not been implemented, since | |
82 * these are supposed to be invoked when the document is parsed and at this | |
83 * point the document exists in memory and is known to have no errors. </p> | |
84 * | |
85 * @version $Revision: 1.40 $, $Date: 2007/11/10 05:29:01 $ | |
86 * @author Brett McLaughlin | |
87 * @author Jason Hunter | |
88 * @author Fred Trimble | |
89 * @author Bradley S. Huffman | |
90 */ | |
91 public class SAXOutputter { | |
92 | |
93 private static final String CVS_ID = | |
94 "@(#) $RCSfile: SAXOutputter.java,v $ $Revision: 1.40 $ $Date: 2007/11/10 05:29:01 $ $Name: jdom_1_1_1 $"; | |
95 | |
96 /** Shortcut for SAX namespaces core feature */ | |
97 private static final String NAMESPACES_SAX_FEATURE = | |
98 "http://xml.org/sax/features/namespaces"; | |
99 | |
100 /** Shortcut for SAX namespace-prefixes core feature */ | |
101 private static final String NS_PREFIXES_SAX_FEATURE = | |
102 "http://xml.org/sax/features/namespace-prefixes"; | |
103 | |
104 /** Shortcut for SAX validation core feature */ | |
105 private static final String VALIDATION_SAX_FEATURE = | |
106 "http://xml.org/sax/features/validation"; | |
107 | |
108 /** Shortcut for SAX-ext. lexical handler property */ | |
109 private static final String LEXICAL_HANDLER_SAX_PROPERTY = | |
110 "http://xml.org/sax/properties/lexical-handler"; | |
111 | |
112 /** Shortcut for SAX-ext. declaration handler property */ | |
113 private static final String DECL_HANDLER_SAX_PROPERTY = | |
114 "http://xml.org/sax/properties/declaration-handler"; | |
115 | |
116 /** | |
117 * Shortcut for SAX-ext. lexical handler alternate property. | |
118 * Although this property URI is not the one defined by the SAX | |
119 * "standard", some parsers use it instead of the official one. | |
120 */ | |
121 private static final String LEXICAL_HANDLER_ALT_PROPERTY = | |
122 "http://xml.org/sax/handlers/LexicalHandler"; | |
123 | |
124 /** Shortcut for SAX-ext. declaration handler alternate property */ | |
125 private static final String DECL_HANDLER_ALT_PROPERTY = | |
126 "http://xml.org/sax/handlers/DeclHandler"; | |
127 | |
128 /** | |
129 * Array to map JDOM attribute type (as entry index) to SAX | |
130 * attribute type names. | |
131 */ | |
132 private static final String[] attrTypeToNameMap = new String[] { | |
133 "CDATA", // Attribute.UNDEFINED_ATTRIBUTE, as per SAX 2.0 spec. | |
134 "CDATA", // Attribute.CDATA_TYPE | |
135 "ID", // Attribute.ID_TYPE | |
136 "IDREF", // Attribute.IDREF_TYPE | |
137 "IDREFS", // Attribute.IDREFS_TYPE | |
138 "ENTITY", // Attribute.ENTITY_TYPE | |
139 "ENTITIES", // Attribute.ENTITIES_TYPE | |
140 "NMTOKEN", // Attribute.NMTOKEN_TYPE | |
141 "NMTOKENS", // Attribute.NMTOKENS_TYPE | |
142 "NOTATION", // Attribute.NOTATION_TYPE | |
143 "NMTOKEN", // Attribute.ENUMERATED_TYPE, as per SAX 2.0 spec. | |
144 }; | |
145 | |
146 /** registered <code>ContentHandler</code> */ | |
147 private ContentHandler contentHandler; | |
148 | |
149 /** registered <code>ErrorHandler</code> */ | |
150 private ErrorHandler errorHandler; | |
151 | |
152 /** registered <code>DTDHandler</code> */ | |
153 private DTDHandler dtdHandler; | |
154 | |
155 /** registered <code>EntityResolver</code> */ | |
156 private EntityResolver entityResolver; | |
157 | |
158 /** registered <code>LexicalHandler</code> */ | |
159 private LexicalHandler lexicalHandler; | |
160 | |
161 /** registered <code>DeclHandler</code> */ | |
162 private DeclHandler declHandler; | |
163 | |
164 /** | |
165 * Whether to report attribute namespace declarations as xmlns attributes. | |
166 * Defaults to <code>false</code> as per SAX specifications. | |
167 * | |
168 * @see <a href="http://www.megginson.com/SAX/Java/namespaces.html"> | |
169 * SAX namespace specifications</a> | |
170 */ | |
171 private boolean declareNamespaces = false; | |
172 | |
173 /** | |
174 * Whether to report DTD events to DeclHandlers and LexicalHandlers. | |
175 * Defaults to <code>true</code>. | |
176 */ | |
177 private boolean reportDtdEvents = true; | |
178 | |
179 /** | |
180 * A SAX Locator that points at the JDOM node currently being | |
181 * outputted. | |
182 */ | |
183 private JDOMLocator locator = null; | |
184 | |
185 /** | |
186 * This will create a <code>SAXOutputter</code> without any | |
187 * registered handler. The application is then responsible for | |
188 * registering them using the <code>setXxxHandler()</code> methods. | |
189 */ | |
190 public SAXOutputter() { | |
191 } | |
192 | |
193 /** | |
194 * This will create a <code>SAXOutputter</code> with the | |
195 * specified <code>ContentHandler</code>. | |
196 * | |
197 * @param contentHandler contains <code>ContentHandler</code> | |
198 * callback methods | |
199 */ | |
200 public SAXOutputter(ContentHandler contentHandler) { | |
201 this(contentHandler, null, null, null, null); | |
202 } | |
203 | |
204 /** | |
205 * This will create a <code>SAXOutputter</code> with the | |
206 * specified SAX2 handlers. At this time, only <code>ContentHandler</code> | |
207 * and <code>EntityResolver</code> are supported. | |
208 * | |
209 * @param contentHandler contains <code>ContentHandler</code> | |
210 * callback methods | |
211 * @param errorHandler contains <code>ErrorHandler</code> callback methods | |
212 * @param dtdHandler contains <code>DTDHandler</code> callback methods | |
213 * @param entityResolver contains <code>EntityResolver</code> | |
214 * callback methods | |
215 */ | |
216 public SAXOutputter(ContentHandler contentHandler, | |
217 ErrorHandler errorHandler, | |
218 DTDHandler dtdHandler, | |
219 EntityResolver entityResolver) { | |
220 this(contentHandler, errorHandler, dtdHandler, entityResolver, null); | |
221 } | |
222 | |
223 /** | |
224 * This will create a <code>SAXOutputter</code> with the | |
225 * specified SAX2 handlers. At this time, only <code>ContentHandler</code> | |
226 * and <code>EntityResolver</code> are supported. | |
227 * | |
228 * @param contentHandler contains <code>ContentHandler</code> | |
229 * callback methods | |
230 * @param errorHandler contains <code>ErrorHandler</code> callback methods | |
231 * @param dtdHandler contains <code>DTDHandler</code> callback methods | |
232 * @param entityResolver contains <code>EntityResolver</code> | |
233 * callback methods | |
234 * @param lexicalHandler contains <code>LexicalHandler</code> callbacks. | |
235 */ | |
236 public SAXOutputter(ContentHandler contentHandler, | |
237 ErrorHandler errorHandler, | |
238 DTDHandler dtdHandler, | |
239 EntityResolver entityResolver, | |
240 LexicalHandler lexicalHandler) { | |
241 this.contentHandler = contentHandler; | |
242 this.errorHandler = errorHandler; | |
243 this.dtdHandler = dtdHandler; | |
244 this.entityResolver = entityResolver; | |
245 this.lexicalHandler = lexicalHandler; | |
246 } | |
247 | |
248 /** | |
249 * This will set the <code>ContentHandler</code>. | |
250 * | |
251 * @param contentHandler contains <code>ContentHandler</code> | |
252 * callback methods. | |
253 */ | |
254 public void setContentHandler(ContentHandler contentHandler) { | |
255 this.contentHandler = contentHandler; | |
256 } | |
257 | |
258 /** | |
259 * Returns the registered <code>ContentHandler</code>. | |
260 * | |
261 * @return the current <code>ContentHandler</code> or | |
262 * <code>null</code> if none was registered. | |
263 */ | |
264 public ContentHandler getContentHandler() { | |
265 return this.contentHandler; | |
266 } | |
267 | |
268 /** | |
269 * This will set the <code>ErrorHandler</code>. | |
270 * | |
271 * @param errorHandler contains <code>ErrorHandler</code> callback methods. | |
272 */ | |
273 public void setErrorHandler(ErrorHandler errorHandler) { | |
274 this.errorHandler = errorHandler; | |
275 } | |
276 | |
277 /** | |
278 * Return the registered <code>ErrorHandler</code>. | |
279 * | |
280 * @return the current <code>ErrorHandler</code> or | |
281 * <code>null</code> if none was registered. | |
282 */ | |
283 public ErrorHandler getErrorHandler() { | |
284 return this.errorHandler; | |
285 } | |
286 | |
287 /** | |
288 * This will set the <code>DTDHandler</code>. | |
289 * | |
290 * @param dtdHandler contains <code>DTDHandler</code> callback methods. | |
291 */ | |
292 public void setDTDHandler(DTDHandler dtdHandler) { | |
293 this.dtdHandler = dtdHandler; | |
294 } | |
295 | |
296 /** | |
297 * Return the registered <code>DTDHandler</code>. | |
298 * | |
299 * @return the current <code>DTDHandler</code> or | |
300 * <code>null</code> if none was registered. | |
301 */ | |
302 public DTDHandler getDTDHandler() { | |
303 return this.dtdHandler; | |
304 } | |
305 | |
306 /** | |
307 * This will set the <code>EntityResolver</code>. | |
308 * | |
309 * @param entityResolver contains EntityResolver callback methods. | |
310 */ | |
311 public void setEntityResolver(EntityResolver entityResolver) { | |
312 this.entityResolver = entityResolver; | |
313 } | |
314 | |
315 /** | |
316 * Return the registered <code>EntityResolver</code>. | |
317 * | |
318 * @return the current <code>EntityResolver</code> or | |
319 * <code>null</code> if none was registered. | |
320 */ | |
321 public EntityResolver getEntityResolver() { | |
322 return this.entityResolver; | |
323 } | |
324 | |
325 /** | |
326 * This will set the <code>LexicalHandler</code>. | |
327 * | |
328 * @param lexicalHandler contains lexical callback methods. | |
329 */ | |
330 public void setLexicalHandler(LexicalHandler lexicalHandler) { | |
331 this.lexicalHandler = lexicalHandler; | |
332 } | |
333 | |
334 /** | |
335 * Return the registered <code>LexicalHandler</code>. | |
336 * | |
337 * @return the current <code>LexicalHandler</code> or | |
338 * <code>null</code> if none was registered. | |
339 */ | |
340 public LexicalHandler getLexicalHandler() { | |
341 return this.lexicalHandler; | |
342 } | |
343 | |
344 /** | |
345 * This will set the <code>DeclHandler</code>. | |
346 * | |
347 * @param declHandler contains declaration callback methods. | |
348 */ | |
349 public void setDeclHandler(DeclHandler declHandler) { | |
350 this.declHandler = declHandler; | |
351 } | |
352 | |
353 /** | |
354 * Return the registered <code>DeclHandler</code>. | |
355 * | |
356 * @return the current <code>DeclHandler</code> or | |
357 * <code>null</code> if none was registered. | |
358 */ | |
359 public DeclHandler getDeclHandler() { | |
360 return this.declHandler; | |
361 } | |
362 | |
363 /** | |
364 * Returns whether attribute namespace declarations shall be reported as | |
365 * "xmlns" attributes. | |
366 * | |
367 * @return whether attribute namespace declarations shall be reported as | |
368 * "xmlns" attributes. | |
369 */ | |
370 public boolean getReportNamespaceDeclarations() { | |
371 return declareNamespaces; | |
372 } | |
373 | |
374 /** | |
375 * This will define whether attribute namespace declarations shall be | |
376 * reported as "xmlns" attributes. This flag defaults to <code>false</code> | |
377 * and behaves as the "namespace-prefixes" SAX core feature. | |
378 * | |
379 * @param declareNamespaces whether attribute namespace declarations | |
380 * shall be reported as "xmlns" attributes. | |
381 */ | |
382 public void setReportNamespaceDeclarations(boolean declareNamespaces) { | |
383 this.declareNamespaces = declareNamespaces; | |
384 } | |
385 | |
386 /** | |
387 * Returns whether DTD events will be reported. | |
388 * | |
389 * @return whether DTD events will be reported | |
390 */ | |
391 public boolean getReportDTDEvents() { | |
392 return reportDtdEvents; | |
393 } | |
394 | |
395 /** | |
396 * This will define whether to report DTD events to SAX DeclHandlers | |
397 * and LexicalHandlers if these handlers are registered and the | |
398 * document to output includes a DocType declaration. | |
399 * | |
400 * @param reportDtdEvents whether to notify DTD events. | |
401 */ | |
402 public void setReportDTDEvents(boolean reportDtdEvents) { | |
403 this.reportDtdEvents = reportDtdEvents; | |
404 } | |
405 | |
406 /** | |
407 * This will set the state of a SAX feature. | |
408 * <p> | |
409 * All XMLReaders are required to support setting to true and to false. | |
410 * </p> | |
411 * <p> | |
412 * SAXOutputter currently supports the following SAX core features: | |
413 * <dl> | |
414 * <dt><code>http://xml.org/sax/features/namespaces</code></dt> | |
415 * <dd><strong>description:</strong> <code>true</code> indicates | |
416 * namespace URIs and unprefixed local names for element and | |
417 * attribute names will be available</dd> | |
418 * <dd><strong>access:</strong> read/write, but always | |
419 * <code>true</code>!</dd> | |
420 * <dt><code>http://xml.org/sax/features/namespace-prefixes</code></dt> | |
421 * <dd><strong>description:</strong> <code>true</code> indicates | |
422 * XML 1.0 names (with prefixes) and attributes (including xmlns* | |
423 * attributes) will be available</dd> | |
424 * <dd><strong>access:</strong> read/write</dd> | |
425 * <dt><code>http://xml.org/sax/features/validation</code></dt> | |
426 * <dd><strong>description:</strong> controls whether SAXOutputter | |
427 * is reporting DTD-related events; if <code>true</code>, the | |
428 * DocType internal subset will be parsed to fire DTD events</dd> | |
429 * <dd><strong>access:</strong> read/write, defaults to | |
430 * <code>true</code></dd> | |
431 * </dl> | |
432 * </p> | |
433 * | |
434 * @param name <code>String</code> the feature name, which is a | |
435 * fully-qualified URI. | |
436 * @param value <code>boolean</code> the requested state of the | |
437 * feature (true or false). | |
438 * | |
439 * @throws SAXNotRecognizedException when SAXOutputter does not | |
440 * recognize the feature name. | |
441 * @throws SAXNotSupportedException when SAXOutputter recognizes | |
442 * the feature name but cannot set the requested value. | |
443 */ | |
444 public void setFeature(String name, boolean value) | |
445 throws SAXNotRecognizedException, SAXNotSupportedException { | |
446 if (NS_PREFIXES_SAX_FEATURE.equals(name)) { | |
447 // Namespace prefix declarations. | |
448 this.setReportNamespaceDeclarations(value); | |
449 } | |
450 else { | |
451 if (NAMESPACES_SAX_FEATURE.equals(name)) { | |
452 if (value != true) { | |
453 // Namespaces feature always supported by SAXOutputter. | |
454 throw new SAXNotSupportedException(name); | |
455 } | |
456 // Else: true is OK! | |
457 } | |
458 else { | |
459 if (VALIDATION_SAX_FEATURE.equals(name)) { | |
460 // Report DTD events. | |
461 this.setReportDTDEvents(value); | |
462 } | |
463 else { | |
464 // Not a supported feature. | |
465 throw new SAXNotRecognizedException(name); | |
466 } | |
467 } | |
468 } | |
469 } | |
470 | |
471 /** | |
472 * This will look up the value of a SAX feature. | |
473 * | |
474 * @param name <code>String</code> the feature name, which is a | |
475 * fully-qualified URI. | |
476 * @return <code>boolean</code> the current state of the feature | |
477 * (true or false). | |
478 * | |
479 * @throws SAXNotRecognizedException when SAXOutputter does not | |
480 * recognize the feature name. | |
481 * @throws SAXNotSupportedException when SAXOutputter recognizes | |
482 * the feature name but determine its value at this time. | |
483 */ | |
484 public boolean getFeature(String name) | |
485 throws SAXNotRecognizedException, SAXNotSupportedException { | |
486 if (NS_PREFIXES_SAX_FEATURE.equals(name)) { | |
487 // Namespace prefix declarations. | |
488 return (this.declareNamespaces); | |
489 } | |
490 else { | |
491 if (NAMESPACES_SAX_FEATURE.equals(name)) { | |
492 // Namespaces feature always supported by SAXOutputter. | |
493 return (true); | |
494 } | |
495 else { | |
496 if (VALIDATION_SAX_FEATURE.equals(name)) { | |
497 // Report DTD events. | |
498 return (this.reportDtdEvents); | |
499 } | |
500 else { | |
501 // Not a supported feature. | |
502 throw new SAXNotRecognizedException(name); | |
503 } | |
504 } | |
505 } | |
506 } | |
507 | |
508 /** | |
509 * This will set the value of a SAX property. | |
510 * This method is also the standard mechanism for setting extended | |
511 * handlers. | |
512 * <p> | |
513 * SAXOutputter currently supports the following SAX properties: | |
514 * <dl> | |
515 * <dt><code>http://xml.org/sax/properties/lexical-handler</code></dt> | |
516 * <dd><strong>data type:</strong> | |
517 * <code>org.xml.sax.ext.LexicalHandler</code></dd> | |
518 * <dd><strong>description:</strong> An optional extension handler for | |
519 * lexical events like comments.</dd> | |
520 * <dd><strong>access:</strong> read/write</dd> | |
521 * <dt><code>http://xml.org/sax/properties/declaration-handler</code></dt> | |
522 * <dd><strong>data type:</strong> | |
523 * <code>org.xml.sax.ext.DeclHandler</code></dd> | |
524 * <dd><strong>description:</strong> An optional extension handler for | |
525 * DTD-related events other than notations and unparsed entities.</dd> | |
526 * <dd><strong>access:</strong> read/write</dd> | |
527 * </dl> | |
528 * </p> | |
529 * | |
530 * @param name <code>String</code> the property name, which is a | |
531 * fully-qualified URI. | |
532 * @param value <code>Object</code> the requested value for the property. | |
533 * | |
534 * @throws SAXNotRecognizedException when SAXOutputter does not recognize | |
535 * the property name. | |
536 * @throws SAXNotSupportedException when SAXOutputter recognizes the | |
537 * property name but cannot set the requested value. | |
538 */ | |
539 public void setProperty(String name, Object value) | |
540 throws SAXNotRecognizedException, SAXNotSupportedException { | |
541 if ((LEXICAL_HANDLER_SAX_PROPERTY.equals(name)) || | |
542 (LEXICAL_HANDLER_ALT_PROPERTY.equals(name))) { | |
543 this.setLexicalHandler((LexicalHandler)value); | |
544 } | |
545 else { | |
546 if ((DECL_HANDLER_SAX_PROPERTY.equals(name)) || | |
547 (DECL_HANDLER_ALT_PROPERTY.equals(name))) { | |
548 this.setDeclHandler((DeclHandler)value); | |
549 } | |
550 else { | |
551 throw new SAXNotRecognizedException(name); | |
552 } | |
553 } | |
554 } | |
555 | |
556 /** | |
557 * This will look up the value of a SAX property. | |
558 * | |
559 * @param name <code>String</code> the property name, which is a | |
560 * fully-qualified URI. | |
561 * @return <code>Object</code> the current value of the property. | |
562 * | |
563 * @throws SAXNotRecognizedException when SAXOutputter does not recognize | |
564 * the property name. | |
565 * @throws SAXNotSupportedException when SAXOutputter recognizes the | |
566 * property name but cannot determine its value at this time. | |
567 */ | |
568 public Object getProperty(String name) | |
569 throws SAXNotRecognizedException, SAXNotSupportedException { | |
570 if ((LEXICAL_HANDLER_SAX_PROPERTY.equals(name)) || | |
571 (LEXICAL_HANDLER_ALT_PROPERTY.equals(name))) { | |
572 return this.getLexicalHandler(); | |
573 } | |
574 else { | |
575 if ((DECL_HANDLER_SAX_PROPERTY.equals(name)) || | |
576 (DECL_HANDLER_ALT_PROPERTY.equals(name))) { | |
577 return this.getDeclHandler(); | |
578 } | |
579 else { | |
580 throw new SAXNotRecognizedException(name); | |
581 } | |
582 } | |
583 } | |
584 | |
585 | |
586 /** | |
587 * This will output the <code>JDOM Document</code>, firing off the | |
588 * SAX events that have been registered. | |
589 * | |
590 * @param document <code>JDOM Document</code> to output. | |
591 * | |
592 * @throws JDOMException if any error occurred. | |
593 */ | |
594 public void output(Document document) throws JDOMException { | |
595 if (document == null) { | |
596 return; | |
597 } | |
598 | |
599 // contentHandler.setDocumentLocator() | |
600 documentLocator(document); | |
601 | |
602 // contentHandler.startDocument() | |
603 startDocument(); | |
604 | |
605 // Fire DTD events | |
606 if (this.reportDtdEvents) { | |
607 dtdEvents(document); | |
608 } | |
609 | |
610 // Handle root element, as well as any root level | |
611 // processing instructions and comments | |
612 Iterator i = document.getContent().iterator(); | |
613 while (i.hasNext()) { | |
614 Object obj = i.next(); | |
615 | |
616 // update locator | |
617 locator.setNode(obj); | |
618 | |
619 if (obj instanceof Element) { | |
620 // process root element and its content | |
621 element(document.getRootElement(), new NamespaceStack()); | |
622 } | |
623 else if (obj instanceof ProcessingInstruction) { | |
624 // contentHandler.processingInstruction() | |
625 processingInstruction((ProcessingInstruction) obj); | |
626 } | |
627 else if (obj instanceof Comment) { | |
628 // lexicalHandler.comment() | |
629 comment(((Comment) obj).getText()); | |
630 } | |
631 } | |
632 | |
633 // contentHandler.endDocument() | |
634 endDocument(); | |
635 } | |
636 | |
637 /** | |
638 * This will output a list of JDOM nodes as a document, firing | |
639 * off the SAX events that have been registered. | |
640 * <p> | |
641 * <strong>Warning</strong>: This method may output ill-formed XML | |
642 * documents if the list contains top-level objects that are not | |
643 * legal at the document level (e.g. Text or CDATA nodes, multiple | |
644 * Element nodes, etc.). Thus, it should only be used to output | |
645 * document portions towards ContentHandlers capable of accepting | |
646 * such ill-formed documents (such as XSLT processors).</p> | |
647 * | |
648 * @param nodes <code>List</code> of JDOM nodes to output. | |
649 * | |
650 * @throws JDOMException if any error occurred. | |
651 * | |
652 * @see #output(org.jdom.Document) | |
653 */ | |
654 public void output(List nodes) throws JDOMException { | |
655 if ((nodes == null) || (nodes.size() == 0)) { | |
656 return; | |
657 } | |
658 | |
659 // contentHandler.setDocumentLocator() | |
660 documentLocator(null); | |
661 | |
662 // contentHandler.startDocument() | |
663 startDocument(); | |
664 | |
665 // Process node list. | |
666 elementContent(nodes, new NamespaceStack()); | |
667 | |
668 // contentHandler.endDocument() | |
669 endDocument(); | |
670 } | |
671 | |
672 /** | |
673 * This will output a single JDOM element as a document, firing | |
674 * off the SAX events that have been registered. | |
675 * | |
676 * @param node the <code>Element</code> node to output. | |
677 * | |
678 * @throws JDOMException if any error occurred. | |
679 */ | |
680 public void output(Element node) throws JDOMException { | |
681 if (node == null) { | |
682 return; | |
683 } | |
684 | |
685 // contentHandler.setDocumentLocator() | |
686 documentLocator(null); | |
687 | |
688 // contentHandler.startDocument() | |
689 startDocument(); | |
690 | |
691 // Output node. | |
692 elementContent(node, new NamespaceStack()); | |
693 | |
694 // contentHandler.endDocument() | |
695 endDocument(); | |
696 } | |
697 | |
698 /** | |
699 * This will output a list of JDOM nodes as a fragment of an XML | |
700 * document, firing off the SAX events that have been registered. | |
701 * <p> | |
702 * <strong>Warning</strong>: This method does not call the | |
703 * {@link ContentHandler#setDocumentLocator}, | |
704 * {@link ContentHandler#startDocument} and | |
705 * {@link ContentHandler#endDocument} callbacks on the | |
706 * {@link #setContentHandler ContentHandler}. The user shall | |
707 * invoke these methods directly prior/after outputting the | |
708 * document fragments.</p> | |
709 * | |
710 * @param nodes <code>List</code> of JDOM nodes to output. | |
711 * | |
712 * @throws JDOMException if any error occurred. | |
713 * | |
714 * @see #outputFragment(org.jdom.Content) | |
715 */ | |
716 public void outputFragment(List nodes) throws JDOMException { | |
717 if ((nodes == null) || (nodes.size() == 0)) { | |
718 return; | |
719 } | |
720 | |
721 // Output node list as a document fragment. | |
722 elementContent(nodes, new NamespaceStack()); | |
723 } | |
724 | |
725 /** | |
726 * This will output a single JDOM nodes as a fragment of an XML | |
727 * document, firing off the SAX events that have been registered. | |
728 * <p> | |
729 * <strong>Warning</strong>: This method does not call the | |
730 * {@link ContentHandler#setDocumentLocator}, | |
731 * {@link ContentHandler#startDocument} and | |
732 * {@link ContentHandler#endDocument} callbacks on the | |
733 * {@link #setContentHandler ContentHandler}. The user shall | |
734 * invoke these methods directly prior/after outputting the | |
735 * document fragments.</p> | |
736 * | |
737 * @param node the <code>Content</code> node to output. | |
738 * | |
739 * @throws JDOMException if any error occurred. | |
740 * | |
741 * @see #outputFragment(java.util.List) | |
742 */ | |
743 public void outputFragment(Content node) throws JDOMException { | |
744 if (node == null) { | |
745 return; | |
746 } | |
747 | |
748 // Output single node as a document fragment. | |
749 elementContent(node, new NamespaceStack()); | |
750 } | |
751 | |
752 /** | |
753 * This parses a DTD declaration to fire the related events towards | |
754 * the registered handlers. | |
755 * | |
756 * @param document <code>JDOM Document</code> the DocType is to | |
757 * process. | |
758 */ | |
759 private void dtdEvents(Document document) throws JDOMException { | |
760 DocType docType = document.getDocType(); | |
761 | |
762 // Fire DTD-related events only if handlers have been registered. | |
763 if ((docType != null) && | |
764 ((dtdHandler != null) || (declHandler != null))) { | |
765 | |
766 // Build a dummy XML document that only references the DTD... | |
767 String dtdDoc = new XMLOutputter().outputString(docType); | |
768 | |
769 try { | |
770 // And parse it to fire DTD events. | |
771 createDTDParser().parse(new InputSource( | |
772 new StringReader(dtdDoc))); | |
773 | |
774 // We should never reach this point as the document is | |
775 // ill-formed; it does not have any root element. | |
776 } | |
777 catch (SAXParseException e) { | |
778 // Expected exception: There's no root element in document. | |
779 } | |
780 catch (SAXException e) { | |
781 throw new JDOMException("DTD parsing error", e); | |
782 } | |
783 catch (IOException e) { | |
784 throw new JDOMException("DTD parsing error", e); | |
785 } | |
786 } | |
787 } | |
788 | |
789 /** | |
790 * <p> | |
791 * This method tells you the line of the XML file being parsed. | |
792 * For an in-memory document, it's meaningless. The location | |
793 * is only valid for the current parsing lifecycle, but | |
794 * the document has already been parsed. Therefore, it returns | |
795 * -1 for both line and column numbers. | |
796 * </p> | |
797 * | |
798 * @param document JDOM <code>Document</code>. | |
799 */ | |
800 private void documentLocator(Document document) { | |
801 locator = new JDOMLocator(); | |
802 String publicID = null; | |
803 String systemID = null; | |
804 | |
805 if (document != null) { | |
806 DocType docType = document.getDocType(); | |
807 if (docType != null) { | |
808 publicID = docType.getPublicID(); | |
809 systemID = docType.getSystemID(); | |
810 } | |
811 } | |
812 locator.setPublicId(publicID); | |
813 locator.setSystemId(systemID); | |
814 locator.setLineNumber(-1); | |
815 locator.setColumnNumber(-1); | |
816 | |
817 contentHandler.setDocumentLocator(locator); | |
818 } | |
819 | |
820 /** | |
821 * <p> | |
822 * This method is always the second method of all callbacks in | |
823 * all handlers to be invoked (setDocumentLocator is always first). | |
824 * </p> | |
825 */ | |
826 private void startDocument() throws JDOMException { | |
827 try { | |
828 contentHandler.startDocument(); | |
829 } | |
830 catch (SAXException se) { | |
831 throw new JDOMException("Exception in startDocument", se); | |
832 } | |
833 } | |
834 | |
835 /** | |
836 * <p> | |
837 * Always the last method of all callbacks in all handlers | |
838 * to be invoked. | |
839 * </p> | |
840 */ | |
841 private void endDocument() throws JDOMException { | |
842 try { | |
843 contentHandler.endDocument(); | |
844 | |
845 // reset locator | |
846 locator = null; | |
847 } | |
848 catch (SAXException se) { | |
849 throw new JDOMException("Exception in endDocument", se); | |
850 } | |
851 } | |
852 | |
853 /** | |
854 * <p> | |
855 * This will invoke the <code>ContentHandler.processingInstruction</code> | |
856 * callback when a processing instruction is encountered. | |
857 * </p> | |
858 * | |
859 * @param pi <code>ProcessingInstruction</code> containing target and data. | |
860 */ | |
861 private void processingInstruction(ProcessingInstruction pi) | |
862 throws JDOMException { | |
863 if (pi != null) { | |
864 String target = pi.getTarget(); | |
865 String data = pi.getData(); | |
866 try { | |
867 contentHandler.processingInstruction(target, data); | |
868 } | |
869 catch (SAXException se) { | |
870 throw new JDOMException( | |
871 "Exception in processingInstruction", se); | |
872 } | |
873 } | |
874 } | |
875 | |
876 /** | |
877 * <p> | |
878 * This will recursively invoke all of the callbacks for a particular | |
879 * element. | |
880 * </p> | |
881 * | |
882 * @param element <code>Element</code> used in callbacks. | |
883 * @param namespaces <code>List</code> stack of Namespaces in scope. | |
884 */ | |
885 private void element(Element element, NamespaceStack namespaces) | |
886 throws JDOMException { | |
887 // used to check endPrefixMapping | |
888 int previouslyDeclaredNamespaces = namespaces.size(); | |
889 | |
890 // contentHandler.startPrefixMapping() | |
891 Attributes nsAtts = startPrefixMapping(element, namespaces); | |
892 | |
893 // contentHandler.startElement() | |
894 startElement(element, nsAtts); | |
895 | |
896 // handle content in the element | |
897 elementContent(element.getContent(), namespaces); | |
898 | |
899 // update locator | |
900 if (locator != null) { | |
901 locator.setNode(element); | |
902 } | |
903 | |
904 // contentHandler.endElement() | |
905 endElement(element); | |
906 | |
907 // contentHandler.endPrefixMapping() | |
908 endPrefixMapping(namespaces, previouslyDeclaredNamespaces); | |
909 } | |
910 | |
911 /** | |
912 * <p> | |
913 * This will invoke the <code>ContentHandler.startPrefixMapping</code> | |
914 * callback | |
915 * when a new namespace is encountered in the <code>Document</code>. | |
916 * </p> | |
917 * | |
918 * @param element <code>Element</code> used in callbacks. | |
919 * @param namespaces <code>List</code> stack of Namespaces in scope. | |
920 * | |
921 * @return <code>Attributes</code> declaring the namespaces local to | |
922 * <code>element</code> or <code>null</code>. | |
923 */ | |
924 private Attributes startPrefixMapping(Element element, | |
925 NamespaceStack namespaces) | |
926 throws JDOMException { | |
927 AttributesImpl nsAtts = null; // The namespaces as xmlns attributes | |
928 | |
929 Namespace ns = element.getNamespace(); | |
930 if (ns != Namespace.XML_NAMESPACE) { | |
931 String prefix = ns.getPrefix(); | |
932 String uri = namespaces.getURI(prefix); | |
933 if (!ns.getURI().equals(uri)) { | |
934 namespaces.push(ns); | |
935 nsAtts = this.addNsAttribute(nsAtts, ns); | |
936 try { | |
937 contentHandler.startPrefixMapping(prefix, ns.getURI()); | |
938 } | |
939 catch (SAXException se) { | |
940 throw new JDOMException( | |
941 "Exception in startPrefixMapping", se); | |
942 } | |
943 } | |
944 } | |
945 | |
946 // Fire additional namespace declarations | |
947 List additionalNamespaces = element.getAdditionalNamespaces(); | |
948 if (additionalNamespaces != null) { | |
949 Iterator itr = additionalNamespaces.iterator(); | |
950 while (itr.hasNext()) { | |
951 ns = (Namespace)itr.next(); | |
952 String prefix = ns.getPrefix(); | |
953 String uri = namespaces.getURI(prefix); | |
954 if (!ns.getURI().equals(uri)) { | |
955 namespaces.push(ns); | |
956 nsAtts = this.addNsAttribute(nsAtts, ns); | |
957 try { | |
958 contentHandler.startPrefixMapping(prefix, ns.getURI()); | |
959 } | |
960 catch (SAXException se) { | |
961 throw new JDOMException( | |
962 "Exception in startPrefixMapping", se); | |
963 } | |
964 } | |
965 } | |
966 } | |
967 return nsAtts; | |
968 } | |
969 | |
970 /** | |
971 * <p> | |
972 * This will invoke the <code>endPrefixMapping</code> callback in the | |
973 * <code>ContentHandler</code> when a namespace is goes out of scope | |
974 * in the <code>Document</code>. | |
975 * </p> | |
976 * | |
977 * @param namespaces <code>List</code> stack of Namespaces in scope. | |
978 * @param previouslyDeclaredNamespaces number of previously declared | |
979 * namespaces | |
980 */ | |
981 private void endPrefixMapping(NamespaceStack namespaces, | |
982 int previouslyDeclaredNamespaces) | |
983 throws JDOMException { | |
984 while (namespaces.size() > previouslyDeclaredNamespaces) { | |
985 String prefix = namespaces.pop(); | |
986 try { | |
987 contentHandler.endPrefixMapping(prefix); | |
988 } | |
989 catch (SAXException se) { | |
990 throw new JDOMException("Exception in endPrefixMapping", se); | |
991 } | |
992 } | |
993 } | |
994 | |
995 /** | |
996 * <p> | |
997 * This will invoke the <code>startElement</code> callback | |
998 * in the <code>ContentHandler</code>. | |
999 * </p> | |
1000 * | |
1001 * @param element <code>Element</code> used in callbacks. | |
1002 * @param nsAtts <code>List</code> of namespaces to declare with | |
1003 * the element or <code>null</code>. | |
1004 */ | |
1005 private void startElement(Element element, Attributes nsAtts) | |
1006 throws JDOMException { | |
1007 String namespaceURI = element.getNamespaceURI(); | |
1008 String localName = element.getName(); | |
1009 String rawName = element.getQualifiedName(); | |
1010 | |
1011 // Allocate attribute list. | |
1012 AttributesImpl atts = (nsAtts != null)? | |
1013 new AttributesImpl(nsAtts): new AttributesImpl(); | |
1014 | |
1015 List attributes = element.getAttributes(); | |
1016 Iterator i = attributes.iterator(); | |
1017 while (i.hasNext()) { | |
1018 Attribute a = (Attribute) i.next(); | |
1019 atts.addAttribute(a.getNamespaceURI(), | |
1020 a.getName(), | |
1021 a.getQualifiedName(), | |
1022 getAttributeTypeName(a.getAttributeType()), | |
1023 a.getValue()); | |
1024 } | |
1025 | |
1026 try { | |
1027 contentHandler.startElement(namespaceURI, localName, rawName, atts); | |
1028 } | |
1029 catch (SAXException se) { | |
1030 throw new JDOMException("Exception in startElement", se); | |
1031 } | |
1032 } | |
1033 | |
1034 /** | |
1035 * <p> | |
1036 * This will invoke the <code>endElement</code> callback | |
1037 * in the <code>ContentHandler</code>. | |
1038 * </p> | |
1039 * | |
1040 * @param element <code>Element</code> used in callbacks. | |
1041 */ | |
1042 private void endElement(Element element) throws JDOMException { | |
1043 String namespaceURI = element.getNamespaceURI(); | |
1044 String localName = element.getName(); | |
1045 String rawName = element.getQualifiedName(); | |
1046 | |
1047 try { | |
1048 contentHandler.endElement(namespaceURI, localName, rawName); | |
1049 } | |
1050 catch (SAXException se) { | |
1051 throw new JDOMException("Exception in endElement", se); | |
1052 } | |
1053 } | |
1054 | |
1055 /** | |
1056 * <p> | |
1057 * This will invoke the callbacks for the content of an element. | |
1058 * </p> | |
1059 * | |
1060 * @param content element content as a <code>List</code> of nodes. | |
1061 * @param namespaces <code>List</code> stack of Namespaces in scope. | |
1062 */ | |
1063 private void elementContent(List content, NamespaceStack namespaces) | |
1064 throws JDOMException { | |
1065 for (Iterator i=content.iterator(); i.hasNext(); ) { | |
1066 Object obj = i.next(); | |
1067 | |
1068 if (obj instanceof Content) { | |
1069 this.elementContent((Content)obj, namespaces); | |
1070 } | |
1071 else { | |
1072 // Not a valid element child. This could happen with | |
1073 // application-provided lists which may contain non | |
1074 // JDOM objects. | |
1075 handleError(new JDOMException( | |
1076 "Invalid element content: " + obj)); | |
1077 } | |
1078 } | |
1079 } | |
1080 | |
1081 /** | |
1082 * <p> | |
1083 * This will invoke the callbacks for the content of an element. | |
1084 * </p> | |
1085 * | |
1086 * @param node a <code>Content</code> node. | |
1087 * @param namespaces <code>List</code> stack of Namespaces in scope. | |
1088 */ | |
1089 private void elementContent(Content node, NamespaceStack namespaces) | |
1090 throws JDOMException { | |
1091 // update locator | |
1092 if (locator != null) { | |
1093 locator.setNode(node); | |
1094 } | |
1095 | |
1096 if (node instanceof Element) { | |
1097 element((Element) node, namespaces); | |
1098 } | |
1099 else if (node instanceof CDATA) { | |
1100 cdata(((CDATA) node).getText()); | |
1101 } | |
1102 else if (node instanceof Text) { | |
1103 // contentHandler.characters() | |
1104 characters(((Text) node).getText()); | |
1105 } | |
1106 else if (node instanceof ProcessingInstruction) { | |
1107 // contentHandler.processingInstruction() | |
1108 processingInstruction((ProcessingInstruction) node); | |
1109 } | |
1110 else if (node instanceof Comment) { | |
1111 // lexicalHandler.comment() | |
1112 comment(((Comment) node).getText()); | |
1113 } | |
1114 else if (node instanceof EntityRef) { | |
1115 // contentHandler.skippedEntity() | |
1116 entityRef((EntityRef) node); | |
1117 } | |
1118 else { | |
1119 // Not a valid element child. This could happen with | |
1120 // application-provided lists which may contain non | |
1121 // JDOM objects. | |
1122 handleError(new JDOMException("Invalid element content: " + node)); | |
1123 } | |
1124 } | |
1125 | |
1126 /** | |
1127 * <p> | |
1128 * This will be called for each chunk of CDATA section encountered. | |
1129 * </p> | |
1130 * | |
1131 * @param cdataText all text in the CDATA section, including whitespace. | |
1132 */ | |
1133 private void cdata(String cdataText) throws JDOMException { | |
1134 try { | |
1135 if (lexicalHandler != null) { | |
1136 lexicalHandler.startCDATA(); | |
1137 characters(cdataText); | |
1138 lexicalHandler.endCDATA(); | |
1139 } | |
1140 else { | |
1141 characters(cdataText); | |
1142 } | |
1143 } | |
1144 catch (SAXException se) { | |
1145 throw new JDOMException("Exception in CDATA", se); | |
1146 } | |
1147 } | |
1148 | |
1149 /** | |
1150 * <p> | |
1151 * This will be called for each chunk of character data encountered. | |
1152 * </p> | |
1153 * | |
1154 * @param elementText all text in an element, including whitespace. | |
1155 */ | |
1156 private void characters(String elementText) throws JDOMException { | |
1157 char[] c = elementText.toCharArray(); | |
1158 try { | |
1159 contentHandler.characters(c, 0, c.length); | |
1160 } | |
1161 catch (SAXException se) { | |
1162 throw new JDOMException("Exception in characters", se); | |
1163 } | |
1164 } | |
1165 | |
1166 /** | |
1167 * <p> | |
1168 * This will be called for each chunk of comment data encontered. | |
1169 * </p> | |
1170 * | |
1171 * @param commentText all text in a comment, including whitespace. | |
1172 */ | |
1173 private void comment(String commentText) throws JDOMException { | |
1174 if (lexicalHandler != null) { | |
1175 char[] c = commentText.toCharArray(); | |
1176 try { | |
1177 lexicalHandler.comment(c, 0, c.length); | |
1178 } catch (SAXException se) { | |
1179 throw new JDOMException("Exception in comment", se); | |
1180 } | |
1181 } | |
1182 } | |
1183 | |
1184 /** | |
1185 * <p> | |
1186 * This will invoke the <code>ContentHandler.skippedEntity</code> | |
1187 * callback when an entity reference is encountered. | |
1188 * </p> | |
1189 * | |
1190 * @param entity <code>EntityRef</code>. | |
1191 */ | |
1192 private void entityRef(EntityRef entity) throws JDOMException { | |
1193 if (entity != null) { | |
1194 try { | |
1195 // No need to worry about appending a '%' character as | |
1196 // we do not support parameter entities | |
1197 contentHandler.skippedEntity(entity.getName()); | |
1198 } | |
1199 catch (SAXException se) { | |
1200 throw new JDOMException("Exception in entityRef", se); | |
1201 } | |
1202 } | |
1203 } | |
1204 | |
1205 | |
1206 /** | |
1207 * <p> | |
1208 * Appends a namespace declaration in the form of a xmlns attribute to | |
1209 * an attribute list, crerating this latter if needed. | |
1210 * </p> | |
1211 * | |
1212 * @param atts <code>AttributeImpl</code> where to add the attribute. | |
1213 * @param ns <code>Namespace</code> the namespace to declare. | |
1214 * | |
1215 * @return <code>AttributeImpl</code> the updated attribute list. | |
1216 */ | |
1217 private AttributesImpl addNsAttribute(AttributesImpl atts, Namespace ns) { | |
1218 if (this.declareNamespaces) { | |
1219 if (atts == null) { | |
1220 atts = new AttributesImpl(); | |
1221 } | |
1222 | |
1223 String prefix = ns.getPrefix(); | |
1224 if (prefix.equals("")) { | |
1225 atts.addAttribute("", // namespace | |
1226 "", // local name | |
1227 "xmlns", // qualified name | |
1228 "CDATA", // type | |
1229 ns.getURI()); // value | |
1230 } | |
1231 else { | |
1232 atts.addAttribute("", // namespace | |
1233 "", // local name | |
1234 "xmlns:" + ns.getPrefix(), // qualified name | |
1235 "CDATA", // type | |
1236 ns.getURI()); // value | |
1237 } | |
1238 } | |
1239 return atts; | |
1240 } | |
1241 | |
1242 /** | |
1243 * <p> | |
1244 * Returns the SAX 2.0 attribute type string from the type of | |
1245 * a JDOM Attribute. | |
1246 * </p> | |
1247 * | |
1248 * @param type <code>int</code> the type of the JDOM attribute. | |
1249 * | |
1250 * @return <code>String</code> the SAX 2.0 attribute type string. | |
1251 * | |
1252 * @see org.jdom.Attribute#getAttributeType | |
1253 * @see org.xml.sax.Attributes#getType | |
1254 */ | |
1255 private static String getAttributeTypeName(int type) { | |
1256 if ((type < 0) || (type >= attrTypeToNameMap.length)) { | |
1257 type = Attribute.UNDECLARED_TYPE; | |
1258 } | |
1259 return attrTypeToNameMap[type]; | |
1260 } | |
1261 | |
1262 /** | |
1263 * <p> | |
1264 * Notifies the registered {@link ErrorHandler SAX error handler} | |
1265 * (if any) of an input processing error. The error handler can | |
1266 * choose to absorb the error and let the processing continue. | |
1267 * </p> | |
1268 * | |
1269 * @param exception <code>JDOMException</code> containing the | |
1270 * error information; will be wrapped in a | |
1271 * {@link SAXParseException} when reported to | |
1272 * the SAX error handler. | |
1273 * | |
1274 * @throws JDOMException if no error handler has been registered | |
1275 * or if the error handler fired a | |
1276 * {@link SAXException}. | |
1277 */ | |
1278 private void handleError(JDOMException exception) throws JDOMException { | |
1279 if (errorHandler != null) { | |
1280 try { | |
1281 errorHandler.error(new SAXParseException( | |
1282 exception.getMessage(), null, exception)); | |
1283 } | |
1284 catch (SAXException se) { | |
1285 if (se.getException() instanceof JDOMException) { | |
1286 throw (JDOMException)(se.getException()); | |
1287 } | |
1288 else { | |
1289 throw new JDOMException(se.getMessage(), se); | |
1290 } | |
1291 } | |
1292 } | |
1293 else { | |
1294 throw exception; | |
1295 } | |
1296 } | |
1297 | |
1298 /** | |
1299 * <p> | |
1300 * Creates a SAX XMLReader. | |
1301 * </p> | |
1302 * | |
1303 * @return <code>XMLReader</code> a SAX2 parser. | |
1304 * | |
1305 * @throws Exception if no parser can be created. | |
1306 */ | |
1307 protected XMLReader createParser() throws Exception { | |
1308 XMLReader parser = null; | |
1309 | |
1310 // Try using JAXP... | |
1311 // Note we need JAXP 1.1, and if JAXP 1.0 is all that's | |
1312 // available then the getXMLReader call fails and we skip | |
1313 // to the hard coded default parser | |
1314 try { | |
1315 Class factoryClass = | |
1316 Class.forName("javax.xml.parsers.SAXParserFactory"); | |
1317 | |
1318 // factory = SAXParserFactory.newInstance(); | |
1319 Method newParserInstance = | |
1320 factoryClass.getMethod("newInstance", null); | |
1321 Object factory = newParserInstance.invoke(null, null); | |
1322 | |
1323 // jaxpParser = factory.newSAXParser(); | |
1324 Method newSAXParser = factoryClass.getMethod("newSAXParser", null); | |
1325 Object jaxpParser = newSAXParser.invoke(factory, null); | |
1326 | |
1327 // parser = jaxpParser.getXMLReader(); | |
1328 Class parserClass = jaxpParser.getClass(); | |
1329 Method getXMLReader = | |
1330 parserClass.getMethod("getXMLReader", null); | |
1331 parser = (XMLReader)getXMLReader.invoke(jaxpParser, null); | |
1332 } catch (ClassNotFoundException e) { | |
1333 //e.printStackTrace(); | |
1334 } catch (InvocationTargetException e) { | |
1335 //e.printStackTrace(); | |
1336 } catch (NoSuchMethodException e) { | |
1337 //e.printStackTrace(); | |
1338 } catch (IllegalAccessException e) { | |
1339 //e.printStackTrace(); | |
1340 } | |
1341 | |
1342 // Check to see if we got a parser yet, if not, try to use a | |
1343 // hard coded default | |
1344 if (parser == null) { | |
1345 parser = XMLReaderFactory.createXMLReader( | |
1346 "org.apache.xerces.parsers.SAXParser"); | |
1347 } | |
1348 return parser; | |
1349 } | |
1350 | |
1351 /** | |
1352 * <p> | |
1353 * This will create a SAX XMLReader capable of parsing a DTD and | |
1354 * configure it so that the DTD parsing events are routed to the | |
1355 * handlers registered onto this SAXOutputter. | |
1356 * </p> | |
1357 * | |
1358 * @return <code>XMLReader</code> a SAX2 parser. | |
1359 * | |
1360 * @throws JDOMException if no parser can be created. | |
1361 */ | |
1362 private XMLReader createDTDParser() throws JDOMException { | |
1363 XMLReader parser = null; | |
1364 | |
1365 // Get a parser instance | |
1366 try | |
1367 { | |
1368 parser = createParser(); | |
1369 } | |
1370 catch (Exception ex1) { | |
1371 throw new JDOMException("Error in SAX parser allocation", ex1); | |
1372 } | |
1373 | |
1374 // Register handlers | |
1375 if (this.getDTDHandler() != null) { | |
1376 parser.setDTDHandler(this.getDTDHandler()); | |
1377 } | |
1378 if (this.getEntityResolver() != null) { | |
1379 parser.setEntityResolver(this.getEntityResolver()); | |
1380 } | |
1381 if (this.getLexicalHandler() != null) { | |
1382 try { | |
1383 parser.setProperty(LEXICAL_HANDLER_SAX_PROPERTY, | |
1384 this.getLexicalHandler()); | |
1385 } | |
1386 catch (SAXException ex1) { | |
1387 try { | |
1388 parser.setProperty(LEXICAL_HANDLER_ALT_PROPERTY, | |
1389 this.getLexicalHandler()); | |
1390 } catch (SAXException ex2) { | |
1391 // Forget it! | |
1392 } | |
1393 } | |
1394 } | |
1395 if (this.getDeclHandler() != null) { | |
1396 try { | |
1397 parser.setProperty(DECL_HANDLER_SAX_PROPERTY, | |
1398 this.getDeclHandler()); | |
1399 } | |
1400 catch (SAXException ex1) { | |
1401 try { | |
1402 parser.setProperty(DECL_HANDLER_ALT_PROPERTY, | |
1403 this.getDeclHandler()); | |
1404 } catch (SAXException ex2) { | |
1405 // Forget it! | |
1406 } | |
1407 } | |
1408 } | |
1409 | |
1410 // Absorb errors as much as possible, per Laurent | |
1411 parser.setErrorHandler(new DefaultHandler()); | |
1412 | |
1413 return parser; | |
1414 } | |
1415 | |
1416 /** | |
1417 * Returns a JDOMLocator object referencing the node currently | |
1418 * being processed by this outputter. The returned object is a | |
1419 * snapshot of the location information and can thus safely be | |
1420 * memorized for later use. | |
1421 * <p> | |
1422 * This method allows direct access to the location information | |
1423 * maintained by SAXOutputter without requiring to implement | |
1424 * <code>XMLFilter</code>. (In SAX, locators are only available | |
1425 * though the <code>ContentHandler</code> interface).</p> | |
1426 * <p> | |
1427 * Note that location information is only available while | |
1428 * SAXOutputter is outputting nodes. Hence this method should | |
1429 * only be used by objects taking part in the output processing | |
1430 * such as <code>ErrorHandler</code>s. | |
1431 * | |
1432 * @return a JDOMLocator object referencing the node currently | |
1433 * being processed or <code>null</code> if no output | |
1434 * operation is being performed. | |
1435 */ | |
1436 public JDOMLocator getLocator() { | |
1437 return (locator != null)? new JDOMLocator(locator): null; | |
1438 } | |
1439 } |