1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xml.utils;
  58. import org.apache.xalan.res.XSLMessages;
  59. import org.apache.xpath.res.XPATHErrorResources;
  60. import org.apache.xml.utils.NodeVector;
  61. import java.util.Stack;
  62. import org.xml.sax.ext.LexicalHandler;
  63. import org.xml.sax.ContentHandler;
  64. import org.xml.sax.Locator;
  65. import org.xml.sax.Attributes;
  66. import org.w3c.dom.*; // we pretty much use everything in the DOM here.
  67. /**
  68. * <meta name="usage" content="general"/>
  69. * This class takes SAX events (in addition to some extra events
  70. * that SAX doesn't handle yet) and adds the result to a document
  71. * or document fragment.
  72. */
  73. public class DOMBuilder
  74. implements ContentHandler, LexicalHandler
  75. {
  76. /** Root document */
  77. public Document m_doc;
  78. /** Current node */
  79. protected Node m_currentNode = null;
  80. /** First node of document fragment or null if not a DocumentFragment */
  81. public DocumentFragment m_docFrag = null;
  82. /** Vector of element nodes */
  83. protected Stack m_elemStack = new Stack();
  84. /**
  85. * DOMBuilder instance constructor... it will add the DOM nodes
  86. * to the document fragment.
  87. *
  88. * @param doc Root document
  89. * @param node Current node
  90. */
  91. public DOMBuilder(Document doc, Node node)
  92. {
  93. m_doc = doc;
  94. m_currentNode = node;
  95. }
  96. /**
  97. * DOMBuilder instance constructor... it will add the DOM nodes
  98. * to the document fragment.
  99. *
  100. * @param doc Root document
  101. * @param docFrag Document fragment
  102. */
  103. public DOMBuilder(Document doc, DocumentFragment docFrag)
  104. {
  105. m_doc = doc;
  106. m_docFrag = docFrag;
  107. }
  108. /**
  109. * DOMBuilder instance constructor... it will add the DOM nodes
  110. * to the document.
  111. *
  112. * @param doc Root document
  113. */
  114. public DOMBuilder(Document doc)
  115. {
  116. m_doc = doc;
  117. }
  118. /**
  119. * Get the root node of the DOM being created. This
  120. * is either a Document or a DocumentFragment.
  121. *
  122. * @return The root document or document fragment if not null
  123. */
  124. public Node getRootNode()
  125. {
  126. return (null != m_docFrag) ? (Node) m_docFrag : (Node) m_doc;
  127. }
  128. /**
  129. * Get the node currently being processed.
  130. *
  131. * @return the current node being processed
  132. */
  133. public Node getCurrentNode()
  134. {
  135. return m_currentNode;
  136. }
  137. /**
  138. * Return null since there is no Writer for this class.
  139. *
  140. * @return null
  141. */
  142. public java.io.Writer getWriter()
  143. {
  144. return null;
  145. }
  146. /**
  147. * Append a node to the current container.
  148. *
  149. * @param newNode New node to append
  150. */
  151. protected void append(Node newNode) throws org.xml.sax.SAXException
  152. {
  153. Node currentNode = m_currentNode;
  154. if (null != currentNode)
  155. {
  156. currentNode.appendChild(newNode);
  157. // System.out.println(newNode.getNodeName());
  158. }
  159. else if (null != m_docFrag)
  160. {
  161. m_docFrag.appendChild(newNode);
  162. }
  163. else
  164. {
  165. boolean ok = true;
  166. short type = newNode.getNodeType();
  167. if (type == Node.TEXT_NODE)
  168. {
  169. String data = newNode.getNodeValue();
  170. if ((null != data) && (data.trim().length() > 0))
  171. {
  172. throw new org.xml.sax.SAXException(
  173. XSLMessages.createXPATHMessage(
  174. XPATHErrorResources.ER_CANT_OUTPUT_TEXT_BEFORE_DOC, null)); //"Warning: can't output text before document element! Ignoring...");
  175. }
  176. ok = false;
  177. }
  178. else if (type == Node.ELEMENT_NODE)
  179. {
  180. if (m_doc.getDocumentElement() != null)
  181. {
  182. throw new org.xml.sax.SAXException(
  183. XSLMessages.createXPATHMessage(
  184. XPATHErrorResources.ER_CANT_HAVE_MORE_THAN_ONE_ROOT, null)); //"Can't have more than one root on a DOM!");
  185. }
  186. }
  187. if (ok)
  188. m_doc.appendChild(newNode);
  189. }
  190. }
  191. /**
  192. * Receive an object for locating the origin of SAX document events.
  193. *
  194. * <p>SAX parsers are strongly encouraged (though not absolutely
  195. * required) to supply a locator: if it does so, it must supply
  196. * the locator to the application by invoking this method before
  197. * invoking any of the other methods in the ContentHandler
  198. * interface.</p>
  199. *
  200. * <p>The locator allows the application to determine the end
  201. * position of any document-related event, even if the parser is
  202. * not reporting an error. Typically, the application will
  203. * use this information for reporting its own errors (such as
  204. * character content that does not match an application's
  205. * business rules). The information returned by the locator
  206. * is probably not sufficient for use with a search engine.</p>
  207. *
  208. * <p>Note that the locator will return correct information only
  209. * during the invocation of the events in this interface. The
  210. * application should not attempt to use it at any other time.</p>
  211. *
  212. * @param locator An object that can return the location of
  213. * any SAX document event.
  214. * @see org.xml.sax.Locator
  215. */
  216. public void setDocumentLocator(Locator locator)
  217. {
  218. // No action for the moment.
  219. }
  220. /**
  221. * Receive notification of the beginning of a document.
  222. *
  223. * <p>The SAX parser will invoke this method only once, before any
  224. * other methods in this interface or in DTDHandler (except for
  225. * setDocumentLocator).</p>
  226. */
  227. public void startDocument() throws org.xml.sax.SAXException
  228. {
  229. // No action for the moment.
  230. }
  231. /**
  232. * Receive notification of the end of a document.
  233. *
  234. * <p>The SAX parser will invoke this method only once, and it will
  235. * be the last method invoked during the parse. The parser shall
  236. * not invoke this method until it has either abandoned parsing
  237. * (because of an unrecoverable error) or reached the end of
  238. * input.</p>
  239. */
  240. public void endDocument() throws org.xml.sax.SAXException
  241. {
  242. // No action for the moment.
  243. }
  244. /**
  245. * Receive notification of the beginning of an element.
  246. *
  247. * <p>The Parser will invoke this method at the beginning of every
  248. * element in the XML document; there will be a corresponding
  249. * endElement() event for every startElement() event (even when the
  250. * element is empty). All of the element's content will be
  251. * reported, in order, before the corresponding endElement()
  252. * event.</p>
  253. *
  254. * <p>If the element name has a namespace prefix, the prefix will
  255. * still be attached. Note that the attribute list provided will
  256. * contain only attributes with explicit values (specified or
  257. * defaulted): #IMPLIED attributes will be omitted.</p>
  258. *
  259. *
  260. * @param ns The namespace of the node
  261. * @param localName The local part of the qualified name
  262. * @param name The element name.
  263. * @param atts The attributes attached to the element, if any.
  264. * @see #endElement
  265. * @see org.xml.sax.Attributes
  266. */
  267. public void startElement(
  268. String ns, String localName, String name, Attributes atts)
  269. throws org.xml.sax.SAXException
  270. {
  271. Element elem;
  272. // Note that the namespace-aware call must be used to correctly
  273. // construct a Level 2 DOM, even for non-namespaced nodes.
  274. if ((null == ns) || (ns.length() == 0))
  275. elem = m_doc.createElementNS(null,name);
  276. else
  277. elem = m_doc.createElementNS(ns, name);
  278. append(elem);
  279. try
  280. {
  281. int nAtts = atts.getLength();
  282. if (0 != nAtts)
  283. {
  284. for (int i = 0; i < nAtts; i++)
  285. {
  286. //System.out.println("type " + atts.getType(i) + " name " + atts.getLocalName(i) );
  287. // First handle a possible ID attribute
  288. if (atts.getType(i).equalsIgnoreCase("ID"))
  289. setIDAttribute(atts.getValue(i), elem);
  290. String attrNS = atts.getURI(i);
  291. String attrQName = atts.getQName(i);
  292. if((attrQName.equals("xmlns") || attrQName.startsWith("xmlns:")) )
  293. {
  294. elem.setAttributeNS("http://www.w3.org/2000/xmlns/",attrQName, atts.getValue(i));
  295. }
  296. else
  297. {
  298. elem.setAttributeNS(atts.getURI(i),attrQName, atts.getValue(i));
  299. }
  300. }
  301. }
  302. // append(elem);
  303. m_elemStack.push(elem);
  304. m_currentNode = elem;
  305. // append(elem);
  306. }
  307. catch(java.lang.Exception de)
  308. {
  309. // de.printStackTrace();
  310. throw new org.xml.sax.SAXException(de);
  311. }
  312. }
  313. /**
  314. * Receive notification of the end of an element.
  315. *
  316. * <p>The SAX parser will invoke this method at the end of every
  317. * element in the XML document; there will be a corresponding
  318. * startElement() event for every endElement() event (even when the
  319. * element is empty).</p>
  320. *
  321. * <p>If the element name has a namespace prefix, the prefix will
  322. * still be attached to the name.</p>
  323. *
  324. *
  325. * @param ns the namespace of the element
  326. * @param localName The local part of the qualified name of the element
  327. * @param name The element name
  328. */
  329. public void endElement(String ns, String localName, String name)
  330. throws org.xml.sax.SAXException
  331. {
  332. m_elemStack.pop();
  333. m_currentNode = m_elemStack.isEmpty() ? null : (Node)m_elemStack.peek();
  334. }
  335. /**
  336. * Set an ID string to node association in the ID table.
  337. *
  338. * @param id The ID string.
  339. * @param elem The associated ID.
  340. */
  341. public void setIDAttribute(String id, Element elem)
  342. {
  343. // Do nothing. This method is meant to be overiden.
  344. }
  345. /**
  346. * Receive notification of character data.
  347. *
  348. * <p>The Parser will call this method to report each chunk of
  349. * character data. SAX parsers may return all contiguous character
  350. * data in a single chunk, or they may split it into several
  351. * chunks; however, all of the characters in any single event
  352. * must come from the same external entity, so that the Locator
  353. * provides useful information.</p>
  354. *
  355. * <p>The application must not attempt to read from the array
  356. * outside of the specified range.</p>
  357. *
  358. * <p>Note that some parsers will report whitespace using the
  359. * ignorableWhitespace() method rather than this one (validating
  360. * parsers must do so).</p>
  361. *
  362. * @param ch The characters from the XML document.
  363. * @param start The start position in the array.
  364. * @param length The number of characters to read from the array.
  365. * @see #ignorableWhitespace
  366. * @see org.xml.sax.Locator
  367. */
  368. public void characters(char ch[], int start, int length) throws org.xml.sax.SAXException
  369. {
  370. if(isOutsideDocElem()
  371. && org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
  372. return; // avoid DOM006 Hierarchy request error
  373. if (m_inCData)
  374. {
  375. cdata(ch, start, length);
  376. return;
  377. }
  378. String s = new String(ch, start, length);
  379. Text text = m_doc.createTextNode(s);
  380. append(text);
  381. }
  382. /**
  383. * If available, when the disable-output-escaping attribute is used,
  384. * output raw text without escaping. A PI will be inserted in front
  385. * of the node with the name "lotusxsl-next-is-raw" and a value of
  386. * "formatter-to-dom".
  387. *
  388. * @param ch Array containing the characters
  389. * @param start Index to start of characters in the array
  390. * @param length Number of characters in the array
  391. */
  392. public void charactersRaw(char ch[], int start, int length)
  393. throws org.xml.sax.SAXException
  394. {
  395. if(isOutsideDocElem()
  396. && org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
  397. return; // avoid DOM006 Hierarchy request error
  398. String s = new String(ch, start, length);
  399. append(m_doc.createProcessingInstruction("xslt-next-is-raw",
  400. "formatter-to-dom"));
  401. append(m_doc.createTextNode(s));
  402. }
  403. /**
  404. * Report the beginning of an entity.
  405. *
  406. * The start and end of the document entity are not reported.
  407. * The start and end of the external DTD subset are reported
  408. * using the pseudo-name "[dtd]". All other events must be
  409. * properly nested within start/end entity events.
  410. *
  411. * @param name The name of the entity. If it is a parameter
  412. * entity, the name will begin with '%'.
  413. * @see #endEntity
  414. * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
  415. * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
  416. */
  417. public void startEntity(String name) throws org.xml.sax.SAXException
  418. {
  419. // Almost certainly the wrong behavior...
  420. // entityReference(name);
  421. }
  422. /**
  423. * Report the end of an entity.
  424. *
  425. * @param name The name of the entity that is ending.
  426. * @see #startEntity
  427. */
  428. public void endEntity(String name) throws org.xml.sax.SAXException{}
  429. /**
  430. * Receive notivication of a entityReference.
  431. *
  432. * @param name name of the entity reference
  433. */
  434. public void entityReference(String name) throws org.xml.sax.SAXException
  435. {
  436. append(m_doc.createEntityReference(name));
  437. }
  438. /**
  439. * Receive notification of ignorable whitespace in element content.
  440. *
  441. * <p>Validating Parsers must use this method to report each chunk
  442. * of ignorable whitespace (see the W3C XML 1.0 recommendation,
  443. * section 2.10): non-validating parsers may also use this method
  444. * if they are capable of parsing and using content models.</p>
  445. *
  446. * <p>SAX parsers may return all contiguous whitespace in a single
  447. * chunk, or they may split it into several chunks; however, all of
  448. * the characters in any single event must come from the same
  449. * external entity, so that the Locator provides useful
  450. * information.</p>
  451. *
  452. * <p>The application must not attempt to read from the array
  453. * outside of the specified range.</p>
  454. *
  455. * @param ch The characters from the XML document.
  456. * @param start The start position in the array.
  457. * @param length The number of characters to read from the array.
  458. * @see #characters
  459. */
  460. public void ignorableWhitespace(char ch[], int start, int length)
  461. throws org.xml.sax.SAXException
  462. {
  463. if(isOutsideDocElem())
  464. return; // avoid DOM006 Hierarchy request error
  465. String s = new String(ch, start, length);
  466. append(m_doc.createTextNode(s));
  467. }
  468. /**
  469. * Tell if the current node is outside the document element.
  470. *
  471. * @return true if the current node is outside the document element.
  472. */
  473. private boolean isOutsideDocElem()
  474. {
  475. return (null == m_docFrag) && m_elemStack.size() == 0 && (null == m_currentNode || m_currentNode.getNodeType() == Node.DOCUMENT_NODE);
  476. }
  477. /**
  478. * Receive notification of a processing instruction.
  479. *
  480. * <p>The Parser will invoke this method once for each processing
  481. * instruction found: note that processing instructions may occur
  482. * before or after the main document element.</p>
  483. *
  484. * <p>A SAX parser should never report an XML declaration (XML 1.0,
  485. * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
  486. * using this method.</p>
  487. *
  488. * @param target The processing instruction target.
  489. * @param data The processing instruction data, or null if
  490. * none was supplied.
  491. */
  492. public void processingInstruction(String target, String data)
  493. throws org.xml.sax.SAXException
  494. {
  495. append(m_doc.createProcessingInstruction(target, data));
  496. }
  497. /**
  498. * Report an XML comment anywhere in the document.
  499. *
  500. * This callback will be used for comments inside or outside the
  501. * document element, including comments in the external DTD
  502. * subset (if read).
  503. *
  504. * @param ch An array holding the characters in the comment.
  505. * @param start The starting position in the array.
  506. * @param length The number of characters to use from the array.
  507. */
  508. public void comment(char ch[], int start, int length) throws org.xml.sax.SAXException
  509. {
  510. append(m_doc.createComment(new String(ch, start, length)));
  511. }
  512. /** Flag indicating that we are processing a CData section */
  513. protected boolean m_inCData = false;
  514. /**
  515. * Report the start of a CDATA section.
  516. *
  517. * @see #endCDATA
  518. */
  519. public void startCDATA() throws org.xml.sax.SAXException
  520. {
  521. m_inCData = true;
  522. }
  523. /**
  524. * Report the end of a CDATA section.
  525. *
  526. * @see #startCDATA
  527. */
  528. public void endCDATA() throws org.xml.sax.SAXException
  529. {
  530. m_inCData = false;
  531. }
  532. /**
  533. * Receive notification of cdata.
  534. *
  535. * <p>The Parser will call this method to report each chunk of
  536. * character data. SAX parsers may return all contiguous character
  537. * data in a single chunk, or they may split it into several
  538. * chunks; however, all of the characters in any single event
  539. * must come from the same external entity, so that the Locator
  540. * provides useful information.</p>
  541. *
  542. * <p>The application must not attempt to read from the array
  543. * outside of the specified range.</p>
  544. *
  545. * <p>Note that some parsers will report whitespace using the
  546. * ignorableWhitespace() method rather than this one (validating
  547. * parsers must do so).</p>
  548. *
  549. * @param ch The characters from the XML document.
  550. * @param start The start position in the array.
  551. * @param length The number of characters to read from the array.
  552. * @see #ignorableWhitespace
  553. * @see org.xml.sax.Locator
  554. */
  555. public void cdata(char ch[], int start, int length) throws org.xml.sax.SAXException
  556. {
  557. if(isOutsideDocElem()
  558. && org.apache.xml.utils.XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
  559. return; // avoid DOM006 Hierarchy request error
  560. String s = new String(ch, start, length);
  561. append(m_doc.createCDATASection(s));
  562. }
  563. /**
  564. * Report the start of DTD declarations, if any.
  565. *
  566. * Any declarations are assumed to be in the internal subset
  567. * unless otherwise indicated.
  568. *
  569. * @param name The document type name.
  570. * @param publicId The declared public identifier for the
  571. * external DTD subset, or null if none was declared.
  572. * @param systemId The declared system identifier for the
  573. * external DTD subset, or null if none was declared.
  574. * @see #endDTD
  575. * @see #startEntity
  576. */
  577. public void startDTD(String name, String publicId, String systemId)
  578. throws org.xml.sax.SAXException
  579. {
  580. // Do nothing for now.
  581. }
  582. /**
  583. * Report the end of DTD declarations.
  584. *
  585. * @see #startDTD
  586. */
  587. public void endDTD() throws org.xml.sax.SAXException
  588. {
  589. // Do nothing for now.
  590. }
  591. /**
  592. * Begin the scope of a prefix-URI Namespace mapping.
  593. *
  594. * <p>The information from this event is not necessary for
  595. * normal Namespace processing: the SAX XML reader will
  596. * automatically replace prefixes for element and attribute
  597. * names when the http://xml.org/sax/features/namespaces
  598. * feature is true (the default).</p>
  599. *
  600. * <p>There are cases, however, when applications need to
  601. * use prefixes in character data or in attribute values,
  602. * where they cannot safely be expanded automatically; the
  603. * start/endPrefixMapping event supplies the information
  604. * to the application to expand prefixes in those contexts
  605. * itself, if necessary.</p>
  606. *
  607. * <p>Note that start/endPrefixMapping events are not
  608. * guaranteed to be properly nested relative to each-other:
  609. * all startPrefixMapping events will occur before the
  610. * corresponding startElement event, and all endPrefixMapping
  611. * events will occur after the corresponding endElement event,
  612. * but their order is not guaranteed.</p>
  613. *
  614. * @param prefix The Namespace prefix being declared.
  615. * @param uri The Namespace URI the prefix is mapped to.
  616. * @see #endPrefixMapping
  617. * @see #startElement
  618. */
  619. public void startPrefixMapping(String prefix, String uri)
  620. throws org.xml.sax.SAXException
  621. {
  622. /*
  623. // Not sure if this is needed or wanted
  624. // Also, it fails in the stree.
  625. if((null != m_currentNode)
  626. && (m_currentNode.getNodeType() == Node.ELEMENT_NODE))
  627. {
  628. String qname;
  629. if(((null != prefix) && (prefix.length() == 0))
  630. || (null == prefix))
  631. qname = "xmlns";
  632. else
  633. qname = "xmlns:"+prefix;
  634. Element elem = (Element)m_currentNode;
  635. String val = elem.getAttribute(qname); // Obsolete, should be DOM2...?
  636. if(val == null)
  637. {
  638. elem.setAttributeNS("http://www.w3.org/XML/1998/namespace",
  639. qname, uri);
  640. }
  641. }
  642. */
  643. }
  644. /**
  645. * End the scope of a prefix-URI mapping.
  646. *
  647. * <p>See startPrefixMapping for details. This event will
  648. * always occur after the corresponding endElement event,
  649. * but the order of endPrefixMapping events is not otherwise
  650. * guaranteed.</p>
  651. *
  652. * @param prefix The prefix that was being mapping.
  653. * @see #startPrefixMapping
  654. * @see #endElement
  655. */
  656. public void endPrefixMapping(String prefix) throws org.xml.sax.SAXException{}
  657. /**
  658. * Receive notification of a skipped entity.
  659. *
  660. * <p>The Parser will invoke this method once for each entity
  661. * skipped. Non-validating processors may skip entities if they
  662. * have not seen the declarations (because, for example, the
  663. * entity was declared in an external DTD subset). All processors
  664. * may skip external entities, depending on the values of the
  665. * http://xml.org/sax/features/external-general-entities and the
  666. * http://xml.org/sax/features/external-parameter-entities
  667. * properties.</p>
  668. *
  669. * @param name The name of the skipped entity. If it is a
  670. * parameter entity, the name will begin with '%'.
  671. */
  672. public void skippedEntity(String name) throws org.xml.sax.SAXException{}
  673. }