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