1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: SAX2DOM.java,v 1.18 2004/02/16 22:57:21 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.trax;
  20. import java.util.Stack;
  21. import java.util.Vector;
  22. import javax.xml.parsers.DocumentBuilderFactory;
  23. import javax.xml.parsers.ParserConfigurationException;
  24. import com.sun.org.apache.xalan.internal.xsltc.runtime.Constants;
  25. import org.w3c.dom.Comment;
  26. import org.w3c.dom.Document;
  27. import org.w3c.dom.Element;
  28. import org.w3c.dom.Node;
  29. import org.w3c.dom.Text;
  30. import org.w3c.dom.ProcessingInstruction;
  31. import org.xml.sax.Attributes;
  32. import org.xml.sax.ContentHandler;
  33. import org.xml.sax.Locator;
  34. import org.xml.sax.SAXException;
  35. import org.xml.sax.ext.LexicalHandler;
  36. /**
  37. * @author G. Todd Miller
  38. */
  39. public class SAX2DOM implements ContentHandler, LexicalHandler, Constants {
  40. private Node _root = null;
  41. private Document _document = null;
  42. private Stack _nodeStk = new Stack();
  43. private Vector _namespaceDecls = null;
  44. private Node _lastSibling = null;
  45. public SAX2DOM() throws ParserConfigurationException {
  46. final DocumentBuilderFactory factory =
  47. DocumentBuilderFactory.newInstance();
  48. _document = factory.newDocumentBuilder().newDocument();
  49. _root = _document;
  50. }
  51. public SAX2DOM(Node root) throws ParserConfigurationException {
  52. _root = root;
  53. if (root instanceof Document) {
  54. _document = (Document)root;
  55. }
  56. else if (root != null) {
  57. _document = root.getOwnerDocument();
  58. }
  59. else {
  60. final DocumentBuilderFactory factory =
  61. DocumentBuilderFactory.newInstance();
  62. _document = factory.newDocumentBuilder().newDocument();
  63. _root = _document;
  64. }
  65. }
  66. public Node getDOM() {
  67. return _root;
  68. }
  69. public void characters(char[] ch, int start, int length) {
  70. final Node last = (Node)_nodeStk.peek();
  71. // No text nodes can be children of root (DOM006 exception)
  72. if (last != _document) {
  73. final String text = new String(ch, start, length);
  74. if( _lastSibling != null && _lastSibling.getNodeType() == Node.TEXT_NODE ){
  75. ((Text)_lastSibling).appendData(text);
  76. }
  77. else{
  78. _lastSibling = last.appendChild(_document.createTextNode(text));
  79. }
  80. }
  81. }
  82. public void startDocument() {
  83. _nodeStk.push(_root);
  84. }
  85. public void endDocument() {
  86. _nodeStk.pop();
  87. }
  88. public void startElement(String namespace, String localName, String qName,
  89. Attributes attrs)
  90. {
  91. final Element tmp = (Element)_document.createElementNS(namespace, qName);
  92. // Add namespace declarations first
  93. if (_namespaceDecls != null) {
  94. final int nDecls = _namespaceDecls.size();
  95. for (int i = 0; i < nDecls; i++) {
  96. final String prefix = (String) _namespaceDecls.elementAt(i++);
  97. if (prefix == null || prefix.equals(EMPTYSTRING)) {
  98. tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX,
  99. (String) _namespaceDecls.elementAt(i));
  100. }
  101. else {
  102. tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix,
  103. (String) _namespaceDecls.elementAt(i));
  104. }
  105. }
  106. _namespaceDecls.clear();
  107. }
  108. // Add attributes to element
  109. final int nattrs = attrs.getLength();
  110. for (int i = 0; i < nattrs; i++) {
  111. if (attrs.getLocalName(i) == null) {
  112. tmp.setAttribute(attrs.getQName(i), attrs.getValue(i));
  113. }
  114. else {
  115. tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i),
  116. attrs.getValue(i));
  117. }
  118. }
  119. // Append this new node onto current stack node
  120. Node last = (Node)_nodeStk.peek();
  121. last.appendChild(tmp);
  122. // Push this node onto stack
  123. _nodeStk.push(tmp);
  124. _lastSibling = null;
  125. }
  126. public void endElement(String namespace, String localName, String qName) {
  127. _nodeStk.pop();
  128. _lastSibling = null;
  129. }
  130. public void startPrefixMapping(String prefix, String uri) {
  131. if (_namespaceDecls == null) {
  132. _namespaceDecls = new Vector(2);
  133. }
  134. _namespaceDecls.addElement(prefix);
  135. _namespaceDecls.addElement(uri);
  136. }
  137. public void endPrefixMapping(String prefix) {
  138. // do nothing
  139. }
  140. /**
  141. * This class is only used internally so this method should never
  142. * be called.
  143. */
  144. public void ignorableWhitespace(char[] ch, int start, int length) {
  145. }
  146. /**
  147. * adds processing instruction node to DOM.
  148. */
  149. public void processingInstruction(String target, String data) {
  150. final Node last = (Node)_nodeStk.peek();
  151. ProcessingInstruction pi = _document.createProcessingInstruction(
  152. target, data);
  153. if (pi != null){
  154. last.appendChild(pi);
  155. _lastSibling = pi;
  156. }
  157. }
  158. /**
  159. * This class is only used internally so this method should never
  160. * be called.
  161. */
  162. public void setDocumentLocator(Locator locator) {
  163. }
  164. /**
  165. * This class is only used internally so this method should never
  166. * be called.
  167. */
  168. public void skippedEntity(String name) {
  169. }
  170. /**
  171. * Lexical Handler method to create comment node in DOM tree.
  172. */
  173. public void comment(char[] ch, int start, int length) {
  174. final Node last = (Node)_nodeStk.peek();
  175. Comment comment = _document.createComment(new String(ch,start,length));
  176. if (comment != null){
  177. last.appendChild(comment);
  178. _lastSibling = comment;
  179. }
  180. }
  181. // Lexical Handler methods- not implemented
  182. public void startCDATA() { }
  183. public void endCDATA() { }
  184. public void startEntity(java.lang.String name) { }
  185. public void endDTD() { }
  186. public void endEntity(String name) { }
  187. public void startDTD(String name, String publicId, String systemId)
  188. throws SAXException { }
  189. }