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