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