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