001 // ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader.
002 // http://www.saxproject.org
003 // Written by David Megginson
004 // NO WARRANTY! This class is in the public domain.
005 // $Id: ParserAdapter.java,v 1.1 2004/12/23 22:38:42 mark Exp $
006
007 package org.xml.sax.helpers;
008
009 import java.io.IOException;
010 import java.util.Enumeration;
011 import java.util.Vector;
012
013 import org.xml.sax.Parser; // deprecated
014 import org.xml.sax.InputSource;
015 import org.xml.sax.Locator;
016 import org.xml.sax.AttributeList; // deprecated
017 import org.xml.sax.EntityResolver;
018 import org.xml.sax.DTDHandler;
019 import org.xml.sax.DocumentHandler; // deprecated
020 import org.xml.sax.ErrorHandler;
021 import org.xml.sax.SAXException;
022 import org.xml.sax.SAXParseException;
023
024 import org.xml.sax.XMLReader;
025 import org.xml.sax.Attributes;
026 import org.xml.sax.ContentHandler;
027 import org.xml.sax.SAXNotRecognizedException;
028 import org.xml.sax.SAXNotSupportedException;
029
030
031 /**
032 * Adapt a SAX1 Parser as a SAX2 XMLReader.
033 *
034 * <blockquote>
035 * <em>This module, both source code and documentation, is in the
036 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
037 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
038 * for further information.
039 * </blockquote>
040 *
041 * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser}
042 * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader},
043 * with feature, property, and Namespace support. Note
044 * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity
045 * skippedEntity} events, since SAX1 does not make that information available.</p>
046 *
047 * <p>This adapter does not test for duplicate Namespace-qualified
048 * attribute names.</p>
049 *
050 * @since SAX 2.0
051 * @author David Megginson
052 * @version 2.0.1 (sax2r2)
053 * @see org.xml.sax.helpers.XMLReaderAdapter
054 * @see org.xml.sax.XMLReader
055 * @see org.xml.sax.Parser
056 */
057 public class ParserAdapter implements XMLReader, DocumentHandler
058 {
059
060
061 ////////////////////////////////////////////////////////////////////
062 // Constructors.
063 ////////////////////////////////////////////////////////////////////
064
065
066 /**
067 * Construct a new parser adapter.
068 *
069 * <p>Use the "org.xml.sax.parser" property to locate the
070 * embedded SAX1 driver.</p>
071 *
072 * @exception SAXException If the embedded driver
073 * cannot be instantiated or if the
074 * org.xml.sax.parser property is not specified.
075 */
076 public ParserAdapter ()
077 throws SAXException
078 {
079 super();
080
081 String driver = System.getProperty("org.xml.sax.parser");
082
083 try {
084 setup(ParserFactory.makeParser());
085 } catch (ClassNotFoundException e1) {
086 throw new
087 SAXException("Cannot find SAX1 driver class " +
088 driver, e1);
089 } catch (IllegalAccessException e2) {
090 throw new
091 SAXException("SAX1 driver class " +
092 driver +
093 " found but cannot be loaded", e2);
094 } catch (InstantiationException e3) {
095 throw new
096 SAXException("SAX1 driver class " +
097 driver +
098 " loaded but cannot be instantiated", e3);
099 } catch (ClassCastException e4) {
100 throw new
101 SAXException("SAX1 driver class " +
102 driver +
103 " does not implement org.xml.sax.Parser");
104 } catch (NullPointerException e5) {
105 throw new
106 SAXException("System property org.xml.sax.parser not specified");
107 }
108 }
109
110
111 /**
112 * Construct a new parser adapter.
113 *
114 * <p>Note that the embedded parser cannot be changed once the
115 * adapter is created; to embed a different parser, allocate
116 * a new ParserAdapter.</p>
117 *
118 * @param parser The SAX1 parser to embed.
119 * @exception java.lang.NullPointerException If the parser parameter
120 * is null.
121 */
122 public ParserAdapter (Parser parser)
123 {
124 super();
125 setup(parser);
126 }
127
128
129 /**
130 * Internal setup method.
131 *
132 * @param parser The embedded parser.
133 * @exception java.lang.NullPointerException If the parser parameter
134 * is null.
135 */
136 private void setup (Parser parser)
137 {
138 if (parser == null) {
139 throw new
140 NullPointerException("Parser argument must not be null");
141 }
142 this.parser = parser;
143 atts = new AttributesImpl();
144 nsSupport = new NamespaceSupport();
145 attAdapter = new AttributeListAdapter();
146 }
147
148
149
150 ////////////////////////////////////////////////////////////////////
151 // Implementation of org.xml.sax.XMLReader.
152 ////////////////////////////////////////////////////////////////////
153
154
155 //
156 // Internal constants for the sake of convenience.
157 //
158 private final static String FEATURES = "http://xml.org/sax/features/";
159 private final static String NAMESPACES = FEATURES + "namespaces";
160 private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes";
161 private final static String XMLNS_URIs = FEATURES + "xmlns-uris";
162
163
164 /**
165 * Set a feature flag for the parser.
166 *
167 * <p>The only features recognized are namespaces and
168 * namespace-prefixes.</p>
169 *
170 * @param name The feature name, as a complete URI.
171 * @param value The requested feature value.
172 * @exception SAXNotRecognizedException If the feature
173 * can't be assigned or retrieved.
174 * @exception SAXNotSupportedException If the feature
175 * can't be assigned that value.
176 * @see org.xml.sax.XMLReader#setFeature
177 */
178 public void setFeature (String name, boolean value)
179 throws SAXNotRecognizedException, SAXNotSupportedException
180 {
181 if (name.equals(NAMESPACES)) {
182 checkNotParsing("feature", name);
183 namespaces = value;
184 if (!namespaces && !prefixes) {
185 prefixes = true;
186 }
187 } else if (name.equals(NAMESPACE_PREFIXES)) {
188 checkNotParsing("feature", name);
189 prefixes = value;
190 if (!prefixes && !namespaces) {
191 namespaces = true;
192 }
193 } else if (name.equals(XMLNS_URIs)) {
194 checkNotParsing("feature", name);
195 uris = value;
196 } else {
197 throw new SAXNotRecognizedException("Feature: " + name);
198 }
199 }
200
201
202 /**
203 * Check a parser feature flag.
204 *
205 * <p>The only features recognized are namespaces and
206 * namespace-prefixes.</p>
207 *
208 * @param name The feature name, as a complete URI.
209 * @return The current feature value.
210 * @exception SAXNotRecognizedException If the feature
211 * value can't be assigned or retrieved.
212 * @exception SAXNotSupportedException If the
213 * feature is not currently readable.
214 * @see org.xml.sax.XMLReader#setFeature
215 */
216 public boolean getFeature (String name)
217 throws SAXNotRecognizedException, SAXNotSupportedException
218 {
219 if (name.equals(NAMESPACES)) {
220 return namespaces;
221 } else if (name.equals(NAMESPACE_PREFIXES)) {
222 return prefixes;
223 } else if (name.equals(XMLNS_URIs)) {
224 return uris;
225 } else {
226 throw new SAXNotRecognizedException("Feature: " + name);
227 }
228 }
229
230
231 /**
232 * Set a parser property.
233 *
234 * <p>No properties are currently recognized.</p>
235 *
236 * @param name The property name.
237 * @param value The property value.
238 * @exception SAXNotRecognizedException If the property
239 * value can't be assigned or retrieved.
240 * @exception SAXNotSupportedException If the property
241 * can't be assigned that value.
242 * @see org.xml.sax.XMLReader#setProperty
243 */
244 public void setProperty (String name, Object value)
245 throws SAXNotRecognizedException, SAXNotSupportedException
246 {
247 throw new SAXNotRecognizedException("Property: " + name);
248 }
249
250
251 /**
252 * Get a parser property.
253 *
254 * <p>No properties are currently recognized.</p>
255 *
256 * @param name The property name.
257 * @return The property value.
258 * @exception SAXNotRecognizedException If the property
259 * value can't be assigned or retrieved.
260 * @exception SAXNotSupportedException If the property
261 * value is not currently readable.
262 * @see org.xml.sax.XMLReader#getProperty
263 */
264 public Object getProperty (String name)
265 throws SAXNotRecognizedException, SAXNotSupportedException
266 {
267 throw new SAXNotRecognizedException("Property: " + name);
268 }
269
270
271 /**
272 * Set the entity resolver.
273 *
274 * @param resolver The new entity resolver.
275 * @see org.xml.sax.XMLReader#setEntityResolver
276 */
277 public void setEntityResolver (EntityResolver resolver)
278 {
279 entityResolver = resolver;
280 }
281
282
283 /**
284 * Return the current entity resolver.
285 *
286 * @return The current entity resolver, or null if none was supplied.
287 * @see org.xml.sax.XMLReader#getEntityResolver
288 */
289 public EntityResolver getEntityResolver ()
290 {
291 return entityResolver;
292 }
293
294
295 /**
296 * Set the DTD handler.
297 *
298 * @param handler the new DTD handler
299 * @see org.xml.sax.XMLReader#setEntityResolver
300 */
301 public void setDTDHandler (DTDHandler handler)
302 {
303 dtdHandler = handler;
304 }
305
306
307 /**
308 * Return the current DTD handler.
309 *
310 * @return the current DTD handler, or null if none was supplied
311 * @see org.xml.sax.XMLReader#getEntityResolver
312 */
313 public DTDHandler getDTDHandler ()
314 {
315 return dtdHandler;
316 }
317
318
319 /**
320 * Set the content handler.
321 *
322 * @param handler the new content handler
323 * @see org.xml.sax.XMLReader#setEntityResolver
324 */
325 public void setContentHandler (ContentHandler handler)
326 {
327 contentHandler = handler;
328 }
329
330
331 /**
332 * Return the current content handler.
333 *
334 * @return The current content handler, or null if none was supplied.
335 * @see org.xml.sax.XMLReader#getEntityResolver
336 */
337 public ContentHandler getContentHandler ()
338 {
339 return contentHandler;
340 }
341
342
343 /**
344 * Set the error handler.
345 *
346 * @param handler The new error handler.
347 * @see org.xml.sax.XMLReader#setEntityResolver
348 */
349 public void setErrorHandler (ErrorHandler handler)
350 {
351 errorHandler = handler;
352 }
353
354
355 /**
356 * Return the current error handler.
357 *
358 * @return The current error handler, or null if none was supplied.
359 * @see org.xml.sax.XMLReader#getEntityResolver
360 */
361 public ErrorHandler getErrorHandler ()
362 {
363 return errorHandler;
364 }
365
366
367 /**
368 * Parse an XML document.
369 *
370 * @param systemId The absolute URL of the document.
371 * @exception java.io.IOException If there is a problem reading
372 * the raw content of the document.
373 * @exception SAXException If there is a problem
374 * processing the document.
375 * @see #parse(org.xml.sax.InputSource)
376 * @see org.xml.sax.Parser#parse(java.lang.String)
377 */
378 public void parse (String systemId)
379 throws IOException, SAXException
380 {
381 parse(new InputSource(systemId));
382 }
383
384
385 /**
386 * Parse an XML document.
387 *
388 * @param input An input source for the document.
389 * @exception java.io.IOException If there is a problem reading
390 * the raw content of the document.
391 * @exception SAXException If there is a problem
392 * processing the document.
393 * @see #parse(java.lang.String)
394 * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
395 */
396 public void parse (InputSource input)
397 throws IOException, SAXException
398 {
399 if (parsing) {
400 throw new SAXException("Parser is already in use");
401 }
402 setupParser();
403 parsing = true;
404 try {
405 parser.parse(input);
406 } finally {
407 parsing = false;
408 }
409 parsing = false;
410 }
411
412
413
414 ////////////////////////////////////////////////////////////////////
415 // Implementation of org.xml.sax.DocumentHandler.
416 ////////////////////////////////////////////////////////////////////
417
418
419 /**
420 * Adapter implementation method; do not call.
421 * Adapt a SAX1 document locator event.
422 *
423 * @param locator A document locator.
424 * @see org.xml.sax.ContentHandler#setDocumentLocator
425 */
426 public void setDocumentLocator (Locator locator)
427 {
428 this.locator = locator;
429 if (contentHandler != null) {
430 contentHandler.setDocumentLocator(locator);
431 }
432 }
433
434
435 /**
436 * Adapter implementation method; do not call.
437 * Adapt a SAX1 start document event.
438 *
439 * @exception SAXException The client may raise a
440 * processing exception.
441 * @see org.xml.sax.DocumentHandler#startDocument
442 */
443 public void startDocument ()
444 throws SAXException
445 {
446 if (contentHandler != null) {
447 contentHandler.startDocument();
448 }
449 }
450
451
452 /**
453 * Adapter implementation method; do not call.
454 * Adapt a SAX1 end document event.
455 *
456 * @exception SAXException The client may raise a
457 * processing exception.
458 * @see org.xml.sax.DocumentHandler#endDocument
459 */
460 public void endDocument ()
461 throws SAXException
462 {
463 if (contentHandler != null) {
464 contentHandler.endDocument();
465 }
466 }
467
468
469 /**
470 * Adapter implementation method; do not call.
471 * Adapt a SAX1 startElement event.
472 *
473 * <p>If necessary, perform Namespace processing.</p>
474 *
475 * @param qName The qualified (prefixed) name.
476 * @param qAtts The XML attribute list (with qnames).
477 * @exception SAXException The client may raise a
478 * processing exception.
479 */
480 public void startElement (String qName, AttributeList qAtts)
481 throws SAXException
482 {
483 // These are exceptions from the
484 // first pass; they should be
485 // ignored if there's a second pass,
486 // but reported otherwise.
487 Vector exceptions = null;
488
489 // If we're not doing Namespace
490 // processing, dispatch this quickly.
491 if (!namespaces) {
492 if (contentHandler != null) {
493 attAdapter.setAttributeList(qAtts);
494 contentHandler.startElement("", "", qName.intern(),
495 attAdapter);
496 }
497 return;
498 }
499
500
501 // OK, we're doing Namespace processing.
502 nsSupport.pushContext();
503 int length = qAtts.getLength();
504
505 // First pass: handle NS decls
506 for (int i = 0; i < length; i++) {
507 String attQName = qAtts.getName(i);
508
509 if (!attQName.startsWith("xmlns"))
510 continue;
511 // Could be a declaration...
512 String prefix;
513 int n = attQName.indexOf(':');
514
515 // xmlns=...
516 if (n == -1 && attQName.length () == 5) {
517 prefix = "";
518 } else if (n != 5) {
519 // XML namespaces spec doesn't discuss "xmlnsf:oo"
520 // (and similarly named) attributes ... at most, warn
521 continue;
522 } else // xmlns:foo=...
523 prefix = attQName.substring(n+1);
524
525 String value = qAtts.getValue(i);
526 if (!nsSupport.declarePrefix(prefix, value)) {
527 reportError("Illegal Namespace prefix: " + prefix);
528 continue;
529 }
530 if (contentHandler != null)
531 contentHandler.startPrefixMapping(prefix, value);
532 }
533
534 // Second pass: copy all relevant
535 // attributes into the SAX2 AttributeList
536 // using updated prefix bindings
537 atts.clear();
538 for (int i = 0; i < length; i++) {
539 String attQName = qAtts.getName(i);
540 String type = qAtts.getType(i);
541 String value = qAtts.getValue(i);
542
543 // Declaration?
544 if (attQName.startsWith("xmlns")) {
545 String prefix;
546 int n = attQName.indexOf(':');
547
548 if (n == -1 && attQName.length () == 5) {
549 prefix = "";
550 } else if (n != 5) {
551 // XML namespaces spec doesn't discuss "xmlnsf:oo"
552 // (and similarly named) attributes ... ignore
553 prefix = null;
554 } else {
555 prefix = attQName.substring(6);
556 }
557 // Yes, decl: report or prune
558 if (prefix != null) {
559 if (prefixes) {
560 if (uris)
561 // note funky case: localname can be null
562 // when declaring the default prefix, and
563 // yet the uri isn't null.
564 atts.addAttribute (nsSupport.XMLNS, prefix,
565 attQName.intern(), type, value);
566 else
567 atts.addAttribute ("", "",
568 attQName.intern(), type, value);
569 }
570 continue;
571 }
572 }
573
574 // Not a declaration -- report
575 try {
576 String attName[] = processName(attQName, true, true);
577 atts.addAttribute(attName[0], attName[1], attName[2],
578 type, value);
579 } catch (SAXException e) {
580 if (exceptions == null)
581 exceptions = new Vector();
582 exceptions.addElement(e);
583 atts.addAttribute("", attQName, attQName, type, value);
584 }
585 }
586
587 // now handle the deferred exception reports
588 if (exceptions != null && errorHandler != null) {
589 for (int i = 0; i < exceptions.size(); i++)
590 errorHandler.error((SAXParseException)
591 (exceptions.elementAt(i)));
592 }
593
594 // OK, finally report the event.
595 if (contentHandler != null) {
596 String name[] = processName(qName, false, false);
597 contentHandler.startElement(name[0], name[1], name[2], atts);
598 }
599 }
600
601
602 /**
603 * Adapter implementation method; do not call.
604 * Adapt a SAX1 end element event.
605 *
606 * @param qName The qualified (prefixed) name.
607 * @exception SAXException The client may raise a
608 * processing exception.
609 * @see org.xml.sax.DocumentHandler#endElement
610 */
611 public void endElement (String qName)
612 throws SAXException
613 {
614 // If we're not doing Namespace
615 // processing, dispatch this quickly.
616 if (!namespaces) {
617 if (contentHandler != null) {
618 contentHandler.endElement("", "", qName.intern());
619 }
620 return;
621 }
622
623 // Split the name.
624 String names[] = processName(qName, false, false);
625 if (contentHandler != null) {
626 contentHandler.endElement(names[0], names[1], names[2]);
627 Enumeration prefixes = nsSupport.getDeclaredPrefixes();
628 while (prefixes.hasMoreElements()) {
629 String prefix = (String)prefixes.nextElement();
630 contentHandler.endPrefixMapping(prefix);
631 }
632 }
633 nsSupport.popContext();
634 }
635
636
637 /**
638 * Adapter implementation method; do not call.
639 * Adapt a SAX1 characters event.
640 *
641 * @param ch An array of characters.
642 * @param start The starting position in the array.
643 * @param length The number of characters to use.
644 * @exception SAXException The client may raise a
645 * processing exception.
646 * @see org.xml.sax.DocumentHandler#characters
647 */
648 public void characters (char ch[], int start, int length)
649 throws SAXException
650 {
651 if (contentHandler != null) {
652 contentHandler.characters(ch, start, length);
653 }
654 }
655
656
657 /**
658 * Adapter implementation method; do not call.
659 * Adapt a SAX1 ignorable whitespace event.
660 *
661 * @param ch An array of characters.
662 * @param start The starting position in the array.
663 * @param length The number of characters to use.
664 * @exception SAXException The client may raise a
665 * processing exception.
666 * @see org.xml.sax.DocumentHandler#ignorableWhitespace
667 */
668 public void ignorableWhitespace (char ch[], int start, int length)
669 throws SAXException
670 {
671 if (contentHandler != null) {
672 contentHandler.ignorableWhitespace(ch, start, length);
673 }
674 }
675
676
677 /**
678 * Adapter implementation method; do not call.
679 * Adapt a SAX1 processing instruction event.
680 *
681 * @param target The processing instruction target.
682 * @param data The remainder of the processing instruction
683 * @exception SAXException The client may raise a
684 * processing exception.
685 * @see org.xml.sax.DocumentHandler#processingInstruction
686 */
687 public void processingInstruction (String target, String data)
688 throws SAXException
689 {
690 if (contentHandler != null) {
691 contentHandler.processingInstruction(target, data);
692 }
693 }
694
695
696
697 ////////////////////////////////////////////////////////////////////
698 // Internal utility methods.
699 ////////////////////////////////////////////////////////////////////
700
701
702 /**
703 * Initialize the parser before each run.
704 */
705 private void setupParser ()
706 {
707 // catch an illegal "nonsense" state.
708 if (!prefixes && !namespaces)
709 throw new IllegalStateException ();
710
711 nsSupport.reset();
712 if (uris)
713 nsSupport.setNamespaceDeclUris (true);
714
715 if (entityResolver != null) {
716 parser.setEntityResolver(entityResolver);
717 }
718 if (dtdHandler != null) {
719 parser.setDTDHandler(dtdHandler);
720 }
721 if (errorHandler != null) {
722 parser.setErrorHandler(errorHandler);
723 }
724 parser.setDocumentHandler(this);
725 locator = null;
726 }
727
728
729 /**
730 * Process a qualified (prefixed) name.
731 *
732 * <p>If the name has an undeclared prefix, use only the qname
733 * and make an ErrorHandler.error callback in case the app is
734 * interested.</p>
735 *
736 * @param qName The qualified (prefixed) name.
737 * @param isAttribute true if this is an attribute name.
738 * @return The name split into three parts.
739 * @exception SAXException The client may throw
740 * an exception if there is an error callback.
741 */
742 private String [] processName (String qName, boolean isAttribute,
743 boolean useException)
744 throws SAXException
745 {
746 String parts[] = nsSupport.processName(qName, nameParts,
747 isAttribute);
748 if (parts == null) {
749 if (useException)
750 throw makeException("Undeclared prefix: " + qName);
751 reportError("Undeclared prefix: " + qName);
752 parts = new String[3];
753 parts[0] = parts[1] = "";
754 parts[2] = qName.intern();
755 }
756 return parts;
757 }
758
759
760 /**
761 * Report a non-fatal error.
762 *
763 * @param message The error message.
764 * @exception SAXException The client may throw
765 * an exception.
766 */
767 void reportError (String message)
768 throws SAXException
769 {
770 if (errorHandler != null)
771 errorHandler.error(makeException(message));
772 }
773
774
775 /**
776 * Construct an exception for the current context.
777 *
778 * @param message The error message.
779 */
780 private SAXParseException makeException (String message)
781 {
782 if (locator != null) {
783 return new SAXParseException(message, locator);
784 } else {
785 return new SAXParseException(message, null, null, -1, -1);
786 }
787 }
788
789
790 /**
791 * Throw an exception if we are parsing.
792 *
793 * <p>Use this method to detect illegal feature or
794 * property changes.</p>
795 *
796 * @param type The type of thing (feature or property).
797 * @param name The feature or property name.
798 * @exception SAXNotSupportedException If a
799 * document is currently being parsed.
800 */
801 private void checkNotParsing (String type, String name)
802 throws SAXNotSupportedException
803 {
804 if (parsing) {
805 throw new SAXNotSupportedException("Cannot change " +
806 type + ' ' +
807 name + " while parsing");
808
809 }
810 }
811
812
813
814 ////////////////////////////////////////////////////////////////////
815 // Internal state.
816 ////////////////////////////////////////////////////////////////////
817
818 private NamespaceSupport nsSupport;
819 private AttributeListAdapter attAdapter;
820
821 private boolean parsing = false;
822 private String nameParts[] = new String[3];
823
824 private Parser parser = null;
825
826 private AttributesImpl atts = null;
827
828 // Features
829 private boolean namespaces = true;
830 private boolean prefixes = false;
831 private boolean uris = false;
832
833 // Properties
834
835 // Handlers
836 Locator locator;
837
838 EntityResolver entityResolver = null;
839 DTDHandler dtdHandler = null;
840 ContentHandler contentHandler = null;
841 ErrorHandler errorHandler = null;
842
843
844
845 ////////////////////////////////////////////////////////////////////
846 // Inner class to wrap an AttributeList when not doing NS proc.
847 ////////////////////////////////////////////////////////////////////
848
849
850 /**
851 * Adapt a SAX1 AttributeList as a SAX2 Attributes object.
852 *
853 * <p>This class is in the Public Domain, and comes with NO
854 * WARRANTY of any kind.</p>
855 *
856 * <p>This wrapper class is used only when Namespace support
857 * is disabled -- it provides pretty much a direct mapping
858 * from SAX1 to SAX2, except that names and types are
859 * interned whenever requested.</p>
860 */
861 final class AttributeListAdapter implements Attributes
862 {
863
864 /**
865 * Construct a new adapter.
866 */
867 AttributeListAdapter ()
868 {
869 }
870
871
872 /**
873 * Set the embedded AttributeList.
874 *
875 * <p>This method must be invoked before any of the others
876 * can be used.</p>
877 *
878 * @param The SAX1 attribute list (with qnames).
879 */
880 void setAttributeList (AttributeList qAtts)
881 {
882 this.qAtts = qAtts;
883 }
884
885
886 /**
887 * Return the length of the attribute list.
888 *
889 * @return The number of attributes in the list.
890 * @see org.xml.sax.Attributes#getLength
891 */
892 public int getLength ()
893 {
894 return qAtts.getLength();
895 }
896
897
898 /**
899 * Return the Namespace URI of the specified attribute.
900 *
901 * @param The attribute's index.
902 * @return Always the empty string.
903 * @see org.xml.sax.Attributes#getURI
904 */
905 public String getURI (int i)
906 {
907 return "";
908 }
909
910
911 /**
912 * Return the local name of the specified attribute.
913 *
914 * @param The attribute's index.
915 * @return Always the empty string.
916 * @see org.xml.sax.Attributes#getLocalName
917 */
918 public String getLocalName (int i)
919 {
920 return "";
921 }
922
923
924 /**
925 * Return the qualified (prefixed) name of the specified attribute.
926 *
927 * @param The attribute's index.
928 * @return The attribute's qualified name, internalized.
929 */
930 public String getQName (int i)
931 {
932 return qAtts.getName(i).intern();
933 }
934
935
936 /**
937 * Return the type of the specified attribute.
938 *
939 * @param The attribute's index.
940 * @return The attribute's type as an internalized string.
941 */
942 public String getType (int i)
943 {
944 return qAtts.getType(i).intern();
945 }
946
947
948 /**
949 * Return the value of the specified attribute.
950 *
951 * @param The attribute's index.
952 * @return The attribute's value.
953 */
954 public String getValue (int i)
955 {
956 return qAtts.getValue(i);
957 }
958
959
960 /**
961 * Look up an attribute index by Namespace name.
962 *
963 * @param uri The Namespace URI or the empty string.
964 * @param localName The local name.
965 * @return The attributes index, or -1 if none was found.
966 * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
967 */
968 public int getIndex (String uri, String localName)
969 {
970 return -1;
971 }
972
973
974 /**
975 * Look up an attribute index by qualified (prefixed) name.
976 *
977 * @param qName The qualified name.
978 * @return The attributes index, or -1 if none was found.
979 * @see org.xml.sax.Attributes#getIndex(java.lang.String)
980 */
981 public int getIndex (String qName)
982 {
983 int max = atts.getLength();
984 for (int i = 0; i < max; i++) {
985 if (qAtts.getName(i).equals(qName)) {
986 return i;
987 }
988 }
989 return -1;
990 }
991
992
993 /**
994 * Look up the type of an attribute by Namespace name.
995 *
996 * @param uri The Namespace URI
997 * @param localName The local name.
998 * @return The attribute's type as an internalized string.
999 */
1000 public String getType (String uri, String localName)
1001 {
1002 return null;
1003 }
1004
1005
1006 /**
1007 * Look up the type of an attribute by qualified (prefixed) name.
1008 *
1009 * @param qName The qualified name.
1010 * @return The attribute's type as an internalized string.
1011 */
1012 public String getType (String qName)
1013 {
1014 return qAtts.getType(qName).intern();
1015 }
1016
1017
1018 /**
1019 * Look up the value of an attribute by Namespace name.
1020 *
1021 * @param uri The Namespace URI
1022 * @param localName The local name.
1023 * @return The attribute's value.
1024 */
1025 public String getValue (String uri, String localName)
1026 {
1027 return null;
1028 }
1029
1030
1031 /**
1032 * Look up the value of an attribute by qualified (prefixed) name.
1033 *
1034 * @param qName The qualified name.
1035 * @return The attribute's value.
1036 */
1037 public String getValue (String qName)
1038 {
1039 return qAtts.getValue(qName);
1040 }
1041
1042 private AttributeList qAtts;
1043 }
1044 }
1045
1046 // end of ParserAdapter.java