1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
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
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
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
180
181
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 }