1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 package org.dom4j.io.aelfred2;
50
51 import java.io.*;
52
53 import java.net.MalformedURLException;
54 import java.net.URL;
55 import java.util.Locale;
56 import java.util.Stack;
57
58
59
60 import java.util.ArrayList;
61 import java.util.Collections;
62 import java.util.Enumeration;
63 import java.util.Hashtable;
64 import java.util.Iterator;
65 import java.util.List;
66 import java.util.Vector;
67
68 import org.xml.sax.*;
69 import org.xml.sax.ext.*;
70 import org.xml.sax.helpers.NamespaceSupport;
71
72
73 /***
74 * An enhanced SAX2 version of Microstar's Ælfred XML parser.
75 * The enhancements primarily relate to significant improvements in
76 * conformance to the XML specification, and SAX2 support. Performance
77 * has been improved. See the package level documentation for more
78 * information.
79 *
80 * <table border="1" width='100%' cellpadding='3' cellspacing='0'>
81 * <tr bgcolor='#ccccff'>
82 * <th><font size='+1'>Name</font></th>
83 * <th><font size='+1'>Notes</font></th></tr>
84 *
85 * <tr><td colspan=2><center><em>Features ... URL prefix is
86 * <b>http://xml.org/sax/features/</b></em></center></td></tr>
87 *
88 * <tr><td>(URL)/external-general-entities</td>
89 * <td>Value defaults to <em>true</em></td></tr>
90 * <tr><td>(URL)/external-parameter-entities</td>
91 * <td>Value defaults to <em>true</em></td></tr>
92 * <tr><td>(URL)/is-standalone</td>
93 * <td>(PRELIMINARY) Returns true iff the document's parsing
94 * has started (some non-error event after <em>startDocument()</em>
95 * was reported) and the document's standalone flag is set.</td></tr>
96 * <tr><td>(URL)/namespace-prefixes</td>
97 * <td>Value defaults to <em>false</em> (but XML 1.0 names are
98 * always reported)</td></tr>
99 * <tr><td>(URL)/lexical-handler/parameter-entities</td>
100 * <td>Value is fixed at <em>true</em></td></tr>
101 * <tr><td>(URL)/namespaces</td>
102 * <td>Value defaults to <em>true</em></td></tr>
103 * <tr><td>(URL)/resolve-dtd-uris</td>
104 * <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
105 * <tr><td>(URL)/string-interning</td>
106 * <td>Value is fixed at <em>true</em></td></tr>
107 * <tr><td>(URL)/use-attributes2</td>
108 * <td>(PRELIMINARY) Value is fixed at <em>true</em></td></tr>
109 * <tr><td>(URL)/use-entity-resolver2</td>
110 * <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
111 * <tr><td>(URL)/validation</td>
112 * <td>Value is fixed at <em>false</em></td></tr>
113 *
114 * <tr><td colspan=2><center><em>Handler Properties ... URL prefix is
115 * <b>http://xml.org/sax/properties/</b></em></center></td></tr>
116 *
117 * <tr><td>(URL)/declaration-handler</td>
118 * <td>A declaration handler may be provided. </td></tr>
119 * <tr><td>(URL)/lexical-handler</td>
120 * <td>A lexical handler may be provided. </td></tr>
121 * </table>
122 *
123 * <p>This parser currently implements the SAX1 Parser API, but
124 * it may not continue to do so in the future.
125 *
126 * @author Written by David Megginson (version 1.2a from Microstar)
127 * @author Updated by David Brownell <dbrownell@users.sourceforge.net>
128 * @see org.xml.sax.Parser
129 */
130 final public class SAXDriver
131 implements Locator, Attributes2, XMLReader, Parser, AttributeList
132 {
133 private final DefaultHandler2 base = new DefaultHandler2 ();
134 private XmlParser parser;
135
136 private EntityResolver entityResolver = base;
137 private EntityResolver2 resolver2 = null;
138 private ContentHandler contentHandler = base;
139 private DTDHandler dtdHandler = base;
140 private ErrorHandler errorHandler = base;
141 private DeclHandler declHandler = base;
142 private LexicalHandler lexicalHandler = base;
143
144 private String elementName;
145 private Stack entityStack;
146
147
148 private List attributesList = Collections.synchronizedList(new ArrayList());
149
150 private boolean attributeSpecified [] = new boolean[10];
151 private boolean attributeDeclared [] = new boolean[10];
152
153 private boolean namespaces = true;
154 private boolean xmlNames = false;
155 private boolean extGE = true;
156 private boolean extPE = true;
157 private boolean resolveAll = true;
158 private boolean useResolver2 = true;
159 private boolean stringInterning = true;
160
161 private int attributeCount;
162 private boolean attributes;
163 private String nsTemp [];
164 private NamespaceSupport prefixStack;
165
166
167
168
169
170 /*** Constructs a SAX Parser. */
171 public SAXDriver ()
172 {
173 reset ();
174 }
175
176 private void reset ()
177 {
178 elementName = null;
179 entityStack = new Stack ();
180 attributesList = Collections.synchronizedList(new ArrayList());
181 attributeSpecified = new boolean[10];
182 attributeDeclared = new boolean[10];
183 attributeCount = 0;
184 attributes = false;
185 nsTemp = new String[3];
186 prefixStack = null;
187 }
188
189
190
191
192
193
194 /***
195 * <b>SAX1</b>: Sets the locale used for diagnostics; currently,
196 * only locales using the English language are supported.
197 * @param locale The locale for which diagnostics will be generated
198 */
199 public void setLocale (Locale locale)
200 throws SAXException
201 {
202 if ("en".equals (locale.getLanguage ()))
203 return ;
204
205 throw new SAXException ("AElfred2 only supports English locales.");
206 }
207
208
209 /***
210 * <b>SAX2</b>: Returns the object used when resolving external
211 * entities during parsing (both general and parameter entities).
212 */
213 public EntityResolver getEntityResolver ()
214 {
215 return (entityResolver == base) ? null : entityResolver;
216 }
217
218 /***
219 * <b>SAX1, SAX2</b>: Set the entity resolver for this parser.
220 * @param handler The object to receive entity events.
221 */
222 public void setEntityResolver (EntityResolver resolver)
223 {
224 if (resolver instanceof EntityResolver2)
225 resolver2 = (EntityResolver2) resolver;
226 else
227 resolver2 = null;
228 if (resolver == null)
229 resolver = base;
230 entityResolver = resolver;
231 }
232
233
234 /***
235 * <b>SAX2</b>: Returns the object used to process declarations related
236 * to notations and unparsed entities.
237 */
238 public DTDHandler getDTDHandler ()
239 {
240 return (dtdHandler == base) ? null : dtdHandler;
241 }
242
243 /***
244 * <b>SAX1, SAX2</b>: Set the DTD handler for this parser.
245 * @param handler The object to receive DTD events.
246 */
247 public void setDTDHandler (DTDHandler handler)
248 {
249 if (handler == null)
250 handler = base;
251 this.dtdHandler = handler;
252 }
253
254
255 /***
256 * <b>SAX1</b>: Set the document handler for this parser. If a
257 * content handler was set, this document handler will supplant it.
258 * The parser is set to report all XML 1.0 names rather than to
259 * filter out "xmlns" attributes (the "namespace-prefixes" feature
260 * is set to true).
261 *
262 * @deprecated SAX2 programs should use the XMLReader interface
263 * and a ContentHandler.
264 *
265 * @param handler The object to receive document events.
266 */
267 public void setDocumentHandler (DocumentHandler handler)
268 {
269 contentHandler = new Adapter (handler);
270 xmlNames = true;
271 }
272
273 /***
274 * <b>SAX2</b>: Returns the object used to report the logical
275 * content of an XML document.
276 */
277 public ContentHandler getContentHandler ()
278 {
279 return contentHandler == base ? null : contentHandler;
280 }
281
282 /***
283 * <b>SAX2</b>: Assigns the object used to report the logical
284 * content of an XML document. If a document handler was set,
285 * this content handler will supplant it (but XML 1.0 style name
286 * reporting may remain enabled).
287 */
288 public void setContentHandler (ContentHandler handler)
289 {
290 if (handler == null)
291 handler = base;
292 contentHandler = handler;
293 }
294
295 /***
296 * <b>SAX1, SAX2</b>: Set the error handler for this parser.
297 * @param handler The object to receive error events.
298 */
299 public void setErrorHandler (ErrorHandler handler)
300 {
301 if (handler == null)
302 handler = base;
303 this.errorHandler = handler;
304 }
305
306 /***
307 * <b>SAX2</b>: Returns the object used to receive callbacks for XML
308 * errors of all levels (fatal, nonfatal, warning); this is never null;
309 */
310 public ErrorHandler getErrorHandler ()
311 { return errorHandler == base ? null : errorHandler; }
312
313
314 /***
315 * <b>SAX1, SAX2</b>: Auxiliary API to parse an XML document, used mostly
316 * when no URI is available.
317 * If you want anything useful to happen, you should set
318 * at least one type of handler.
319 * @param source The XML input source. Don't set 'encoding' unless
320 * you know for a fact that it's correct.
321 * @see #setEntityResolver
322 * @see #setDTDHandler
323 * @see #setContentHandler
324 * @see #setErrorHandler
325 * @exception SAXException The handlers may throw any SAXException,
326 * and the parser normally throws SAXParseException objects.
327 * @exception IOException IOExceptions are normally through through
328 * the parser if there are problems reading the source document.
329 */
330 public void parse (InputSource source)
331 throws SAXException, IOException
332 {
333 synchronized (base) {
334 parser = new XmlParser ();
335 if (namespaces)
336 prefixStack = new NamespaceSupport ();
337 else if (!xmlNames)
338 throw new IllegalStateException ();
339 parser.setHandler (this);
340
341 try {
342
343 Reader r = source.getCharacterStream();
344 InputStream in = source.getByteStream();
345
346
347 parser.doParse (source.getSystemId (),
348 source.getPublicId (),
349 r,
350 in,
351 source.getEncoding ());
352 } catch (SAXException e) {
353 throw e;
354 } catch (IOException e) {
355 throw e;
356 } catch (RuntimeException e) {
357 throw e;
358 } catch (Exception e) {
359 throw new SAXParseException (e.getMessage (), this, e);
360 } finally {
361 contentHandler.endDocument ();
362 reset();
363 }
364 }
365 }
366
367
368 /***
369 * <b>SAX1, SAX2</b>: Preferred API to parse an XML document, using a
370 * system identifier (URI).
371 */
372 public void parse (String systemId)
373 throws SAXException, IOException
374 {
375 parse (new InputSource (systemId));
376 }
377
378
379
380
381 static final String FEATURE = "http://xml.org/sax/features/";
382 static final String PROPERTY = "http://xml.org/sax/properties/";
383
384 /***
385 * <b>SAX2</b>: Tells the value of the specified feature flag.
386 *
387 * @exception SAXNotRecognizedException thrown if the feature flag
388 * is neither built in, nor yet assigned.
389 */
390 public boolean getFeature (String featureId)
391 throws SAXNotRecognizedException, SAXNotSupportedException
392 {
393 if ((FEATURE + "validation").equals (featureId))
394 return false;
395
396
397 if ((FEATURE + "external-general-entities").equals (featureId))
398 return extGE;
399 if ((FEATURE + "external-parameter-entities") .equals (featureId))
400 return extPE;
401
402
403 if ((FEATURE + "namespace-prefixes").equals (featureId))
404 return xmlNames;
405
406
407 if ((FEATURE + "namespaces").equals (featureId))
408 return namespaces;
409
410
411 if ((FEATURE + "lexical-handler/parameter-entities").equals (featureId))
412 return true;
413
414
415 if ((FEATURE + "string-interning").equals (featureId))
416 return stringInterning;
417
418
419
420
421 if ((FEATURE + "use-attributes2").equals (featureId))
422 return true;
423
424
425 if ((FEATURE + "is-standalone").equals (featureId)) {
426 if (parser == null)
427 throw new SAXNotSupportedException (featureId);
428 return parser.isStandalone ();
429 }
430
431
432 if ((FEATURE + "resolve-dtd-uris").equals (featureId))
433 return resolveAll;
434
435
436 if ((FEATURE + "use-entity-resolver2").equals (featureId))
437 return useResolver2;
438
439 throw new SAXNotRecognizedException (featureId);
440 }
441
442
443 DeclHandler getDeclHandler () { return declHandler; }
444
445
446 boolean resolveURIs () { return resolveAll; }
447
448 /***
449 * <b>SAX2</b>: Returns the specified property.
450 *
451 * @exception SAXNotRecognizedException thrown if the property value
452 * is neither built in, nor yet stored.
453 */
454 public Object getProperty (String propertyId)
455 throws SAXNotRecognizedException
456 {
457 if ((PROPERTY + "declaration-handler").equals (propertyId))
458 return declHandler == base ? null : declHandler;
459
460 if ((PROPERTY + "lexical-handler").equals (propertyId))
461 return lexicalHandler == base ? null : lexicalHandler;
462
463
464 throw new SAXNotRecognizedException (propertyId);
465 }
466
467 /***
468 * <b>SAX2</b>: Sets the state of feature flags in this parser. Some
469 * built-in feature flags are mutable.
470 */
471 public void setFeature (String featureId, boolean value)
472 throws SAXNotRecognizedException, SAXNotSupportedException
473 {
474 boolean state;
475
476
477 state = getFeature (featureId);
478
479 if (state == value)
480 return;
481 if (parser != null)
482 throw new SAXNotSupportedException ("not while parsing");
483
484 if ((FEATURE + "namespace-prefixes").equals (featureId)) {
485
486 xmlNames = value;
487
488 if (!xmlNames)
489 namespaces = true;
490 return;
491 }
492
493 if ((FEATURE + "namespaces").equals (featureId)) {
494 namespaces = value;
495
496 if (!namespaces)
497 xmlNames = true;
498 return;
499 }
500
501 if ((FEATURE + "external-general-entities").equals (featureId)) {
502 extGE = value;
503 return;
504 }
505 if ((FEATURE + "external-parameter-entities") .equals (featureId)) {
506 extPE = value;
507 return;
508 }
509 if ((FEATURE + "resolve-dtd-uris").equals (featureId)) {
510 resolveAll = value;
511 return;
512 }
513
514 if ((FEATURE + "use-entity-resolver2").equals (featureId)) {
515 useResolver2 = value;
516 return;
517 }
518
519 throw new SAXNotRecognizedException (featureId);
520 }
521
522 /***
523 * <b>SAX2</b>: Assigns the specified property. Like SAX1 handlers,
524 * these may be changed at any time.
525 */
526 public void setProperty (String propertyId, Object value)
527 throws SAXNotRecognizedException, SAXNotSupportedException
528 {
529
530 getProperty (propertyId);
531
532
533
534 if ((PROPERTY + "declaration-handler").equals (propertyId)) {
535 if (value == null)
536 declHandler = base;
537 else if (! (value instanceof DeclHandler))
538 throw new SAXNotSupportedException (propertyId);
539 else
540 declHandler = (DeclHandler) value;
541 return ;
542 }
543
544 if ((PROPERTY + "lexical-handler").equals (propertyId)) {
545 if (value == null)
546 lexicalHandler = base;
547 else if (! (value instanceof LexicalHandler))
548 throw new SAXNotSupportedException (propertyId);
549 else
550 lexicalHandler = (LexicalHandler) value;
551 return ;
552 }
553
554 throw new SAXNotSupportedException (propertyId);
555 }
556
557
558
559
560
561
562
563
564 void startDocument ()
565 throws SAXException
566 {
567 contentHandler.setDocumentLocator (this);
568 contentHandler.startDocument ();
569 attributesList.clear ();
570 }
571
572 void skippedEntity (String name)
573 throws SAXException
574 { contentHandler.skippedEntity (name); }
575
576 InputSource getExternalSubset (String name, String baseURI)
577 throws SAXException, IOException
578 {
579 if (resolver2 == null || !useResolver2 || !extPE)
580 return null;
581 return resolver2.getExternalSubset (name, baseURI);
582 }
583
584 InputSource resolveEntity (boolean isPE, String name,
585 InputSource in, String baseURI)
586 throws SAXException, IOException
587 {
588 InputSource source;
589
590
591 if (isPE && !extPE)
592 return null;
593 if (!isPE && !extGE)
594 return null;
595
596
597 lexicalHandler.startEntity (name);
598 if (resolver2 != null && useResolver2) {
599 source = resolver2.resolveEntity (name, in.getPublicId (),
600 baseURI, in.getSystemId ());
601 if (source == null) {
602 in.setSystemId (absolutize (baseURI,
603 in.getSystemId (), false));
604 source = in;
605 }
606 } else {
607 in.setSystemId (absolutize (baseURI, in.getSystemId (), false));
608 source = entityResolver.resolveEntity (in.getPublicId (),
609 in.getSystemId ());
610 if (source == null)
611 source = in;
612 }
613 startExternalEntity (name, source.getSystemId (), true);
614 return source;
615 }
616
617
618
619 String absolutize (String baseURI, String systemId, boolean nice)
620 throws MalformedURLException, SAXException
621 {
622
623
624
625
626 try {
627 if (baseURI == null) {
628 warn ("No base URI; hope this SYSTEM id is absolute: "
629 + systemId);
630 return new URL (systemId).toString ();
631 } else
632 return new URL (new URL (baseURI), systemId).toString ();
633
634 } catch (MalformedURLException e) {
635
636
637
638 if (!nice)
639 throw e;
640
641
642
643 warn ("Can't absolutize SYSTEM id: " + e.getMessage ());
644 return systemId;
645 }
646 }
647
648 void startExternalEntity (String name, String systemId,
649 boolean stackOnly)
650 throws SAXException
651 {
652
653
654
655
656
657
658
659 if (!stackOnly)
660 lexicalHandler.startEntity (name);
661 entityStack.push (systemId);
662 }
663
664 void endExternalEntity (String name)
665 throws SAXException
666 {
667 if (!"[document]".equals (name))
668 lexicalHandler.endEntity (name);
669 entityStack.pop ();
670 }
671
672 void startInternalEntity (String name)
673 throws SAXException
674 {
675 lexicalHandler.startEntity (name);
676 }
677
678 void endInternalEntity (String name)
679 throws SAXException
680 {
681 lexicalHandler.endEntity (name);
682 }
683
684 void doctypeDecl (String name, String publicId, String systemId)
685 throws SAXException
686 {
687 lexicalHandler.startDTD (name, publicId, systemId);
688
689
690
691
692
693
694
695 }
696
697 void notationDecl (String name, String ids [])
698 throws SAXException
699 {
700 try {
701 dtdHandler.notationDecl (name, ids [0],
702 (resolveAll && ids [1] != null)
703 ? absolutize (ids [2], ids [1], true)
704 : ids [1]);
705 } catch (IOException e) {
706
707 throw new SAXParseException (e.getMessage (), this, e);
708 }
709 }
710
711 void unparsedEntityDecl (String name, String ids [], String notation)
712 throws SAXException
713 {
714 try {
715 dtdHandler.unparsedEntityDecl (name, ids [0],
716 resolveAll
717 ? absolutize (ids [2], ids [1], true)
718 : ids [1],
719 notation);
720 } catch (IOException e) {
721
722 throw new SAXParseException (e.getMessage (), this, e);
723 }
724 }
725
726 void endDoctype ()
727 throws SAXException
728 {
729 lexicalHandler.endDTD ();
730 }
731
732 private void declarePrefix (String prefix, String uri)
733 throws SAXException
734 {
735 int index = uri.indexOf (':');
736
737
738
739 if (index < 1 && uri.length () != 0)
740 warn ("relative URI for namespace: " + uri);
741
742
743
744
745
746
747 boolean prefixEquality = prefix.equals("xml");
748 boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace");
749 if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
750 fatal ("xml is by definition bound to the namespace name " +
751 "http://www.w3.org/XML/1998/namespace");
752
753
754 if (prefixEquality && uriEquality)
755 return;
756
757
758 prefixEquality = prefix.equals("xmlns");
759 uriEquality = uri.equals("http://www.w3.org/2000/xmlns/");
760 if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
761 fatal("http://www.w3.org/2000/xmlns/ is by definition bound" +
762 " to prefix xmlns");
763
764
765 if (prefixEquality && uriEquality)
766 fatal ("declaring the xmlns prefix is illegal");
767
768 uri = uri.intern ();
769 prefixStack.declarePrefix (prefix, uri);
770 contentHandler.startPrefixMapping (prefix, uri);
771 }
772
773 void attribute (String qname, String value, boolean isSpecified)
774 throws SAXException
775 {
776 if (!attributes) {
777 attributes = true;
778 if (namespaces)
779 prefixStack.pushContext ();
780 }
781
782
783
784 if (namespaces) {
785 int index;
786
787
788 if (getFeature (FEATURE + "string-interning")) {
789 if ("xmlns" == qname) {
790 declarePrefix ("", value);
791 if (!xmlNames)
792 return;
793 }
794
795 else if ((index = qname.indexOf (':')) == 5
796 && qname.startsWith ("xmlns")) {
797 String prefix = qname.substring (6);
798
799 if (prefix.equals(""))
800 fatal ("missing prefix in namespace declaration attribute");
801 if (value.length () == 0) {
802 verror ("missing URI in namespace declaration attribute: "
803 + qname);
804 } else
805 declarePrefix (prefix, value);
806 if (!xmlNames)
807 return;
808 }
809 } else {
810 if ("xmlns".equals(qname)) {
811 declarePrefix ("", value);
812 if (!xmlNames)
813 return;
814 }
815
816 else if ((index = qname.indexOf (':')) == 5
817 && qname.startsWith ("xmlns")) {
818 String prefix = qname.substring (6);
819
820 if (value.length () == 0) {
821 verror ("missing URI in namespace decl attribute: "
822 + qname);
823 } else
824 declarePrefix (prefix, value);
825 if (!xmlNames)
826 return;
827 }
828 }
829 }
830
831
832 if (attributeCount == attributeSpecified.length) {
833 boolean temp [] = new boolean [attributeSpecified.length + 5];
834 System.arraycopy (attributeSpecified, 0, temp, 0, attributeCount);
835 attributeSpecified = temp;
836 }
837 attributeSpecified [attributeCount] = isSpecified;
838
839 attributeCount++;
840
841
842 attributesList.add(new Attribute(qname, value));
843
844 }
845
846 void startElement (String elname)
847 throws SAXException
848 {
849 ContentHandler handler = contentHandler;
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864 if (!attributes) {
865 if (namespaces)
866 prefixStack.pushContext ();
867 } else if (namespaces) {
868
869
870
871 Iterator itt = attributesList.iterator ();
872 while(itt.hasNext())
873 {
874 Attribute attribute = (Attribute) itt.next();
875 String qname = attribute.name;
876 int index;
877
878
879 if (getFeature (FEATURE + "string-interning")) {
880 if ("xmlns" == qname)
881 continue;
882 } else {
883 if ("xmlns".equals(qname))
884 continue;
885 }
886
887
888 if (qname.equals (":"))
889 fatal ("namespace names consisting of a single colon " +
890 "character are invalid");
891 index = qname.indexOf (':');
892
893
894 if (index == 5 && qname.startsWith ("xmlns"))
895 continue;
896
897
898 if (prefixStack.processName (qname, nsTemp, true) == null)
899 fatal ("undeclared attribute prefix in: " + qname);
900 else {
901 attribute.nameSpace = nsTemp[0];
902 attribute.localName = nsTemp[1];
903 }
904 }
905 }
906
907
908 elementName = elname;
909 if (namespaces) {
910 if (prefixStack.processName (elname, nsTemp, false) == null) {
911 fatal ("undeclared element prefix in: " + elname);
912 nsTemp [0] = nsTemp [1] = "";
913 }
914 handler.startElement (nsTemp [0], nsTemp [1], elname, this);
915 } else
916 handler.startElement ("", "", elname, this);
917
918
919
920 if (attributes) {
921 attributesList.clear();
922 attributeCount = 0;
923 attributes = false;
924 }
925 }
926
927 void endElement (String elname)
928 throws SAXException
929 {
930 ContentHandler handler = contentHandler;
931
932 if (!namespaces) {
933 handler.endElement ("", "", elname);
934 return;
935 }
936 prefixStack.processName (elname, nsTemp, false);
937 handler.endElement (nsTemp [0], nsTemp [1], elname);
938
939 Enumeration prefixes = prefixStack.getDeclaredPrefixes ();
940
941 while (prefixes.hasMoreElements ())
942 handler.endPrefixMapping ((String) prefixes.nextElement ());
943 prefixStack.popContext ();
944 }
945
946 void startCDATA ()
947 throws SAXException
948 {
949 lexicalHandler.startCDATA ();
950 }
951
952 void charData (char ch[], int start, int length)
953 throws SAXException
954 {
955 contentHandler.characters (ch, start, length);
956 }
957
958 void endCDATA ()
959 throws SAXException
960 {
961 lexicalHandler.endCDATA ();
962 }
963
964 void ignorableWhitespace (char ch[], int start, int length)
965 throws SAXException
966 {
967 contentHandler.ignorableWhitespace (ch, start, length);
968 }
969
970 void processingInstruction (String target, String data)
971 throws SAXException
972 {
973 contentHandler.processingInstruction (target, data);
974 }
975
976 void comment (char ch[], int start, int length)
977 throws SAXException
978 {
979 if (lexicalHandler != base)
980 lexicalHandler.comment (ch, start, length);
981 }
982
983 void fatal (String message)
984 throws SAXException
985 {
986 SAXParseException fatal;
987
988 fatal = new SAXParseException (message, this);
989 errorHandler.fatalError (fatal);
990
991
992 throw fatal;
993 }
994
995
996
997 void verror (String message)
998 throws SAXException
999 {
1000 SAXParseException err;
1001
1002 err = new SAXParseException (message, this);
1003 errorHandler.error (err);
1004 }
1005
1006 void warn (String message)
1007 throws SAXException
1008 {
1009 SAXParseException err;
1010
1011 err = new SAXParseException (message, this);
1012 errorHandler.warning (err);
1013 }
1014
1015
1016
1017
1018
1019
1020 /***
1021 * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1022 * (don't invoke on parser);
1023 */
1024 public int getLength ()
1025 {
1026 return attributesList.size ();
1027 }
1028
1029 /***
1030 * <b>SAX2 Attributes</b> method (don't invoke on parser);
1031 */
1032 public String getURI (int index)
1033 {
1034 return ((Attribute) attributesList.get (index)).nameSpace;
1035 }
1036
1037 /***
1038 * <b>SAX2 Attributes</b> method (don't invoke on parser);
1039 */
1040 public String getLocalName (int index)
1041 {
1042 return ((Attribute) attributesList.get (index)).localName;
1043 }
1044
1045 /***
1046 * <b>SAX2 Attributes</b> method (don't invoke on parser);
1047 */
1048 public String getQName (int i)
1049 {
1050 return ((Attribute) attributesList.get (i)).name;
1051 }
1052
1053 /***
1054 * <b>SAX1 AttributeList</b> method (don't invoke on parser);
1055 */
1056 public String getName (int i)
1057 {
1058 return ((Attribute) attributesList.get (i)).name;
1059 }
1060
1061 /***
1062 * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1063 * (don't invoke on parser);
1064 */
1065 public String getType (int i)
1066 {
1067 String type = parser.getAttributeType (elementName, getQName (i));
1068 if (type == null)
1069 return "CDATA";
1070
1071 if (type == "ENUMERATION")
1072 return "NMTOKEN";
1073 return type;
1074 }
1075
1076
1077 /***
1078 * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1079 * (don't invoke on parser);
1080 */
1081 public String getValue (int i)
1082 {
1083 return ((Attribute) attributesList.get (i)).value;
1084 }
1085
1086
1087 /***
1088 * <b>SAX2 Attributes</b> method (don't invoke on parser);
1089 */
1090 public int getIndex (String uri, String local)
1091 {
1092 int length = getLength ();
1093
1094 for (int i = 0; i < length; i++) {
1095 if (!getURI (i).equals (uri))
1096 continue;
1097 if (getLocalName (i).equals (local))
1098 return i;
1099 }
1100 return -1;
1101 }
1102
1103
1104 /***
1105 * <b>SAX2 Attributes</b> method (don't invoke on parser);
1106 */
1107 public int getIndex (String xmlName)
1108 {
1109 int length = getLength ();
1110
1111 for (int i = 0; i < length; i++) {
1112 if (getQName (i).equals (xmlName))
1113 return i;
1114 }
1115 return -1;
1116 }
1117
1118
1119 /***
1120 * <b>SAX2 Attributes</b> method (don't invoke on parser);
1121 */
1122 public String getType (String uri, String local)
1123 {
1124 int index = getIndex (uri, local);
1125
1126 if (index < 0)
1127 return null;
1128 return getType (index);
1129 }
1130
1131
1132 /***
1133 * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1134 * (don't invoke on parser);
1135 */
1136 public String getType (String xmlName)
1137 {
1138 int index = getIndex (xmlName);
1139
1140 if (index < 0)
1141 return null;
1142 return getType (index);
1143 }
1144
1145
1146 /***
1147 * <b>SAX Attributes</b> method (don't invoke on parser);
1148 */
1149 public String getValue (String uri, String local)
1150 {
1151 int index = getIndex (uri, local);
1152
1153 if (index < 0)
1154 return null;
1155 return getValue (index);
1156 }
1157
1158
1159 /***
1160 * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1161 * (don't invoke on parser);
1162 */
1163 public String getValue (String xmlName)
1164 {
1165 int index = getIndex (xmlName);
1166
1167 if (index < 0)
1168 return null;
1169 return getValue (index);
1170 }
1171
1172
1173
1174
1175
1176
1177
1178 /*** @return false unless the attribute was declared in the DTD.
1179 * @throws java.lang.ArrayIndexOutOfBoundsException
1180 * When the supplied index does not identify an attribute.
1181 */
1182 public boolean isDeclared (int index)
1183 {
1184 if (index < 0 || index >= attributeCount)
1185 throw new ArrayIndexOutOfBoundsException ();
1186 return attributeDeclared [index];
1187 }
1188
1189 /*** @return false unless the attribute was declared in the DTD.
1190 * @throws java.lang.IllegalArgumentException
1191 * When the supplied names do not identify an attribute.
1192 */
1193 public boolean isDeclared (java.lang.String qName)
1194 {
1195 int index = getIndex (qName);
1196 if (index < 0)
1197 throw new IllegalArgumentException ();
1198 return attributeDeclared [index];
1199 }
1200
1201 /*** @return false unless the attribute was declared in the DTD.
1202 * @throws java.lang.IllegalArgumentException
1203 * When the supplied names do not identify an attribute.
1204 */
1205 public boolean isDeclared (java.lang.String uri, java.lang.String localName)
1206 {
1207 int index = getIndex (uri, localName);
1208 if (index < 0)
1209 throw new IllegalArgumentException ();
1210 return attributeDeclared [index];
1211 }
1212
1213
1214 /***
1215 * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
1216 */
1217 public boolean isSpecified (int index)
1218 {
1219 if (index < 0 || index >= attributeCount)
1220 throw new ArrayIndexOutOfBoundsException ();
1221 return attributeSpecified [index];
1222 }
1223
1224 /***
1225 * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
1226 */
1227 public boolean isSpecified (String uri, String local)
1228 {
1229 int index = getIndex (uri, local);
1230
1231 if (index < 0)
1232 throw new IllegalArgumentException ();
1233 return attributeSpecified [index];
1234 }
1235
1236 /***
1237 * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
1238 */
1239 public boolean isSpecified (String xmlName)
1240 {
1241 int index = getIndex (xmlName);
1242
1243 if (index < 0)
1244 throw new IllegalArgumentException ();
1245 return attributeSpecified [index];
1246 }
1247
1248
1249
1250
1251
1252
1253 /***
1254 * <b>SAX Locator</b> method (don't invoke on parser);
1255 */
1256 public String getPublicId ()
1257 {
1258 return null;
1259 }
1260
1261 /***
1262 * <b>SAX Locator</b> method (don't invoke on parser);
1263 */
1264 public String getSystemId ()
1265 {
1266 if (entityStack.empty ())
1267 return null;
1268 else
1269 return (String) entityStack.peek ();
1270 }
1271
1272 /***
1273 * <b>SAX Locator</b> method (don't invoke on parser);
1274 */
1275 public int getLineNumber ()
1276 {
1277 return parser.getLineNumber ();
1278 }
1279
1280 /***
1281 * <b>SAX Locator</b> method (don't invoke on parser);
1282 */
1283 public int getColumnNumber ()
1284 {
1285 return parser.getColumnNumber ();
1286 }
1287
1288
1289 private static class Adapter implements ContentHandler
1290 {
1291 private DocumentHandler docHandler;
1292
1293 Adapter (DocumentHandler dh)
1294 { docHandler = dh; }
1295
1296
1297 public void setDocumentLocator (Locator l)
1298 { docHandler.setDocumentLocator (l); }
1299
1300 public void startDocument () throws SAXException
1301 { docHandler.startDocument (); }
1302
1303 public void processingInstruction (String target, String data)
1304 throws SAXException
1305 { docHandler.processingInstruction (target, data); }
1306
1307 public void startPrefixMapping (String prefix, String uri)
1308 {
1309
1310 public void startElement (
1311 String namespace,
1312 String local,
1313 String name,
1314 Attributes attrs
1315 ) throws SAXException
1316 { docHandler.startElement (name, (AttributeList) attrs); }
1317
1318 public void characters (char buf [], int offset, int len)
1319 throws SAXException
1320 { docHandler.characters (buf, offset, len); }
1321
1322 public void ignorableWhitespace (char buf [], int offset, int len)
1323 throws SAXException
1324 { docHandler.ignorableWhitespace (buf, offset, len); }
1325
1326 public void skippedEntity (String name)
1327 {
1328
1329 public void endElement (String u, String l, String name)
1330 throws SAXException
1331 { docHandler.endElement (name); }
1332
1333 public void endPrefixMapping (String prefix)
1334 {
1335
1336 public void endDocument () throws SAXException
1337 { docHandler.endDocument (); }
1338 }
1339 }
1340
1341 class Attribute
1342 {
1343
1344 String name;
1345 String value;
1346 String nameSpace;
1347 String localName;
1348
1349 Attribute(String name, String value)
1350 {
1351 this.name = name;
1352 this.value = value;
1353 }
1354 }