1. /*
  2. * $Id: XmlDocumentBuilder.java,v 1.6 2001/09/14 00:50:25 edwingo Exp $
  3. *
  4. * The Apache Software License, Version 1.1
  5. *
  6. *
  7. * Copyright (c) 2000 The Apache Software Foundation. All rights
  8. * reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * 3. The end-user documentation included with the redistribution,
  23. * if any, must include the following acknowledgment:
  24. * "This product includes software developed by the
  25. * Apache Software Foundation (http://www.apache.org/)."
  26. * Alternately, this acknowledgment may appear in the software itself,
  27. * if and wherever such third-party acknowledgments normally appear.
  28. *
  29. * 4. The names "Crimson" and "Apache Software Foundation" must
  30. * not be used to endorse or promote products derived from this
  31. * software without prior written permission. For written
  32. * permission, please contact apache@apache.org.
  33. *
  34. * 5. Products derived from this software may not be called "Apache",
  35. * nor may "Apache" appear in their name, without prior written
  36. * permission of the Apache Software Foundation.
  37. *
  38. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  39. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  40. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  41. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  42. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  44. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  45. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  46. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  47. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  48. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  49. * SUCH DAMAGE.
  50. * ====================================================================
  51. *
  52. * This software consists of voluntary contributions made by many
  53. * individuals on behalf of the Apache Software Foundation and was
  54. * originally based on software copyright (c) 1999, Sun Microsystems, Inc.,
  55. * http://www.sun.com. For more information on the Apache Software
  56. * Foundation, please see <http://www.apache.org/>.
  57. */
  58. package org.apache.crimson.tree;
  59. import java.io.IOException;
  60. import java.net.URL;
  61. import java.util.Dictionary;
  62. import java.util.Hashtable;
  63. import java.util.Locale;
  64. import java.util.Vector;
  65. import org.w3c.dom.CDATASection;
  66. import org.w3c.dom.Comment;
  67. import org.w3c.dom.Document;
  68. import org.w3c.dom.EntityReference;
  69. import org.w3c.dom.DOMException;
  70. import org.w3c.dom.DOMImplementation;
  71. import org.xml.sax.ErrorHandler;
  72. import org.xml.sax.InputSource;
  73. import org.xml.sax.Locator;
  74. import org.xml.sax.SAXException;
  75. import org.xml.sax.SAXParseException;
  76. import org.xml.sax.ContentHandler;
  77. import org.xml.sax.DTDHandler;
  78. import org.xml.sax.Attributes;
  79. import org.xml.sax.ext.LexicalHandler;
  80. import org.xml.sax.ext.DeclHandler;
  81. import org.apache.crimson.parser.AttributesEx;
  82. /**
  83. * This class is a SAX2 ContentHandler which converts a stream of parse
  84. * events into an in-memory DOM document. After each <em>Parser.parse()</em>
  85. * invocation returns, a resulting DOM Document may be accessed via the
  86. * <em>getDocument</em> method. The parser and its builder should be used
  87. * together; the builder may be used with only one parser at a time.
  88. *
  89. * <P> This builder optionally does XML namespace processing, reporting
  90. * conformance problems as recoverable errors using the parser's error
  91. * handler.
  92. *
  93. * <P> Note: element factories are deprecated because they are non-standard
  94. * and are provided here only for backwards compatibility. To customize
  95. * the document, a powerful technique involves using an element factory
  96. * specifying what element tags (from a given XML namespace) correspond to
  97. * what implementation classes. Parse trees produced by such a builder can
  98. * have nodes which add behaviors to achieve application-specific
  99. * functionality, such as modifing the tree as it is parsed.
  100. *
  101. * <P> The object model here is that XML elements are polymorphic, with
  102. * semantic intelligence embedded through customized internal nodes.
  103. * Those nodes are created as the parse tree is built. Such trees now
  104. * build on the W3C Document Object Model (DOM), and other models may be
  105. * supported by the customized nodes. This allows both generic tools
  106. * (understanding generic interfaces such as the DOM core) and specialized
  107. * tools (supporting specialized behaviors, such as the HTML extensions
  108. * to the DOM core; or for XSL elements) to share data structures.
  109. *
  110. * <P> Normally only "model" semantics are in document data structures,
  111. * but "view" or "controller" semantics can be supported if desired.
  112. *
  113. * <P> Elements may choose to intercept certain parsing events directly.
  114. * They do this by overriding the default implementations of methods
  115. * in the <em>XmlReadable</em> interface. This is normally done to make
  116. * the DOM tree represent application level modeling requirements, rather
  117. * than matching an XML structure that may not be optimized appropriately.
  118. *
  119. * @author David Brownell
  120. * @version $Revision: 1.6 $
  121. */
  122. public class XmlDocumentBuilder implements ContentHandler, LexicalHandler,
  123. DeclHandler, DTDHandler
  124. {
  125. // used during parsing
  126. protected XmlDocument document;
  127. protected Locator locator;
  128. private Locale locale = Locale.getDefault ();
  129. private ElementFactory factory;
  130. private Vector attrTmp = new Vector ();
  131. protected ParentNode elementStack[];
  132. protected int topOfStack;
  133. private boolean inDTD;
  134. private boolean inCDataSection;
  135. private Doctype doctype;
  136. // parser modes
  137. private boolean disableNamespaces = true; /* Keep this for
  138. backward API
  139. compatibility,
  140. but it does
  141. not change any
  142. behavior. */
  143. private boolean ignoreWhitespace = false;
  144. private boolean expandEntityRefs = true;
  145. private boolean ignoreComments = false;
  146. private boolean putCDATAIntoText = false;
  147. /**
  148. * Default constructor is for use in conjunction with a SAX2 parser.
  149. */
  150. public XmlDocumentBuilder() {
  151. // No-op
  152. }
  153. /**
  154. * Returns true if certain lexical information is automatically
  155. * discarded when a DOM tree is built, producing smaller parse trees
  156. * that are easier to use.
  157. * <b>Obsolete:</b> for backwards compatibility
  158. */
  159. public boolean isIgnoringLexicalInfo () {
  160. return ignoreWhitespace && expandEntityRefs
  161. && ignoreComments && putCDATAIntoText;
  162. }
  163. /**
  164. * Controls whether certain lexical information is discarded.
  165. *
  166. * <P> That information includes whitespace in element content which
  167. * is ignorable (note that some nonvalidating XML parsers will not
  168. * report that information); all comments; which text is found in
  169. * CDATA sections; and boundaries of entity references.
  170. *
  171. * <P> "Ignorable whitespace" as reported by parsers is whitespace
  172. * used to format XML markup. That is, all whitespace except that in
  173. * "mixed" or ANY content models is ignorable. When it is discarded,
  174. * pretty-printing may be necessary to make the document be readable
  175. * again by humans.
  176. *
  177. * <P> Whitespace inside "mixed" and ANY content models needs different
  178. * treatment, since it could be part of the document content. In such
  179. * cases XML defines a <em>xml:space</em> attribute which applications
  180. * should use to determine whether whitespace must be preserved (value
  181. * of the attribute is <em>preserve</em>) or whether default behavior
  182. * (such as eliminating leading and trailing space, and normalizing
  183. * consecutive internal whitespace to a single space) is allowed.
  184. *
  185. * @param value true indicates that such lexical information should
  186. * be discarded during parsing.
  187. * <b>Obsolete:</b> for backwards compatibility
  188. */
  189. public void setIgnoringLexicalInfo (boolean value) {
  190. ignoreWhitespace = value;
  191. expandEntityRefs = value;
  192. ignoreComments = value;
  193. putCDATAIntoText = value;
  194. }
  195. /**
  196. * Internal API used by JAXP implementation. Access is set to "public"
  197. * to enable inter-package access. Use JAXP DocumentBuilderFactory
  198. * class to access this functionality.
  199. */
  200. public void setIgnoreWhitespace(boolean value) {
  201. ignoreWhitespace = value;
  202. }
  203. /**
  204. * Internal API used by JAXP implementation. Access is set to "public"
  205. * to enable inter-package access. Use JAXP DocumentBuilderFactory
  206. * class to access this functionality.
  207. */
  208. public void setExpandEntityReferences(boolean value) {
  209. expandEntityRefs = value;
  210. }
  211. /**
  212. * Internal API used by JAXP implementation. Access is set to "public"
  213. * to enable inter-package access. Use JAXP DocumentBuilderFactory
  214. * class to access this functionality.
  215. */
  216. public void setIgnoreComments(boolean value) {
  217. ignoreComments = value;
  218. }
  219. /**
  220. * Internal API used by JAXP implementation. Access is set to "public"
  221. * to enable inter-package access. Use JAXP DocumentBuilderFactory
  222. * class to access this functionality.
  223. */
  224. public void setPutCDATAIntoText(boolean value) {
  225. putCDATAIntoText = value;
  226. }
  227. /**
  228. * Returns true if namespace conformance is not checked as the
  229. * DOM tree is built.
  230. */
  231. public boolean getDisableNamespaces () {
  232. return disableNamespaces;
  233. }
  234. /**
  235. * Controls whether namespace conformance is checked during DOM
  236. * tree construction, or (the default) not. In this framework, the
  237. * DOM Builder is responsible for enforcing all namespace constraints.
  238. * When enabled, this makes constructing a DOM tree slightly slower.
  239. * (However, at this time it can't enforce the requirement that
  240. * parameter entity names not contain colons.)
  241. */
  242. public void setDisableNamespaces (boolean value) {
  243. disableNamespaces = value;
  244. }
  245. /**
  246. * Return the result of parsing, after a SAX parser has used this as a
  247. * content handler during parsing.
  248. */
  249. public XmlDocument getDocument() {
  250. return document;
  251. }
  252. /**
  253. * Returns the locale to be used for diagnostic messages by
  254. * this builder, and by documents it produces. This uses
  255. * the locale of any associated parser.
  256. */
  257. public Locale getLocale() {
  258. return locale;
  259. }
  260. /**
  261. * Assigns the locale to be used for diagnostic messages.
  262. * Multi-language applications, such as web servers dealing with
  263. * clients from different locales, need the ability to interact
  264. * with clients in languages other than the server's default.
  265. *
  266. * <P>When an XmlDocument is created, its locale is the default
  267. * locale for the virtual machine. If a parser was recorded,
  268. * the locale will be associated with that parser.
  269. *
  270. * @see #chooseLocale
  271. */
  272. public void setLocale(Locale locale)
  273. throws SAXException
  274. {
  275. if (locale == null) {
  276. locale = Locale.getDefault();
  277. }
  278. this.locale = locale;
  279. }
  280. /**
  281. * Chooses a client locale to use for diagnostics, using the first
  282. * language specified in the list that is supported by this builder.
  283. * That locale is then automatically assigned using <a
  284. * href="#setLocale(java.util.Locale)">setLocale()</a>. Such a list
  285. * could be provided by a variety of user preference mechanisms,
  286. * including the HTTP <em>Accept-Language</em> header field.
  287. *
  288. * @see org.apache.crimson.util.MessageCatalog
  289. *
  290. * @param languages Array of language specifiers, ordered with the most
  291. * preferable one at the front. For example, "en-ca" then "fr-ca",
  292. * followed by "zh_CN". Both RFC 1766 and Java styles are supported.
  293. * @return The chosen locale, or null.
  294. */
  295. public Locale chooseLocale (String languages [])
  296. throws SAXException
  297. {
  298. Locale l = XmlDocument.catalog.chooseLocale (languages);
  299. if (l != null)
  300. setLocale (l);
  301. return l;
  302. }
  303. /*
  304. * Gets the messages from the resource bundles for the given messageId.
  305. */
  306. String getMessage (String messageId) {
  307. return getMessage (messageId, null);
  308. }
  309. /*
  310. * Gets the messages from the resource bundles for the given messageId
  311. * after formatting it with the parameters passed to it.
  312. */
  313. String getMessage (String messageId, Object[] parameters) {
  314. if (locale == null) {
  315. getLocale ();
  316. }
  317. return XmlDocument.catalog.getMessage (locale, messageId, parameters);
  318. }
  319. //////////////////////////////////////////////////////////////////////
  320. // ContentHandler callbacks
  321. //////////////////////////////////////////////////////////////////////
  322. /**
  323. * Receive an object for locating the origin of SAX document events.
  324. */
  325. public void setDocumentLocator(Locator locator) {
  326. this.locator = locator;
  327. }
  328. /**
  329. * This is a factory method, used to create an XmlDocument.
  330. * Subclasses may override this method, for example to provide
  331. * document classes with particular behaviors, or provide
  332. * particular factory behaviours (such as returning elements
  333. * that support the HTML DOM methods, if they have the right
  334. * name and are in the right namespace).
  335. */
  336. public XmlDocument createDocument ()
  337. {
  338. XmlDocument retval = new XmlDocument ();
  339. if (factory != null) {
  340. retval.setElementFactory(factory);
  341. }
  342. return retval;
  343. }
  344. /**
  345. * Assigns the factory to be associated with documents produced
  346. * by this builder.
  347. * @deprecated
  348. */
  349. final public void setElementFactory(ElementFactory factory) {
  350. this.factory = factory;
  351. }
  352. /**
  353. * Returns the factory to be associated with documents produced
  354. * by this builder.
  355. * @deprecated
  356. */
  357. final public ElementFactory getElementFactory() {
  358. return factory;
  359. }
  360. /**
  361. * Receive notification of the beginning of a document.
  362. */
  363. public void startDocument () throws SAXException
  364. {
  365. document = createDocument ();
  366. if (locator != null)
  367. document.setSystemId (locator.getSystemId ());
  368. //
  369. // XXX don't want fixed size limits! Fix someday. For
  370. // now, wide trees predominate, not deep ones. This is
  371. // allowing a _very_ deep tree ... we typically observe
  372. // depths on the order of a dozen.
  373. //
  374. elementStack = new ParentNode [200];
  375. topOfStack = 0;
  376. elementStack [topOfStack] = document;
  377. inDTD = false;
  378. }
  379. /**
  380. * Receive notification of the end of a document.
  381. */
  382. public void endDocument () throws SAXException
  383. {
  384. if (topOfStack != 0)
  385. throw new IllegalStateException (getMessage ("XDB-000"));
  386. document.trimToSize ();
  387. }
  388. /**
  389. * Begin the scope of a prefix-URI Namespace mapping.
  390. */
  391. public void startPrefixMapping(String prefix, String uri)
  392. throws SAXException
  393. {
  394. // No-op
  395. }
  396. /**
  397. * End the scope of a prefix-URI mapping.
  398. */
  399. public void endPrefixMapping(String prefix) throws SAXException {
  400. // No-op
  401. }
  402. /**
  403. * Receive notification of the beginning of an element.
  404. */
  405. public void startElement(String namespaceURI, String localName,
  406. String qName, Attributes attributes)
  407. throws SAXException
  408. {
  409. //
  410. // Convert set of attributes to DOM representation.
  411. //
  412. AttributeSet attSet = null;
  413. int length = attributes.getLength();
  414. if (length != 0) {
  415. try {
  416. attSet = AttributeSet.createAttributeSet1(attributes);
  417. } catch (DOMException ex) {
  418. throw new SAXParseException(getMessage("XDB-002",
  419. new Object[] { ex.getMessage() }), locator, ex);
  420. }
  421. }
  422. //
  423. // Then create the element, associate its attributes, and
  424. // stack it for later addition.
  425. //
  426. ElementNode e = null;
  427. try {
  428. e = (ElementNode) document.createElementEx(qName);
  429. } catch (DOMException ex) {
  430. throw new SAXParseException(getMessage("XDB-004",
  431. new Object[] { ex.getMessage() }), locator, ex);
  432. }
  433. if (attributes instanceof AttributesEx) {
  434. e.setIdAttributeName(
  435. ((AttributesEx)attributes).getIdAttributeName());
  436. }
  437. if (length != 0) {
  438. e.setAttributes(attSet);
  439. }
  440. elementStack[topOfStack++].appendChild(e);
  441. elementStack[topOfStack] = e;
  442. }
  443. /**
  444. * Receive notification of the end of an element.
  445. */
  446. public void endElement(String namespaceURI, String localName,
  447. String qName)
  448. throws SAXException
  449. {
  450. ParentNode e = (ParentNode) elementStack[topOfStack];
  451. elementStack[topOfStack--] = null;
  452. // Trusting that the SAX parser is correct, and hasn't
  453. // mismatched start/end element callbacks.
  454. // if (!tag.equals (e.getTagName ()))
  455. // throw new SAXParseException ((getMessage ("XDB-009", new
  456. // Object[] { tag, e.getTagName () })), locator);
  457. e.reduceWaste(); // use less space
  458. }
  459. /**
  460. * Receive notification of character data.
  461. */
  462. public void characters(char buf [], int offset, int len)
  463. throws SAXException
  464. {
  465. ParentNode top = elementStack [topOfStack];
  466. if (inCDataSection) {
  467. String temp = new String (buf, offset, len);
  468. CDATASection section;
  469. section = (CDATASection) top.getLastChild ();
  470. section.appendData (temp);
  471. return;
  472. }
  473. try {
  474. NodeBase lastChild = (NodeBase) top.getLastChild ();
  475. if (lastChild != null && lastChild.getClass() == TextNode.class) {
  476. // Merge only TextNode data and not CDataNode data
  477. String tmp = new String (buf, offset, len);
  478. ((TextNode)lastChild).appendData (tmp);
  479. } else {
  480. TextNode text = document.newText (buf, offset, len);
  481. top.appendChild (text);
  482. }
  483. } catch (DOMException ex) {
  484. throw new SAXParseException(getMessage("XDB-004",
  485. new Object[] { ex.getMessage() }), locator, ex);
  486. }
  487. }
  488. /**
  489. * Receive notification of ignorable whitespace in element content.
  490. *
  491. * Reports ignorable whitespace; if lexical information is not ignored
  492. * the whitespace reported here is recorded in a DOM text (or CDATA, as
  493. * appropriate) node.
  494. *
  495. * @param buf holds text characters
  496. * @param offset initial index of characters in <em>buf</em>
  497. * @param len how many characters are being passed
  498. * @exception SAXException as appropriate
  499. */
  500. public void ignorableWhitespace(char buf [], int offset, int len)
  501. throws SAXException
  502. {
  503. if (ignoreWhitespace)
  504. return;
  505. characters(buf, offset, len);
  506. }
  507. /**
  508. * Receive notification of a processing instruction.
  509. */
  510. public void processingInstruction(String name, String instruction)
  511. throws SAXException
  512. {
  513. // Ignore PIs in DTD for DOM support
  514. if (inDTD)
  515. return;
  516. ParentNode top = elementStack [topOfStack];
  517. PINode pi;
  518. try {
  519. pi = (PINode) document.createProcessingInstruction (name,
  520. instruction);
  521. top.appendChild (pi);
  522. } catch (DOMException ex) {
  523. throw new SAXParseException(getMessage("XDB-004",
  524. new Object[] { ex.getMessage() }), locator, ex);
  525. }
  526. }
  527. /**
  528. * Receive notification of a skipped entity.
  529. */
  530. public void skippedEntity(String name) throws SAXException {
  531. // No-op
  532. }
  533. //////////////////////////////////////////////////////////////////////
  534. // org.xml.sax.ext.LexicalHandler callbacks
  535. //////////////////////////////////////////////////////////////////////
  536. /**
  537. * Report the start of DTD declarations, if any.
  538. */
  539. public void startDTD(String name, String publicId, String systemId)
  540. throws SAXException
  541. {
  542. DOMImplementation impl = document.getImplementation();
  543. doctype = (Doctype)impl.createDocumentType(name, publicId, systemId);
  544. // Set the owner since DOM2 specifies this to be null
  545. doctype.setOwnerDocument(document);
  546. inDTD = true;
  547. }
  548. /**
  549. * Report the end of DTD declarations.
  550. */
  551. public void endDTD() throws SAXException {
  552. document.appendChild(doctype);
  553. inDTD = false;
  554. }
  555. /**
  556. * Report the beginning of an entity in content.
  557. */
  558. public void startEntity(String name) throws SAXException {
  559. // Our parser doesn't report Paramater entities. Need to make
  560. // changes for that.
  561. // Ignore entity refs while parsing DTD
  562. if (expandEntityRefs || inDTD) {
  563. return;
  564. }
  565. EntityReference e = document.createEntityReference(name);
  566. elementStack[topOfStack++].appendChild(e);
  567. elementStack[topOfStack] = (ParentNode)e;
  568. }
  569. /**
  570. * Report the end of an entity.
  571. */
  572. public void endEntity(String name) throws SAXException {
  573. // Ignore entity refs while parsing DTD
  574. if (inDTD) {
  575. return;
  576. }
  577. ParentNode entity = elementStack[topOfStack];
  578. if (!(entity instanceof EntityReference))
  579. return;
  580. entity.setReadonly(true);
  581. elementStack[topOfStack--] = null;
  582. if (!name.equals(entity.getNodeName())) {
  583. throw new SAXParseException(getMessage("XDB-011",
  584. new Object[] { name, entity.getNodeName() }), locator);
  585. }
  586. }
  587. /**
  588. * Report the start of a CDATA section.
  589. *
  590. * <P>If this builder is set to record lexical information then this
  591. * callback arranges that character data (and ignorable whitespace) be
  592. * recorded as part of a CDATA section, until the matching
  593. * <em>endCDATA</em> method is called.
  594. */
  595. public void startCDATA() throws SAXException {
  596. if (putCDATAIntoText) {
  597. return;
  598. }
  599. CDATASection text = document.createCDATASection("");
  600. ParentNode top = elementStack[topOfStack];
  601. try {
  602. inCDataSection = true;
  603. top.appendChild(text);
  604. } catch (DOMException ex) {
  605. throw new SAXParseException(getMessage("XDB-004",
  606. new Object[] { ex.getMessage() }), locator, ex);
  607. }
  608. }
  609. /**
  610. * Report the end of a CDATA section.
  611. */
  612. public void endCDATA() throws SAXException {
  613. inCDataSection = false;
  614. }
  615. /**
  616. * Report an XML comment anywhere in the document.
  617. */
  618. public void comment(char[] ch, int start, int length) throws SAXException {
  619. // Ignore comments if lexical info is to be ignored,
  620. // or if parsing the DTD
  621. if (ignoreComments || inDTD) {
  622. return;
  623. }
  624. String text = new String(ch, start, length);
  625. Comment comment = document.createComment(text);
  626. ParentNode top = elementStack[topOfStack];
  627. try {
  628. top.appendChild(comment);
  629. } catch (DOMException ex) {
  630. throw new SAXParseException(getMessage("XDB-004",
  631. new Object[] { ex.getMessage() }), locator, ex);
  632. }
  633. }
  634. //////////////////////////////////////////////////////////////////////
  635. // org.xml.sax.ext.DeclHandler callbacks
  636. //////////////////////////////////////////////////////////////////////
  637. /**
  638. * Report an element type declaration.
  639. */
  640. public void elementDecl(String name, String model) throws SAXException {
  641. // ignored
  642. }
  643. /**
  644. * Report an attribute type declaration.
  645. */
  646. public void attributeDecl(String eName, String aName, String type,
  647. String valueDefault, String value)
  648. throws SAXException
  649. {
  650. // ignored
  651. }
  652. /**
  653. * Report an internal entity declaration.
  654. */
  655. public void internalEntityDecl(String name, String value)
  656. throws SAXException
  657. {
  658. // SAX2 reports PEDecls which we ignore for DOM2. SAX2 also reports
  659. // only the first defined GEDecl which matches with DOM2.
  660. if (!name.startsWith("%")) {
  661. doctype.addEntityNode(name, value);
  662. }
  663. }
  664. /**
  665. * Report a parsed external entity declaration.
  666. */
  667. public void externalEntityDecl(String name, String publicId,
  668. String systemId)
  669. throws SAXException
  670. {
  671. // SAX2 reports PEDecls which we ignore for DOM2. SAX2 also reports
  672. // only the first defined GEDecl which matches with DOM2.
  673. if (!name.startsWith("%")) {
  674. doctype.addEntityNode(name, publicId, systemId, null);
  675. }
  676. }
  677. //////////////////////////////////////////////////////////////////////
  678. // org.xml.sax.DTDHandler callbacks
  679. //////////////////////////////////////////////////////////////////////
  680. /**
  681. * Receive notification of a notation declaration event.
  682. */
  683. public void notationDecl(String n, String p, String s)
  684. throws SAXException
  685. {
  686. doctype.addNotation(n, p, s);
  687. }
  688. /**
  689. * Receive notification of an unparsed entity declaration event.
  690. */
  691. public void unparsedEntityDecl(String name, String publicId,
  692. String systemId, String notation)
  693. throws SAXException
  694. {
  695. doctype.addEntityNode(name, publicId, systemId, notation);
  696. }
  697. }