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 //////////////////////////////////////////////////////////////////// 61 // Constructors. 62 //////////////////////////////////////////////////////////////////// 63 64 65 /** 66 * Construct a new parser adapter. 67 * 68 * <p>Use the "org.xml.sax.parser" property to locate the 69 * embedded SAX1 driver.</p> 70 * 71 * @exception SAXException If the embedded driver 72 * cannot be instantiated or if the 73 * org.xml.sax.parser property is not specified. 74 */ 75 public ParserAdapter () 76 throws SAXException 77 { 78 79 String driver = System.getProperty("org.xml.sax.parser"); 80 81 try { 82 setup(ParserFactory.makeParser()); 83 } catch (ClassNotFoundException e1) { 84 throw new 85 SAXException("Cannot find SAX1 driver class " + 86 driver, e1); 87 } catch (IllegalAccessException e2) { 88 throw new 89 SAXException("SAX1 driver class " + 90 driver + 91 " found but cannot be loaded", e2); 92 } catch (InstantiationException e3) { 93 throw new 94 SAXException("SAX1 driver class " + 95 driver + 96 " loaded but cannot be instantiated", e3); 97 } catch (ClassCastException e4) { 98 throw new 99 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 setup(parser); 123 } 124 125 126 /** 127 * Internal setup method. 128 * 129 * @param parser The embedded parser. 130 * @exception java.lang.NullPointerException If the parser parameter 131 * is null. 132 */ 133 private void setup (Parser parser) 134 { 135 if (parser == null) { 136 throw new 137 NullPointerException("Parser argument must not be null"); 138 } 139 this.parser = parser; 140 atts = new AttributesImpl(); 141 nsSupport = new NamespaceSupport(); 142 attAdapter = new AttributeListAdapter(); 143 } 144 145 146 147 //////////////////////////////////////////////////////////////////// 149 // Implementation of org.xml.sax.XMLReader. 150 //////////////////////////////////////////////////////////////////// 151 152 153 // 154 // Internal constants for the sake of convenience. 155 // 156 private static final String FEATURES = "http://xml.org/sax/features/"; 157 private static final String NAMESPACES = FEATURES + "namespaces"; 158 private static final String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes"; 159 private static final String XMLNS_URIs = FEATURES + "xmlns-uris"; 160 161 162 /** 163 * Set a feature flag for the parser. 164 * 165 * <p>The only features recognized are namespaces and 166 * namespace-prefixes.</p> 167 * 168 * @param name The feature name, as a complete URI. 169 * @param value The requested feature value. 170 * @exception SAXNotRecognizedException If the feature 171 * can't be assigned or retrieved. 172 * @exception SAXNotSupportedException If the feature 173 * can't be assigned that value. 174 * @see org.xml.sax.XMLReader#setFeature 175 */ 176 public void setFeature (String name, boolean value) 177 throws SAXNotRecognizedException, SAXNotSupportedException 178 { 179 if (name.equals(NAMESPACES)) { 180 checkNotParsing("feature", name); 181 namespaces = value; 182 if (!namespaces && !prefixes) { 183 prefixes = true; 184 } 185 } else if (name.equals(NAMESPACE_PREFIXES)) { 186 checkNotParsing("feature", name); 187 prefixes = value; 188 if (!prefixes && !namespaces) { 189 namespaces = true; 190 } 191 } else if (name.equals(XMLNS_URIs)) { 192 checkNotParsing("feature", name); 193 uris = value; 194 } else { 195 throw new SAXNotRecognizedException("Feature: " + name); 196 } 197 } 198 199 200 /** 201 * Check a parser feature flag. 202 * 203 * <p>The only features recognized are namespaces and 204 * namespace-prefixes.</p> 205 * 206 * @param name The feature name, as a complete URI. 207 * @return The current feature value. 208 * @exception SAXNotRecognizedException If the feature 209 * value can't be assigned or retrieved. 210 * @exception SAXNotSupportedException If the 211 * feature is not currently readable. 212 * @see org.xml.sax.XMLReader#setFeature 213 */ 214 public boolean getFeature (String name) 215 throws SAXNotRecognizedException, SAXNotSupportedException 216 { 217 if (name.equals(NAMESPACES)) { 218 return namespaces; 219 } else if (name.equals(NAMESPACE_PREFIXES)) { 220 return prefixes; 221 } else if (name.equals(XMLNS_URIs)) { 222 return uris; 223 } else { 224 throw new SAXNotRecognizedException("Feature: " + name); 225 } 226 } 227 228 229 /** 230 * Set a parser property. 231 * 232 * <p>No properties are currently recognized.</p> 233 * 234 * @param name The property name. 235 * @param value The property value. 236 * @exception SAXNotRecognizedException If the property 237 * value can't be assigned or retrieved. 238 * @exception SAXNotSupportedException If the property 239 * can't be assigned that value. 240 * @see org.xml.sax.XMLReader#setProperty 241 */ 242 public void setProperty (String name, Object value) 243 throws SAXNotRecognizedException, SAXNotSupportedException 244 { 245 throw new SAXNotRecognizedException("Property: " + name); 246 } 247 248 249 /** 250 * Get a parser property. 251 * 252 * <p>No properties are currently recognized.</p> 253 * 254 * @param name The property name. 255 * @return The property value. 256 * @exception SAXNotRecognizedException If the property 257 * value can't be assigned or retrieved. 258 * @exception SAXNotSupportedException If the property 259 * value is not currently readable. 260 * @see org.xml.sax.XMLReader#getProperty 261 */ 262 public Object getProperty (String name) 263 throws SAXNotRecognizedException, SAXNotSupportedException 264 { 265 throw new SAXNotRecognizedException("Property: " + name); 266 } 267 268 269 /** 270 * Set the entity resolver. 271 * 272 * @param resolver The new entity resolver. 273 * @see org.xml.sax.XMLReader#setEntityResolver 274 */ 275 public void setEntityResolver (EntityResolver resolver) 276 { 277 entityResolver = resolver; 278 } 279 280 281 /** 282 * Return the current entity resolver. 283 * 284 * @return The current entity resolver, or null if none was supplied. 285 * @see org.xml.sax.XMLReader#getEntityResolver 286 */ 287 public EntityResolver getEntityResolver () 288 { 289 return entityResolver; 290 } 291 292 293 /** 294 * Set the DTD handler. 295 * 296 * @param handler the new DTD handler 297 * @see org.xml.sax.XMLReader#setEntityResolver 298 */ 299 public void setDTDHandler (DTDHandler handler) 300 { 301 dtdHandler = handler; 302 } 303 304 305 /** 306 * Return the current DTD handler. 307 * 308 * @return the current DTD handler, or null if none was supplied 309 * @see org.xml.sax.XMLReader#getEntityResolver 310 */ 311 public DTDHandler getDTDHandler () 312 { 313 return dtdHandler; 314 } 315 316 317 /** 318 * Set the content handler. 319 * 320 * @param handler the new content handler 321 * @see org.xml.sax.XMLReader#setEntityResolver 322 */ 323 public void setContentHandler (ContentHandler handler) 324 { 325 contentHandler = handler; 326 } 327 328 329 /** 330 * Return the current content handler. 331 * 332 * @return The current content handler, or null if none was supplied. 333 * @see org.xml.sax.XMLReader#getEntityResolver 334 */ 335 public ContentHandler getContentHandler () 336 { 337 return contentHandler; 338 } 339 340 341 /** 342 * Set the error handler. 343 * 344 * @param handler The new error handler. 345 * @see org.xml.sax.XMLReader#setEntityResolver 346 */ 347 public void setErrorHandler (ErrorHandler handler) 348 { 349 errorHandler = handler; 350 } 351 352 353 /** 354 * Return the current error handler. 355 * 356 * @return The current error handler, or null if none was supplied. 357 * @see org.xml.sax.XMLReader#getEntityResolver 358 */ 359 public ErrorHandler getErrorHandler () 360 { 361 return errorHandler; 362 } 363 364 365 /** 366 * Parse an XML document. 367 * 368 * @param systemId The absolute URL of the document. 369 * @exception java.io.IOException If there is a problem reading 370 * the raw content of the document. 371 * @exception SAXException If there is a problem 372 * processing the document. 373 * @see #parse(org.xml.sax.InputSource) 374 * @see org.xml.sax.Parser#parse(java.lang.String) 375 */ 376 public void parse (String systemId) 377 throws IOException, SAXException 378 { 379 parse(new InputSource(systemId)); 380 } 381 382 383 /** 384 * Parse an XML document. 385 * 386 * @param input An input source for the document. 387 * @exception java.io.IOException If there is a problem reading 388 * the raw content of the document. 389 * @exception SAXException If there is a problem 390 * processing the document. 391 * @see #parse(java.lang.String) 392 * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) 393 */ 394 public void parse (InputSource input) 395 throws IOException, SAXException 396 { 397 if (parsing) { 398 throw new SAXException("Parser is already in use"); 399 } 400 setupParser(); 401 parsing = true; 402 try { 403 parser.parse(input); 404 } finally { 405 parsing = false; 406 } 407 parsing = false; 408 } 409 410 411 412 //////////////////////////////////////////////////////////////////// 413 // Implementation of org.xml.sax.DocumentHandler. 414 //////////////////////////////////////////////////////////////////// 415 416 417 /** 418 * Adapter implementation method; do not call. 419 * Adapt a SAX1 document locator event. 420 * 421 * @param locator A document locator. 422 * @see org.xml.sax.ContentHandler#setDocumentLocator 423 */ 424 public void setDocumentLocator (Locator locator) 425 { 426 this.locator = locator; 427 if (contentHandler != null) { 428 contentHandler.setDocumentLocator(locator); 429 } 430 } 431 432 433 /** 434 * Adapter implementation method; do not call. 435 * Adapt a SAX1 start document event. 436 * 437 * @exception SAXException The client may raise a 438 * processing exception. 439 * @see org.xml.sax.DocumentHandler#startDocument 440 */ 441 public void startDocument () 442 throws SAXException 443 { 444 if (contentHandler != null) { 445 contentHandler.startDocument(); 446 } 447 } 448 449 450 /** 451 * Adapter implementation method; do not call. 452 * Adapt a SAX1 end document event. 453 * 454 * @exception SAXException The client may raise a 455 * processing exception. 456 * @see org.xml.sax.DocumentHandler#endDocument 457 */ 458 public void endDocument () 459 throws SAXException 460 { 461 if (contentHandler != null) { 462 contentHandler.endDocument(); 463 } 464 } 465 466 467 /** 468 * Adapter implementation method; do not call. 469 * Adapt a SAX1 startElement event. 470 * 471 * <p>If necessary, perform Namespace processing.</p> 472 * 473 * @param qName The qualified (prefixed) name. 474 * @param qAtts The XML attribute list (with qnames). 475 * @exception SAXException The client may raise a 476 * processing exception. 477 */ 478 public void startElement (String qName, AttributeList qAtts) throws SAXException { 479 // These are exceptions from the 480 // first pass; they should be 481 // ignored if there's a second pass, 482 // but reported otherwise. 483 ArrayList<SAXParseException> exceptions = null; 484 485 // If we're not doing Namespace 486 // processing, dispatch this quickly. 487 if (!namespaces) { 488 if (contentHandler != null) { 489 attAdapter.setAttributeList(qAtts); 490 contentHandler.startElement("", "", qName.intern(), 491 attAdapter); 492 } 493 return; 494 } 495 496 497 // OK, we're doing Namespace processing. 498 nsSupport.pushContext(); 499 int length = qAtts.getLength(); 500 501 // First pass: handle NS decls 502 for (int i = 0; i < length; i++) { 503 String attQName = qAtts.getName(i); 504 505 if (!attQName.startsWith("xmlns")) 506 continue; 507 // Could be a declaration... 508 String prefix; 509 int n = attQName.indexOf(':'); 510 511 // xmlns=... 512 if (n == -1 && attQName.length () == 5) { 513 prefix = ""; 514 } else if (n != 5) { 515 // XML namespaces spec doesn't discuss "xmlnsf:oo" 516 // (and similarly named) attributes ... at most, warn 517 continue; 518 } else // xmlns:foo=... 519 prefix = attQName.substring(n+1); 520 521 String value = qAtts.getValue(i); 522 if (!nsSupport.declarePrefix(prefix, value)) { 523 reportError("Illegal Namespace prefix: " + prefix); 524 continue; 525 } 526 if (contentHandler != null) 527 contentHandler.startPrefixMapping(prefix, value); 528 } 529 530 // Second pass: copy all relevant 531 // attributes into the SAX2 AttributeList 532 // using updated prefix bindings 533 atts.clear(); 534 for (int i = 0; i < length; i++) { 535 String attQName = qAtts.getName(i); 536 String type = qAtts.getType(i); 537 String value = qAtts.getValue(i); 538 539 // Declaration? 540 if (attQName.startsWith("xmlns")) { 541 String prefix; 542 int n = attQName.indexOf(':'); 543 544 if (n == -1 && attQName.length () == 5) { 545 prefix = ""; 546 } else if (n != 5) { 547 // XML namespaces spec doesn't discuss "xmlnsf:oo" 548 // (and similarly named) attributes ... ignore 549 prefix = null; 550 } else { 551 prefix = attQName.substring(6); 552 } 553 // Yes, decl: report or prune 554 if (prefix != null) { 555 if (prefixes) { 556 if (uris) 557 // note funky case: localname can be null 558 // when declaring the default prefix, and 559 // yet the uri isn't null. 560 atts.addAttribute (nsSupport.XMLNS, prefix, 561 attQName.intern(), type, value); 562 else 563 atts.addAttribute ("", "", 564 attQName.intern(), type, value); 565 } 566 continue; 567 } 568 } 569 570 // Not a declaration -- report 571 try { 572 String attName[] = processName(attQName, true, true); 573 atts.addAttribute(attName[0], attName[1], attName[2], 574 type, value); 575 } catch (SAXException e) { 576 if (exceptions == null) { 577 exceptions = new ArrayList<SAXParseException>(); 578 } 579 exceptions.add((SAXParseException) e); 580 atts.addAttribute("", attQName, attQName, type, value); 581 } 582 } 583 584 // now handle the deferred exception reports 585 if (exceptions != null && errorHandler != null) { 586 for (SAXParseException ex : exceptions) { 587 errorHandler.error(ex); 588 } 589 } 590 591 // OK, finally report the event. 592 if (contentHandler != null) { 593 String name[] = processName(qName, false, false); 594 contentHandler.startElement(name[0], name[1], name[2], atts); 595 } 596 } 597 598 599 /** 600 * Adapter implementation method; do not call. 601 * Adapt a SAX1 end element event. 602 * 603 * @param qName The qualified (prefixed) name. 604 * @exception SAXException The client may raise a 605 * processing exception. 606 * @see org.xml.sax.DocumentHandler#endElement 607 */ 608 public void endElement (String qName) 609 throws SAXException 610 { 611 // If we're not doing Namespace 612 // processing, dispatch this quickly. 613 if (!namespaces) { 614 if (contentHandler != null) { 615 contentHandler.endElement("", "", qName.intern()); 616 } 617 return; 618 } 619 620 // Split the name. 621 String names[] = processName(qName, false, false); 622 if (contentHandler != null) { 623 contentHandler.endElement(names[0], names[1], names[2]); 624 Enumeration prefixes = nsSupport.getDeclaredPrefixes(); 625 while (prefixes.hasMoreElements()) { 626 String prefix = (String)prefixes.nextElement(); 627 contentHandler.endPrefixMapping(prefix); 628 } 629 } 630 nsSupport.popContext(); 631 } 632 633 634 /** 635 * Adapter implementation method; do not call. 636 * Adapt a SAX1 characters event. 637 * 638 * @param ch An array of characters. 639 * @param start The starting position in the array. 640 * @param length The number of characters to use. 641 * @exception SAXException The client may raise a 642 * processing exception. 643 * @see org.xml.sax.DocumentHandler#characters 644 */ 645 public void characters (char ch[], int start, int length) 646 throws SAXException 647 { 648 if (contentHandler != null) { 649 contentHandler.characters(ch, start, length); 650 } 651 } 652 653 654 /** 655 * Adapter implementation method; do not call. 656 * Adapt a SAX1 ignorable whitespace event. 657 * 658 * @param ch An array of characters. 659 * @param start The starting position in the array. 660 * @param length The number of characters to use. 661 * @exception SAXException The client may raise a 662 * processing exception. 663 * @see org.xml.sax.DocumentHandler#ignorableWhitespace 664 */ 665 public void ignorableWhitespace (char ch[], int start, int length) 666 throws SAXException 667 { 668 if (contentHandler != null) { 669 contentHandler.ignorableWhitespace(ch, start, length); 670 } 671 } 672 673 674 /** 675 * Adapter implementation method; do not call. 676 * Adapt a SAX1 processing instruction event. 677 * 678 * @param target The processing instruction target. 679 * @param data The remainder of the processing instruction 680 * @exception SAXException The client may raise a 681 * processing exception. 682 * @see org.xml.sax.DocumentHandler#processingInstruction 683 */ 684 public void processingInstruction (String target, String data) 685 throws SAXException 686 { 687 if (contentHandler != null) { 688 contentHandler.processingInstruction(target, data); 689 } 690 } 691 692 693 694 //////////////////////////////////////////////////////////////////// 696 // Internal utility methods. 697 //////////////////////////////////////////////////////////////////// 698 699 700 /** 701 * Initialize the parser before each run. 702 */ 703 private void setupParser () 704 { 705 // catch an illegal "nonsense" state. 706 if (!prefixes && !namespaces) 707 throw new IllegalStateException (); 708 709 nsSupport.reset(); 710 if (uris) 711 nsSupport.setNamespaceDeclUris (true); 712 713 if (entityResolver != null) { 714 parser.setEntityResolver(entityResolver); 715 } 716 if (dtdHandler != null) { 717 parser.setDTDHandler(dtdHandler); 718 } 719 if (errorHandler != null) { 720 parser.setErrorHandler(errorHandler); 721 } 722 parser.setDocumentHandler(this); 723 locator = null; 724 } 725 726 727 /** 728 * Process a qualified (prefixed) name. 729 * 730 * <p>If the name has an undeclared prefix, use only the qname 731 * and make an ErrorHandler.error callback in case the app is 732 * interested.</p> 733 * 734 * @param qName The qualified (prefixed) name. 735 * @param isAttribute true if this is an attribute name. 736 * @return The name split into three parts. 737 * @exception SAXException The client may throw 738 * an exception if there is an error callback. 739 */ 740 private String [] processName (String qName, boolean isAttribute, 741 boolean useException) 742 throws SAXException 743 { 744 String parts[] = nsSupport.processName(qName, nameParts, 745 isAttribute); 746 if (parts == null) { 747 if (useException) 748 throw makeException("Undeclared prefix: " + qName); 749 reportError("Undeclared prefix: " + qName); 750 parts = new String[3]; 751 parts[0] = parts[1] = ""; 752 parts[2] = qName.intern(); 753 } 754 return parts; 755 } 756 757 758 /** 759 * Report a non-fatal error. 760 * 761 * @param message The error message. 762 * @exception SAXException The client may throw 763 * an exception. 764 */ 765 void reportError (String message) 766 throws SAXException 767 { 768 if (errorHandler != null) 769 errorHandler.error(makeException(message)); 770 } 771 772 773 /** 774 * Construct an exception for the current context. 775 * 776 * @param message The error message. 777 */ 778 private SAXParseException makeException (String message) 779 { 780 if (locator != null) { 781 return new SAXParseException(message, locator); 782 } else { 783 return new SAXParseException(message, null, null, -1, -1); 784 } 785 } 786 787 788 /** 789 * Throw an exception if we are parsing. 790 * 791 * <p>Use this method to detect illegal feature or 792 * property changes.</p> 793 * 794 * @param type The type of thing (feature or property). 795 * @param name The feature or property name. 796 * @exception SAXNotSupportedException If a 797 * document is currently being parsed. 798 */ 799 private void checkNotParsing (String type, String name) 800 throws SAXNotSupportedException 801 { 802 if (parsing) { 803 throw new SAXNotSupportedException("Cannot change " + 804 type + ' ' + 805 name + " while parsing"); 806 807 } 808 } 809 810 811 812 //////////////////////////////////////////////////////////////////// 814 // Internal state. 815 //////////////////////////////////////////////////////////////////// 816 817 private NamespaceSupport nsSupport; 818 private AttributeListAdapter attAdapter; 819 820 private boolean parsing = false; 821 private String nameParts[] = new String[3]; 822 823 private Parser parser = null; 824 825 private AttributesImpl atts = null; 826 827 // Features 828 private boolean namespaces = true; 829 private boolean prefixes = false; 830 private boolean uris = false; 831 832 // Properties 833 834 // Handlers 835 Locator locator; 836 837 EntityResolver entityResolver = null; 838 DTDHandler dtdHandler = null; 839 ContentHandler contentHandler = null; 840 ErrorHandler errorHandler = null; 841 842 843 844 //////////////////////////////////////////////////////////////////// 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 1047