SAXDriver.java 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
  1. /* SAXDriver.java --
  2. Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version.
  31. Portions derived from code which carried the following notice:
  32. Copyright (c) 1997, 1998 by Microstar Software Ltd.
  33. AElfred is free for both commercial and non-commercial use and
  34. redistribution, provided that Microstar's copyright and disclaimer are
  35. retained intact. You are free to modify AElfred for your own use and
  36. to redistribute AElfred with your modifications, provided that the
  37. modifications are clearly documented.
  38. This program is distributed in the hope that it will be useful, but
  39. WITHOUT ANY WARRANTY; without even the implied warranty of
  40. merchantability or fitness for a particular purpose. Please use it AT
  41. YOUR OWN RISK.
  42. */
  43. package gnu.xml.aelfred2;
  44. import java.io.*;
  45. import java.net.MalformedURLException;
  46. import java.net.URL;
  47. import java.util.Locale;
  48. import java.util.Stack;
  49. import java.util.ArrayList;
  50. import java.util.Collections;
  51. import java.util.Enumeration;
  52. import java.util.Iterator;
  53. import java.util.List;
  54. import org.xml.sax.*;
  55. import org.xml.sax.ext.*;
  56. import org.xml.sax.helpers.NamespaceSupport;
  57. /**
  58. * An enhanced SAX2 version of Microstar's Ælfred XML parser.
  59. * The enhancements primarily relate to significant improvements in
  60. * conformance to the XML specification, and SAX2 support. Performance
  61. * has been improved. See the package level documentation for more
  62. * information.
  63. *
  64. * <table border="1" width='100%' cellpadding='3' cellspacing='0'>
  65. * <tr bgcolor='#ccccff'>
  66. * <th><font size='+1'>Name</font></th>
  67. * <th><font size='+1'>Notes</font></th></tr>
  68. *
  69. * <tr><td colspan=2><center><em>Features ... URL prefix is
  70. * <b>http://xml.org/sax/features/</b></em></center></td></tr>
  71. *
  72. * <tr><td>(URL)/external-general-entities</td>
  73. * <td>Value defaults to <em>true</em></td></tr>
  74. * <tr><td>(URL)/external-parameter-entities</td>
  75. * <td>Value defaults to <em>true</em></td></tr>
  76. * <tr><td>(URL)/is-standalone</td>
  77. * <td>(PRELIMINARY) Returns true iff the document's parsing
  78. * has started (some non-error event after <em>startDocument()</em>
  79. * was reported) and the document's standalone flag is set.</td></tr>
  80. * <tr><td>(URL)/namespace-prefixes</td>
  81. * <td>Value defaults to <em>false</em> (but XML 1.0 names are
  82. * always reported)</td></tr>
  83. * <tr><td>(URL)/lexical-handler/parameter-entities</td>
  84. * <td>Value is fixed at <em>true</em></td></tr>
  85. * <tr><td>(URL)/namespaces</td>
  86. * <td>Value defaults to <em>true</em></td></tr>
  87. * <tr><td>(URL)/resolve-dtd-uris</td>
  88. * <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
  89. * <tr><td>(URL)/string-interning</td>
  90. * <td>Value is fixed at <em>true</em></td></tr>
  91. * <tr><td>(URL)/use-attributes2</td>
  92. * <td>(PRELIMINARY) Value is fixed at <em>true</em></td></tr>
  93. * <tr><td>(URL)/use-entity-resolver2</td>
  94. * <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
  95. * <tr><td>(URL)/validation</td>
  96. * <td>Value is fixed at <em>false</em></td></tr>
  97. *
  98. * <tr><td colspan=2><center><em>Handler Properties ... URL prefix is
  99. * <b>http://xml.org/sax/properties/</b></em></center></td></tr>
  100. *
  101. * <tr><td>(URL)/declaration-handler</td>
  102. * <td>A declaration handler may be provided. </td></tr>
  103. * <tr><td>(URL)/lexical-handler</td>
  104. * <td>A lexical handler may be provided. </td></tr>
  105. * </table>
  106. *
  107. * <p>This parser currently implements the SAX1 Parser API, but
  108. * it may not continue to do so in the future.
  109. *
  110. * @author Written by David Megginson (version 1.2a from Microstar)
  111. * @author Updated by David Brownell &lt;dbrownell@users.sourceforge.net&gt;
  112. * @see org.xml.sax.Parser
  113. */
  114. final public class SAXDriver
  115. implements Locator, Attributes2, XMLReader, Parser, AttributeList
  116. {
  117. private final DefaultHandler2 base = new DefaultHandler2();
  118. private XmlParser parser;
  119. private EntityResolver entityResolver = base;
  120. private EntityResolver2 resolver2 = null;
  121. private ContentHandler contentHandler = base;
  122. private DTDHandler dtdHandler = base;
  123. private ErrorHandler errorHandler = base;
  124. private DeclHandler declHandler = base;
  125. private LexicalHandler lexicalHandler = base;
  126. private String elementName;
  127. private Stack entityStack;
  128. // one vector (of object/struct): faster, smaller
  129. private List attributesList;
  130. private boolean namespaces = true;
  131. private boolean xmlNames = false;
  132. private boolean extGE = true;
  133. private boolean extPE = true;
  134. private boolean resolveAll = true;
  135. private boolean useResolver2 = true;
  136. // package private to allow (read-only) access in XmlParser
  137. boolean stringInterning = true;
  138. private int attributeCount;
  139. private boolean attributes;
  140. private String[] nsTemp;
  141. private NamespaceSupport prefixStack;
  142. //
  143. // Constructor.
  144. //
  145. /**
  146. * Constructs a SAX Parser.
  147. */
  148. public SAXDriver()
  149. {
  150. reset();
  151. }
  152. private void reset()
  153. {
  154. elementName = null;
  155. entityStack = new Stack();
  156. attributesList = Collections.synchronizedList(new ArrayList());
  157. attributeCount = 0;
  158. attributes = false;
  159. nsTemp = new String[3];
  160. prefixStack = null;
  161. }
  162. //
  163. // Implementation of org.xml.sax.Parser.
  164. //
  165. /**
  166. * <b>SAX1</b>: Sets the locale used for diagnostics; currently,
  167. * only locales using the English language are supported.
  168. * @param locale The locale for which diagnostics will be generated
  169. */
  170. public void setLocale(Locale locale)
  171. throws SAXException
  172. {
  173. if ("en".equals(locale.getLanguage()))
  174. {
  175. return;
  176. }
  177. throw new SAXException ("AElfred2 only supports English locales.");
  178. }
  179. /**
  180. * <b>SAX2</b>: Returns the object used when resolving external
  181. * entities during parsing (both general and parameter entities).
  182. */
  183. public EntityResolver getEntityResolver()
  184. {
  185. return (entityResolver == base) ? null : entityResolver;
  186. }
  187. /**
  188. * <b>SAX1, SAX2</b>: Set the entity resolver for this parser.
  189. * @param handler The object to receive entity events.
  190. */
  191. public void setEntityResolver(EntityResolver resolver)
  192. {
  193. if (resolver instanceof EntityResolver2)
  194. {
  195. resolver2 = (EntityResolver2) resolver;
  196. }
  197. else
  198. {
  199. resolver2 = null;
  200. }
  201. if (resolver == null)
  202. {
  203. resolver = base;
  204. }
  205. entityResolver = resolver;
  206. }
  207. /**
  208. * <b>SAX2</b>: Returns the object used to process declarations related
  209. * to notations and unparsed entities.
  210. */
  211. public DTDHandler getDTDHandler()
  212. {
  213. return (dtdHandler == base) ? null : dtdHandler;
  214. }
  215. /**
  216. * <b>SAX1, SAX2</b>: Set the DTD handler for this parser.
  217. * @param handler The object to receive DTD events.
  218. */
  219. public void setDTDHandler(DTDHandler handler)
  220. {
  221. if (handler == null)
  222. {
  223. handler = base;
  224. }
  225. this.dtdHandler = handler;
  226. }
  227. /**
  228. * <b>SAX1</b>: Set the document handler for this parser. If a
  229. * content handler was set, this document handler will supplant it.
  230. * The parser is set to report all XML 1.0 names rather than to
  231. * filter out "xmlns" attributes (the "namespace-prefixes" feature
  232. * is set to true).
  233. *
  234. * @deprecated SAX2 programs should use the XMLReader interface
  235. * and a ContentHandler.
  236. *
  237. * @param handler The object to receive document events.
  238. */
  239. public void setDocumentHandler(DocumentHandler handler)
  240. {
  241. contentHandler = new Adapter(handler);
  242. xmlNames = true;
  243. }
  244. /**
  245. * <b>SAX2</b>: Returns the object used to report the logical
  246. * content of an XML document.
  247. */
  248. public ContentHandler getContentHandler()
  249. {
  250. return (contentHandler == base) ? null : contentHandler;
  251. }
  252. /**
  253. * <b>SAX2</b>: Assigns the object used to report the logical
  254. * content of an XML document. If a document handler was set,
  255. * this content handler will supplant it (but XML 1.0 style name
  256. * reporting may remain enabled).
  257. */
  258. public void setContentHandler(ContentHandler handler)
  259. {
  260. if (handler == null)
  261. {
  262. handler = base;
  263. }
  264. contentHandler = handler;
  265. }
  266. /**
  267. * <b>SAX1, SAX2</b>: Set the error handler for this parser.
  268. * @param handler The object to receive error events.
  269. */
  270. public void setErrorHandler(ErrorHandler handler)
  271. {
  272. if (handler == null)
  273. {
  274. handler = base;
  275. }
  276. this.errorHandler = handler;
  277. }
  278. /**
  279. * <b>SAX2</b>: Returns the object used to receive callbacks for XML
  280. * errors of all levels (fatal, nonfatal, warning); this is never null;
  281. */
  282. public ErrorHandler getErrorHandler()
  283. {
  284. return (errorHandler == base) ? null : errorHandler;
  285. }
  286. /**
  287. * <b>SAX1, SAX2</b>: Auxiliary API to parse an XML document, used mostly
  288. * when no URI is available.
  289. * If you want anything useful to happen, you should set
  290. * at least one type of handler.
  291. * @param source The XML input source. Don't set 'encoding' unless
  292. * you know for a fact that it's correct.
  293. * @see #setEntityResolver
  294. * @see #setDTDHandler
  295. * @see #setContentHandler
  296. * @see #setErrorHandler
  297. * @exception SAXException The handlers may throw any SAXException,
  298. * and the parser normally throws SAXParseException objects.
  299. * @exception IOException IOExceptions are normally through through
  300. * the parser if there are problems reading the source document.
  301. */
  302. public void parse(InputSource source)
  303. throws SAXException, IOException
  304. {
  305. synchronized (base)
  306. {
  307. parser = new XmlParser();
  308. if (namespaces)
  309. {
  310. prefixStack = new NamespaceSupport();
  311. }
  312. else if (!xmlNames)
  313. {
  314. throw new IllegalStateException();
  315. }
  316. parser.setHandler(this);
  317. try
  318. {
  319. Reader r = source.getCharacterStream();
  320. InputStream in = source.getByteStream();
  321. parser.doParse(source.getSystemId(),
  322. source.getPublicId(),
  323. r,
  324. in,
  325. source.getEncoding());
  326. }
  327. catch (SAXException e)
  328. {
  329. throw e;
  330. }
  331. catch (IOException e)
  332. {
  333. throw e;
  334. }
  335. catch (RuntimeException e)
  336. {
  337. throw e;
  338. }
  339. catch (Exception e)
  340. {
  341. throw new SAXParseException(e.getMessage(), this, e);
  342. }
  343. finally
  344. {
  345. contentHandler.endDocument();
  346. reset();
  347. }
  348. }
  349. }
  350. /**
  351. * <b>SAX1, SAX2</b>: Preferred API to parse an XML document, using a
  352. * system identifier (URI).
  353. */
  354. public void parse(String systemId)
  355. throws SAXException, IOException
  356. {
  357. parse(new InputSource(systemId));
  358. }
  359. //
  360. // Implementation of SAX2 "XMLReader" interface
  361. //
  362. static final String FEATURE = "http://xml.org/sax/features/";
  363. static final String PROPERTY = "http://xml.org/sax/properties/";
  364. /**
  365. * <b>SAX2</b>: Tells the value of the specified feature flag.
  366. *
  367. * @exception SAXNotRecognizedException thrown if the feature flag
  368. * is neither built in, nor yet assigned.
  369. */
  370. public boolean getFeature(String featureId)
  371. throws SAXNotRecognizedException, SAXNotSupportedException
  372. {
  373. if ((FEATURE + "validation").equals(featureId))
  374. {
  375. return false;
  376. }
  377. // external entities (both types) are optionally included
  378. if ((FEATURE + "external-general-entities").equals(featureId))
  379. {
  380. return extGE;
  381. }
  382. if ((FEATURE + "external-parameter-entities").equals(featureId))
  383. {
  384. return extPE;
  385. }
  386. // element/attribute names are as written in document; no mangling
  387. if ((FEATURE + "namespace-prefixes").equals(featureId))
  388. {
  389. return xmlNames;
  390. }
  391. // report element/attribute namespaces?
  392. if ((FEATURE + "namespaces").equals(featureId))
  393. {
  394. return namespaces;
  395. }
  396. // all PEs and GEs are reported
  397. if ((FEATURE + "lexical-handler/parameter-entities").equals(featureId))
  398. {
  399. return true;
  400. }
  401. // default is true
  402. if ((FEATURE + "string-interning").equals(featureId))
  403. {
  404. return stringInterning;
  405. }
  406. // EXTENSIONS 1.1
  407. // always returns isSpecified info
  408. if ((FEATURE + "use-attributes2").equals(featureId))
  409. {
  410. return true;
  411. }
  412. // meaningful between startDocument/endDocument
  413. if ((FEATURE + "is-standalone").equals(featureId))
  414. {
  415. if (parser == null)
  416. {
  417. throw new SAXNotSupportedException(featureId);
  418. }
  419. return parser.isStandalone();
  420. }
  421. // optionally don't absolutize URIs in declarations
  422. if ((FEATURE + "resolve-dtd-uris").equals(featureId))
  423. {
  424. return resolveAll;
  425. }
  426. // optionally use resolver2 interface methods, if possible
  427. if ((FEATURE + "use-entity-resolver2").equals(featureId))
  428. {
  429. return useResolver2;
  430. }
  431. throw new SAXNotRecognizedException(featureId);
  432. }
  433. // package private
  434. DeclHandler getDeclHandler()
  435. {
  436. return declHandler;
  437. }
  438. // package private
  439. boolean resolveURIs()
  440. {
  441. return resolveAll;
  442. }
  443. /**
  444. * <b>SAX2</b>: Returns the specified property.
  445. *
  446. * @exception SAXNotRecognizedException thrown if the property value
  447. * is neither built in, nor yet stored.
  448. */
  449. public Object getProperty(String propertyId)
  450. throws SAXNotRecognizedException
  451. {
  452. if ((PROPERTY + "declaration-handler").equals(propertyId))
  453. {
  454. return (declHandler == base) ? null : declHandler;
  455. }
  456. if ((PROPERTY + "lexical-handler").equals(propertyId))
  457. {
  458. return (lexicalHandler == base) ? null : lexicalHandler;
  459. }
  460. // unknown properties
  461. throw new SAXNotRecognizedException(propertyId);
  462. }
  463. /**
  464. * <b>SAX2</b>: Sets the state of feature flags in this parser. Some
  465. * built-in feature flags are mutable.
  466. */
  467. public void setFeature(String featureId, boolean value)
  468. throws SAXNotRecognizedException, SAXNotSupportedException
  469. {
  470. boolean state;
  471. // Features with a defined value, we just change it if we can.
  472. state = getFeature (featureId);
  473. if (state == value)
  474. {
  475. return;
  476. }
  477. if (parser != null)
  478. {
  479. throw new SAXNotSupportedException("not while parsing");
  480. }
  481. if ((FEATURE + "namespace-prefixes").equals(featureId))
  482. {
  483. // in this implementation, this only affects xmlns reporting
  484. xmlNames = value;
  485. // forcibly prevent illegal parser state
  486. if (!xmlNames)
  487. {
  488. namespaces = true;
  489. }
  490. return;
  491. }
  492. if ((FEATURE + "namespaces").equals(featureId))
  493. {
  494. namespaces = value;
  495. // forcibly prevent illegal parser state
  496. if (!namespaces)
  497. {
  498. xmlNames = true;
  499. }
  500. return;
  501. }
  502. if ((FEATURE + "external-general-entities").equals(featureId))
  503. {
  504. extGE = value;
  505. return;
  506. }
  507. if ((FEATURE + "external-parameter-entities").equals(featureId))
  508. {
  509. extPE = value;
  510. return;
  511. }
  512. if ((FEATURE + "resolve-dtd-uris").equals(featureId))
  513. {
  514. resolveAll = value;
  515. return;
  516. }
  517. if ((FEATURE + "use-entity-resolver2").equals(featureId))
  518. {
  519. useResolver2 = value;
  520. return;
  521. }
  522. throw new SAXNotRecognizedException(featureId);
  523. }
  524. /**
  525. * <b>SAX2</b>: Assigns the specified property. Like SAX1 handlers,
  526. * these may be changed at any time.
  527. */
  528. public void setProperty(String propertyId, Object value)
  529. throws SAXNotRecognizedException, SAXNotSupportedException
  530. {
  531. // see if the property is recognized
  532. getProperty(propertyId);
  533. // Properties with a defined value, we just change it if we can.
  534. if ((PROPERTY + "declaration-handler").equals(propertyId))
  535. {
  536. if (value == null)
  537. {
  538. declHandler = base;
  539. }
  540. else if (!(value instanceof DeclHandler))
  541. {
  542. throw new SAXNotSupportedException(propertyId);
  543. }
  544. else
  545. {
  546. declHandler = (DeclHandler) value;
  547. }
  548. return ;
  549. }
  550. if ((PROPERTY + "lexical-handler").equals(propertyId))
  551. {
  552. if (value == null)
  553. {
  554. lexicalHandler = base;
  555. }
  556. else if (!(value instanceof LexicalHandler))
  557. {
  558. throw new SAXNotSupportedException(propertyId);
  559. }
  560. else
  561. {
  562. lexicalHandler = (LexicalHandler) value;
  563. }
  564. return;
  565. }
  566. throw new SAXNotSupportedException(propertyId);
  567. }
  568. //
  569. // This is where the driver receives XmlParser callbacks and translates
  570. // them into SAX callbacks. Some more callbacks have been added for
  571. // SAX2 support.
  572. //
  573. void startDocument()
  574. throws SAXException
  575. {
  576. contentHandler.setDocumentLocator(this);
  577. contentHandler.startDocument();
  578. attributesList.clear();
  579. }
  580. void skippedEntity(String name)
  581. throws SAXException
  582. {
  583. contentHandler.skippedEntity(name);
  584. }
  585. InputSource getExternalSubset(String name, String baseURI)
  586. throws SAXException, IOException
  587. {
  588. if (resolver2 == null || !useResolver2 || !extPE)
  589. {
  590. return null;
  591. }
  592. return resolver2.getExternalSubset(name, baseURI);
  593. }
  594. InputSource resolveEntity(boolean isPE, String name,
  595. InputSource in, String baseURI)
  596. throws SAXException, IOException
  597. {
  598. InputSource source;
  599. // external entities might be skipped
  600. if (isPE && !extPE)
  601. {
  602. return null;
  603. }
  604. if (!isPE && !extGE)
  605. {
  606. return null;
  607. }
  608. // ... or not
  609. lexicalHandler.startEntity(name);
  610. if (resolver2 != null && useResolver2)
  611. {
  612. source = resolver2.resolveEntity(name, in.getPublicId(),
  613. baseURI, in.getSystemId());
  614. if (source == null)
  615. {
  616. in.setSystemId(absolutize(baseURI,
  617. in.getSystemId(), false));
  618. source = in;
  619. }
  620. }
  621. else
  622. {
  623. in.setSystemId(absolutize(baseURI,
  624. in.getSystemId(),
  625. entityResolver != base));
  626. source = entityResolver.resolveEntity(in.getPublicId(),
  627. in.getSystemId());
  628. if (source == null)
  629. {
  630. source = in;
  631. }
  632. }
  633. startExternalEntity(name, source.getSystemId(), true);
  634. return source;
  635. }
  636. // absolutize a system ID relative to the specified base URI
  637. // (temporarily) package-visible for external entity decls
  638. String absolutize(String baseURI, String systemId, boolean nice)
  639. throws MalformedURLException, SAXException
  640. {
  641. // FIXME normalize system IDs -- when?
  642. // - Convert to UTF-8
  643. // - Map reserved and non-ASCII characters to %HH
  644. try
  645. {
  646. if (baseURI == null)
  647. {
  648. if (XmlParser.uriWarnings)
  649. {
  650. warn ("No base URI; hope this SYSTEM id is absolute: "
  651. + systemId);
  652. }
  653. return new URL(systemId).toString();
  654. }
  655. else
  656. {
  657. return new URL(new URL(baseURI), systemId).toString();
  658. }
  659. }
  660. catch (MalformedURLException e)
  661. {
  662. // Let unknown URI schemes pass through unless we need
  663. // the JVM to map them to i/o streams for us...
  664. if (!nice)
  665. {
  666. throw e;
  667. }
  668. // sometimes sysids for notations or unparsed entities
  669. // aren't really URIs...
  670. warn("Can't absolutize SYSTEM id: " + e.getMessage());
  671. return systemId;
  672. }
  673. }
  674. void startExternalEntity(String name, String systemId, boolean stackOnly)
  675. throws SAXException
  676. {
  677. // The following warning was deleted because the application has the
  678. // option of not setting systemId. Sun's JAXP or Xerces seems to
  679. // ignore this case.
  680. /*
  681. if (systemId == null)
  682. warn ("URI was not reported to parser for entity " + name);
  683. */
  684. if (!stackOnly) // spliced [dtd] needs startEntity
  685. {
  686. lexicalHandler.startEntity(name);
  687. }
  688. entityStack.push(systemId);
  689. }
  690. void endExternalEntity(String name)
  691. throws SAXException
  692. {
  693. if (!"[document]".equals(name))
  694. {
  695. lexicalHandler.endEntity(name);
  696. }
  697. entityStack.pop();
  698. }
  699. void startInternalEntity(String name)
  700. throws SAXException
  701. {
  702. lexicalHandler.startEntity(name);
  703. }
  704. void endInternalEntity(String name)
  705. throws SAXException
  706. {
  707. lexicalHandler.endEntity(name);
  708. }
  709. void doctypeDecl(String name, String publicId, String systemId)
  710. throws SAXException
  711. {
  712. lexicalHandler.startDTD(name, publicId, systemId);
  713. // ... the "name" is a declaration and should be given
  714. // to the DeclHandler (but sax2 doesn't).
  715. // the IDs for the external subset are lexical details,
  716. // as are the contents of the internal subset; but sax2
  717. // doesn't provide the internal subset "pre-parse"
  718. }
  719. void notationDecl(String name, String publicId, String systemId,
  720. String baseUri)
  721. throws SAXException
  722. {
  723. try
  724. {
  725. dtdHandler.notationDecl(name, publicId,
  726. (resolveAll && systemId != null)
  727. ? absolutize(baseUri, systemId, true)
  728. : systemId);
  729. }
  730. catch (IOException e)
  731. {
  732. // "can't happen"
  733. throw new SAXParseException(e.getMessage(), this, e);
  734. }
  735. }
  736. void unparsedEntityDecl(String name, String publicId, String systemId,
  737. String baseUri, String notation)
  738. throws SAXException
  739. {
  740. try
  741. {
  742. dtdHandler.unparsedEntityDecl(name, publicId,
  743. resolveAll
  744. ? absolutize(baseUri, systemId, true)
  745. : systemId,
  746. notation);
  747. }
  748. catch (IOException e)
  749. {
  750. // "can't happen"
  751. throw new SAXParseException(e.getMessage(), this, e);
  752. }
  753. }
  754. void endDoctype()
  755. throws SAXException
  756. {
  757. lexicalHandler.endDTD();
  758. }
  759. private void declarePrefix(String prefix, String uri)
  760. throws SAXException
  761. {
  762. int index = uri.indexOf(':');
  763. // many versions of nwalsh docbook stylesheets
  764. // have bogus URLs; so this can't be an error...
  765. if (index < 1 && uri.length() != 0)
  766. {
  767. warn("relative URI for namespace: " + uri);
  768. }
  769. // FIXME: char [0] must be ascii alpha; chars [1..index]
  770. // must be ascii alphanumeric or in "+-." [RFC 2396]
  771. //Namespace Constraints
  772. //name for xml prefix must be http://www.w3.org/XML/1998/namespace
  773. boolean prefixEquality = prefix.equals("xml");
  774. boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace");
  775. if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
  776. {
  777. fatal("xml is by definition bound to the namespace name " +
  778. "http://www.w3.org/XML/1998/namespace");
  779. }
  780. //xmlns prefix declaration is illegal but xml prefix declaration is llegal...
  781. if (prefixEquality && uriEquality)
  782. {
  783. return;
  784. }
  785. //name for xmlns prefix must be http://www.w3.org/2000/xmlns/
  786. prefixEquality = prefix.equals("xmlns");
  787. uriEquality = uri.equals("http://www.w3.org/2000/xmlns/");
  788. if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
  789. {
  790. fatal("http://www.w3.org/2000/xmlns/ is by definition bound" +
  791. " to prefix xmlns");
  792. }
  793. //even if the uri is http://www.w3.org/2000/xmlns/
  794. // it is illegal to declare it
  795. if (prefixEquality && uriEquality)
  796. {
  797. fatal ("declaring the xmlns prefix is illegal");
  798. }
  799. uri = uri.intern();
  800. prefixStack.declarePrefix(prefix, uri);
  801. contentHandler.startPrefixMapping(prefix, uri);
  802. }
  803. void attribute(String qname, String value, boolean isSpecified)
  804. throws SAXException
  805. {
  806. if (!attributes)
  807. {
  808. attributes = true;
  809. if (namespaces)
  810. {
  811. prefixStack.pushContext();
  812. }
  813. }
  814. // process namespace decls immediately;
  815. // then maybe forget this as an attribute
  816. if (namespaces)
  817. {
  818. int index;
  819. // default NS declaration?
  820. if (stringInterning)
  821. {
  822. if ("xmlns" == qname)
  823. {
  824. declarePrefix("", value);
  825. if (!xmlNames)
  826. {
  827. return;
  828. }
  829. }
  830. // NS prefix declaration?
  831. else if ((index = qname.indexOf(':')) == 5
  832. && qname.startsWith("xmlns"))
  833. {
  834. String prefix = qname.substring(6);
  835. if (prefix.equals(""))
  836. {
  837. fatal("missing prefix " +
  838. "in namespace declaration attribute");
  839. }
  840. if (value.length() == 0)
  841. {
  842. verror("missing URI in namespace declaration attribute: "
  843. + qname);
  844. }
  845. else
  846. {
  847. declarePrefix(prefix, value);
  848. }
  849. if (!xmlNames)
  850. {
  851. return;
  852. }
  853. }
  854. }
  855. else
  856. {
  857. if ("xmlns".equals(qname))
  858. {
  859. declarePrefix("", value);
  860. if (!xmlNames)
  861. {
  862. return;
  863. }
  864. }
  865. // NS prefix declaration?
  866. else if ((index = qname.indexOf(':')) == 5
  867. && qname.startsWith("xmlns"))
  868. {
  869. String prefix = qname.substring(6);
  870. if (value.length() == 0)
  871. {
  872. verror("missing URI in namespace decl attribute: "
  873. + qname);
  874. }
  875. else
  876. {
  877. declarePrefix(prefix, value);
  878. }
  879. if (!xmlNames)
  880. {
  881. return;
  882. }
  883. }
  884. }
  885. }
  886. // remember this attribute ...
  887. attributeCount++;
  888. // attribute type comes from querying parser's DTD records
  889. attributesList.add(new Attribute(qname, value, isSpecified));
  890. }
  891. void startElement(String elname)
  892. throws SAXException
  893. {
  894. ContentHandler handler = contentHandler;
  895. //
  896. // NOTE: this implementation of namespace support adds something
  897. // like six percent to parsing CPU time, in a large (~50 MB)
  898. // document that doesn't use namespaces at all. (Measured by PC
  899. // sampling, with a bug where endElement processing was omitted.)
  900. // [Measurement referred to older implementation, older JVM ...]
  901. //
  902. // It ought to become notably faster in such cases. Most
  903. // costs are the prefix stack calling Hashtable.get() (2%),
  904. // String.hashCode() (1.5%) and about 1.3% each for pushing
  905. // the context, and two chunks of name processing.
  906. //
  907. if (!attributes)
  908. {
  909. if (namespaces)
  910. {
  911. prefixStack.pushContext();
  912. }
  913. }
  914. else if (namespaces)
  915. {
  916. // now we can patch up namespace refs; we saw all the
  917. // declarations, so now we'll do the Right Thing
  918. Iterator itt = attributesList.iterator();
  919. while (itt.hasNext())
  920. {
  921. Attribute attribute = (Attribute) itt.next();
  922. String qname = attribute.name;
  923. int index;
  924. // default NS declaration?
  925. if (stringInterning)
  926. {
  927. if ("xmlns" == qname)
  928. {
  929. continue;
  930. }
  931. }
  932. else
  933. {
  934. if ("xmlns".equals(qname))
  935. {
  936. continue;
  937. }
  938. }
  939. //Illegal in the new Namespaces Draft
  940. //should it be only in 1.1 docs??
  941. if (qname.equals (":"))
  942. {
  943. fatal("namespace names consisting of a single colon " +
  944. "character are invalid");
  945. }
  946. index = qname.indexOf(':');
  947. // NS prefix declaration?
  948. if (index == 5 && qname.startsWith("xmlns"))
  949. {
  950. continue;
  951. }
  952. // it's not a NS decl; patch namespace info items
  953. if (prefixStack.processName(qname, nsTemp, true) == null)
  954. {
  955. fatal("undeclared attribute prefix in: " + qname);
  956. }
  957. else
  958. {
  959. attribute.nameSpace = nsTemp[0];
  960. attribute.localName = nsTemp[1];
  961. }
  962. }
  963. }
  964. // save element name so attribute callbacks work
  965. elementName = elname;
  966. if (namespaces)
  967. {
  968. if (prefixStack.processName(elname, nsTemp, false) == null)
  969. {
  970. fatal("undeclared element prefix in: " + elname);
  971. nsTemp[0] = nsTemp[1] = "";
  972. }
  973. handler.startElement(nsTemp[0], nsTemp[1], elname, this);
  974. }
  975. else
  976. {
  977. handler.startElement("", "", elname, this);
  978. }
  979. // elementName = null;
  980. // elements with no attributes are pretty common!
  981. if (attributes)
  982. {
  983. attributesList.clear();
  984. attributeCount = 0;
  985. attributes = false;
  986. }
  987. }
  988. void endElement(String elname)
  989. throws SAXException
  990. {
  991. ContentHandler handler = contentHandler;
  992. if (!namespaces)
  993. {
  994. handler.endElement("", "", elname);
  995. return;
  996. }
  997. prefixStack.processName(elname, nsTemp, false);
  998. handler.endElement(nsTemp[0], nsTemp[1], elname);
  999. Enumeration prefixes = prefixStack.getDeclaredPrefixes();
  1000. while (prefixes.hasMoreElements())
  1001. {
  1002. handler.endPrefixMapping((String) prefixes.nextElement());
  1003. }
  1004. prefixStack.popContext();
  1005. }
  1006. void startCDATA()
  1007. throws SAXException
  1008. {
  1009. lexicalHandler.startCDATA();
  1010. }
  1011. void charData(char[] ch, int start, int length)
  1012. throws SAXException
  1013. {
  1014. contentHandler.characters(ch, start, length);
  1015. }
  1016. void endCDATA()
  1017. throws SAXException
  1018. {
  1019. lexicalHandler.endCDATA();
  1020. }
  1021. void ignorableWhitespace(char[] ch, int start, int length)
  1022. throws SAXException
  1023. {
  1024. contentHandler.ignorableWhitespace(ch, start, length);
  1025. }
  1026. void processingInstruction(String target, String data)
  1027. throws SAXException
  1028. {
  1029. contentHandler.processingInstruction(target, data);
  1030. }
  1031. void comment(char[] ch, int start, int length)
  1032. throws SAXException
  1033. {
  1034. if (lexicalHandler != base)
  1035. {
  1036. lexicalHandler.comment(ch, start, length);
  1037. }
  1038. }
  1039. void fatal(String message)
  1040. throws SAXException
  1041. {
  1042. SAXParseException fatal;
  1043. fatal = new SAXParseException(message, this);
  1044. errorHandler.fatalError(fatal);
  1045. // Even if the application can continue ... we can't!
  1046. throw fatal;
  1047. }
  1048. // We can safely report a few validity errors that
  1049. // make layered SAX2 DTD validation more conformant
  1050. void verror(String message)
  1051. throws SAXException
  1052. {
  1053. SAXParseException err;
  1054. err = new SAXParseException(message, this);
  1055. errorHandler.error(err);
  1056. }
  1057. void warn(String message)
  1058. throws SAXException
  1059. {
  1060. SAXParseException err;
  1061. err = new SAXParseException(message, this);
  1062. errorHandler.warning(err);
  1063. }
  1064. //
  1065. // Implementation of org.xml.sax.Attributes.
  1066. //
  1067. /**
  1068. * <b>SAX1 AttributeList, SAX2 Attributes</b> method
  1069. * (don't invoke on parser);
  1070. */
  1071. public int getLength()
  1072. {
  1073. return attributesList.size();
  1074. }
  1075. /**
  1076. * <b>SAX2 Attributes</b> method (don't invoke on parser);
  1077. */
  1078. public String getURI(int index)
  1079. {
  1080. if (index < 0 || index >= attributesList.size())
  1081. {
  1082. return null;
  1083. }
  1084. return ((Attribute) attributesList.get(index)).nameSpace;
  1085. }
  1086. /**
  1087. * <b>SAX2 Attributes</b> method (don't invoke on parser);
  1088. */
  1089. public String getLocalName(int index)
  1090. {
  1091. if (index < 0 || index >= attributesList.size())
  1092. {
  1093. return null;
  1094. }
  1095. Attribute attr = (Attribute) attributesList.get(index);
  1096. // FIXME attr.localName is sometimes null, why?
  1097. if (namespaces && attr.localName == null)
  1098. {
  1099. // XXX fix this here for now
  1100. int ci = attr.name.indexOf(':');
  1101. attr.localName = (ci == -1) ? attr.name :
  1102. attr.name.substring(ci + 1);
  1103. }
  1104. return (attr.localName == null) ? "" : attr.localName;
  1105. }
  1106. /**
  1107. * <b>SAX2 Attributes</b> method (don't invoke on parser);
  1108. */
  1109. public String getQName(int index)
  1110. {
  1111. if (index < 0 || index >= attributesList.size())
  1112. {
  1113. return null;
  1114. }
  1115. Attribute attr = (Attribute) attributesList.get(index);
  1116. return (attr.name == null) ? "" : attr.name;
  1117. }
  1118. /**
  1119. * <b>SAX1 AttributeList</b> method (don't invoke on parser);
  1120. */
  1121. public String getName(int index)
  1122. {
  1123. return getQName(index);
  1124. }
  1125. /**
  1126. * <b>SAX1 AttributeList, SAX2 Attributes</b> method
  1127. * (don't invoke on parser);
  1128. */
  1129. public String getType(int index)
  1130. {
  1131. if (index < 0 || index >= attributesList.size())
  1132. {
  1133. return null;
  1134. }
  1135. String type = parser.getAttributeType(elementName, getQName(index));
  1136. if (type == null)
  1137. {
  1138. return "CDATA";
  1139. }
  1140. // ... use DeclHandler.attributeDecl to see enumerations
  1141. if (type == "ENUMERATION")
  1142. {
  1143. return "NMTOKEN";
  1144. }
  1145. return type;
  1146. }
  1147. /**
  1148. * <b>SAX1 AttributeList, SAX2 Attributes</b> method
  1149. * (don't invoke on parser);
  1150. */
  1151. public String getValue(int index)
  1152. {
  1153. if (index < 0 || index >= attributesList.size())
  1154. {
  1155. return null;
  1156. }
  1157. return ((Attribute) attributesList.get(index)).value;
  1158. }
  1159. /**
  1160. * <b>SAX2 Attributes</b> method (don't invoke on parser);
  1161. */
  1162. public int getIndex(String uri, String local)
  1163. {
  1164. int length = getLength();
  1165. for (int i = 0; i < length; i++)
  1166. {
  1167. if (!getURI(i).equals(uri))
  1168. {
  1169. continue;
  1170. }
  1171. if (getLocalName(i).equals(local))
  1172. {
  1173. return i;
  1174. }
  1175. }
  1176. return -1;
  1177. }
  1178. /**
  1179. * <b>SAX2 Attributes</b> method (don't invoke on parser);
  1180. */
  1181. public int getIndex(String xmlName)
  1182. {
  1183. int length = getLength();
  1184. for (int i = 0; i < length; i++)
  1185. {
  1186. if (getQName(i).equals(xmlName))
  1187. {
  1188. return i;
  1189. }
  1190. }
  1191. return -1;
  1192. }
  1193. /**
  1194. * <b>SAX2 Attributes</b> method (don't invoke on parser);
  1195. */
  1196. public String getType(String uri, String local)
  1197. {
  1198. int index = getIndex(uri, local);
  1199. if (index < 0)
  1200. {
  1201. return null;
  1202. }
  1203. return getType(index);
  1204. }
  1205. /**
  1206. * <b>SAX1 AttributeList, SAX2 Attributes</b> method
  1207. * (don't invoke on parser);
  1208. */
  1209. public String getType(String xmlName)
  1210. {
  1211. int index = getIndex(xmlName);
  1212. if (index < 0)
  1213. {
  1214. return null;
  1215. }
  1216. return getType(index);
  1217. }
  1218. /**
  1219. * <b>SAX Attributes</b> method (don't invoke on parser);
  1220. */
  1221. public String getValue(String uri, String local)
  1222. {
  1223. int index = getIndex(uri, local);
  1224. if (index < 0)
  1225. {
  1226. return null;
  1227. }
  1228. return getValue(index);
  1229. }
  1230. /**
  1231. * <b>SAX1 AttributeList, SAX2 Attributes</b> method
  1232. * (don't invoke on parser);
  1233. */
  1234. public String getValue(String xmlName)
  1235. {
  1236. int index = getIndex(xmlName);
  1237. if (index < 0)
  1238. {
  1239. return null;
  1240. }
  1241. return getValue(index);
  1242. }
  1243. //
  1244. // Implementation of org.xml.sax.ext.Attributes2
  1245. //
  1246. /** @return false unless the attribute was declared in the DTD.
  1247. * @throws java.lang.ArrayIndexOutOfBoundsException
  1248. * When the supplied index does not identify an attribute.
  1249. */
  1250. public boolean isDeclared(int index)
  1251. {
  1252. if (index < 0 || index >= attributeCount)
  1253. {
  1254. throw new ArrayIndexOutOfBoundsException();
  1255. }
  1256. String type = parser.getAttributeType(elementName, getQName(index));
  1257. return (type != null);
  1258. }
  1259. /** @return false unless the attribute was declared in the DTD.
  1260. * @throws java.lang.IllegalArgumentException
  1261. * When the supplied names do not identify an attribute.
  1262. */
  1263. public boolean isDeclared(String qName)
  1264. {
  1265. int index = getIndex(qName);
  1266. if (index < 0)
  1267. {
  1268. throw new IllegalArgumentException();
  1269. }
  1270. String type = parser.getAttributeType(elementName, qName);
  1271. return (type != null);
  1272. }
  1273. /** @return false unless the attribute was declared in the DTD.
  1274. * @throws java.lang.IllegalArgumentException
  1275. * When the supplied names do not identify an attribute.
  1276. */
  1277. public boolean isDeclared(String uri, String localName)
  1278. {
  1279. int index = getIndex(uri, localName);
  1280. return isDeclared(index);
  1281. }
  1282. /**
  1283. * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
  1284. */
  1285. public boolean isSpecified(int index)
  1286. {
  1287. return ((Attribute) attributesList.get(index)).specified;
  1288. }
  1289. /**
  1290. * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
  1291. */
  1292. public boolean isSpecified(String uri, String local)
  1293. {
  1294. int index = getIndex (uri, local);
  1295. return isSpecified(index);
  1296. }
  1297. /**
  1298. * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
  1299. */
  1300. public boolean isSpecified(String xmlName)
  1301. {
  1302. int index = getIndex (xmlName);
  1303. return isSpecified(index);
  1304. }
  1305. //
  1306. // Implementation of org.xml.sax.Locator.
  1307. //
  1308. /**
  1309. * <b>SAX Locator</b> method (don't invoke on parser);
  1310. */
  1311. public String getPublicId()
  1312. {
  1313. return null; // FIXME track public IDs too
  1314. }
  1315. /**
  1316. * <b>SAX Locator</b> method (don't invoke on parser);
  1317. */
  1318. public String getSystemId()
  1319. {
  1320. if (entityStack.empty())
  1321. {
  1322. return null;
  1323. }
  1324. else
  1325. {
  1326. return (String) entityStack.peek();
  1327. }
  1328. }
  1329. /**
  1330. * <b>SAX Locator</b> method (don't invoke on parser);
  1331. */
  1332. public int getLineNumber()
  1333. {
  1334. return parser.getLineNumber();
  1335. }
  1336. /**
  1337. * <b>SAX Locator</b> method (don't invoke on parser);
  1338. */
  1339. public int getColumnNumber()
  1340. {
  1341. return parser.getColumnNumber();
  1342. }
  1343. // adapter between SAX2 content handler and SAX1 document handler callbacks
  1344. private static class Adapter
  1345. implements ContentHandler
  1346. {
  1347. private DocumentHandler docHandler;
  1348. Adapter(DocumentHandler dh)
  1349. {
  1350. docHandler = dh;
  1351. }
  1352. public void setDocumentLocator(Locator l)
  1353. {
  1354. docHandler.setDocumentLocator(l);
  1355. }
  1356. public void startDocument()
  1357. throws SAXException
  1358. {
  1359. docHandler.startDocument();
  1360. }
  1361. public void processingInstruction(String target, String data)
  1362. throws SAXException
  1363. {
  1364. docHandler.processingInstruction(target, data);
  1365. }
  1366. public void startPrefixMapping(String prefix, String uri)
  1367. {
  1368. /* ignored */
  1369. }
  1370. public void startElement(String namespace,
  1371. String local,
  1372. String name,
  1373. Attributes attrs)
  1374. throws SAXException
  1375. {
  1376. docHandler.startElement(name, (AttributeList) attrs);
  1377. }
  1378. public void characters(char[] buf, int offset, int len)
  1379. throws SAXException
  1380. {
  1381. docHandler.characters(buf, offset, len);
  1382. }
  1383. public void ignorableWhitespace(char[] buf, int offset, int len)
  1384. throws SAXException
  1385. {
  1386. docHandler.ignorableWhitespace(buf, offset, len);
  1387. }
  1388. public void skippedEntity(String name)
  1389. {
  1390. /* ignored */
  1391. }
  1392. public void endElement(String u, String l, String name)
  1393. throws SAXException
  1394. {
  1395. docHandler.endElement(name);
  1396. }
  1397. public void endPrefixMapping(String prefix)
  1398. {
  1399. /* ignored */
  1400. }
  1401. public void endDocument()
  1402. throws SAXException
  1403. {
  1404. docHandler.endDocument();
  1405. }
  1406. }
  1407. private static class Attribute
  1408. {
  1409. String name;
  1410. String value;
  1411. String nameSpace;
  1412. String localName;
  1413. boolean specified;
  1414. Attribute(String name, String value, boolean specified)
  1415. {
  1416. this.name = name;
  1417. this.value = value;
  1418. this.nameSpace = "";
  1419. this.specified = specified;
  1420. }
  1421. }
  1422. }