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