Save This Page
Home » openjdk-7 » com.sun.org.apache.xalan » internal » xsltc » trax » [javadoc | source]
    1   /*
    2    * reserved comment block
    3    * DO NOT REMOVE OR ALTER!
    4    */
    5   /*
    6    * Copyright 2001-2004 The Apache Software Foundation.
    7    *
    8    * Licensed under the Apache License, Version 2.0 (the "License");
    9    * you may not use this file except in compliance with the License.
   10    * You may obtain a copy of the License at
   11    *
   12    *     http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing, software
   15    * distributed under the License is distributed on an "AS IS" BASIS,
   16    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   17    * See the License for the specific language governing permissions and
   18    * limitations under the License.
   19    */
   20   /*
   21    * $Id: DOM2SAX.java,v 1.2.4.1 2005/09/06 11:52:46 pvedula Exp $
   22    */
   23   
   24   
   25   package com.sun.org.apache.xalan.internal.xsltc.trax;
   26   
   27   import java.io.IOException;
   28   import java.util.Hashtable;
   29   import java.util.Stack;
   30   import java.util.Vector;
   31   
   32   import org.w3c.dom.NamedNodeMap;
   33   import org.w3c.dom.Node;
   34   
   35   import org.xml.sax.ContentHandler;
   36   import org.xml.sax.DTDHandler;
   37   import org.xml.sax.EntityResolver;
   38   import org.xml.sax.ErrorHandler;
   39   import org.xml.sax.InputSource;
   40   import org.xml.sax.Locator;
   41   import org.xml.sax.SAXException;
   42   import org.xml.sax.SAXNotRecognizedException;
   43   import org.xml.sax.SAXNotSupportedException;
   44   import org.xml.sax.XMLReader;
   45   import org.xml.sax.ext.LexicalHandler;
   46   import org.xml.sax.helpers.AttributesImpl;
   47   import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;
   48   import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
   49   
   50   /**
   51    * @author G. Todd Miller
   52    */
   53   public class DOM2SAX implements XMLReader, Locator {
   54   
   55       private final static String EMPTYSTRING = "";
   56       private static final String XMLNS_PREFIX = "xmlns";
   57   
   58       private Node _dom = null;
   59       private ContentHandler _sax = null;
   60       private LexicalHandler _lex = null;
   61       private SAXImpl _saxImpl = null;
   62       private Hashtable _nsPrefixes = new Hashtable();
   63   
   64       public DOM2SAX(Node root) {
   65           _dom = root;
   66       }
   67   
   68       public ContentHandler getContentHandler() {
   69           return _sax;
   70       }
   71   
   72       public void setContentHandler(ContentHandler handler) throws
   73           NullPointerException
   74       {
   75           _sax = handler;
   76           if (handler instanceof LexicalHandler) {
   77               _lex = (LexicalHandler) handler;
   78           }
   79   
   80           if (handler instanceof SAXImpl) {
   81               _saxImpl = (SAXImpl)handler;
   82           }
   83       }
   84   
   85       /**
   86        * Begin the scope of namespace prefix. Forward the event to the
   87        * SAX handler only if the prefix is unknown or it is mapped to a
   88        * different URI.
   89        */
   90       private boolean startPrefixMapping(String prefix, String uri)
   91           throws SAXException
   92       {
   93           boolean pushed = true;
   94           Stack uriStack = (Stack) _nsPrefixes.get(prefix);
   95   
   96           if (uriStack != null) {
   97               if (uriStack.isEmpty()) {
   98                   _sax.startPrefixMapping(prefix, uri);
   99                   uriStack.push(uri);
  100               }
  101               else {
  102                   final String lastUri = (String) uriStack.peek();
  103                   if (!lastUri.equals(uri)) {
  104                       _sax.startPrefixMapping(prefix, uri);
  105                       uriStack.push(uri);
  106                   }
  107                   else {
  108                       pushed = false;
  109                   }
  110               }
  111           }
  112           else {
  113               _sax.startPrefixMapping(prefix, uri);
  114               _nsPrefixes.put(prefix, uriStack = new Stack());
  115               uriStack.push(uri);
  116           }
  117           return pushed;
  118       }
  119   
  120       /*
  121        * End the scope of a name prefix by popping it from the stack and
  122        * passing the event to the SAX Handler.
  123        */
  124       private void endPrefixMapping(String prefix)
  125           throws SAXException
  126       {
  127           final Stack uriStack = (Stack) _nsPrefixes.get(prefix);
  128   
  129           if (uriStack != null) {
  130               _sax.endPrefixMapping(prefix);
  131               uriStack.pop();
  132           }
  133       }
  134   
  135       /**
  136        * If the DOM was created using a DOM 1.0 API, the local name may be
  137        * null. If so, get the local name from the qualified name before
  138        * generating the SAX event.
  139        */
  140       private static String getLocalName(Node node) {
  141           final String localName = node.getLocalName();
  142   
  143           if (localName == null) {
  144               final String qname = node.getNodeName();
  145               final int col = qname.lastIndexOf(':');
  146               return (col > 0) ? qname.substring(col + 1) : qname;
  147           }
  148           return localName;
  149       }
  150   
  151       public void parse(InputSource unused) throws IOException, SAXException {
  152           parse(_dom);
  153       }
  154   
  155       public void parse() throws IOException, SAXException {
  156           if (_dom != null) {
  157               boolean isIncomplete =
  158                   (_dom.getNodeType() != org.w3c.dom.Node.DOCUMENT_NODE);
  159   
  160               if (isIncomplete) {
  161                   _sax.startDocument();
  162                   parse(_dom);
  163                   _sax.endDocument();
  164               }
  165               else {
  166                   parse(_dom);
  167               }
  168           }
  169       }
  170   
  171       /**
  172        * Traverse the DOM and generate SAX events for a handler. A
  173        * startElement() event passes all attributes, including namespace
  174        * declarations.
  175        */
  176       private void parse(Node node) throws IOException, SAXException {
  177           Node first = null;
  178           if (node == null) return;
  179   
  180           switch (node.getNodeType()) {
  181           case Node.ATTRIBUTE_NODE:         // handled by ELEMENT_NODE
  182           case Node.DOCUMENT_FRAGMENT_NODE:
  183           case Node.DOCUMENT_TYPE_NODE :
  184           case Node.ENTITY_NODE :
  185           case Node.ENTITY_REFERENCE_NODE:
  186           case Node.NOTATION_NODE :
  187               // These node types are ignored!!!
  188               break;
  189           case Node.CDATA_SECTION_NODE:
  190               final String cdata = node.getNodeValue();
  191               if (_lex != null) {
  192                   _lex.startCDATA();
  193                   _sax.characters(cdata.toCharArray(), 0, cdata.length());
  194                   _lex.endCDATA();
  195               }
  196               else {
  197                   // in the case where there is no lex handler, we still
  198                   // want the text of the cdate to make its way through.
  199                   _sax.characters(cdata.toCharArray(), 0, cdata.length());
  200               }
  201               break;
  202   
  203           case Node.COMMENT_NODE:           // should be handled!!!
  204               if (_lex != null) {
  205                   final String value = node.getNodeValue();
  206                   _lex.comment(value.toCharArray(), 0, value.length());
  207               }
  208               break;
  209           case Node.DOCUMENT_NODE:
  210               _sax.setDocumentLocator(this);
  211   
  212               _sax.startDocument();
  213               Node next = node.getFirstChild();
  214               while (next != null) {
  215                   parse(next);
  216                   next = next.getNextSibling();
  217               }
  218               _sax.endDocument();
  219               break;
  220   
  221           case Node.ELEMENT_NODE:
  222               String prefix;
  223               Vector pushedPrefixes = new Vector();
  224               final AttributesImpl attrs = new AttributesImpl();
  225               final NamedNodeMap map = node.getAttributes();
  226               final int length = map.getLength();
  227   
  228               // Process all namespace declarations
  229               for (int i = 0; i < length; i++) {
  230                   final Node attr = map.item(i);
  231                   final String qnameAttr = attr.getNodeName();
  232   
  233                   // Ignore everything but NS declarations here
  234                   if (qnameAttr.startsWith(XMLNS_PREFIX)) {
  235                       final String uriAttr = attr.getNodeValue();
  236                       final int colon = qnameAttr.lastIndexOf(':');
  237                       prefix = (colon > 0) ? qnameAttr.substring(colon + 1) : EMPTYSTRING;
  238                       if (startPrefixMapping(prefix, uriAttr)) {
  239                           pushedPrefixes.addElement(prefix);
  240                       }
  241                   }
  242               }
  243   
  244               // Process all other attributes
  245               for (int i = 0; i < length; i++) {
  246                   final Node attr = map.item(i);
  247                   String qnameAttr = attr.getNodeName();
  248   
  249                   // Ignore NS declarations here
  250                   if (!qnameAttr.startsWith(XMLNS_PREFIX)) {
  251                       final String uriAttr = attr.getNamespaceURI();
  252                       final String localNameAttr = getLocalName(attr);
  253   
  254                       // Uri may be implicitly declared
  255                       if (uriAttr != null) {
  256                           final int colon = qnameAttr.lastIndexOf(':');
  257                           if (colon > 0) {
  258                               prefix = qnameAttr.substring(0, colon);
  259                           }
  260                           else {
  261                               // If no prefix for this attr, we need to create
  262                               // one because we cannot use the default ns
  263                               prefix = BasisLibrary.generatePrefix();
  264                               qnameAttr = prefix + ':' + qnameAttr;
  265                           }
  266                           if (startPrefixMapping(prefix, uriAttr)) {
  267                               pushedPrefixes.addElement(prefix);
  268                           }
  269                       }
  270   
  271                       // Add attribute to list
  272                       attrs.addAttribute(attr.getNamespaceURI(), getLocalName(attr),
  273                           qnameAttr, "CDATA", attr.getNodeValue());
  274                   }
  275               }
  276   
  277               // Now process the element itself
  278               final String qname = node.getNodeName();
  279               final String uri = node.getNamespaceURI();
  280               final String localName = getLocalName(node);
  281   
  282               // Uri may be implicitly declared
  283               if (uri != null) {
  284                   final int colon = qname.lastIndexOf(':');
  285                   prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING;
  286                   if (startPrefixMapping(prefix, uri)) {
  287                       pushedPrefixes.addElement(prefix);
  288                   }
  289               }
  290   
  291               // Generate SAX event to start element
  292               if (_saxImpl != null) {
  293                   _saxImpl.startElement(uri, localName, qname, attrs, node);
  294               }
  295               else {
  296                   _sax.startElement(uri, localName, qname, attrs);
  297               }
  298   
  299               // Traverse all child nodes of the element (if any)
  300               next = node.getFirstChild();
  301               while (next != null) {
  302                   parse(next);
  303                   next = next.getNextSibling();
  304               }
  305   
  306               // Generate SAX event to close element
  307               _sax.endElement(uri, localName, qname);
  308   
  309               // Generate endPrefixMapping() for all pushed prefixes
  310               final int nPushedPrefixes = pushedPrefixes.size();
  311               for (int i = 0; i < nPushedPrefixes; i++) {
  312                   endPrefixMapping((String) pushedPrefixes.elementAt(i));
  313               }
  314               break;
  315   
  316           case Node.PROCESSING_INSTRUCTION_NODE:
  317               _sax.processingInstruction(node.getNodeName(),
  318                                          node.getNodeValue());
  319               break;
  320   
  321           case Node.TEXT_NODE:
  322               final String data = node.getNodeValue();
  323               _sax.characters(data.toCharArray(), 0, data.length());
  324               break;
  325           }
  326       }
  327   
  328       /**
  329        * This class is only used internally so this method should never
  330        * be called.
  331        */
  332       public DTDHandler getDTDHandler() {
  333           return null;
  334       }
  335   
  336       /**
  337        * This class is only used internally so this method should never
  338        * be called.
  339        */
  340       public ErrorHandler getErrorHandler() {
  341           return null;
  342       }
  343   
  344       /**
  345        * This class is only used internally so this method should never
  346        * be called.
  347        */
  348       public boolean getFeature(String name) throws SAXNotRecognizedException,
  349           SAXNotSupportedException
  350       {
  351           return false;
  352       }
  353   
  354       /**
  355        * This class is only used internally so this method should never
  356        * be called.
  357        */
  358       public void setFeature(String name, boolean value) throws
  359           SAXNotRecognizedException, SAXNotSupportedException
  360       {
  361       }
  362   
  363       /**
  364        * This class is only used internally so this method should never
  365        * be called.
  366        */
  367       public void parse(String sysId) throws IOException, SAXException {
  368           throw new IOException("This method is not yet implemented.");
  369       }
  370   
  371       /**
  372        * This class is only used internally so this method should never
  373        * be called.
  374        */
  375       public void setDTDHandler(DTDHandler handler) throws NullPointerException {
  376       }
  377   
  378       /**
  379        * This class is only used internally so this method should never
  380        * be called.
  381        */
  382       public void setEntityResolver(EntityResolver resolver) throws
  383           NullPointerException
  384       {
  385       }
  386   
  387       /**
  388        * This class is only used internally so this method should never
  389        * be called.
  390        */
  391       public EntityResolver getEntityResolver() {
  392           return null;
  393       }
  394   
  395       /**
  396        * This class is only used internally so this method should never
  397        * be called.
  398        */
  399       public void setErrorHandler(ErrorHandler handler) throws
  400           NullPointerException
  401       {
  402       }
  403   
  404       /**
  405        * This class is only used internally so this method should never
  406        * be called.
  407        */
  408       public void setProperty(String name, Object value) throws
  409           SAXNotRecognizedException, SAXNotSupportedException {
  410       }
  411   
  412       /**
  413        * This class is only used internally so this method should never
  414        * be called.
  415        */
  416       public Object getProperty(String name) throws SAXNotRecognizedException,
  417           SAXNotSupportedException
  418       {
  419           return null;
  420       }
  421   
  422       /**
  423        * This class is only used internally so this method should never
  424        * be called.
  425        */
  426       public int getColumnNumber() {
  427           return 0;
  428       }
  429   
  430       /**
  431        * This class is only used internally so this method should never
  432        * be called.
  433        */
  434       public int getLineNumber() {
  435           return 0;
  436       }
  437   
  438       /**
  439        * This class is only used internally so this method should never
  440        * be called.
  441        */
  442       public String getPublicId() {
  443           return null;
  444       }
  445   
  446       /**
  447        * This class is only used internally so this method should never
  448        * be called.
  449        */
  450       public String getSystemId() {
  451           return null;
  452       }
  453   
  454       // Debugging
  455       private String getNodeTypeFromCode(short code) {
  456           String retval = null;
  457           switch (code) {
  458           case Node.ATTRIBUTE_NODE :
  459               retval = "ATTRIBUTE_NODE"; break;
  460           case Node.CDATA_SECTION_NODE :
  461               retval = "CDATA_SECTION_NODE"; break;
  462           case Node.COMMENT_NODE :
  463               retval = "COMMENT_NODE"; break;
  464           case Node.DOCUMENT_FRAGMENT_NODE :
  465               retval = "DOCUMENT_FRAGMENT_NODE"; break;
  466           case Node.DOCUMENT_NODE :
  467               retval = "DOCUMENT_NODE"; break;
  468           case Node.DOCUMENT_TYPE_NODE :
  469               retval = "DOCUMENT_TYPE_NODE"; break;
  470           case Node.ELEMENT_NODE :
  471               retval = "ELEMENT_NODE"; break;
  472           case Node.ENTITY_NODE :
  473               retval = "ENTITY_NODE"; break;
  474           case Node.ENTITY_REFERENCE_NODE :
  475               retval = "ENTITY_REFERENCE_NODE"; break;
  476           case Node.NOTATION_NODE :
  477               retval = "NOTATION_NODE"; break;
  478           case Node.PROCESSING_INSTRUCTION_NODE :
  479               retval = "PROCESSING_INSTRUCTION_NODE"; break;
  480           case Node.TEXT_NODE:
  481               retval = "TEXT_NODE"; break;
  482           }
  483           return retval;
  484       }
  485   }

Save This Page
Home » openjdk-7 » com.sun.org.apache.xalan » internal » xsltc » trax » [javadoc | source]