Frames | No Frames |
1: // XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser 2: // http://www.saxproject.org 3: // Written by David Megginson 4: // NO WARRANTY! This class is in the public domain. 5: // $Id: XMLReaderAdapter.java,v 1.2 2006-12-10 20:25:41 gnu_andrew Exp $ 6: 7: package org.xml.sax.helpers; 8: 9: import java.io.IOException; 10: import java.util.Locale; 11: 12: import org.xml.sax.Parser; // deprecated 13: import org.xml.sax.Locator; 14: import org.xml.sax.InputSource; 15: import org.xml.sax.AttributeList; // deprecated 16: import org.xml.sax.EntityResolver; 17: import org.xml.sax.DTDHandler; 18: import org.xml.sax.DocumentHandler; // deprecated 19: import org.xml.sax.ErrorHandler; 20: import org.xml.sax.SAXException; 21: 22: import org.xml.sax.XMLReader; 23: import org.xml.sax.Attributes; 24: import org.xml.sax.ContentHandler; 25: import org.xml.sax.SAXNotSupportedException; 26: 27: 28: /** 29: * Adapt a SAX2 XMLReader as a SAX1 Parser. 30: * 31: * <blockquote> 32: * <em>This module, both source code and documentation, is in the 33: * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> 34: * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> 35: * for further information. 36: * </blockquote> 37: * 38: * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader} 39: * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}. The XMLReader 40: * must support a true value for the 41: * http://xml.org/sax/features/namespace-prefixes property or parsing will fail 42: * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader 43: * supports a false value for the http://xml.org/sax/features/namespaces 44: * property, that will also be used to improve efficiency.</p> 45: * 46: * @since SAX 2.0 47: * @author David Megginson 48: * @version 2.0.1 (sax2r2) 49: * @see org.xml.sax.Parser 50: * @see org.xml.sax.XMLReader 51: */ 52: public class XMLReaderAdapter implements Parser, ContentHandler 53: { 54: 55: 56: //////////////////////////////////////////////////////////////////// 57: // Constructor. 58: //////////////////////////////////////////////////////////////////// 59: 60: 61: /** 62: * Create a new adapter. 63: * 64: * <p>Use the "org.xml.sax.driver" property to locate the SAX2 65: * driver to embed.</p> 66: * 67: * @exception org.xml.sax.SAXException If the embedded driver 68: * cannot be instantiated or if the 69: * org.xml.sax.driver property is not specified. 70: */ 71: public XMLReaderAdapter () 72: throws SAXException 73: { 74: setup(XMLReaderFactory.createXMLReader()); 75: } 76: 77: 78: /** 79: * Create a new adapter. 80: * 81: * <p>Create a new adapter, wrapped around a SAX2 XMLReader. 82: * The adapter will make the XMLReader act like a SAX1 83: * Parser.</p> 84: * 85: * @param xmlReader The SAX2 XMLReader to wrap. 86: * @exception java.lang.NullPointerException If the argument is null. 87: */ 88: public XMLReaderAdapter (XMLReader xmlReader) 89: { 90: setup(xmlReader); 91: } 92: 93: 94: 95: /** 96: * Internal setup. 97: * 98: * @param xmlReader The embedded XMLReader. 99: */ 100: private void setup (XMLReader xmlReader) 101: { 102: if (xmlReader == null) { 103: throw new NullPointerException("XMLReader must not be null"); 104: } 105: this.xmlReader = xmlReader; 106: qAtts = new AttributesAdapter(); 107: } 108: 109: 110: 111: //////////////////////////////////////////////////////////////////// 112: // Implementation of org.xml.sax.Parser. 113: //////////////////////////////////////////////////////////////////// 114: 115: 116: /** 117: * Set the locale for error reporting. 118: * 119: * <p>This is not supported in SAX2, and will always throw 120: * an exception.</p> 121: * 122: * @param locale the locale for error reporting. 123: * @see org.xml.sax.Parser#setLocale 124: * @exception org.xml.sax.SAXException Thrown unless overridden. 125: */ 126: public void setLocale (Locale locale) 127: throws SAXException 128: { 129: throw new SAXNotSupportedException("setLocale not supported"); 130: } 131: 132: 133: /** 134: * Register the entity resolver. 135: * 136: * @param resolver The new resolver. 137: * @see org.xml.sax.Parser#setEntityResolver 138: */ 139: public void setEntityResolver (EntityResolver resolver) 140: { 141: xmlReader.setEntityResolver(resolver); 142: } 143: 144: 145: /** 146: * Register the DTD event handler. 147: * 148: * @param handler The new DTD event handler. 149: * @see org.xml.sax.Parser#setDTDHandler 150: */ 151: public void setDTDHandler (DTDHandler handler) 152: { 153: xmlReader.setDTDHandler(handler); 154: } 155: 156: 157: /** 158: * Register the SAX1 document event handler. 159: * 160: * <p>Note that the SAX1 document handler has no Namespace 161: * support.</p> 162: * 163: * @param handler The new SAX1 document event handler. 164: * @see org.xml.sax.Parser#setDocumentHandler 165: */ 166: public void setDocumentHandler (DocumentHandler handler) 167: { 168: documentHandler = handler; 169: } 170: 171: 172: /** 173: * Register the error event handler. 174: * 175: * @param handler The new error event handler. 176: * @see org.xml.sax.Parser#setErrorHandler 177: */ 178: public void setErrorHandler (ErrorHandler handler) 179: { 180: xmlReader.setErrorHandler(handler); 181: } 182: 183: 184: /** 185: * Parse the document. 186: * 187: * <p>This method will throw an exception if the embedded 188: * XMLReader does not support the 189: * http://xml.org/sax/features/namespace-prefixes property.</p> 190: * 191: * @param systemId The absolute URL of the document. 192: * @exception java.io.IOException If there is a problem reading 193: * the raw content of the document. 194: * @exception org.xml.sax.SAXException If there is a problem 195: * processing the document. 196: * @see #parse(org.xml.sax.InputSource) 197: * @see org.xml.sax.Parser#parse(java.lang.String) 198: */ 199: public void parse (String systemId) 200: throws IOException, SAXException 201: { 202: parse(new InputSource(systemId)); 203: } 204: 205: 206: /** 207: * Parse the document. 208: * 209: * <p>This method will throw an exception if the embedded 210: * XMLReader does not support the 211: * http://xml.org/sax/features/namespace-prefixes property.</p> 212: * 213: * @param input An input source for the document. 214: * @exception java.io.IOException If there is a problem reading 215: * the raw content of the document. 216: * @exception org.xml.sax.SAXException If there is a problem 217: * processing the document. 218: * @see #parse(java.lang.String) 219: * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) 220: */ 221: public void parse (InputSource input) 222: throws IOException, SAXException 223: { 224: setupXMLReader(); 225: xmlReader.parse(input); 226: } 227: 228: 229: /** 230: * Set up the XML reader. 231: */ 232: private void setupXMLReader () 233: throws SAXException 234: { 235: xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); 236: try { 237: xmlReader.setFeature("http://xml.org/sax/features/namespaces", 238: false); 239: } catch (SAXException e) { 240: // NO OP: it's just extra information, and we can ignore it 241: } 242: xmlReader.setContentHandler(this); 243: } 244: 245: 246: 247: //////////////////////////////////////////////////////////////////// 248: // Implementation of org.xml.sax.ContentHandler. 249: //////////////////////////////////////////////////////////////////// 250: 251: 252: /** 253: * Set a document locator. 254: * 255: * @param locator The document locator. 256: * @see org.xml.sax.ContentHandler#setDocumentLocator 257: */ 258: public void setDocumentLocator (Locator locator) 259: { 260: if (documentHandler != null) 261: documentHandler.setDocumentLocator(locator); 262: } 263: 264: 265: /** 266: * Start document event. 267: * 268: * @exception org.xml.sax.SAXException The client may raise a 269: * processing exception. 270: * @see org.xml.sax.ContentHandler#startDocument 271: */ 272: public void startDocument () 273: throws SAXException 274: { 275: if (documentHandler != null) 276: documentHandler.startDocument(); 277: } 278: 279: 280: /** 281: * End document event. 282: * 283: * @exception org.xml.sax.SAXException The client may raise a 284: * processing exception. 285: * @see org.xml.sax.ContentHandler#endDocument 286: */ 287: public void endDocument () 288: throws SAXException 289: { 290: if (documentHandler != null) 291: documentHandler.endDocument(); 292: } 293: 294: 295: /** 296: * Adapt a SAX2 start prefix mapping event. 297: * 298: * @param prefix The prefix being mapped. 299: * @param uri The Namespace URI being mapped to. 300: * @see org.xml.sax.ContentHandler#startPrefixMapping 301: */ 302: public void startPrefixMapping (String prefix, String uri) 303: { 304: } 305: 306: 307: /** 308: * Adapt a SAX2 end prefix mapping event. 309: * 310: * @param prefix The prefix being mapped. 311: * @see org.xml.sax.ContentHandler#endPrefixMapping 312: */ 313: public void endPrefixMapping (String prefix) 314: { 315: } 316: 317: 318: /** 319: * Adapt a SAX2 start element event. 320: * 321: * @param uri The Namespace URI. 322: * @param localName The Namespace local name. 323: * @param qName The qualified (prefixed) name. 324: * @param atts The SAX2 attributes. 325: * @exception org.xml.sax.SAXException The client may raise a 326: * processing exception. 327: * @see org.xml.sax.ContentHandler#endDocument 328: */ 329: public void startElement (String uri, String localName, 330: String qName, Attributes atts) 331: throws SAXException 332: { 333: if (documentHandler != null) { 334: qAtts.setAttributes(atts); 335: documentHandler.startElement(qName, qAtts); 336: } 337: } 338: 339: 340: /** 341: * Adapt a SAX2 end element event. 342: * 343: * @param uri The Namespace URI. 344: * @param localName The Namespace local name. 345: * @param qName The qualified (prefixed) name. 346: * @exception org.xml.sax.SAXException The client may raise a 347: * processing exception. 348: * @see org.xml.sax.ContentHandler#endElement 349: */ 350: public void endElement (String uri, String localName, 351: String qName) 352: throws SAXException 353: { 354: if (documentHandler != null) 355: documentHandler.endElement(qName); 356: } 357: 358: 359: /** 360: * Adapt a SAX2 characters event. 361: * 362: * @param ch An array of characters. 363: * @param start The starting position in the array. 364: * @param length The number of characters to use. 365: * @exception org.xml.sax.SAXException The client may raise a 366: * processing exception. 367: * @see org.xml.sax.ContentHandler#characters 368: */ 369: public void characters (char ch[], int start, int length) 370: throws SAXException 371: { 372: if (documentHandler != null) 373: documentHandler.characters(ch, start, length); 374: } 375: 376: 377: /** 378: * Adapt a SAX2 ignorable whitespace event. 379: * 380: * @param ch An array of characters. 381: * @param start The starting position in the array. 382: * @param length The number of characters to use. 383: * @exception org.xml.sax.SAXException The client may raise a 384: * processing exception. 385: * @see org.xml.sax.ContentHandler#ignorableWhitespace 386: */ 387: public void ignorableWhitespace (char ch[], int start, int length) 388: throws SAXException 389: { 390: if (documentHandler != null) 391: documentHandler.ignorableWhitespace(ch, start, length); 392: } 393: 394: 395: /** 396: * Adapt a SAX2 processing instruction event. 397: * 398: * @param target The processing instruction target. 399: * @param data The remainder of the processing instruction 400: * @exception org.xml.sax.SAXException The client may raise a 401: * processing exception. 402: * @see org.xml.sax.ContentHandler#processingInstruction 403: */ 404: public void processingInstruction (String target, String data) 405: throws SAXException 406: { 407: if (documentHandler != null) 408: documentHandler.processingInstruction(target, data); 409: } 410: 411: 412: /** 413: * Adapt a SAX2 skipped entity event. 414: * 415: * @param name The name of the skipped entity. 416: * @see org.xml.sax.ContentHandler#skippedEntity 417: * @exception org.xml.sax.SAXException Throwable by subclasses. 418: */ 419: public void skippedEntity (String name) 420: throws SAXException 421: { 422: } 423: 424: 425: 426: //////////////////////////////////////////////////////////////////// 427: // Internal state. 428: //////////////////////////////////////////////////////////////////// 429: 430: XMLReader xmlReader; 431: DocumentHandler documentHandler; 432: AttributesAdapter qAtts; 433: 434: 435: 436: //////////////////////////////////////////////////////////////////// 437: // Internal class. 438: //////////////////////////////////////////////////////////////////// 439: 440: 441: /** 442: * Internal class to wrap a SAX2 Attributes object for SAX1. 443: */ 444: final class AttributesAdapter implements AttributeList 445: { 446: AttributesAdapter () 447: { 448: } 449: 450: 451: /** 452: * Set the embedded Attributes object. 453: * 454: * @param The embedded SAX2 Attributes. 455: */ 456: void setAttributes (Attributes attributes) 457: { 458: this.attributes = attributes; 459: } 460: 461: 462: /** 463: * Return the number of attributes. 464: * 465: * @return The length of the attribute list. 466: * @see org.xml.sax.AttributeList#getLength 467: */ 468: public int getLength () 469: { 470: return attributes.getLength(); 471: } 472: 473: 474: /** 475: * Return the qualified (prefixed) name of an attribute by position. 476: * 477: * @return The qualified name. 478: * @see org.xml.sax.AttributeList#getName 479: */ 480: public String getName (int i) 481: { 482: return attributes.getQName(i); 483: } 484: 485: 486: /** 487: * Return the type of an attribute by position. 488: * 489: * @return The type. 490: * @see org.xml.sax.AttributeList#getType(int) 491: */ 492: public String getType (int i) 493: { 494: return attributes.getType(i); 495: } 496: 497: 498: /** 499: * Return the value of an attribute by position. 500: * 501: * @return The value. 502: * @see org.xml.sax.AttributeList#getValue(int) 503: */ 504: public String getValue (int i) 505: { 506: return attributes.getValue(i); 507: } 508: 509: 510: /** 511: * Return the type of an attribute by qualified (prefixed) name. 512: * 513: * @return The type. 514: * @see org.xml.sax.AttributeList#getType(java.lang.String) 515: */ 516: public String getType (String qName) 517: { 518: return attributes.getType(qName); 519: } 520: 521: 522: /** 523: * Return the value of an attribute by qualified (prefixed) name. 524: * 525: * @return The value. 526: * @see org.xml.sax.AttributeList#getValue(java.lang.String) 527: */ 528: public String getValue (String qName) 529: { 530: return attributes.getValue(qName); 531: } 532: 533: private Attributes attributes; 534: } 535: 536: } 537: 538: // end of XMLReaderAdapter.java