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