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