1   /*
2    * $Header$
3    * $Revision$
4    * $Date$
5    *
6    * ====================================================================
7    *
8    * Copyright (C) 2005 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$
60   */
61  
62  
63  package org.jaxen;
64  
65  import java.io.File;
66  import java.io.IOException;
67  import java.util.Iterator;
68  import java.util.List;
69  
70  import javax.xml.parsers.DocumentBuilder;
71  import javax.xml.parsers.DocumentBuilderFactory;
72  import javax.xml.parsers.ParserConfigurationException;
73  
74  import org.jaxen.dom.DOMXPath;
75  import org.jaxen.dom.NamespaceNode;
76  import org.jaxen.pattern.Pattern;
77  import org.jaxen.saxpath.helpers.XPathReaderFactory;
78  import org.w3c.dom.Attr;
79  import org.w3c.dom.Element;
80  import org.w3c.dom.Node;
81  import org.w3c.dom.Text;
82  import org.xml.sax.SAXException;
83  
84  import junit.framework.TestCase;
85  
86  /***
87   * <p>
88   * Tests for org.jaxen.BaseXPath.
89   * </p>
90   * 
91   * @author Elliotte Rusty Harold
92   * @version 1.1b7
93   *
94   */
95  public class BaseXPathTest extends TestCase {
96  
97      private org.w3c.dom.Document doc;
98      private DocumentBuilder builder;
99  
100     public BaseXPathTest(String name) {
101         super(name);
102     }
103     
104     protected void setUp() throws ParserConfigurationException {
105         
106         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
107         factory.setNamespaceAware(true);
108         doc = factory.newDocumentBuilder().newDocument();
109         builder = factory.newDocumentBuilder();
110         
111     }
112     
113     public void testSelectSingleNodeForContext() throws JaxenException {
114         
115         BaseXPath xpath = new BaseXPath("1 + 2");
116         
117         String stringValue = xpath.stringValueOf(xpath);
118         assertEquals("3", stringValue);
119         
120         Number numberValue = xpath.numberValueOf(xpath);
121         assertEquals(3, numberValue.doubleValue(), 0.00001);
122         
123     }
124     
125     
126     public void testParentOfSelection() throws JaxenException {
127         /*
128         html
129             a
130                 img
131             a        <- return that node
132                 img   <- select this node
133         */
134         XPath xpath = new DOMXPath("(/html/a/img[contains(@src,'gif')])[2]/..");
135         org.w3c.dom.Element html = doc.createElementNS("", "html");
136         org.w3c.dom.Element a1 = doc.createElementNS("", "a");
137         org.w3c.dom.Element a2 = doc.createElementNS("", "a");
138         org.w3c.dom.Element img1 = doc.createElementNS("", "img");
139           org.w3c.dom.Attr img1_src = doc.createAttributeNS("", "src");
140         img1_src.setValue("1.gif");
141         org.w3c.dom.Element img2 = doc.createElementNS("", "img");
142         org.w3c.dom.Attr img2_src = doc.createAttributeNS("", "src");
143         img2_src.setValue("2.gif");
144 
145         img1.setAttributeNode(img1_src);
146         img2.setAttributeNode(img2_src);
147         a1.appendChild(img1);
148         a2.appendChild(img2);
149         html.appendChild(a1);
150         html.appendChild(a2);
151         doc.appendChild(html);
152 
153         List result = xpath.selectNodes(doc);
154         assertEquals(1, result.size());
155         assertEquals(a2, result.get(0));
156     }
157 
158 
159     
160     
161     public void testEvaluateString() throws JaxenException {
162         
163         BaseXPath xpath = new DOMXPath("string(/*)");
164         
165         doc.appendChild(doc.createElement("root"));
166         String stringValue = (String) xpath.evaluate(doc);
167         assertEquals("", stringValue);
168         
169     }
170     
171     
172     public void testNumberValueOfEmptyNodeSetIsNaN() throws JaxenException {
173         
174         BaseXPath xpath = new DOMXPath("/x");
175         
176         doc.appendChild(doc.createElement("root"));
177         Double numberValue = (Double) xpath.numberValueOf(doc);
178         assertTrue(numberValue.isNaN());
179         
180     }
181     
182     
183     public void testPathWithParentheses() throws JaxenException {
184         
185         BaseXPath xpath = new DOMXPath("(/root)/child");
186         
187         Element root = doc.createElement("root");
188         doc.appendChild(root);
189         Element child = doc.createElement("child");
190         root.appendChild(child);
191         
192         assertEquals(child, xpath.selectSingleNode(doc));
193         
194     }
195     
196     
197     public void testEvaluateWithMultiNodeAnswer() throws JaxenException {
198         
199         BaseXPath xpath = new DOMXPath("(/descendant-or-self::node())");
200         
201         doc.appendChild(doc.createElement("root"));
202         List result = (List) xpath.evaluate(doc);
203         assertEquals(2, result.size());
204         
205     }
206     
207     
208     public void testValueOfEmptyListIsEmptyString() throws JaxenException {
209         
210         BaseXPath xpath = new DOMXPath("/element");
211         doc.appendChild(doc.createElement("root"));
212         
213         String stringValue = xpath.stringValueOf(doc);
214         assertEquals("", stringValue);
215         
216     }
217 
218     public void testAllNodesQuery() throws JaxenException {
219         
220         BaseXPath xpath = new DOMXPath("//. | /");
221         org.w3c.dom.Element root = doc.createElementNS("http://www.example.org/", "root");
222         doc.appendChild(root);
223         
224         String stringValue = xpath.stringValueOf(doc);
225         assertEquals("", stringValue);
226         
227     }
228 
229     
230     public void testAncestorAxis() throws JaxenException {
231         
232         BaseXPath xpath = new DOMXPath("ancestor::*");
233         org.w3c.dom.Element root = doc.createElementNS("", "root");
234         org.w3c.dom.Element parent = doc.createElementNS("", "parent");
235         doc.appendChild(root);
236         org.w3c.dom.Element child = doc.createElementNS("", "child");
237         root.appendChild(parent);
238         parent.appendChild(child);
239         
240         List result = xpath.selectNodes(child);
241         assertEquals(2, result.size());
242         assertEquals(root, result.get(0));   
243         assertEquals(parent, result.get(1));
244         
245     }    
246     
247     
248     public void testPrecedingSiblingAxisIsInDocumentOrder() throws JaxenException {
249         
250         BaseXPath xpath = new DOMXPath("preceding-sibling::*");
251         org.w3c.dom.Element root = doc.createElementNS("", "root");
252         doc.appendChild(root);
253         org.w3c.dom.Element child1 = doc.createElementNS("", "child1");
254         root.appendChild(child1);
255         org.w3c.dom.Element child2 = doc.createElementNS("", "child2");
256         root.appendChild(child2);
257         org.w3c.dom.Element child3 = doc.createElementNS("", "child3");
258         root.appendChild(child3);
259         
260         List result = xpath.selectNodes(child3);
261         assertEquals(2, result.size());
262         assertEquals(child1, result.get(0));   
263         assertEquals(child2, result.get(1));
264         
265     }    
266     
267     
268     public void testPrecedingAxisIsInDocumentOrder() throws JaxenException {
269         
270         BaseXPath xpath = new DOMXPath("preceding::*");
271         org.w3c.dom.Element root = doc.createElementNS("", "root");
272         doc.appendChild(root);
273         org.w3c.dom.Element parent1 = doc.createElementNS("", "parent1");
274         root.appendChild(parent1);
275         org.w3c.dom.Element parent2 = doc.createElementNS("", "parent2");
276         root.appendChild(parent2);
277         org.w3c.dom.Element child1 = doc.createElementNS("", "child1");
278         parent2.appendChild(child1);
279         org.w3c.dom.Element child2 = doc.createElementNS("", "child2");
280         parent2.appendChild(child2);
281         org.w3c.dom.Element child3 = doc.createElementNS("", "child3");
282         parent2.appendChild(child3);
283         
284         List result = xpath.selectNodes(child3);
285         assertEquals(3, result.size());
286         assertEquals(parent1, result.get(0));   
287         assertEquals(child1, result.get(1));   
288         assertEquals(child2, result.get(2));
289         
290     }    
291     
292     
293     public void testPrecedingAxisWithPositionalPredicate() throws JaxenException {
294         
295         BaseXPath xpath = new DOMXPath("preceding::*[1]");
296         org.w3c.dom.Element root = doc.createElementNS("", "root");
297         doc.appendChild(root);
298         org.w3c.dom.Element child1 = doc.createElementNS("", "child1");
299         root.appendChild(child1);
300         org.w3c.dom.Element child2 = doc.createElementNS("", "child2");
301         root.appendChild(child2);
302         org.w3c.dom.Element child3 = doc.createElementNS("", "child3");
303         root.appendChild(child3);
304         
305         List result = xpath.selectNodes(child3);
306         assertEquals(1, result.size());  
307         assertEquals(child2, result.get(0));
308         
309     }    
310     
311     
312     public void testAncestorAxisWithPositionalPredicate() throws JaxenException {
313         
314         BaseXPath xpath = new DOMXPath("ancestor::*[1]");
315         org.w3c.dom.Element root = doc.createElementNS("", "root");
316         doc.appendChild(root);
317         org.w3c.dom.Element child1 = doc.createElementNS("", "child1");
318         root.appendChild(child1);
319         org.w3c.dom.Element child2 = doc.createElementNS("", "child2");
320         child1.appendChild(child2);
321         org.w3c.dom.Element child3 = doc.createElementNS("", "child3");
322         child2.appendChild(child3);
323         
324         List result = xpath.selectNodes(child3);
325         assertEquals(1, result.size());  
326         assertEquals(child2, result.get(0));
327         
328     }    
329     
330     
331     public void testAncestorOrSelfAxis() throws JaxenException {
332         
333         BaseXPath xpath = new DOMXPath("ancestor-or-self::*");
334         org.w3c.dom.Element root = doc.createElementNS("", "root");
335         org.w3c.dom.Element parent = doc.createElementNS("", "parent");
336         doc.appendChild(root);
337         org.w3c.dom.Element child = doc.createElementNS("", "child");
338         root.appendChild(parent);
339         parent.appendChild(child);
340         
341         List result = xpath.selectNodes(child);
342         assertEquals(3, result.size());
343         assertEquals(root, result.get(0));   
344         assertEquals(parent, result.get(1));
345         assertEquals(child, result.get(2));
346         
347     }    
348     
349     
350     // test case for JAXEN-55
351     public void testAbbreviatedDoubleSlashAxis() throws JaxenException {
352         
353         BaseXPath xpath = new DOMXPath("//x");
354         org.w3c.dom.Element a = doc.createElementNS("", "a");
355         org.w3c.dom.Element b = doc.createElementNS("", "b");
356         doc.appendChild(a);
357         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
358         x1.appendChild(doc.createTextNode("1"));
359         a.appendChild(x1);
360         a.appendChild(b);
361         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
362         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
363         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
364         a.appendChild(x4);
365         b.appendChild(x2);
366         b.appendChild(x3);
367         x2.appendChild(doc.createTextNode("2"));
368         x3.appendChild(doc.createTextNode("3"));
369         x4.appendChild(doc.createTextNode("4"));
370         
371         List result = xpath.selectNodes(doc);
372         assertEquals(4, result.size());
373         assertEquals(x1, result.get(0));   
374         assertEquals(x2, result.get(1));   
375         assertEquals(x3, result.get(2));   
376         assertEquals(x4, result.get(3));
377         
378     }    
379     
380     
381     // test case for JAXEN-55
382     public void testAncestorFollowedByChildren() throws JaxenException {
383         
384         BaseXPath xpath = new DOMXPath("/a/b/x/ancestor::*/child::x");
385         org.w3c.dom.Element a = doc.createElementNS("", "a");
386         org.w3c.dom.Element b = doc.createElementNS("", "b");
387         doc.appendChild(a);
388         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
389         x1.appendChild(doc.createTextNode("1"));
390         a.appendChild(x1);
391         a.appendChild(b);
392         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
393         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
394         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
395         a.appendChild(x4);
396         b.appendChild(x2);
397         b.appendChild(x3);
398         x2.appendChild(doc.createTextNode("2"));
399         x3.appendChild(doc.createTextNode("3"));
400         x4.appendChild(doc.createTextNode("4"));
401         
402         List result = xpath.selectNodes(doc);
403         assertEquals(4, result.size());
404         assertEquals(x1, result.get(0));   
405         assertEquals(x2, result.get(1));   
406         assertEquals(x3, result.get(2));   
407         assertEquals(x4, result.get(3));
408         
409     }    
410     
411     
412     // test case for JAXEN-55
413     public void testDescendantAxis() throws JaxenException {
414         
415         BaseXPath xpath = new DOMXPath("/descendant::x");
416         org.w3c.dom.Element a = doc.createElementNS("", "a");
417         org.w3c.dom.Element b = doc.createElementNS("", "b");
418         doc.appendChild(a);
419         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
420         x1.appendChild(doc.createTextNode("1"));
421         a.appendChild(x1);
422         a.appendChild(b);
423         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
424         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
425         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
426         a.appendChild(x4);
427         b.appendChild(x2);
428         b.appendChild(x3);
429         x2.appendChild(doc.createTextNode("2"));
430         x3.appendChild(doc.createTextNode("3"));
431         x4.appendChild(doc.createTextNode("4"));
432         
433         List result = xpath.selectNodes(doc);
434         assertEquals(4, result.size());
435         assertEquals(x1, result.get(0));   
436         assertEquals(x2, result.get(1));   
437         assertEquals(x3, result.get(2));   
438         assertEquals(x4, result.get(3));
439         
440     }    
441     
442     public void testDescendantAxisWithAttributes() throws JaxenException {
443         
444         BaseXPath xpath = new DOMXPath("/descendant::x/@*");
445         org.w3c.dom.Element a = doc.createElementNS("", "a");
446         org.w3c.dom.Element b = doc.createElementNS("", "b");
447         doc.appendChild(a);
448         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
449         a.appendChild(x1);
450         a.appendChild(b);
451         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
452         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
453         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
454         a.appendChild(x4);
455         b.appendChild(x2);
456         b.appendChild(x3);
457         
458         Attr a1 = doc.createAttribute("name");
459         a1.setNodeValue("1");
460         x1.setAttributeNode(a1);
461         Attr a2 = doc.createAttribute("name");
462         a2.setNodeValue("2");
463         x2.setAttributeNode(a2);
464         Attr a3 = doc.createAttribute("name");
465         a3.setNodeValue("3");
466         x3.setAttributeNode(a3);
467         Attr a4 = doc.createAttribute("name");
468         a4.setNodeValue("4");
469         x4.setAttributeNode(a4);
470         
471         List result = xpath.selectNodes(doc);
472         assertEquals(4, result.size());
473         assertEquals(a1, result.get(0));   
474         assertEquals(a2, result.get(1));   
475         assertEquals(a3, result.get(2));   
476         assertEquals(a4, result.get(3));
477         
478     }    
479     
480     public void testDescendantAxisWithNamespaceNodes() throws JaxenException {
481         
482         BaseXPath xpath = new DOMXPath("/descendant::x/namespace::node()");
483         org.w3c.dom.Element a = doc.createElementNS("", "a");
484         org.w3c.dom.Element b = doc.createElementNS("", "b");
485         doc.appendChild(a);
486         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
487         a.appendChild(x1);
488         a.appendChild(b);
489         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
490         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
491         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
492         a.appendChild(x4);
493         b.appendChild(x2);
494         b.appendChild(x3);
495         
496         Attr a1 = doc.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:a");
497         a1.setNodeValue("http://www.example.org/");
498         x1.setAttributeNode(a1);
499         Attr a2 = doc.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:b");
500         a2.setNodeValue("http://www.example.org/");
501         x2.setAttributeNode(a2);
502         Attr a3 = doc.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:c");
503         a3.setNodeValue("http://www.example.org/");
504         x3.setAttributeNode(a3);
505         Attr a4 = doc.createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:d");
506         a4.setNodeValue("http://www.example.org/");
507         x4.setAttributeNode(a4);
508         
509         List result = xpath.selectNodes(doc);
510         assertEquals(8, result.size());
511         Iterator iterator = result.iterator();
512         StringBuffer sb = new StringBuffer(4);
513         while (iterator.hasNext()) {
514             NamespaceNode ns = (NamespaceNode) iterator.next();
515             if (ns.getNodeValue().equals("http://www.example.org/")) {
516                 String name = ns.getNodeName();
517                 sb.append(name);
518             }
519         }
520         assertEquals("abcd", sb.toString());
521         
522     }    
523     
524     public void testMultipleAttributesOnElement() throws JaxenException {
525         
526         BaseXPath xpath = new DOMXPath("/descendant::x/@*");
527         org.w3c.dom.Element a = doc.createElementNS("", "a");
528         org.w3c.dom.Element b = doc.createElementNS("", "b");
529         doc.appendChild(a);
530         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
531         a.appendChild(x1);
532         a.appendChild(b);
533         
534         Attr a1 = doc.createAttribute("name1");
535         a1.setNodeValue("1");
536         x1.setAttributeNode(a1);
537         Attr a2 = doc.createAttribute("name2");
538         a2.setNodeValue("2");
539         x1.setAttributeNode(a2);
540         Attr a3 = doc.createAttribute("name3");
541         a3.setNodeValue("3");
542         x1.setAttributeNode(a3);
543         Attr a4 = doc.createAttribute("name4");
544         a4.setNodeValue("4");
545         x1.setAttributeNode(a4);
546         
547         List result = xpath.selectNodes(doc);
548         assertEquals(4, result.size());
549         assertTrue(result.contains(a1));
550         assertTrue(result.contains(a2));
551         assertTrue(result.contains(a3));
552         assertTrue(result.contains(a4));
553         
554     }   
555     
556     public void testXMLNamespaceAttributeOrderOnAncestorAxis() 
557       throws JaxenException {
558      
559         org.w3c.dom.Element superroot = doc.createElement("superroot");
560         doc.appendChild(superroot);
561         org.w3c.dom.Element root = doc.createElement("root");
562         superroot.appendChild(root);
563         
564         org.w3c.dom.Attr p0 = doc.createAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:id");
565         p0.setValue("p0");
566         superroot.setAttributeNodeNS(p0);
567         org.w3c.dom.Attr p1 = doc.createAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:id");
568         p1.setValue("p1");
569         root.setAttributeNodeNS(p1);
570         
571         org.w3c.dom.Element child = doc.createElement("child312");
572         root.appendChild(child);
573         
574         BaseXPath xpath = new DOMXPath("ancestor::*/@xml:*");
575         List result = xpath.selectNodes(child);
576         assertEquals(2, result.size());
577         assertEquals(p0, result.get(0));
578         assertEquals(p1, result.get(1));
579         
580     }
581     
582     public void testDescendantAxisWithAttributesAndChildren() throws JaxenException {
583         
584         BaseXPath xpath = new DOMXPath("/descendant::x/@* | /descendant::x");
585         org.w3c.dom.Element a = doc.createElementNS("", "a");
586         org.w3c.dom.Element b = doc.createElementNS("", "b");
587         doc.appendChild(a);
588         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
589         a.appendChild(x1);
590         a.appendChild(b);
591         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
592         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
593         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
594         a.appendChild(x4);
595         b.appendChild(x2);
596         b.appendChild(x3);
597         
598         Attr a1 = doc.createAttribute("name");
599         a1.setNodeValue("1");
600         x1.setAttributeNode(a1);
601         Attr a2 = doc.createAttribute("name");
602         a2.setNodeValue("2");
603         x2.setAttributeNode(a2);
604         Attr a3 = doc.createAttribute("name");
605         a3.setNodeValue("3");
606         x3.setAttributeNode(a3);
607         Attr a4 = doc.createAttribute("name");
608         a4.setNodeValue("4");
609         x4.setAttributeNode(a4);
610         
611         List result = xpath.selectNodes(doc);
612         assertEquals(8, result.size());
613         assertEquals(x1, result.get(0));   
614         assertEquals(a1, result.get(1));   
615         assertEquals(x2, result.get(2));   
616         assertEquals(a2, result.get(3));
617         assertEquals(x3, result.get(4));   
618         assertEquals(a3, result.get(5));   
619         assertEquals(x4, result.get(6));   
620         assertEquals(a4, result.get(7));
621         
622     }    
623     
624     public void testAncestorAxisWithAttributes() throws JaxenException {
625         
626         BaseXPath xpath = new DOMXPath("ancestor::*/@*");
627         org.w3c.dom.Element a = doc.createElementNS("", "a");
628         org.w3c.dom.Element b = doc.createElementNS("", "b");
629         doc.appendChild(a);
630         a.appendChild(b);
631         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
632         b.appendChild(x3);
633         
634         Attr a1 = doc.createAttribute("name");
635         a1.setNodeValue("1");
636         a.setAttributeNode(a1);
637         Attr a2 = doc.createAttribute("name");
638         a2.setNodeValue("2");
639         b.setAttributeNode(a2);
640         Attr a3 = doc.createAttribute("name");
641         x3.setNodeValue("3");
642         x3.setAttributeNode(a3);
643         
644         List result = xpath.selectNodes(x3);
645         assertEquals(2, result.size());
646         assertEquals(a1, result.get(0));   
647         assertEquals(a2, result.get(1)); 
648         
649     }    
650     
651     // test for Jaxen-83
652     public void testPrincipalNodeTypeOfSelfAxisIsElement() throws JaxenException {
653         
654         BaseXPath xpath = new DOMXPath("child/@*[self::test]");
655         org.w3c.dom.Element a = doc.createElementNS("", "child");
656         org.w3c.dom.Attr test = doc.createAttributeNS("", "test");
657         test.setValue("value");
658         a.setAttributeNode(test);
659         doc.appendChild(a);
660         
661         List result = xpath.selectNodes(doc);
662         assertEquals(0, result.size()); 
663         
664     }
665     
666     // test to make sure Jaxen-83 fix doesn't go too far
667     public void testSelfAxisWithNodeTestCanReturnNonPrincipalNodeType() throws JaxenException {
668         
669         BaseXPath xpath = new DOMXPath("child/@*[self::node()]");
670         org.w3c.dom.Element a = doc.createElementNS("", "child");
671         org.w3c.dom.Attr test = doc.createAttributeNS("", "test");
672         test.setValue("value");
673         a.setAttributeNode(test);
674         doc.appendChild(a);
675         
676         List result = xpath.selectNodes(doc);
677         assertEquals(1, result.size());   
678         
679     } 
680     
681     // another Jaxen-55 test to try to pin down exactly what does
682     // and doesn't work
683     public void testDescendantOrSelfAxis() throws JaxenException {
684         
685         BaseXPath xpath = new DOMXPath("/descendant-or-self::x");
686         org.w3c.dom.Element a = doc.createElementNS("", "a");
687         org.w3c.dom.Element b = doc.createElementNS("", "b");
688         doc.appendChild(a);
689         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
690         x1.appendChild(doc.createTextNode("1"));
691         a.appendChild(x1);
692         a.appendChild(b);
693         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
694         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
695         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
696         a.appendChild(x4);
697         b.appendChild(x2);
698         b.appendChild(x3);
699         x2.appendChild(doc.createTextNode("2"));
700         x3.appendChild(doc.createTextNode("3"));
701         x4.appendChild(doc.createTextNode("4"));
702         
703         List result = xpath.selectNodes(doc);
704         assertEquals(4, result.size());
705         assertEquals(x1, result.get(0));   
706         assertEquals(x2, result.get(1));   
707         assertEquals(x3, result.get(2));   
708         assertEquals(x4, result.get(3));
709         
710     }    
711     
712     
713     public void testDuplicateNodes() throws JaxenException {
714         
715         BaseXPath xpath = new DOMXPath("//x | //*");
716         org.w3c.dom.Element a = doc.createElementNS("", "a");
717         org.w3c.dom.Element b = doc.createElementNS("", "b");
718         doc.appendChild(a);
719         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
720         x1.appendChild(doc.createTextNode("1"));
721         a.appendChild(x1);
722         a.appendChild(b);
723         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
724         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
725         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
726         a.appendChild(x4);
727         b.appendChild(x2);
728         b.appendChild(x3);
729         x2.appendChild(doc.createTextNode("2"));
730         x3.appendChild(doc.createTextNode("3"));
731         x4.appendChild(doc.createTextNode("4"));
732         
733         List result = xpath.selectNodes(doc);
734         assertEquals(6, result.size());
735         
736     }    
737        
738     public void testUnionOfNodesWithNonNodes() throws JaxenException {
739         
740         BaseXPath xpath = new DOMXPath("count(//*) | //x ");
741         org.w3c.dom.Element a = doc.createElementNS("", "a");
742         org.w3c.dom.Element b = doc.createElementNS("", "b");
743         doc.appendChild(a);
744         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
745         x1.appendChild(doc.createTextNode("1"));
746         a.appendChild(x1);
747         a.appendChild(b);
748         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
749         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
750         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
751         a.appendChild(x4);
752         b.appendChild(x2);
753         b.appendChild(x3);
754         x2.appendChild(doc.createTextNode("2"));
755         x3.appendChild(doc.createTextNode("3"));
756         x4.appendChild(doc.createTextNode("4"));
757         
758         try {
759             xpath.selectNodes(doc);
760             fail("Allowed union with non-node-set");
761         }
762         catch (JaxenException ex) {
763             assertNotNull(ex.getMessage());
764         }
765         
766     }    
767     
768     public void testUnionOfEmptyNodeSetWithNonNodes() throws JaxenException {
769         
770         BaseXPath xpath = new DOMXPath("//y | count(//*)");
771         org.w3c.dom.Element a = doc.createElementNS("", "a");
772         org.w3c.dom.Element b = doc.createElementNS("", "b");
773         doc.appendChild(a);
774         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
775         x1.appendChild(doc.createTextNode("1"));
776         a.appendChild(x1);
777         a.appendChild(b);
778         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
779         b.appendChild(x2);
780         x2.appendChild(doc.createTextNode("2"));
781         
782         try {
783             xpath.selectNodes(doc);
784             fail("Allowed union with non-node-set");
785         }
786         catch (JaxenException ex) {
787             assertNotNull(ex.getMessage());
788         }
789         
790     } 
791     
792     public void testSelectSingleNodeSelectsNothing() 
793       throws JaxenException {
794         
795         BaseXPath xpath = new DOMXPath("id('p1')");
796         org.w3c.dom.Element a = doc.createElementNS("", "a");
797         doc.appendChild(a);
798         Object result = xpath.selectSingleNode(doc);
799         assertNull(result);
800         
801     }  
802     
803     public void testSAXPathExceptionThrownFromConstructor() {
804         
805         System.setProperty( XPathReaderFactory.DRIVER_PROPERTY,
806                             "java.lang.String" );
807         
808         try {
809             new DOMXPath("id('p1')");
810         }
811         catch (JaxenException e) {
812             assertNotNull(e.getMessage());
813         }
814         finally {
815             System.setProperty( XPathReaderFactory.DRIVER_PROPERTY,
816                             "" );
817         }
818         
819     }  
820     
821     public void testBooleanValueOfEmptyNodeSetIsFalse() 
822       throws JaxenException {
823         
824         BaseXPath xpath = new DOMXPath("/b/c");
825         org.w3c.dom.Element a = doc.createElementNS("", "a");
826         doc.appendChild(a);
827         List result = xpath.selectNodes(doc);
828         assertTrue(! xpath.booleanValueOf(result));
829         
830     } 
831     
832     public void testAddNamespaceWithNonSimpleNamespaceContext() throws JaxenException {
833         
834         BaseXPath xpath = new DOMXPath("/b/c");
835         xpath.setNamespaceContext(new NamespaceContext() {
836 
837             public String translateNamespacePrefixToUri(String prefix) {
838                 return prefix;
839             }
840             
841         });
842         try {
843             xpath.addNamespace("pre", "foo");            
844             fail("Added namespace");
845         }
846         catch (JaxenException ex) {
847             assertNotNull(ex.getMessage());
848         }
849         
850     } 
851     
852     public void testDebug() throws JaxenException {
853         
854         BaseXPath xpath = new DOMXPath("/b/c");
855         assertEquals("[(DefaultXPath): [(DefaultAbsoluteLocationPath): [(DefaultNameStep): :b]/[(DefaultNameStep): :c]]]", xpath.debug());
856         
857     } 
858     
859     public void testGetRootExpr() throws JaxenException {
860         BaseXPath xpath = new DOMXPath("/b/c");
861         assertTrue(xpath.getRootExpr() instanceof org.jaxen.expr.LocationPath);
862     } 
863     
864     public void testUnionUsesDocumentOrder() throws JaxenException {
865         
866         BaseXPath xpath = new DOMXPath("/descendant::x | /a | /a/b");
867         org.w3c.dom.Element a = doc.createElementNS("", "a");
868         org.w3c.dom.Element b = doc.createElementNS("", "b");
869         doc.appendChild(a);
870         org.w3c.dom.Element x1 = doc.createElementNS("", "x");
871         x1.appendChild(doc.createTextNode("1"));
872         a.appendChild(x1);
873         a.appendChild(b);
874         org.w3c.dom.Element x2 = doc.createElementNS("", "x");
875         org.w3c.dom.Element x3 = doc.createElementNS("", "x");
876         org.w3c.dom.Element x4 = doc.createElementNS("", "x");
877         a.appendChild(x4);
878         b.appendChild(x2);
879         b.appendChild(x3);
880         x2.appendChild(doc.createTextNode("2"));
881         x3.appendChild(doc.createTextNode("3"));
882         x4.appendChild(doc.createTextNode("4"));
883         
884         List result = xpath.selectNodes(doc);
885         assertEquals(6, result.size());
886         assertEquals(a, result.get(0));   
887         assertEquals(x1, result.get(1));   
888         assertEquals(b, result.get(2));   
889         assertEquals(x2, result.get(3));   
890         assertEquals(x3, result.get(4));   
891         assertEquals(x4, result.get(5));
892         
893     }
894     
895     public void testArithmeticAssociativity() throws JaxenException {
896         XPath xpath = new DOMXPath("2+1-1+1");
897         Double result = (Double) xpath.evaluate(doc);
898         assertEquals(3, result.intValue());
899     }
900     
901     public void testLogicalAssociativity() throws JaxenException {
902         XPath xpath = new DOMXPath("false() or true() and true() and false()");
903         Boolean result = (Boolean) xpath.evaluate(doc);
904         assertFalse(result.booleanValue());
905     }
906     
907     public void testRelationalAssociativity3() throws JaxenException {
908         XPath xpath = new DOMXPath("3 > 2 > 1");
909         Boolean result = (Boolean) xpath.evaluate(doc);
910         assertFalse(result.booleanValue());
911     }
912     
913     public void testRelationalAssociativity4() throws JaxenException {
914         XPath xpath = new DOMXPath("4 > 3 > 2 > 1");
915         Boolean result = (Boolean) xpath.evaluate(doc);
916         assertFalse(result.booleanValue());
917     }
918     
919     public void testRelationalGTAssociativity5() throws JaxenException {
920         XPath xpath = new DOMXPath("5 > 4 > 3 > 2 > 1");
921         Boolean result = (Boolean) xpath.evaluate(doc);
922         assertFalse(result.booleanValue());
923     }
924     
925     public void testRelationalLTAssociativity5() throws JaxenException {
926         XPath xpath = new DOMXPath("1 < 2 < 3 < 4 < 5");
927         Boolean result = (Boolean) xpath.evaluate(doc);
928         assertTrue(result.booleanValue());
929     }
930     
931     public void testRelationalLEAssociativity5() throws JaxenException {
932         XPath xpath = new DOMXPath("1 <= 2 <= 3 <= 4 <= 5");
933         Boolean result = (Boolean) xpath.evaluate(doc);
934         assertTrue(result.booleanValue());
935     }
936     
937     public void testRelationalGEAssociativity5() throws JaxenException {
938         XPath xpath = new DOMXPath("5 >= 4 >= 3 >= 2 >= 1");
939         Boolean result = (Boolean) xpath.evaluate(doc);
940         assertFalse(result.booleanValue());
941     }
942     
943     public void testRelationalGEAssociativity3() throws JaxenException {
944         XPath xpath = new DOMXPath("3 >= 2 >= 1");
945         Boolean result = (Boolean) xpath.evaluate(doc);
946         assertTrue(result.booleanValue());
947     }
948     
949     public void testRelationalGEAssociativity2() throws JaxenException {
950         XPath xpath = new DOMXPath("2 >= 1");
951         Boolean result = (Boolean) xpath.evaluate(doc);
952         assertTrue(result.booleanValue());
953     }
954     
955     public void testRelationalGEAssociativity4() throws JaxenException {
956         XPath xpath = new DOMXPath("4 >= 3 >= 2 >= 1");
957         Boolean result = (Boolean) xpath.evaluate(doc);
958         assertFalse(result.booleanValue());
959     }
960     
961     // This is the same test but with parentheses to make explicit
962     // how the previous test should be evaluated.
963     public void testRelationalAssociativity5P() throws JaxenException {
964         XPath xpath = new DOMXPath("((((5 > 4) > 3) > 2) > 1)");
965         Boolean result = (Boolean) xpath.evaluate(doc);
966         assertFalse(result.booleanValue());
967     }
968     
969     public void testInequalityAssociativity5() throws JaxenException {
970         XPath xpath = new DOMXPath("2 != 3 != 1 != 4 != 0");
971         Boolean result = (Boolean) xpath.evaluate(doc);
972         assertTrue(result.booleanValue());
973     }
974     
975     // This is the same test but with parentheses to make explicit
976     // how the previous test should be evaluated.
977     public void testInequalityAssociativity5P() throws JaxenException {
978         XPath xpath = new DOMXPath("(((2 != 3) != 1) != 4) != 0");
979         Boolean result = (Boolean) xpath.evaluate(doc);
980         assertTrue(result.booleanValue());
981     }
982     
983     public void testInequalityAssociativity5B() throws JaxenException {
984         XPath xpath = new DOMXPath("2 != 3 != 1 != 4 != 1");
985         Boolean result = (Boolean) xpath.evaluate(doc);
986         assertFalse(result.booleanValue());
987     }
988     
989     // This is the same test but with parentheses to make explicit
990     // how the previous test should be evaluated.
991     public void testInequalityAssociativity5BP() throws JaxenException {
992         XPath xpath = new DOMXPath("(((2 != 3) != 1) != 4) != 1");
993         Boolean result = (Boolean) xpath.evaluate(doc);
994         assertFalse(result.booleanValue());
995     }
996     
997     public void testEqualityAssociativity5() throws JaxenException {
998         XPath xpath = new DOMXPath("2 = 3 = 1 = 4 = 0");
999         Boolean result = (Boolean) xpath.evaluate(doc);
1000         assertTrue(result.booleanValue());
1001     }
1002     
1003     // This is the same test but with parentheses to make explicit
1004     // how the previous test should be evaluated.
1005     public void testEqualityAssociativity5P() throws JaxenException {
1006         XPath xpath = new DOMXPath("(((2 = 3) = 1) = 4) = 0");
1007         Boolean result = (Boolean) xpath.evaluate(doc);
1008         assertTrue(result.booleanValue());
1009     }
1010     
1011     public void testEqualityAssociativity5B() throws JaxenException {
1012         XPath xpath = new DOMXPath("2 = 3 = 1 = 4 = 1");
1013         Boolean result = (Boolean) xpath.evaluate(doc);
1014         assertFalse(result.booleanValue());
1015     }
1016     
1017     // This is the same test but with parentheses to make explicit
1018     // how the previous test should be evaluated.
1019     public void testEqualityAssociativity5BP() throws JaxenException {
1020         XPath xpath = new DOMXPath("(((2 = 3) = 1) = 4) = 1");
1021         Boolean result = (Boolean) xpath.evaluate(doc);
1022         assertFalse(result.booleanValue());
1023     }
1024     
1025     public void testMoreComplexArithmeticAssociativity() throws JaxenException {
1026         XPath xpath = new DOMXPath("1+2+1-1+1");
1027         Double result = (Double) xpath.evaluate(doc);
1028         assertEquals(4, result.intValue());
1029     }
1030     
1031     
1032     public void testMostComplexArithmeticAssociativity() throws JaxenException {
1033         XPath xpath = new DOMXPath("1+1+2+1-1+1");
1034         Double result = (Double) xpath.evaluate(doc);
1035         assertEquals(5, result.intValue());
1036     }
1037     
1038     
1039     public void testSimplerArithmeticAssociativity() throws JaxenException {
1040         XPath xpath = new DOMXPath("1-1+1");
1041         Double result = (Double) xpath.evaluate(doc);
1042         assertEquals(1, result.intValue());
1043     }
1044     
1045     
1046     public void testNamespaceNodesComeBeforeAttributeNodesInDocumentOrder() throws JaxenException {
1047         
1048         org.w3c.dom.Element root = doc.createElementNS("http://www.example.org", "pre:b");
1049         doc.appendChild(root);
1050         root.setAttribute("name", "value");
1051         XPath xpath = new DOMXPath("/*/attribute::* | /*/namespace::node()");
1052         List result = xpath.selectNodes(doc);
1053         assertTrue(((org.w3c.dom.Node) result.get(0)).getNodeType() == Pattern.NAMESPACE_NODE);
1054         assertTrue(((org.w3c.dom.Node) result.get(1)).getNodeType() == Pattern.NAMESPACE_NODE);
1055         assertTrue(((org.w3c.dom.Node) result.get(2)).getNodeType() == Node.ATTRIBUTE_NODE);
1056         
1057         // now flip the order of the statement and retest
1058         xpath = new DOMXPath("/*/namespace::node() | /*/attribute::* ");
1059         result = xpath.selectNodes(doc);
1060         assertTrue(((org.w3c.dom.Node) result.get(0)).getNodeType() == Pattern.NAMESPACE_NODE);
1061         assertTrue(((org.w3c.dom.Node) result.get(1)).getNodeType() == Pattern.NAMESPACE_NODE);
1062         assertTrue(((org.w3c.dom.Node) result.get(2)).getNodeType() == Node.ATTRIBUTE_NODE);
1063    
1064     }
1065 
1066     public void testJaxen97() throws JaxenException {
1067         // jaxen 97 claims this expression throws an exception.
1068         new DOMXPath("/aaa:element/text()");
1069     }
1070 
1071     public void testAttributeNodesOnParentComeBeforeNamespaceNodesInChildInDocumentOrder() 
1072      throws JaxenException {
1073         
1074         org.w3c.dom.Element root = doc.createElement("root");
1075         doc.appendChild(root);
1076         root.setAttribute("name", "value");
1077         Element child = doc.createElementNS("http://www.example.org", "pre:child");
1078         root.appendChild(child);
1079         
1080         XPath xpath = new DOMXPath("/*/*/namespace::node() | //attribute::* ");
1081         List result = xpath.selectNodes(doc);
1082         assertEquals(3, result.size());
1083         assertTrue(((org.w3c.dom.Node) result.get(0)).getNodeType() == Node.ATTRIBUTE_NODE);
1084         assertTrue(((org.w3c.dom.Node) result.get(1)).getNodeType() == Pattern.NAMESPACE_NODE);
1085    
1086     }
1087 
1088     public void testJaxen107() throws JaxenException {
1089         
1090         org.w3c.dom.Element a = doc.createElementNS("http://www.a.com/", "a:foo");
1091         doc.appendChild(a);
1092         Element b = doc.createElementNS("http://www.b.com/", "b:bar");
1093         a.appendChild(b);
1094         
1095         XPath xpath = new DOMXPath("/a:foo/b:bar/namespace::*/parent::*");
1096         SimpleNamespaceContext context1 = new SimpleNamespaceContext();
1097         context1.addNamespace("a", "http://www.a.com/");
1098         context1.addNamespace("b", "http://www.b.com/");
1099         xpath.setNamespaceContext(context1);
1100         List result = xpath.selectNodes(doc);
1101         assertEquals(1, result.size());
1102         assertEquals(b, result.get(0));
1103    
1104     }
1105     
1106     
1107     public void testJaxen107FromFile() throws JaxenException, SAXException, IOException {
1108         
1109         doc = builder.parse(new File("xml/testNamespaces.xml"));
1110         XPath xpath = new DOMXPath("/Template/Application2/namespace::*/parent::*");
1111         List result = xpath.selectNodes(doc);
1112         assertEquals(1, result.size());
1113    
1114     }
1115     
1116     public void testSelectNodesReturnsANonNodeSet() throws JaxenException {
1117         XPath xpath = new DOMXPath("1 + 2 + 3");
1118         List result = xpath.selectNodes(doc);
1119         assertEquals(1, result.size());
1120     }
1121     
1122     public void testNonElementContextNode() throws JaxenException {
1123         
1124         org.w3c.dom.Element a = doc.createElementNS("http://www.a.com/", "a:foo");
1125         doc.appendChild(a);
1126         Text b = doc.createTextNode("ready");
1127         a.appendChild(b);
1128         
1129         XPath xpath = new DOMXPath("..");
1130         List result = (List) xpath.evaluate(b);
1131         assertEquals(1, result.size());
1132         assertEquals(a, result.get(0));
1133    
1134     }
1135     
1136     public void testNonNodeContext() throws JaxenException {
1137         
1138         org.w3c.dom.Element a = doc.createElementNS("http://www.a.com/", "a:foo");
1139         doc.appendChild(a);
1140         Text b = doc.createTextNode("ready");
1141         a.appendChild(b);
1142         
1143         XPath xpath = new DOMXPath("..");
1144         try {
1145             xpath.evaluate("String");
1146             fail("Allowed String as context");
1147         }
1148         catch (ClassCastException ex) {
1149             // success
1150         }
1151    
1152     }
1153     
1154     
1155     
1156 }