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
63 package org.jaxen.xom;
64
65
66 import nu.xom.Attribute;
67 import nu.xom.Comment;
68 import nu.xom.Document;
69 import nu.xom.Element;
70 import nu.xom.ProcessingInstruction;
71 import nu.xom.Text;
72 import nu.xom.Node;
73 import nu.xom.Builder;
74 import nu.xom.NodeFactory;
75 import nu.xom.ParentNode;
76
77 import org.jaxen.XPath;
78 import org.jaxen.UnsupportedAxisException;
79 import org.jaxen.FunctionCallException;
80 import org.jaxen.BaseXPath;
81 import org.jaxen.JaxenConstants;
82 import org.jaxen.util.SingleObjectIterator;
83
84 import org.jaxen.saxpath.SAXPathException;
85
86 import java.util.Iterator;
87 import java.util.HashMap;
88 import java.util.Map;
89
90 /***
91 * Interface for navigating around the XOM object model.
92 *
93 * <p>
94 * This class is not intended for direct usage, but is
95 * used by the Jaxen engine during evaluation.
96 * </p>
97 *
98 * @see XPath
99 *
100 */
101 public class DocumentNavigator extends org.jaxen.DefaultNavigator
102 {
103 public boolean isAttribute(Object o) {
104 return o instanceof Attribute;
105 }
106
107 public boolean isComment(Object o) {
108 return o instanceof Comment;
109 }
110
111 public boolean isDocument(Object o) {
112 return o instanceof Document;
113 }
114
115 public boolean isElement(Object o) {
116 return o instanceof Element;
117 }
118
119 public boolean isNamespace(Object o) {
120 return o instanceof XPathNamespace;
121 }
122
123 public boolean isProcessingInstruction(Object o) {
124 return o instanceof ProcessingInstruction;
125 }
126
127 public boolean isText(Object o) {
128 return o instanceof Text;
129 }
130
131
132
133 public String getAttributeName(Object o) {
134 return (isAttribute(o) ? ((Attribute)o).getLocalName() : null);
135 }
136
137 public String getAttributeNamespaceUri(Object o) {
138 return (isAttribute(o) ? ((Attribute)o).getNamespaceURI() : null);
139 }
140
141 public String getAttributeQName(Object o) {
142 return (isAttribute(o) ? ((Attribute)o).getQualifiedName() : null);
143 }
144
145 public String getAttributeStringValue(Object o) {
146 return (isAttribute(o) ? ((Attribute)o).getValue() : null);
147 }
148
149
150
151 public String getCommentStringValue(Object o) {
152 return (isComment(o) ? ((Comment)o).getValue() : null);
153 }
154
155 public String getElementName(Object o) {
156 return (isElement(o) ? ((Element)o).getLocalName() : null);
157 }
158
159 public String getElementNamespaceUri(Object o) {
160 return (isElement(o) ? ((Element)o).getNamespaceURI() : null);
161 }
162
163 public String getElementQName(Object o) {
164 return (isElement(o) ? ((Element)o).getQualifiedName() : null);
165 }
166
167 public String getElementStringValue(Object o) {
168 return (o instanceof Node ? ((Node)o).getValue() : null);
169 }
170
171
172
173 public String getNamespacePrefix(Object o) {
174 if (isElement(o)) {
175 return ((Element)o).getNamespacePrefix();
176 } else if (isAttribute(o)) {
177 return ((Attribute)o).getNamespacePrefix();
178 } else if (o instanceof XPathNamespace) {
179 return ((XPathNamespace)o).getNamespacePrefix();
180 }
181 return null;
182 }
183
184 public String getNamespaceStringValue(Object o) {
185 if (isElement(o)) {
186 return ((Element)o).getNamespaceURI();
187 } else if (isAttribute(o)) {
188 return ((Attribute)o).getNamespaceURI();
189 } else if (o instanceof XPathNamespace) {
190 return ((XPathNamespace)o).getNamespaceURI();
191 }
192 return null;
193 }
194
195
196
197 public String getTextStringValue(Object o) {
198 return (o instanceof Text ? ((Text)o).getValue() : null);
199 }
200
201
202
203 public Object getDocument(String s) throws FunctionCallException {
204 try {
205 return new Builder(new NodeFactory()).build(s);
206 } catch (Exception pe) {
207 throw new FunctionCallException(pe);
208 }
209 }
210
211 public Object getDocumentNode(Object o) {
212 ParentNode parent = null;
213 if (o instanceof ParentNode) {
214 parent = (ParentNode)o;
215 } else if (o instanceof Node) {
216 parent = ((Node)o).getParent();
217 }
218 return parent.getDocument();
219 }
220
221
222
223 private abstract static class IndexIterator implements Iterator {
224 private Object o = null;
225 private int pos = 0, end = -1;
226 public IndexIterator(Object o, int pos, int end) {
227 this.o = o;
228 this.pos = pos;
229 this.end = end;
230 }
231 public boolean hasNext() {
232 return pos < end;
233 }
234 public abstract Object get(Object o, int i);
235
236 public Object next() {
237 return get(o, pos++);
238 }
239
240 public void remove() {
241 throw new UnsupportedOperationException();
242 }
243 }
244
245
246
247 public Iterator getAttributeAxisIterator(Object o) throws UnsupportedAxisException {
248 if (isElement(o)) {
249 return new IndexIterator(o, 0, ((Element)o).getAttributeCount()) {
250 public Object get(Object o, int i) {
251 return ((Element)o).getAttribute(i);
252 }
253 };
254 }
255 return JaxenConstants.EMPTY_ITERATOR;
256 }
257
258 public Iterator getChildAxisIterator(Object o) throws UnsupportedAxisException {
259 if (isElement(o) || (o instanceof Document)) {
260 return new IndexIterator(o, 0, ((ParentNode)o).getChildCount()) {
261 public Object get(Object o, int i) {
262 return ((ParentNode)o).getChild(i);
263 }
264 };
265 }
266 return JaxenConstants.EMPTY_ITERATOR;
267 }
268
269
270
271 public Iterator getParentAxisIterator(Object o) throws UnsupportedAxisException {
272 Object parent = null;
273 if (o instanceof Node) {
274 parent = ((Node)o).getParent();
275 } else if (isNamespace(o)) {
276 parent = ((XPathNamespace)o).getElement();
277 }
278 return (parent != null ? new SingleObjectIterator(parent) : null);
279 }
280
281 public Object getParentNode(Object o) throws UnsupportedAxisException {
282 return (o instanceof Node ? ((Node)o).getParent() : null);
283 }
284
285
286
287 public Iterator getPrecedingAxisIterator(Object o) throws UnsupportedAxisException {
288 return super.getPrecedingAxisIterator(o);
289 }
290
291 public Iterator getPrecedingSiblingAxisIterator(Object o) throws UnsupportedAxisException {
292 return super.getPrecedingSiblingAxisIterator(o);
293 }
294
295
296
297 public String getProcessingInstructionData(Object o) {
298 return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getValue() : null);
299 }
300
301 public String getProcessingInstructionTarget(Object o) {
302 return (o instanceof ProcessingInstruction ? ((ProcessingInstruction)o).getTarget() : null);
303 }
304
305
306
307 public String translateNamespacePrefixToUri(String s, Object o) {
308 Element element = null;
309 if (o instanceof Element) {
310 element = (Element) o;
311 } else if (o instanceof ParentNode) {
312 }
313 else if (o instanceof Node) {
314 element = (Element)((Node)o).getParent();
315 }
316 else if (o instanceof XPathNamespace)
317 {
318 element = ((XPathNamespace)o).getElement();
319 }
320 if (element != null) {
321 return element.getNamespaceURI(s);
322 }
323 return null;
324 }
325
326
327
328 public XPath parseXPath(String s) throws SAXPathException {
329 return new BaseXPath(s, this);
330 }
331
332
333
334 /*** Wrapper for XOM namespace nodes to give them a parent,
335 * as required by the XPath data model.
336 *
337 * @author Erwin Bolwidt
338 */
339 private static class XPathNamespace
340 {
341 private Element element;
342
343 private String uri, prefix;
344
345 public XPathNamespace(Element elt, String uri, String prefix)
346 {
347 element = elt;
348 this.uri = uri;
349 this.prefix = prefix;
350 }
351
352 /*** Returns the XOM element from which this namespace node has been
353 * retrieved. The result may be null when the namespace node has not yet
354 * been assigned to an element.
355 */
356 public Element getElement()
357 {
358 return element;
359 }
360
361 public String getNamespaceURI()
362 {
363 return uri;
364 }
365
366 public String getNamespacePrefix()
367 {
368 return prefix;
369 }
370
371 public String toString()
372 {
373 return ( "[xmlns:" + prefix + "=\"" +
374 uri + "\", element=" +
375 element.getLocalName() + "]" );
376 }
377 }
378
379
380
381 private boolean addNamespaceForElement(Element elt, String uri, String prefix, Map map)
382 {
383 if (uri != null && uri.length() > 0 && (! map.containsKey(prefix))) {
384 map.put(prefix, new XPathNamespace(elt, uri, prefix));
385 return true;
386 }
387 return false;
388 }
389
390 public Iterator getNamespaceAxisIterator(Object o)
391 {
392 if (! isElement(o)) {
393 return JaxenConstants.EMPTY_ITERATOR;
394 }
395 Map nsMap = new HashMap();
396 Element elt = (Element)o;
397 ParentNode parent = elt;
398
399 while (parent instanceof Element) {
400 elt = (Element)parent;
401 String uri = elt.getNamespaceURI();
402 String prefix = elt.getNamespacePrefix();
403 addNamespaceForElement(elt, uri, prefix, nsMap);
404 int count = elt.getNamespaceDeclarationCount();
405 for (int i = 0; i < count; i++) {
406 prefix = elt.getNamespacePrefix(i);
407 uri = elt.getNamespaceURI(prefix);
408 addNamespaceForElement(elt, uri, prefix, nsMap);
409 }
410 parent = elt.getParent();
411 }
412 addNamespaceForElement(elt, "http://www.w3.org/XML/1998/namespace", "xml", nsMap);
413
414 return nsMap.values().iterator();
415 }
416 }