View Javadoc

1   /*
2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/dom/html/DocumentNavigator.java,v 1.4 2005/03/25 23:22:29 elharo Exp $
3    * $Revision: 1.4 $
4    * $Date: 2005/03/25 23:22:29 $
5    *
6    * ====================================================================
7    *
8    * Copyright (C) 2000-2003 bob mcwhirter & James Strachan.
9    * All rights reserved.
10   *
11   * Redistribution and use in source and binary forms, with or without
12   * modification, are permitted provided that the following conditions
13   * are met:
14   *
15   * 1. Redistributions of source code must retain the above copyright
16   *    notice, this list of conditions, and the following disclaimer.
17   *
18   * 2. Redistributions in binary form must reproduce the above copyright
19   *    notice, this list of conditions, and the disclaimer that follows
20   *    these conditions in the documentation and/or other materials
21   *    provided with the distribution.
22   *
23   * 3. The name "Jaxen" must not be used to endorse or promote products
24   *    derived from this software without prior written permission.  For
25   *    written permission, please contact license@jaxen.org.
26   *
27   * 4. Products derived from this software may not be called "Jaxen", nor
28   *    may "Jaxen" appear in their name, without prior written permission
29   *    from the Jaxen Project Management (pm@jaxen.org).
30   *
31   * In addition, we request (but do not require) that you include in the
32   * end-user documentation provided with the redistribution and/or in the
33   * software itself an acknowledgement equivalent to the following:
34   *     "This product includes software developed by the
35   *      Jaxen Project (http://www.jaxen.org/)."
36   * Alternatively, the acknowledgment may be graphical using the logos
37   * available at http://www.jaxen.org/
38   *
39   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42   * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
43   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50   * SUCH DAMAGE.
51   *
52   * ====================================================================
53   * This software consists of voluntary contributions made by many
54   * individuals on behalf of the Jaxen Project and was originally
55   * created by bob mcwhirter <bob@werken.com> and
56   * James Strachan <jstrachan@apache.org>.  For more information on the
57   * Jaxen Project, please see <http://www.jaxen.org/>.
58   *
59   * $Id: DocumentNavigator.java,v 1.4 2005/03/25 23:22:29 elharo Exp $
60   */
61  
62  package org.jaxen.dom.html;
63  
64  import java.util.Locale;
65  
66  import org.jaxen.XPath;
67  import org.jaxen.Navigator;
68  import org.jaxen.saxpath.SAXPathException;
69  import org.w3c.dom.Node;
70  
71  /***
72   * Interface for navigating around the W3C HTML DOM object model.
73   *
74   * <p>
75   * This class is not intended for direct usage, but is
76   * used by the Jaxen engine during evaluation.
77   * </p>
78   *
79   * <p>XML is case-sensitive. HTML is not. This navigator is an extension
80   * of the DOM DocumentNavigator that automatically
81   * changes all element, but not attribute, names to lowercase or uppercase
82   * to aid in navigating through HTML documents.  Note that case modification
83   * are bypassed for XHTML documents.  XHTML is case sensitive and can be
84   * expected to store all elements and attributes in lower case. Also note that
85   * HTML attribute names are stored as lower case in the HTML (and XHTML) DOM
86   * already which is why the case of attribute names are not modified.
87   *
88   *  @author David Peterson
89   *
90   *  @see XPath
91   *  @see org.jaxen.dom.DOMXPath
92   *  @see org.jaxen.dom.NamespaceNode
93   */
94  public class DocumentNavigator extends org.jaxen.dom.DocumentNavigator
95  {
96  
97      ////////////////////////////////////////////////////////////////////
98      // Constants.
99      ////////////////////////////////////////////////////////////////////
100 
101     /***
102      * Constant: lowercase navigator.
103      */
104     private final static DocumentNavigator LOWERCASE =
105         new DocumentNavigator(true);
106 
107     private final static DocumentNavigator UPPERCASE =
108         new DocumentNavigator(false);
109 
110     private final boolean toLowerCase;
111 
112     ////////////////////////////////////////////////////////////////////
113     // Constructor.
114     ////////////////////////////////////////////////////////////////////
115 
116     /***
117      * Constructs a new DocumentNavigator that will convert to lowercase.
118      */
119     public DocumentNavigator ()
120     {
121         this(true);
122     }
123 
124     /***
125      * Constructs a new DocumentNavigator that will convert to lowercase.
126      * 
127      * @param toLowerCase whether to convert all names to lowercase
128      */
129     public DocumentNavigator(boolean toLowerCase)
130     {
131         this.toLowerCase = toLowerCase;
132     }
133 
134     /***
135      * Returns <code>true</code> if the navigator is converting to lowercase.
136      * 
137      * @return true if the navigator is converting to lowercase; false otherwise
138      */
139     public boolean isToLowerCase()
140     {
141       return toLowerCase;
142     }
143 
144     /***
145      * Get a singleton DocumentNavigator for efficiency.
146      *
147      * @return a singleton instance of a DocumentNavigator
148      */
149     public static Navigator getInstance (boolean toLowerCase)
150     {
151         if (toLowerCase) return LOWERCASE;
152         return UPPERCASE;
153     }
154 
155     ////////////////////////////////////////////////////////////////////
156     // Implementation of the navigator.
157     ////////////////////////////////////////////////////////////////////
158 
159     /*** Returns a parsed form of the given xpath string, which will be suitable
160      *  for queries on HTML DOM documents.
161      */
162     public XPath parseXPath (String xpath) throws SAXPathException
163     {
164         return new HTMLXPath(xpath);
165     }
166 
167   /***
168    * Get the name of the node in the case specified for the current object
169    *
170    * @param node the target node. Used to avoid case modification of node
171    *        names in XML documents.
172    * @param name the name of the node, presumably in the case natively
173    *        stored by the DOM
174    * @return the name of the node, case-modified as desired, if the current
175    *         document is HTML and not XML
176    */
177   protected String getHTMLNodeName(Node node, String name)
178   {
179       //modify case if, and only if, the
180       //name is not null and the document
181       //is not an XML document.
182       if (name != null && !isXMLNode(node))
183       {
184           if (toLowerCase) name = name.toLowerCase(Locale.ENGLISH);
185           else name = name.toUpperCase(Locale.ENGLISH);
186       }
187       return name;
188   }
189 
190   public String getElementName(Object object)
191   {
192       return getHTMLNodeName((Node)object, super.getElementName(object));
193   }
194 
195   public String getElementQName(Object object)
196   {
197       return getHTMLNodeName((Node)object, super.getElementQName(object));
198   }
199 
200   /***
201    * Determine if a node is definitely an XML node.
202    * Note: This will not work if the XML node has not been namespaced.
203    * However, since we are dealing with HTML documents, this is a minimal
204    * risk.
205    */
206   private boolean isXMLNode(Node node) {
207       return (node != null) && (node.getNamespaceURI() != null);
208   }
209 
210 }