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