Home | History | Annotate | Download | only in utils
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: DOM2Helper.java 468655 2006-10-28 07:12:06Z minchau $
     20  */
     21 package org.apache.xml.utils;
     22 
     23 import java.io.IOException;
     24 
     25 import javax.xml.parsers.DocumentBuilder;
     26 import javax.xml.parsers.DocumentBuilderFactory;
     27 import javax.xml.parsers.ParserConfigurationException;
     28 import javax.xml.transform.TransformerException;
     29 
     30 import org.w3c.dom.Attr;
     31 import org.w3c.dom.Document;
     32 import org.w3c.dom.Element;
     33 import org.w3c.dom.Node;
     34 
     35 import org.xml.sax.InputSource;
     36 
     37 /**
     38  * @deprecated Since the introduction of the DTM, this class will be removed.
     39  * This class provides a DOM level 2 "helper", which provides services currently
     40  * not provided be the DOM standard.
     41  */
     42 public class DOM2Helper extends DOMHelper
     43 {
     44 
     45   /**
     46    * Construct an instance.
     47    */
     48   public DOM2Helper(){}
     49 
     50   /**
     51    * Check node to see if it was created by a DOM implementation
     52    * that this helper is intended to support. This is currently
     53    * disabled, and assumes all nodes are acceptable rather than checking
     54    * that they implement org.apache.xerces.dom.NodeImpl.
     55    *
     56    * @param node The node to be tested.
     57    *
     58    * @throws TransformerException if the node is not one which this
     59    * DOM2Helper can support. If we return without throwing the exception,
     60    * the node is compatable.
     61    * @xsl.usage internal
     62    */
     63   public void checkNode(Node node) throws TransformerException
     64   {
     65 
     66     // if(!(node instanceof org.apache.xerces.dom.NodeImpl))
     67     //  throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_XERCES_CANNOT_HANDLE_NODES, new Object[]{((Object)node).getClass()})); //"DOM2Helper can not handle nodes of type"
     68     //+((Object)node).getClass());
     69   }
     70 
     71   /**
     72    * Returns true if the DOM implementation handled by this helper
     73    * supports the SAX ContentHandler interface.
     74    *
     75    * @return true (since Xerces does).
     76    */
     77   public boolean supportsSAX()
     78   {
     79     return true;
     80   }
     81 
     82   /** Field m_doc: Document Node for the document this helper is currently
     83    * accessing or building
     84    * @see #setDocument
     85    * @see #getDocument
     86    *  */
     87   private Document m_doc;
     88 
     89   /**
     90    * Specify which document this helper is currently operating on.
     91    *
     92    * @param doc The DOM Document node for this document.
     93    * @see #getDocument
     94    */
     95   public void setDocument(Document doc)
     96   {
     97     m_doc = doc;
     98   }
     99 
    100   /**
    101    * Query which document this helper is currently operating on.
    102    *
    103    * @return The DOM Document node for this document.
    104    * @see #setDocument
    105    */
    106   public Document getDocument()
    107   {
    108     return m_doc;
    109   }
    110 
    111   /**
    112    * Parse an XML document.
    113    *
    114    * <p>Right now the Xerces DOMParser class is used.  This needs
    115    * fixing, either via jaxp, or via some other, standard method.</p>
    116    *
    117    * <p>The application can use this method to instruct the SAX parser
    118    * to begin parsing an XML document from any valid input
    119    * source (a character stream, a byte stream, or a URI).</p>
    120    *
    121    * <p>Applications may not invoke this method while a parse is in
    122    * progress (they should create a new Parser instead for each
    123    * additional XML document).  Once a parse is complete, an
    124    * application may reuse the same Parser object, possibly with a
    125    * different input source.</p>
    126    *
    127    * @param source The input source for the top-level of the
    128    *        XML document.
    129    *
    130    * @throws TransformerException if any checked exception is thrown.
    131    * @xsl.usage internal
    132    */
    133   public void parse(InputSource source) throws TransformerException
    134   {
    135 
    136     try
    137     {
    138 
    139       // I guess I should use JAXP factory here... when it's legal.
    140       // org.apache.xerces.parsers.DOMParser parser
    141       //  = new org.apache.xerces.parsers.DOMParser();
    142       DocumentBuilderFactory builderFactory =
    143         DocumentBuilderFactory.newInstance();
    144 
    145       builderFactory.setNamespaceAware(true);
    146       builderFactory.setValidating(true);
    147 
    148       DocumentBuilder parser = builderFactory.newDocumentBuilder();
    149 
    150       /*
    151       // domParser.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", getShouldExpandEntityRefs()? false : true);
    152       if(m_useDOM2getNamespaceURI)
    153       {
    154       parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", true);
    155       parser.setFeature("http://xml.org/sax/features/namespaces", true);
    156       }
    157       else
    158       {
    159       parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
    160       }
    161 
    162       parser.setFeature("http://apache.org/xml/features/allow-java-encodings", true);
    163       */
    164 
    165       parser.setErrorHandler(
    166         new org.apache.xml.utils.DefaultErrorHandler());
    167 
    168       // if(null != m_entityResolver)
    169       // {
    170       // System.out.println("Setting the entity resolver.");
    171       //  parser.setEntityResolver(m_entityResolver);
    172       // }
    173       setDocument(parser.parse(source));
    174     }
    175     catch (org.xml.sax.SAXException se)
    176     {
    177       throw new TransformerException(se);
    178     }
    179     catch (ParserConfigurationException pce)
    180     {
    181       throw new TransformerException(pce);
    182     }
    183     catch (IOException ioe)
    184     {
    185       throw new TransformerException(ioe);
    186     }
    187 
    188     // setDocument(((org.apache.xerces.parsers.DOMParser)parser).getDocument());
    189   }
    190 
    191   /**
    192    * Given an XML ID, return the element. This requires assistance from the
    193    * DOM and parser, and is meaningful only in the context of a DTD
    194    * or schema which declares attributes as being of type ID. This
    195    * information may or may not be available in all parsers, may or
    196    * may not be available for specific documents, and may or may not
    197    * be available when validation is not turned on.
    198    *
    199    * @param id The ID to search for, as a String.
    200    * @param doc The document to search within, as a DOM Document node.
    201    * @return DOM Element node with an attribute of type ID whose value
    202    * uniquely matches the requested id string, or null if there isn't
    203    * such an element or if the DOM can't answer the question for other
    204    * reasons.
    205    */
    206   public Element getElementByID(String id, Document doc)
    207   {
    208     return doc.getElementById(id);
    209   }
    210 
    211   /**
    212    * Figure out whether node2 should be considered as being later
    213    * in the document than node1, in Document Order as defined
    214    * by the XPath model. This may not agree with the ordering defined
    215    * by other XML applications.
    216    * <p>
    217    * There are some cases where ordering isn't defined, and neither are
    218    * the results of this function -- though we'll generally return true.
    219    * <p>
    220    * TODO: Make sure this does the right thing with attribute nodes!!!
    221    *
    222    * @param node1 DOM Node to perform position comparison on.
    223    * @param node2 DOM Node to perform position comparison on .
    224    *
    225    * @return false if node2 comes before node1, otherwise return true.
    226    * You can think of this as
    227    * <code>(node1.documentOrderPosition &lt;= node2.documentOrderPosition)</code>.
    228    */
    229   public static boolean isNodeAfter(Node node1, Node node2)
    230   {
    231 
    232     // Assume first that the nodes are DTM nodes, since discovering node
    233     // order is massivly faster for the DTM.
    234     if(node1 instanceof DOMOrder && node2 instanceof DOMOrder)
    235     {
    236       int index1 = ((DOMOrder) node1).getUid();
    237       int index2 = ((DOMOrder) node2).getUid();
    238 
    239       return index1 <= index2;
    240     }
    241     else
    242     {
    243 
    244       // isNodeAfter will return true if node is after countedNode
    245       // in document order. The base isNodeAfter is sloooow (relatively).
    246       return DOMHelper.isNodeAfter(node1, node2);
    247     }
    248   }
    249 
    250   /**
    251    * Get the XPath-model parent of a node.  This version takes advantage
    252    * of the DOM Level 2 Attr.ownerElement() method; the base version we
    253    * would otherwise inherit is prepared to fall back on exhaustively
    254    * walking the document to find an Attr's parent.
    255    *
    256    * @param node Node to be examined
    257    *
    258    * @return the DOM parent of the input node, if there is one, or the
    259    * ownerElement if the input node is an Attr, or null if the node is
    260    * a Document, a DocumentFragment, or an orphan.
    261    */
    262   public static Node getParentOfNode(Node node)
    263   {
    264           Node parent=node.getParentNode();
    265           if(parent==null && (Node.ATTRIBUTE_NODE == node.getNodeType()) )
    266            parent=((Attr) node).getOwnerElement();
    267           return parent;
    268   }
    269 
    270   /**
    271    * Returns the local name of the given node, as defined by the
    272    * XML Namespaces specification. This is prepared to handle documents
    273    * built using DOM Level 1 methods by falling back upon explicitly
    274    * parsing the node name.
    275    *
    276    * @param n Node to be examined
    277    *
    278    * @return String containing the local name, or null if the node
    279    * was not assigned a Namespace.
    280    */
    281   public String getLocalNameOfNode(Node n)
    282   {
    283 
    284     String name = n.getLocalName();
    285 
    286     return (null == name) ? super.getLocalNameOfNode(n) : name;
    287   }
    288 
    289   /**
    290    * Returns the Namespace Name (Namespace URI) for the given node.
    291    * In a Level 2 DOM, you can ask the node itself. Note, however, that
    292    * doing so conflicts with our decision in getLocalNameOfNode not
    293    * to trust the that the DOM was indeed created using the Level 2
    294    * methods. If Level 1 methods were used, these two functions will
    295    * disagree with each other.
    296    * <p>
    297    * TODO: Reconcile with getLocalNameOfNode.
    298    *
    299    * @param n Node to be examined
    300    *
    301    * @return String containing the Namespace URI bound to this DOM node
    302    * at the time the Node was created.
    303    */
    304   public String getNamespaceOfNode(Node n)
    305   {
    306     return n.getNamespaceURI();
    307   }
    308 
    309   /** Field m_useDOM2getNamespaceURI is a compile-time flag which
    310    *  gates some of the parser options used to build a DOM -- but
    311    * that code is commented out at this time and nobody else
    312    * references it, so I've commented this out as well. */
    313   //private boolean m_useDOM2getNamespaceURI = false;
    314 }
    315