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