1   /*
2    * $Header$
3    * $Revision$
4    * $Date$
5    *
6    * ====================================================================
7    *
8    * Copyright 2000-2002 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 junit.framework.TestCase;
52  
53  import org.jaxen.*;
54  import org.jaxen.dom.DOMXPath;
55  import org.jaxen.function.StringFunction;
56  import org.jaxen.saxpath.helpers.XPathReaderFactory;
57  import org.jaxen.pattern.Pattern;
58  
59  import java.util.ArrayList;
60  import java.util.Iterator;
61  import java.util.List;
62  
63  public abstract class XPathTestBase extends TestCase
64  {
65      protected static String VAR_URI   = "http://jaxen.org/test-harness/var";
66      protected static String TESTS_XML = "xml/test/tests.xml";
67  
68      protected static boolean verbose = false;
69      protected static boolean debug = false;
70      private ContextSupport contextSupport;
71  
72      protected XPathTestBase(String name)
73      {
74          super(name);
75      }
76  
77      protected void setUp() throws Exception
78      {
79          this.contextSupport = null;
80          System.setProperty(XPathReaderFactory.DRIVER_PROPERTY,
81                  "");
82          log("-----------------------------");
83      }
84  
85      public void log(String text)
86      {
87          log(verbose,
88                  text);
89      }
90  
91      private void log(boolean actualVerbose,
92                      String text)
93      {
94          if (actualVerbose) System.out.println(text);
95      }
96  
97      private void assertCountXPath(int expectedSize, Object context, String xpathStr) throws JaxenException
98      {
99          assertCountXPath2(expectedSize, context, xpathStr);
100     }
101 
102     private Object assertCountXPath2(int expectedSize, Object context, String xpathStr) throws JaxenException
103     {
104         log(debug,
105                 "  Select :: " + xpathStr);
106         DOMXPath xpath = new DOMXPath(xpathStr);
107         List results = xpath.selectNodes(getContext(context));
108         log(debug,
109                 "    Expected Size :: " + expectedSize);
110         log(debug,
111                 "    Result Size   :: " + results.size());
112         if (expectedSize != results.size())
113         {
114             log(debug,
115                     "      ## FAILED");
116             log(debug,
117                     "      ## xpath: " + xpath + " = " + xpath.debug());
118             Iterator resultIter = results.iterator();
119             while (resultIter.hasNext())
120             {
121                 log(debug,
122                         "      --> " + resultIter.next());
123             }
124         }
125         assertEquals(xpathStr,
126                 expectedSize,
127                 results.size());
128         assertExprGetTextIdempotent(xpath);
129         if (expectedSize > 0)
130         {
131             return results.get(0);
132         }
133         return null;
134     }
135 
136     private void assertInvalidXPath(Object context, String xpathStr)
137     {
138         try
139         {
140             log(debug,
141                     "  Select :: " + xpathStr);
142             DOMXPath xpath = new DOMXPath(xpathStr);
143             List results = xpath.selectNodes(getContext(context));
144             log(debug,
145                     "    Result Size   :: " + results.size());
146             fail("An exception was expected.");
147         }
148         catch (JaxenException e)
149         {
150             log(debug, "    Caught expected exception " + e.getMessage());
151         }
152     }
153 
154     private void assertValueOfXPath(String expected, Object context, String xpathStr) throws JaxenException
155     {
156             DOMXPath xpath = new DOMXPath(xpathStr);
157             Object node = xpath.evaluate(getContext(context));
158             String result = StringFunction.evaluate(node,
159                     getNavigator());
160             log(debug,
161                     "  Select :: " + xpathStr);
162             log(debug,
163                     "    Expected :: " + expected);
164             log(debug,
165                     "    Result   :: " + result);
166             if (!expected.equals(result))
167             {
168                 log(debug,
169                         "      ## FAILED");
170                 log(debug,
171                         "      ## xpath: " + xpath + " = " + xpath.debug());
172             }
173             assertEquals(xpathStr,
174                     expected,
175                     result);
176             assertExprGetTextIdempotent(xpath);
177         }
178 
179     private void assertExprGetTextIdempotent(BaseXPath xpath) throws JaxenException
180     {
181     	assertEquals(0, ExprComparator.EXPR_COMPARATOR.compare(xpath.getRootExpr(), 
182           new BaseXPath(xpath.getRootExpr().getText(), null).getRootExpr()));
183     }
184     
185     private Context getContext(Object contextNode)
186     {
187         Context context = new Context(getContextSupport());
188         List list = new ArrayList(1);
189         list.add(contextNode);
190         context.setNodeSet(list);
191         return context;
192     }
193 
194     private ContextSupport getContextSupport()
195     {
196         if (this.contextSupport == null)
197         {
198             this.contextSupport = new ContextSupport(new SimpleNamespaceContext(),
199                     XPathFunctionContext.getInstance(),
200                     new SimpleVariableContext(),
201                     getNavigator());
202         }
203         return this.contextSupport;
204     }
205 
206     protected abstract Navigator getNavigator();
207     protected abstract Object getDocument(String url) throws Exception;
208 
209     public void testGetNodeType() throws FunctionCallException, UnsupportedAxisException
210     {
211         Navigator nav = getNavigator();
212         Object document = nav.getDocument("xml/testNamespaces.xml");
213         int count = 0;
214         Iterator descendantOrSelfAxisIterator = nav.getDescendantOrSelfAxisIterator(document);
215         while (descendantOrSelfAxisIterator.hasNext())
216         {
217             Object node = descendantOrSelfAxisIterator.next();
218             Iterator namespaceAxisIterator = nav.getNamespaceAxisIterator(node);
219             while (namespaceAxisIterator.hasNext())
220             {
221                 count++;
222                 assertEquals("Node type mismatch", Pattern.NAMESPACE_NODE, nav.getNodeType(namespaceAxisIterator.next()));
223             }
224         }
225         assertEquals(25, count);
226     }
227 
228 
229     /**
230      *  test for jaxen-24
231      */
232     public void testJaxen24() throws JaxenException
233     {
234         Navigator nav = getNavigator();
235         String url = "xml/jaxen24.xml";
236         log("Document [" + url + "]");
237         Object document = nav.getDocument(url);
238         XPath contextpath = new BaseXPath("/body/div", nav);
239         log("Initial Context :: " + contextpath);
240         List list = contextpath.selectNodes(document);
241         Iterator iter = list.iterator();
242         while (iter.hasNext())
243         {
244             Object context = iter.next();
245             assertCountXPath(1, context, "preceding::*[1]");
246             assertValueOfXPath("span", context, "local-name(preceding::*[1])");
247         }
248     }
249 
250     /**
251      *  jaxen-58
252      */
253     public void testJaxen58() throws JaxenException
254     {
255         Navigator nav = getNavigator();
256         String url = "xml/jaxen24.xml";
257         log("Document [" + url + "]");
258         Object document = nav.getDocument(url);
259         XPath contextpath = new BaseXPath("/", nav);
260         log("Initial Context :: " + contextpath);
261         List list = contextpath.selectNodes(document);
262         Iterator iter = list.iterator();
263         while (iter.hasNext())
264         {
265             Object context = iter.next();
266             assertCountXPath(0, context, "//preceding::x");
267             assertCountXPath(0, context, "//following::x");
268             assertCountXPath(0, context, "/descendant::*/preceding::x");
269             assertCountXPath(0, context, "/descendant::node()/preceding::x");
270         }
271     }
272 
273     /**
274      *  test for jaxen-3
275      */
276     public void testJaxen3() throws JaxenException
277     {
278         Navigator nav = getNavigator();
279         String url = "xml/simple.xml";
280         log("Document [" + url + "]");
281         Object document = nav.getDocument(url);
282         XPath contextpath = new BaseXPath("/", nav);
283         log("Initial Context :: " + contextpath);
284         List list = contextpath.selectNodes(document);
285         Iterator iter = list.iterator();
286         while (iter.hasNext())
287         {
288             Object context = iter.next();
289             assertValueOfXPath("abd", context, "string()");
290         }
291     }
292 
293     public void testStringFunction1() throws JaxenException
294     {
295         Navigator nav = getNavigator();
296         String url = "xml/simple.xml";
297         log("Document [" + url + "]");
298         Object document = nav.getDocument(url);
299         XPath contextpath = new BaseXPath("/root", nav);
300         log("Initial Context :: " + contextpath);
301         List list = contextpath.selectNodes(document);
302         Iterator iter = list.iterator();
303         while (iter.hasNext())
304         {
305             Object context = iter.next();
306             assertValueOfXPath("abd", context, "string()");
307         }
308     }
309 
310     public void testStringFunction2() throws JaxenException
311     {
312         Navigator nav = getNavigator();
313         String url = "xml/simple.xml";
314         log("Document [" + url + "]");
315         Object document = nav.getDocument(url);
316         XPath contextpath = new BaseXPath("/root/a", nav);
317         log("Initial Context :: " + contextpath);
318         List list = contextpath.selectNodes(document);
319         Iterator iter = list.iterator();
320         while (iter.hasNext())
321         {
322             Object context = iter.next();
323             assertValueOfXPath("a", context, "string()");
324         }
325     }
326 
327     public void testStringFunction3() throws JaxenException
328     {
329         Navigator nav = getNavigator();
330         String url = "xml/simple.xml";
331         log("Document [" + url + "]");
332         Object document = nav.getDocument(url);
333         XPath contextpath = new BaseXPath("/root/c", nav);
334         log("Initial Context :: " + contextpath);
335         List list = contextpath.selectNodes(document);
336         Iterator iter = list.iterator();
337         while (iter.hasNext())
338         {
339             Object context = iter.next();
340             assertValueOfXPath("d", context, "string()");
341         }
342     }
343 
344     /**
345      *  test for jaxen-3
346      */
347     public void testJaxen3dupe() throws JaxenException
348     {
349         Navigator nav = getNavigator();
350         String url = "xml/jaxen3.xml";
351         log("Document [" + url + "]");
352         Object document = nav.getDocument(url);
353         XPath contextpath = new BaseXPath("/", nav);
354         log("Initial Context :: " + contextpath);
355         List list = contextpath.selectNodes(document);
356         Iterator iter = list.iterator();
357         while (iter.hasNext())
358         {
359             Object context = iter.next();
360             assertCountXPath(1, context, "/Configuration/hostname/attrlist/hostname[. = 'CE-A'] ");
361         }
362     }
363 
364     /**
365      *  parser test cases all of which should fail
366      */
367     public void testForParserErrors() throws JaxenException
368     {
369         Navigator nav = getNavigator();
370         String url = "xml/numbers.xml";
371         log("Document [" + url + "]");
372         Object document = nav.getDocument(url);
373         XPath contextpath = new BaseXPath("/", nav);
374         log("Initial Context :: " + contextpath);
375         List list = contextpath.selectNodes(document);
376         Iterator iter = list.iterator();
377         while (iter.hasNext())
378         {
379             Object context = iter.next();
380             
381             // repeated xpaths, jaxen-35
382             assertInvalidXPath(context, "/numbers numbers");
383             // invalid xpath, jaxen-34
384             assertInvalidXPath(context, "/a/b[c > d]efg");
385             
386             // invalid xpath, jaxen-27
387             assertInvalidXPath(context, "/inv/child::");
388             
389             // invalid xpath, jaxen-26
390             assertInvalidXPath(context, "/invoice/@test[abcd");
391             assertInvalidXPath(context, "/invoice/@test[abcd > x");
392             
393             // unterminated string
394             assertInvalidXPath(context, "string-length('a");
395             
396             // various edge cases where code threw no exception
397             assertInvalidXPath(context, "/descendant::()");
398             assertInvalidXPath(context, "(1 + 1");
399             
400             // no ! operator
401             assertInvalidXPath(context, "!false()");
402         }
403     }
404 
405     /**
406      *  test cases for the use of underscores in names
407      */
408     public void testUnderscoresInNames() throws JaxenException
409     {
410         Navigator nav = getNavigator();
411         String url = "xml/underscore.xml";
412         log("Document [" + url + "]");
413         Object document = nav.getDocument(url);
414         XPath contextpath = new BaseXPath("/", nav);
415         log("Initial Context :: " + contextpath);
416         List list = contextpath.selectNodes(document);
417         Iterator iter = list.iterator();
418         while (iter.hasNext())
419         {
420             Object context = iter.next();
421             assertCountXPath(1, context, "/root/@a");
422             assertCountXPath(1, context, "/root/@_a");
423             assertCountXPath(1, context, "/root/b");
424             assertCountXPath(1, context, "/root/_b");
425             assertValueOfXPath("1", context, "/root/@a");
426             assertValueOfXPath("2", context, "/root/@_a");
427             assertValueOfXPath("1", context, "/root/b");
428             assertValueOfXPath("2", context, "/root/_b");
429         }
430     }
431 
432     /** 
433      * test cases for the use of = with node-sets
434      */
435     public void testNodesetEqualsString() throws JaxenException
436     {
437         Navigator nav = getNavigator();
438         String url = "xml/web.xml";
439         log("Document [" + url + "]");
440         Object document = nav.getDocument(url);
441         XPath contextpath = new BaseXPath("/", nav);
442         log("Initial Context :: " + contextpath);
443         List list = contextpath.selectNodes(document);
444         Iterator iter = list.iterator();
445         while (iter.hasNext())
446         {
447             Object context = iter.next();
448             assertValueOfXPath("true", context, "/web-app/servlet/servlet-name = 'file'");
449             assertValueOfXPath("true", context, "/web-app/servlet/servlet-name = 'snoop'");
450         }
451     }
452 
453     public void testNodesetEqualsNumber() throws JaxenException
454     {
455         Navigator nav = getNavigator();
456         String url = "xml/numbers.xml";
457         log("Document [" + url + "]");
458         Object document = nav.getDocument(url);
459         XPath contextpath = new BaseXPath("/", nav);
460         log("Initial Context :: " + contextpath);
461         List list = contextpath.selectNodes(document);
462         Iterator iter = list.iterator();
463         while (iter.hasNext())
464         {
465             Object context = iter.next();
466             assertValueOfXPath("true", context, "/numbers/set/nr = '-3'");
467             assertValueOfXPath("true", context, "/numbers/set/nr = -3");
468             assertValueOfXPath("true", context, "/numbers/set/nr = 24");
469             assertValueOfXPath("true", context, "/numbers/set/nr/@value = '9999'");
470             assertValueOfXPath("true", context, "/numbers/set/nr/@value = 9999.0");
471             assertValueOfXPath("true", context, "/numbers/set/nr/@value = 66");
472         }
473     }
474 
475     /** 
476      * test basic math...
477      */
478     public void testIntegerArithmetic() throws JaxenException
479     {
480         Navigator nav = getNavigator();
481         String url = "xml/numbers.xml";
482         log("Document [" + url + "]");
483         Object document = nav.getDocument(url);
484         XPath contextpath = new BaseXPath("/", nav);
485         log("Initial Context :: " + contextpath);
486         List list = contextpath.selectNodes(document);
487         Iterator iter = list.iterator();
488         while (iter.hasNext())
489         {
490             Object context = iter.next();
491             assertValueOfXPath("true", context, "(8 * 2 + 1) = 17");
492             assertValueOfXPath("true", context, "(1 + 8 * 2) = 17");
493             assertValueOfXPath("true", context, "(7 - 3 + 1) = 5");
494             assertValueOfXPath("true", context, "(8 - 4 + 5 - 6) = 3");
495             /** left-assoc tests, comments show WRONG evaluation
496             */
497             /** 3 - 2 - 1 != 2
498             */
499             assertValueOfXPath("0", context, "3 - 2 - 1");
500             /** 8 div 4 div 2 != 4
501             */
502             assertValueOfXPath("1", context, "8 div 4 div 2");
503             /** 3 mod 5 mod 7 != 1
504             */
505             assertValueOfXPath("3", context, "3 mod 7 mod 5");
506             /** 1=(2=2) is true
507             */
508             assertValueOfXPath("false", context, "1 = 2 = 2");
509             /**  2!=(3!=1) => 2!=1 => true, (2!=3)!=1 => 1!=1 => false
510             */
511             assertValueOfXPath("false", context, "2 != 3 != 1");
512             /** 3 > (2 > 1) is true
513             */
514             assertValueOfXPath("false", context, "3 > 2 > 1");
515             /** 3 >= (2 >= 2) is true
516             */
517             assertValueOfXPath("false", context, "3 >= 2 >= 2");
518             /** 1 < (2 < 3) is false
519             */
520             assertValueOfXPath("true", context, "1 < 2 < 3");
521             /** 0 <= (2 <= 3) is true
522             */
523             assertValueOfXPath("true", context, "2 <= 2 <= 3");
524         }
525     }
526     
527     public void testFloatingPointArithmetic() throws JaxenException
528     {
529         Navigator nav = getNavigator();
530         String url = "xml/numbers.xml";
531         log("Document [" + url + "]");
532         Object document = nav.getDocument(url);
533         XPath contextpath = new BaseXPath("/", nav);
534         log("Initial Context :: " + contextpath);
535         List list = contextpath.selectNodes(document);
536         Iterator iter = list.iterator();
537         while (iter.hasNext())
538         {
539             Object context = iter.next();
540             assertValueOfXPath("true", context, "(8.5 * 2.0 + 1) = 18");
541             assertValueOfXPath("true", context, "(1.00 + 8.5 * 2) = 18.0");
542             assertValueOfXPath("true", context, "(7.1 - 7.1 + 1.5) = 1.5");
543             assertValueOfXPath("true", context, "(8.000 - 4.0 + 5 - 6.00) = 3");
544             assertValueOfXPath("0", context, "3.5 - 2.5 - 1.0");
545             assertValueOfXPath("1", context, "8.0 div 4.0 div 2.0");
546             assertValueOfXPath("3", context, "3.0 mod 7.0 mod 5.0");
547             assertValueOfXPath("false", context, "1.5 = 2.3 = 2.3");
548             assertValueOfXPath("false", context, "2.1 != 3.2 != 1.9");
549             assertValueOfXPath("false", context, "3.8 > 2.7 > 1.6");
550             assertValueOfXPath("false", context, "3.4 >= 2.5 >= 2.5");
551             assertValueOfXPath("true", context, "1.4 < 2.3 < 3.2");
552             assertValueOfXPath("true", context, "2.5 <= 2.5 <= 3.5");
553         }
554     }
555 
556     /** 
557      * test cases for preceding axis with different node types
558      */
559     public void testPrecedingSiblingAxis() throws JaxenException
560     {
561         Navigator nav = getNavigator();
562         String url = "xml/pi2.xml";
563         log("Document [" + url + "]");
564         Object document = nav.getDocument(url);
565         XPath contextpath = new BaseXPath("/a/c", nav);
566         log("Initial Context :: " + contextpath);
567         List list = contextpath.selectNodes(document);
568         Iterator iter = list.iterator();
569         while (iter.hasNext())
570         {
571             Object context = iter.next();
572             assertCountXPath(1, context, "//processing-instruction()");
573             assertCountXPath(1, context, "preceding-sibling::*");
574             assertCountXPath(5, context, "preceding-sibling::node()");
575             assertCountXPath(1, context, "preceding-sibling::*[1]");
576             assertCountXPath(1, context, "preceding-sibling::processing-instruction()");
577             assertValueOfXPath("order-by=\"x\"", context, "preceding-sibling::processing-instruction()");
578             assertValueOfXPath("foo", context, "preceding-sibling::*[1]");
579             assertValueOfXPath("order-by=\"x\"", context, "preceding-sibling::node()[2]");
580         }
581     }
582 
583     public void testVariableLookup() throws JaxenException
584     {
585         Navigator nav = getNavigator();
586         String url = "xml/id.xml";
587         log("Document [" + url + "]");
588         Object document = nav.getDocument(url);
589         XPath contextpath = new BaseXPath("/", nav);
590         log("Initial Context :: " + contextpath);
591         List list = contextpath.selectNodes(document);
592         SimpleVariableContext varContext = new SimpleVariableContext();
593         varContext.setVariableValue(null, "foobar", "foobar");
594         varContext.setVariableValue(null, "foo", "foo");
595         getContextSupport().setVariableContext(varContext);
596         Iterator iter = list.iterator();
597         while (iter.hasNext())
598         {
599             Object context = iter.next();
600             assertValueOfXPath("foobar", context, "$foobar");
601             assertCountXPath(1, context, "/foo[@id=$foobar]");
602             assertCountXPath(0, context, "/foo[@id='$foobar']");
603             assertCountXPath(1, context, "/foo[concat($foo, 'bar')=@id]");
604             assertCountXPath(0, context, "CD_Library/artist[@name=$artist]");
605         }
606     }
607 
608     public void testAttributeParent() throws JaxenException
609     {
610         Navigator nav = getNavigator();
611         String url = "xml/id.xml";
612         log("Document [" + url + "]");
613         Object document = nav.getDocument(url);
614         XPath contextpath = new BaseXPath("/", nav);
615         log("Initial Context :: " + contextpath);
616         List list = contextpath.selectNodes(document);
617         Iterator iter = list.iterator();
618         while (iter.hasNext())
619         {
620             Object context = iter.next();
621             /** attributes have a parent: their element
622             */
623             assertCountXPath(1, context, "/foo/@id/parent::foo");
624         }
625     }
626 
627     /** 
628      * attributes can also be used as context nodes
629      */
630     public void testAttributeAsContext() throws JaxenException
631     {
632         Navigator nav = getNavigator();
633         String url = "xml/id.xml";
634         log("Document [" + url + "]");
635         Object document = nav.getDocument(url);
636         XPath contextpath = new BaseXPath("/foo/@id", nav);
637         log("Initial Context :: " + contextpath);
638         List list = contextpath.selectNodes(document);
639         Iterator iter = list.iterator();
640         while (iter.hasNext())
641         {
642             Object context = iter.next();
643             assertCountXPath(1, context, "parent::foo");
644         }
645     }
646 
647     public void testid53992() throws JaxenException
648     {
649         Navigator nav = getNavigator();
650         String url = "xml/pi.xml";
651         log("Document [" + url + "]");
652         Object document = nav.getDocument(url);
653         XPath contextpath = new BaseXPath("/", nav);
654         log("Initial Context :: " + contextpath);
655         List list = contextpath.selectNodes(document);
656         Iterator iter = list.iterator();
657         while (iter.hasNext())
658         {
659             Object context = iter.next();
660             assertCountXPath(3, context, "//processing-instruction()");
661             assertCountXPath(2, context, "//processing-instruction('cheese')");
662                 Object result = assertCountXPath2(1, context, "//processing-instruction('toast')");
663                 assertValueOfXPath("is tasty", result, "string()");
664             }
665             }
666 
667     /** 
668      * test evaluate() extension function
669      */
670     public void testid54032() throws JaxenException
671     {
672         Navigator nav = getNavigator();
673         String url = "xml/evaluate.xml";
674         log("Document [" + url + "]");
675         Object document = nav.getDocument(url);
676         XPath contextpath = new BaseXPath("/", nav);
677         log("Initial Context :: " + contextpath);
678         List list = contextpath.selectNodes(document);
679         Iterator iter = list.iterator();
680         while (iter.hasNext())
681         {
682             Object context = iter.next();
683             assertCountXPath(3, context, "evaluate('//jumps/*')");
684             assertCountXPath(1, context, "evaluate('//jumps/object/dog')");
685             assertCountXPath(0, context, "evaluate('//jumps/object')/evaluate");
686             assertCountXPath(1, context, "evaluate('//jumps/object')/dog");
687             assertCountXPath(1, context, "evaluate('//jumps/*')/dog");
688             assertCountXPath(1, context, "//metatest[ evaluate(@select) = . ]");
689         }
690     }
691 
692     public void testid54082() throws JaxenException
693     {
694         Navigator nav = getNavigator();
695         String url = "xml/numbers.xml";
696         log("Document [" + url + "]");
697         Object document = nav.getDocument(url);
698         XPath contextpath = new BaseXPath("/numbers/set[1]", nav);
699         log("Initial Context :: " + contextpath);
700         List list = contextpath.selectNodes(document);
701         Iterator iter = list.iterator();
702         while (iter.hasNext())
703         {
704             Object context = iter.next();
705             assertCountXPath(1, context, "*[-3 = .]");
706             assertValueOfXPath("true", context, "54 < *");
707             assertValueOfXPath("true", context, "55 <= *");
708             assertValueOfXPath("false", context, "69 < *");
709             assertValueOfXPath("true", context, "-2 > *");
710             assertValueOfXPath("true", context, "-3 >= *");
711             assertValueOfXPath("false", context, "-4 >= *");
712         }
713     }
714 
715     /* TODO
716     This context should work, but needs a fixed version of saxpath to parse the right-hand side
717     of the greater-than expression.
718     <context select="/numbers/set[2]">
719       <valueOf select="1 &gt; nr/@value">false</valueOf>
720       <valueOf select="55 &gt; nr/@value">false</valueOf>
721       <valueOf select="55 &gt;= nr/@value">true</valueOf>
722       <valueOf select="1000000 &gt; nr/@value">true</valueOf>
723     </context>
724     
725     */
726     /** 
727      * test sibling axes 
728      */
729     public void testid54145() throws JaxenException
730     {
731         Navigator nav = getNavigator();
732         String url = "xml/axis.xml";
733         log("Document [" + url + "]");
734         Object document = nav.getDocument(url);
735         XPath contextpath = new BaseXPath("/root", nav);
736         log("Initial Context :: " + contextpath);
737         List list = contextpath.selectNodes(document);
738         Iterator iter = list.iterator();
739         while (iter.hasNext())
740         {
741             Object context = iter.next();
742             assertCountXPath(0, context, "preceding-sibling::*");
743         }
744     }
745 
746     public void testid54156() throws JaxenException
747     {
748         Navigator nav = getNavigator();
749         String url = "xml/axis.xml";
750         log("Document [" + url + "]");
751         Object document = nav.getDocument(url);
752         XPath contextpath = new BaseXPath("/root/a/a.3", nav);
753         log("Initial Context :: " + contextpath);
754         List list = contextpath.selectNodes(document);
755         Iterator iter = list.iterator();
756         while (iter.hasNext())
757         {
758             Object context = iter.next();
759             assertCountXPath(2, context, "preceding::*");
760         }
761     }
762 
763     public void testid54168() throws JaxenException
764     {
765         Navigator nav = getNavigator();
766         String url = "xml/axis.xml";
767         log("Document [" + url + "]");
768         Object document = nav.getDocument(url);
769         XPath contextpath = new BaseXPath("/root/a/a.3", nav);
770         log("Initial Context :: " + contextpath);
771         List list = contextpath.selectNodes(document);
772         Iterator iter = list.iterator();
773         while (iter.hasNext())
774         {
775             Object context = iter.next();
776             assertCountXPath(2, context, "preceding-sibling::*");
777         }
778     }
779 
780     public void testid54180() throws JaxenException
781     {
782         Navigator nav = getNavigator();
783         String url = "xml/axis.xml";
784         log("Document [" + url + "]");
785         Object document = nav.getDocument(url);
786         XPath contextpath = new BaseXPath("/", nav);
787         log("Initial Context :: " + contextpath);
788         List list = contextpath.selectNodes(document);
789         Iterator iter = list.iterator();
790         while (iter.hasNext())
791         {
792             Object context = iter.next();
793             assertValueOfXPath("a.2", context, "name(/root/a/a.3/preceding-sibling::*[1])");
794             assertValueOfXPath("a.1", context, "name(/root/a/a.3/preceding-sibling::*[2])");
795         }
796     }
797 
798     public void testid54197() throws JaxenException
799     {
800         Navigator nav = getNavigator();
801         String url = "xml/axis.xml";
802         log("Document [" + url + "]");
803         Object document = nav.getDocument(url);
804         XPath contextpath = new BaseXPath("/", nav);
805         log("Initial Context :: " + contextpath);
806         List list = contextpath.selectNodes(document);
807         Iterator iter = list.iterator();
808         while (iter.hasNext())
809         {
810             Object context = iter.next();
811             assertValueOfXPath("a.4", context, "name(/root/a/a.3/following-sibling::*[1])");
812             assertValueOfXPath("a.5", context, "name(/root/a/a.3/following-sibling::*[2])");
813         }
814     }
815 
816     public void testid54219() throws JaxenException
817     {
818         Navigator nav = getNavigator();
819         String url = "xml/web.xml";
820         log("Document [" + url + "]");
821         Object document = nav.getDocument(url);
822         XPath contextpath = new BaseXPath("/", nav);
823         log("Initial Context :: " + contextpath);
824         List list = contextpath.selectNodes(document);
825         Iterator iter = list.iterator();
826         while (iter.hasNext())
827         {
828             Object context = iter.next();
829             assertValueOfXPath("snoop", context, "/web-app/servlet[1]/servlet-name");
830             assertValueOfXPath("snoop", context, "/web-app/servlet[1]/servlet-name/text()");
831             assertValueOfXPath("file", context, "/web-app/servlet[2]/servlet-name");
832             assertValueOfXPath("file", context, "/web-app/servlet[2]/servlet-name/text()");
833         }
834     }
835 
836     public void testid54249() throws JaxenException
837     {
838         Navigator nav = getNavigator();
839         String url = "xml/web.xml";
840         log("Document [" + url + "]");
841         Object document = nav.getDocument(url);
842         XPath contextpath = new BaseXPath("/web-app/servlet[1]", nav);
843         log("Initial Context :: " + contextpath);
844         List list = contextpath.selectNodes(document);
845         Iterator iter = list.iterator();
846         while (iter.hasNext())
847         {
848             Object context = iter.next();
849             assertValueOfXPath("snoop", context, "servlet-name");
850             assertValueOfXPath("snoop", context, "servlet-name/text()");
851         }
852     }
853 
854     public void testid54266() throws JaxenException
855     {
856         Navigator nav = getNavigator();
857         String url = "xml/web.xml";
858         log("Document [" + url + "]");
859         Object document = nav.getDocument(url);
860         XPath contextpath = new BaseXPath("/web-app/servlet[2]/servlet-name", nav);
861         log("Initial Context :: " + contextpath);
862         List list = contextpath.selectNodes(document);
863         Iterator iter = list.iterator();
864         while (iter.hasNext())
865         {
866             Object context = iter.next();
867             assertCountXPath(3, context, "preceding::*");
868         }
869     }
870 
871     public void testid54278() throws JaxenException
872     {
873         Navigator nav = getNavigator();
874         String url = "xml/web.xml";
875         log("Document [" + url + "]");
876         Object document = nav.getDocument(url);
877         XPath contextpath = new BaseXPath("/web-app/servlet[2]/servlet-name", nav);
878         log("Initial Context :: " + contextpath);
879         List list = contextpath.selectNodes(document);
880         Iterator iter = list.iterator();
881         while (iter.hasNext())
882         {
883             Object context = iter.next();
884             assertCountXPath(13, context, "following::*");
885         }
886     }
887 
888     /**
889      *  test name
890      */
891     public void testid54298() throws JaxenException
892     {
893         Navigator nav = getNavigator();
894         String url = "xml/web.xml";
895         log("Document [" + url + "]");
896         Object document = nav.getDocument(url);
897         XPath contextpath = new BaseXPath("/", nav);
898         log("Initial Context :: " + contextpath);
899         List list = contextpath.selectNodes(document);
900         Iterator iter = list.iterator();
901         while (iter.hasNext())
902         {
903             Object context = iter.next();
904                 Object result = assertCountXPath2(1, context, "*");
905                 assertValueOfXPath("web-app", result, "name()");
906             /* NOTE that the child::node() tests only work if the
907                XML document does not contain comments or processing instructions */
908             result = assertCountXPath2(1, context, "./*");
909                 assertValueOfXPath("web-app", result, "name()");
910             result = assertCountXPath2(1, context, "child::*");
911                 assertValueOfXPath("web-app", result, "name()");
912             result = assertCountXPath2(1, context, "/*");
913                 assertValueOfXPath("web-app", result, "name()");
914             result = assertCountXPath2(1, context, "/child::node()");
915                 assertValueOfXPath("web-app", result, "name(.)");
916             result = assertCountXPath2(1, context, "child::node()");
917                 assertValueOfXPath("web-app", result, "name(.)");
918                 
919             // empty names
920             assertValueOfXPath("", context, "name()");
921             assertValueOfXPath("", context, "name(.)");
922             assertValueOfXPath("", context, "name(parent::*)");
923             assertValueOfXPath("", context, "name(/)");
924             assertValueOfXPath("", context, "name(/.)");
925             assertValueOfXPath("", context, "name(/self::node())");
926             /** name of root elemet
927             */
928             assertValueOfXPath("web-app", context, "name(node())");
929             assertValueOfXPath("web-app", context, "name(/node())");
930             assertValueOfXPath("web-app", context, "name(/*)");
931             assertValueOfXPath("web-app", context, "name(/child::*)");
932             assertValueOfXPath("web-app", context, "name(/child::node())");
933             assertValueOfXPath("web-app", context, "name(/child::node())");
934             assertValueOfXPath("web-app", context, "name(child::node())");
935             assertValueOfXPath("web-app", context, "name(./*)");
936             assertValueOfXPath("web-app", context, "name(*)");
937         }
938     }
939 
940     public void testid54467() throws JaxenException
941     {
942         Navigator nav = getNavigator();
943         String url = "xml/web.xml";
944         log("Document [" + url + "]");
945         Object document = nav.getDocument(url);
946         XPath contextpath = new BaseXPath("/*", nav);
947         log("Initial Context :: " + contextpath);
948         List list = contextpath.selectNodes(document);
949         Iterator iter = list.iterator();
950         while (iter.hasNext())
951         {
952             Object context = iter.next();
953             /** empty names
954             */
955             assertValueOfXPath("", context, "name(..)");
956             assertValueOfXPath("", context, "name(parent::node())");
957             assertValueOfXPath("", context, "name(parent::*)");
958             /** name of root elemet
959             */
960             assertValueOfXPath("web-app", context, "name()");
961             assertValueOfXPath("web-app", context, "name(.)");
962             assertValueOfXPath("web-app", context, "name(../*)");
963             assertValueOfXPath("web-app", context, "name(../child::node())");
964         }
965     }
966 
967     /** 
968      * test predicates
969      */
970     public void testid54522() throws JaxenException
971     {
972         Navigator nav = getNavigator();
973         String url = "xml/nitf.xml";
974         log("Document [" + url + "]");
975         Object document = nav.getDocument(url);
976         XPath contextpath = new BaseXPath("/nitf/head/docdata", nav);
977         log("Initial Context :: " + contextpath);
978         List list = contextpath.selectNodes(document);
979         Iterator iter = list.iterator();
980         while (iter.hasNext())
981         {
982             Object context = iter.next();
983             assertCountXPath(1, context, "doc-id[@regsrc='FAKE' and @id-string='YYY']");
984         }
985     }
986 
987     public void testid54534() throws JaxenException
988     {
989         Navigator nav = getNavigator();
990         String url = "xml/nitf.xml";
991         log("Document [" + url + "]");
992         Object document = nav.getDocument(url);
993         XPath contextpath = new BaseXPath("/nitf/head", nav);
994         log("Initial Context :: " + contextpath);
995         List list = contextpath.selectNodes(document);
996         Iterator iter = list.iterator();
997         while (iter.hasNext())
998         {
999             Object context = iter.next();
1000             assertCountXPath(1, context, "meta[@name='fake-cycle']");
1001             assertCountXPath(1, context, "meta[@content='FAKE']");
1002             assertCountXPath(8, context, "meta[@name and @content]");
1003             assertCountXPath(1, context, "meta[@name='fake-cycle' and @content='FAKE']");
1004             assertCountXPath(7, context, "meta[@name != 'fake-cycle']");
1005         }
1006     }
1007 
1008     public void testid54570() throws JaxenException
1009     {
1010         Navigator nav = getNavigator();
1011         String url = "xml/nitf.xml";
1012         log("Document [" + url + "]");
1013         Object document = nav.getDocument(url);
1014         XPath contextpath = new BaseXPath("/", nav);
1015         log("Initial Context :: " + contextpath);
1016         List list = contextpath.selectNodes(document);
1017         Iterator iter = list.iterator();
1018         while (iter.hasNext())
1019         {
1020             Object context = iter.next();
1021             assertCountXPath(1, context, "/nitf/head/meta[@name='fake-cycle']");
1022             assertCountXPath(1, context, "/nitf/head/meta[@content='FAKE']");
1023             assertCountXPath(8, context, "/nitf/head/meta[@name and @content]");
1024             assertCountXPath(1, context, "/nitf/head/meta[@name='fake-cycle' and @content='FAKE']");
1025             assertCountXPath(7, context, "/nitf/head/meta[@name != 'fake-cycle']");
1026         }
1027     }
1028 
1029     public void testid54614() throws JaxenException
1030     {
1031         Navigator nav = getNavigator();
1032         String url = "xml/moreover.xml";
1033         log("Document [" + url + "]");
1034         Object document = nav.getDocument(url);
1035         XPath contextpath = new BaseXPath("/", nav);
1036         log("Initial Context :: " + contextpath);
1037         List list = contextpath.selectNodes(document);
1038         Iterator iter = list.iterator();
1039         while (iter.hasNext())
1040         {
1041             Object context = iter.next();
1042             assertCountXPath(1, context, "/child::node()");
1043             assertCountXPath(1, context, "/*");
1044             assertCountXPath(20, context, "/*/article");
1045             assertCountXPath(221, context, "//*");
1046             assertCountXPath(20, context, "//*[local-name()='article']");
1047             assertCountXPath(20, context, "//article");
1048             assertCountXPath(20, context, "/*/*[@code]");
1049             assertCountXPath(1, context, "/moreovernews/article[@code='13563275']");
1050                 DOMXPath xpath = new DOMXPath("/moreovernews/article[@code='13563275']");
1051                 List results = xpath.selectNodes(getContext(context));
1052                 Object result = results.get(0);
1053                 assertValueOfXPath("http://c.moreover.com/click/here.pl?x13563273", result, "url");
1054             xpath = new DOMXPath("/*/article[@code='13563275']");
1055             results = xpath.selectNodes(getContext(context));
1056             result = results.get(0);
1057                 assertValueOfXPath("http://c.moreover.com/click/here.pl?x13563273", result, "url");
1058             xpath = new DOMXPath("//article[@code='13563275']");
1059             results = xpath.selectNodes(getContext(context));
1060             result = results.get(0);
1061                 assertValueOfXPath("http://c.moreover.com/click/here.pl?x13563273", result, "url");
1062             xpath = new DOMXPath("//*[@code='13563275']");
1063             results = xpath.selectNodes(getContext(context));
1064             result = results.get(0);
1065                 assertValueOfXPath("http://c.moreover.com/click/here.pl?x13563273", result, "url");
1066             xpath = new DOMXPath("/child::node()/child::node()[@code='13563275']");
1067             results = xpath.selectNodes(getContext(context));
1068             result = results.get(0);
1069                 assertValueOfXPath("http://c.moreover.com/click/here.pl?x13563273", result, "url");
1070             xpath = new DOMXPath("/*/*[@code='13563275']");
1071             results = xpath.selectNodes(getContext(context));
1072             result = results.get(0);
1073                 assertValueOfXPath("http://c.moreover.com/click/here.pl?x13563273", result, "url");
1074             }
1075             }
1076 
1077     /** 
1078      * test other node types
1079      */
1080     public void testNodeTypes() throws JaxenException
1081     {
1082         Navigator nav = getNavigator();
1083         String url = "xml/contents.xml";
1084         log("Document [" + url + "]");
1085         Object document = nav.getDocument(url);
1086         XPath contextpath = new BaseXPath("/", nav);
1087         log("Initial Context :: " + contextpath);
1088         List list = contextpath.selectNodes(document);
1089         Iterator iter = list.iterator();
1090         while (iter.hasNext())
1091         {
1092             Object context = iter.next();
1093             assertCountXPath(3, context, "processing-instruction()");
1094             assertCountXPath(3, context, "/processing-instruction()");
1095             assertCountXPath(1, context, "/comment()");
1096             assertCountXPath(1, context, "comment()");
1097             assertCountXPath(2, context, "/child::node()/comment()");
1098             assertCountXPath(2, context, "/*/comment()");
1099             assertCountXPath(3, context, "//comment()");
1100         }
1101     }
1102 
1103     /** 
1104      * test positioning
1105      */
1106     public void testPositioning() throws JaxenException
1107     {
1108         Navigator nav = getNavigator();
1109         String url = "xml/fibo.xml";
1110         log("Document [" + url + "]");
1111         Object document = nav.getDocument(url);
1112         XPath contextpath = new BaseXPath("/", nav);
1113         log("Initial Context :: " + contextpath);
1114         List list = contextpath.selectNodes(document);
1115         Iterator iter = list.iterator();
1116         while (iter.hasNext())
1117         {
1118             Object context = iter.next();
1119             assertCountXPath(9, context, "/*/fibonacci[position() < 10]");
1120             assertValueOfXPath("196417", context, "sum(//fibonacci)");
1121             assertValueOfXPath("325", context, "sum(//fibonacci/@index)");
1122             assertValueOfXPath("1", context, "/*/fibonacci[2]");
1123             assertValueOfXPath("75025", context, "/*/fibonacci[ count(/*/fibonacci) ]");
1124             assertValueOfXPath("46368", context, "/*/fibonacci[ count(/*/fibonacci) - 1 ]");
1125         }
1126     }
1127 
1128     public void testid54853() throws JaxenException
1129     {
1130         Navigator nav = getNavigator();
1131         String url = "xml/web.xml";
1132         log("Document [" + url + "]");
1133         Object document = nav.getDocument(url);
1134         XPath contextpath = new BaseXPath("/", nav);
1135         log("Initial Context :: " + contextpath);
1136         List list = contextpath.selectNodes(document);
1137         Iterator iter = list.iterator();
1138         while (iter.hasNext())
1139         {
1140             Object context = iter.next();
1141             assertCountXPath(19, context, "descendant-or-self::*");
1142             assertCountXPath(19, context, "descendant::*");
1143             assertCountXPath(19, context, "/descendant::*");
1144             assertCountXPath(19, context, "/descendant-or-self::*");
1145             assertCountXPath(2, context, "/descendant::servlet");
1146             assertCountXPath(2, context, "/descendant-or-self::servlet");
1147             assertCountXPath(2, context, "descendant-or-self::servlet");
1148             assertCountXPath(2, context, "descendant::servlet");
1149             assertCountXPath(2, context, "/*/servlet");
1150             assertValueOfXPath("2", context, "count(/*/servlet)");
1151             assertCountXPath(2, context, "//servlet");
1152             assertValueOfXPath("2", context, "count(//servlet)");
1153         }
1154     }
1155 
1156     public void testid54932() throws JaxenException
1157     {
1158         Navigator nav = getNavigator();
1159         String url = "xml/web.xml";
1160         log("Document [" + url + "]");
1161         Object document = nav.getDocument(url);
1162         XPath contextpath = new BaseXPath("/web-app", nav);
1163         log("Initial Context :: " + contextpath);
1164         List list = contextpath.selectNodes(document);
1165         Iterator iter = list.iterator();
1166         while (iter.hasNext())
1167         {
1168             Object context = iter.next();
1169             assertCountXPath(2, context, "/descendant::servlet");
1170             assertCountXPath(2, context, "/descendant-or-self::servlet");
1171             assertCountXPath(2, context, "descendant-or-self::servlet");
1172             assertCountXPath(2, context, "descendant::servlet");
1173         }
1174     }
1175 
1176     public void testCountFunction() throws JaxenException
1177     {
1178         Navigator nav = getNavigator();
1179         String url = "xml/much_ado.xml";
1180         log("Document [" + url + "]");
1181         Object document = nav.getDocument(url);
1182         XPath contextpath = new BaseXPath("/", nav);
1183         log("Initial Context :: " + contextpath);
1184         List list = contextpath.selectNodes(document);
1185         Iterator iter = list.iterator();
1186         while (iter.hasNext())
1187         {
1188             Object context = iter.next();
1189             assertCountXPath(5, context, "/descendant::ACT");
1190             assertCountXPath(5, context, "descendant::ACT");
1191             assertValueOfXPath("Much Ado about Nothing", context, "/PLAY/TITLE");
1192             assertValueOfXPath("4", context, "2+2");
1193             assertValueOfXPath("21", context, "5 * 4 + 1");
1194             assertValueOfXPath("5", context, "count(descendant::ACT)");
1195             assertValueOfXPath("35", context, "10 + count(descendant::ACT) * 5");
1196             assertValueOfXPath("75", context, "(10 + count(descendant::ACT)) * 5");
1197         }
1198     }
1199 
1200     public void testCountFunctionMore() throws JaxenException
1201     {
1202         Navigator nav = getNavigator();
1203         String url = "xml/much_ado.xml";
1204         log("Document [" + url + "]");
1205         Object document = nav.getDocument(url);
1206         XPath contextpath = new BaseXPath("/PLAY/ACT[2]/SCENE[1]", nav);
1207         log("Initial Context :: " + contextpath);
1208         List list = contextpath.selectNodes(document);
1209         Iterator iter = list.iterator();
1210         while (iter.hasNext())
1211         {
1212             Object context = iter.next();
1213             assertCountXPath(5, context, "/descendant::ACT");
1214             assertCountXPath(5, context, "../../descendant::ACT");
1215             assertCountXPath(141, context, "/PLAY/ACT[2]/SCENE[1]/descendant::SPEAKER");
1216             assertCountXPath(141, context, "descendant::SPEAKER");
1217             assertValueOfXPath("646", context, "count(descendant::*)+1");
1218             assertValueOfXPath("142", context, "count(descendant::SPEAKER)+1");
1219             assertValueOfXPath("2", context, "count(ancestor::*)");
1220             assertValueOfXPath("1", context, "count(ancestor::PLAY)");
1221             assertValueOfXPath("3", context, "count(ancestor-or-self::*)");
1222             assertValueOfXPath("1", context, "count(ancestor-or-self::PLAY)");
1223             assertValueOfXPath("6", context, "5+count(ancestor::*)-1");
1224         }
1225     }
1226 
1227     public void testCorrectPredicateApplication() throws JaxenException
1228     {
1229         Navigator nav = getNavigator();
1230         String url = "xml/much_ado.xml";
1231         log("Document [" + url + "]");
1232         Object document = nav.getDocument(url);
1233         XPath contextpath = new BaseXPath("/", nav);
1234         log("Initial Context :: " + contextpath);
1235         List list = contextpath.selectNodes(document);
1236         Iterator iter = list.iterator();
1237         while (iter.hasNext())
1238         {
1239             Object context = iter.next();
1240             // Test correct predicate application
1241             assertValueOfXPath("5", context, "count(/PLAY/ACT/SCENE[1])");
1242         }
1243     }
1244 
1245     /** test axis node ordering
1246     */
1247     public void testAxisNodeOrdering() throws JaxenException
1248     {
1249         Navigator nav = getNavigator();
1250         String url = "xml/web.xml";
1251         log("Document [" + url + "]");
1252         Object document = nav.getDocument(url);
1253         XPath contextpath = new BaseXPath("/", nav);
1254         log("Initial Context :: " + contextpath);
1255         List list = contextpath.selectNodes(document);
1256         Iterator iter = list.iterator();
1257         while (iter.hasNext())
1258         {
1259             Object context = iter.next();
1260             // Reported as Jira issue JAXEN-24
1261             assertCountXPath(1, context, "//servlet-mapping/preceding::*[1][name()='description']");
1262             assertCountXPath(1, context, "/web-app/servlet//description/following::*[1][name()='servlet-mapping']");
1263             assertCountXPath(1, context, "/web-app/servlet//description/following::*[2][name()='servlet-name']");
1264         }
1265     }
1266 
1267     /** 
1268      * test document function
1269      */
1270     public void testDocumentFunction1() throws JaxenException
1271     {
1272         Navigator nav = getNavigator();
1273         String url = "xml/text.xml";
1274         log("Document [" + url + "]");
1275         Object document = nav.getDocument(url);
1276         XPath contextpath = new BaseXPath("/", nav);
1277         log("Initial Context :: " + contextpath);
1278         List list = contextpath.selectNodes(document);
1279         Iterator iter = list.iterator();
1280         while (iter.hasNext())
1281         {
1282             Object context = iter.next();
1283                 Object result = assertCountXPath2(1, context, "document('xml/web.xml')");
1284                 assertValueOfXPath("snoop", result, "/web-app/servlet[1]/servlet-name");
1285                 assertValueOfXPath("snoop", result, "/web-app/servlet[1]/servlet-name/text()");
1286             assertValueOfXPath("snoop", context, "document('xml/web.xml')/web-app/servlet[1]/servlet-name");
1287         }
1288     }
1289 
1290     /** 
1291      * Test to check if the context changes when an extension function is used.
1292      * First test is an example, second is the actual test.
1293      */
1294     public void testDocumentFunctionContextExample() throws JaxenException
1295     {
1296         Navigator nav = getNavigator();
1297         String url = "xml/text.xml";
1298         log("Document [" + url + "]");
1299         Object document = nav.getDocument(url);
1300         XPath contextpath = new BaseXPath("/foo/bar/cheese[1]", nav);
1301         log("Initial Context :: " + contextpath);
1302         List list = contextpath.selectNodes(document);
1303         Iterator iter = list.iterator();
1304         while (iter.hasNext())
1305         {
1306             Object context = iter.next();
1307             assertValueOfXPath("3foo3", context, "concat(./@id,'foo',@id)");
1308             assertValueOfXPath("3snoop3", context, "concat(./@id,document('xml/web.xml')/web-app/servlet[1]/servlet-name,./@id)");
1309         }
1310     }
1311 
1312     public void testDocumentFunctionActual() throws JaxenException
1313     {
1314         Navigator nav = getNavigator();
1315         String url = "xml/message.xml";
1316         log("Document [" + url + "]");
1317         Object document = nav.getDocument(url);
1318         XPath contextpath = new BaseXPath("/", nav);
1319         log("Initial Context :: " + contextpath);
1320         List list = contextpath.selectNodes(document);
1321         Iterator iter = list.iterator();
1322         while (iter.hasNext())
1323         {
1324             Object context = iter.next();
1325             assertValueOfXPath("Pruefgebiete", context, "/message/body/data/items/item[name/text()='parentinfo']/value");
1326             assertValueOfXPath("Pruefgebiete", context, "document('xml/message.xml')/message/body/data/items/item[name/text()='parentinfo']/value");
1327         }
1328     }
1329 
1330     /** 
1331      * test behavior of AbsoluteLocationPath
1332      */
1333     public void testAbsoluteLocationPaths() throws JaxenException
1334     {
1335         Navigator nav = getNavigator();
1336         String url = "xml/simple.xml";
1337         log("Document [" + url + "]");
1338         Object document = nav.getDocument(url);
1339         XPath contextpath = new BaseXPath("/root/a", nav);
1340         log("Initial Context :: " + contextpath);
1341         List list = contextpath.selectNodes(document);
1342         Iterator iter = list.iterator();
1343         while (iter.hasNext())
1344         {
1345             Object context = iter.next();
1346             assertValueOfXPath("ab", context, "concat( ., /root/b )");
1347             assertValueOfXPath("ba", context, "concat( ../b, . )");
1348             assertValueOfXPath("ba", context, "concat( /root/b, . )");
1349             assertValueOfXPath("db", context, "concat( /root/c/d, ../b )");
1350         }
1351     }
1352 
1353     /** 
1354      * test the translate() function
1355      */
1356     public void testTranslateFunction() throws JaxenException
1357     {
1358         Navigator nav = getNavigator();
1359         String url = "xml/simple.xml";
1360         log("Document [" + url + "]");
1361         Object document = nav.getDocument(url);
1362         XPath contextpath = new BaseXPath("/", nav);
1363         log("Initial Context :: " + contextpath);
1364         List list = contextpath.selectNodes(document);
1365         Iterator iter = list.iterator();
1366         while (iter.hasNext())
1367         {
1368             Object context = iter.next();
1369             assertValueOfXPath("", context, "translate( '', '', '' )");
1370             assertValueOfXPath("abcd", context, "translate( 'abcd', '', '' )");
1371             assertValueOfXPath("abcd", context, "translate( 'abcd', 'abcd', 'abcd' )");
1372             assertValueOfXPath("abcd", context, "translate( 'abcd', 'dcba', 'dcba' )");
1373             assertValueOfXPath("dcba", context, "translate( 'abcd', 'abcd', 'dcba' )");
1374             assertValueOfXPath("ab", context, "translate( 'abcd', 'abcd', 'ab' )");
1375             assertValueOfXPath("cd", context, "translate( 'abcd', 'cdab', 'cd' )");
1376             assertValueOfXPath("xy", context, "translate( 'abcd', 'acbd', 'xy' )");
1377             assertValueOfXPath("abcd", context, "translate( 'abcd', 'abcdb', 'abcdb' )");
1378             assertValueOfXPath("abcd", context, "translate( 'abcd', 'abcd', 'abcdb' )");
1379         }
1380     }
1381 
1382     public void testSubstringFunction() throws JaxenException
1383     {
1384         Navigator nav = getNavigator();
1385         String url = "xml/simple.xml";
1386         log("Document [" + url + "]");
1387         Object document = nav.getDocument(url);
1388         XPath contextpath = new BaseXPath("/", nav);
1389         log("Initial Context :: " + contextpath);
1390         List list = contextpath.selectNodes(document);
1391         Iterator iter = list.iterator();
1392         while (iter.hasNext())
1393         {
1394             Object context = iter.next();
1395             assertValueOfXPath("234", context, "substring('12345', 1.5, 2.6)");
1396             assertValueOfXPath("12", context, "substring('12345', 0, 3)");
1397             assertValueOfXPath("", context, "substring('12345', 0 div 0, 3)");
1398             assertValueOfXPath("", context, "substring('12345', 1, 0 div 0)");
1399             assertValueOfXPath("12345", context, "substring('12345', -42, 1 div 0)");
1400             assertValueOfXPath("", context, "substring('12345', -1 div 0, 1 div 0)");
1401             assertValueOfXPath("345", context, "substring('12345', 3)");
1402             assertValueOfXPath("12345", context, "substring('12345',1,15)");
1403         }
1404     }
1405 
1406     /** 
1407      * Some tests for the normalize-space() function
1408      */
1409     public void testNormalizeSpaceFunction() throws JaxenException
1410     {
1411         Navigator nav = getNavigator();
1412         String url = "xml/simple.xml";
1413         log("Document [" + url + "]");
1414         Object document = nav.getDocument(url);
1415         XPath contextpath = new BaseXPath("/", nav);
1416         log("Initial Context :: " + contextpath);
1417         List list = contextpath.selectNodes(document);
1418         Iterator iter = list.iterator();
1419         while (iter.hasNext())
1420         {
1421             Object context = iter.next();
1422             assertValueOfXPath("abc", context, "normalize-space('    abc    ')");
1423             assertValueOfXPath("a b c", context, "normalize-space(' a  b  c  ')");
1424             assertValueOfXPath("a b c", context, "normalize-space(' a \n b \n  c')");
1425             // Next test case addresses issue JAXEN-22
1426             assertValueOfXPath("", context, "normalize-space(' ')");
1427             // Next test case addresses issue JAXEN-29
1428             assertValueOfXPath("", context, "normalize-space('')");
1429         }
1430     }
1431 
1432     /** 
1433      * test cases for String extension functions
1434      */
1435     public void testStringExtensionFunctions() throws JaxenException
1436     {
1437         Navigator nav = getNavigator();
1438         String url = "xml/web.xml";
1439         log("Document [" + url + "]");
1440         Object document = nav.getDocument(url);
1441         XPath contextpath = new BaseXPath("/web-app/servlet[1]", nav);
1442         log("Initial Context :: " + contextpath);
1443         List list = contextpath.selectNodes(document);
1444         Iterator iter = list.iterator();
1445         while (iter.hasNext())
1446         {
1447             Object context = iter.next();
1448             assertValueOfXPath("SNOOPSERVLET", context, "upper-case( servlet-class )");
1449             assertValueOfXPath("snoopservlet", context, "lower-case( servlet-class )");
1450             assertValueOfXPath("SNOOPSERVLET", context, "upper-case( servlet-class, 'fr' )");
1451             assertValueOfXPath("SNOOPSERVLET", context, "upper-case( servlet-class, 'fr-CA' )");
1452             assertValueOfXPath("SNOOPSERVLET", context, "upper-case( servlet-class, 'es-ES-Traditional_WIN' )");
1453             assertValueOfXPath("true", context, "ends-with( servlet-class, 'Servlet' )");
1454             assertValueOfXPath("false", context, "ends-with( servlet-class, 'S' )");
1455         }
1456     }
1457 
1458     /** 
1459      * test cases for the lang() function
1460      */
1461     public void testLangFunction() throws JaxenException
1462     {
1463         Navigator nav = getNavigator();
1464         String url = "xml/lang.xml";
1465         log("Document [" + url + "]");
1466         Object document = nav.getDocument(url);
1467         XPath contextpath = new BaseXPath("/", nav);
1468         log("Initial Context :: " + contextpath);
1469         List list = contextpath.selectNodes(document);
1470         Iterator iter = list.iterator();
1471         while (iter.hasNext())
1472         {
1473             Object context = iter.next();
1474             assertCountXPath(0, context, "/e1/e2[lang('hr')]");
1475             assertCountXPath(1, context, "/e1/e2/e3[lang('en')]");
1476             assertCountXPath(1, context, "/e1/e2/e3[lang('en-US')]");
1477             assertCountXPath(0, context, "/e1/e2/e3[lang('en-GB')]");
1478             assertCountXPath(2, context, "/e1/e2/e3[lang('hu')]");
1479             assertCountXPath(0, context, "/e1/e2/e3[lang('hu-HU')]");
1480             assertCountXPath(1, context, "/e1/e2/e3[lang('es')]");
1481             assertCountXPath(0, context, "/e1/e2/e3[lang('es-BR')]");
1482         }
1483     }
1484 
1485     /** 
1486      * test namespace
1487      */
1488     public void testNamespacesAgain() throws JaxenException
1489     {
1490         Navigator nav = getNavigator();
1491         String url = "xml/namespaces.xml";
1492         log("Document [" + url + "]");
1493         Object document = nav.getDocument(url);
1494         XPath contextpath = new BaseXPath("/", nav);
1495         log("Initial Context :: " + contextpath);
1496         List list = contextpath.selectNodes(document);
1497         SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
1498         nsContext.addNamespace("alias", "http://fooNamespace/");
1499         nsContext.addNamespace("bar", "http://barNamespace/");
1500         nsContext.addNamespace("voo", "http://fooNamespace/");
1501         nsContext.addNamespace("foo", "http://fooNamespace/");
1502         getContextSupport().setNamespaceContext(nsContext);
1503         Iterator iter = list.iterator();
1504         while (iter.hasNext())
1505         {
1506             Object context = iter.next();
1507             assertCountXPath(1, context, "/*");
1508             assertCountXPath(1, context, "/foo:a");
1509             assertCountXPath(1, context, "/foo:a/b");
1510             assertCountXPath(1, context, "/voo:a/b/c");
1511             assertCountXPath(1, context, "/voo:a/bar:f");
1512             assertCountXPath(1, context, "/*[namespace-uri()='http://fooNamespace/' and local-name()='a']");
1513             assertCountXPath(1, context, "/*[local-name()='a' and namespace-uri()='http://fooNamespace/']/*[local-name()='x' and namespace-uri()='http://fooNamespace/']");
1514             assertCountXPath(1, context, "/*[local-name()='a' and namespace-uri()='http://fooNamespace/']/*[local-name()='x' and namespace-uri()='http://fooNamespace/']/*[local-name()='y' and namespace-uri()='http://fooNamespace/']");
1515         }
1516     }
1517 
1518     /** 
1519      * the prefix here and in the document have no relation; it's their
1520      * namespace-uri binding that counts 
1521      */
1522     public void testPrefixDoesntMatter() throws JaxenException
1523     {
1524         Navigator nav = getNavigator();
1525         String url = "xml/namespaces.xml";
1526         log("Document [" + url + "]");
1527         Object document = nav.getDocument(url);
1528         XPath contextpath = new BaseXPath("/", nav);
1529         log("Initial Context :: " + contextpath);
1530         List list = contextpath.selectNodes(document);
1531         SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
1532         nsContext.addNamespace("foo", "http://somethingElse/");
1533         getContextSupport().setNamespaceContext(nsContext);
1534         Iterator iter = list.iterator();
1535         while (iter.hasNext())
1536         {
1537             Object context = iter.next();
1538             assertCountXPath(0, context, "/foo:a/b/c");
1539         }
1540     }
1541 
1542     /** Jaxen-67, affects Jelly and Maven */
1543     public void testCDATASectionsAreIncludedInTextNodes() throws JaxenException
1544     {
1545         Navigator nav = getNavigator();
1546         String url = "xml/cdata.xml";
1547         log("Document [" + url + "]");
1548         Object document = nav.getDocument(url);
1549         XPath contextPath = new BaseXPath("/p/text()", nav);
1550         log("Initial Context :: " + contextPath);
1551         List list = contextPath.selectNodes(document);
1552         // Depending on the object model, there can be anywhere from 
1553         // 1 to 3 nodes returned here.
1554         StringBuffer buffer = new StringBuffer(10);
1555         Iterator iterator = list.iterator();
1556         while (iterator.hasNext()) {
1557             buffer.append(StringFunction.evaluate(iterator.next(), nav));
1558         }
1559         assertEquals("awhateverb", buffer.toString());
1560     }
1561 
1562     public void testNamespaces() throws JaxenException
1563     {
1564         Navigator nav = getNavigator();
1565         String url = "xml/namespaces.xml";
1566         log("Document [" + url + "]");
1567         Object document = nav.getDocument(url);
1568         XPath contextpath = new BaseXPath("/", nav);
1569         log("Initial Context :: " + contextpath);
1570         List list = contextpath.selectNodes(document);
1571         SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
1572         nsContext.addNamespace("alias", "http://fooNamespace/");
1573         nsContext.addNamespace("bar", "http://barNamespace/");
1574         nsContext.addNamespace("foo", "http://fooNamespace/");
1575         getContextSupport().setNamespaceContext(nsContext);
1576         Iterator iter = list.iterator();
1577         while (iter.hasNext())
1578         {
1579             Object context = iter.next();
1580             assertValueOfXPath("Hello", context, "/foo:a/b/c");
1581             assertValueOfXPath("Hey", context, "/foo:a/foo:d/foo:e");
1582             assertValueOfXPath("Hey3", context, "/foo:a/alias:x/alias:y");
1583             assertValueOfXPath("Hey3", context, "/foo:a/foo:x/foo:y");
1584             assertValueOfXPath("Hey3", context, 
1585                     "/*[local-name()='a' and namespace-uri()='http://fooNamespace/']/*[local-name()='x' and namespace-uri()='http://fooNamespace/']/*[local-name()='y' and namespace-uri()='http://fooNamespace/']");
1586         }
1587     }
1588 
1589     public void testNoNamespace() throws JaxenException
1590     {
1591         Navigator nav = getNavigator();
1592         String url = "xml/defaultNamespace.xml";
1593         log("Document [" + url + "]");
1594         Object document = nav.getDocument(url);
1595         XPath contextpath = new BaseXPath("/", nav);
1596         log("Initial Context :: " + contextpath);
1597         List list = contextpath.selectNodes(document);
1598         Iterator iter = list.iterator();
1599         while (iter.hasNext())
1600         {
1601             Object context = iter.next();
1602             // NOTE: /a/b/c selects elements in no namespace only!
1603             assertCountXPath(0, context, "/a/b/c");
1604             /*
1605                 The following test uses an unbound prefix 'x' and should throw an exception.
1606                 Addresses issue JAXEN-18.
1607                 Turns out this isn't really tested as the test didn't fail when the exception wasn't thrown.
1608               <test select="/x:a/x:b/x:c" count="0" exception="true"/>
1609 
1610             */
1611         }
1612     }
1613 
1614     public void testNamespaceResolution() throws JaxenException
1615     {
1616         Navigator nav = getNavigator();
1617         String url = "xml/defaultNamespace.xml";
1618         log("Document [" + url + "]");
1619         Object document = nav.getDocument(url);
1620         XPath contextpath = new BaseXPath("/", nav);
1621         log("Initial Context :: " + contextpath);
1622         List list = contextpath.selectNodes(document);
1623         SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
1624         nsContext.addNamespace("dummy", "http://dummyNamespace/");
1625         getContextSupport().setNamespaceContext(nsContext);
1626         Iterator iter = list.iterator();
1627         while (iter.hasNext())
1628         {
1629             Object context = iter.next();
1630             assertCountXPath(1, context, "/dummy:a/dummy:b/dummy:c");
1631         }
1632     }
1633 
1634     public void testTextNodes() throws JaxenException
1635     {
1636         Navigator nav = getNavigator();
1637         String url = "xml/text.xml";
1638         log("Document [" + url + "]");
1639         Object document = nav.getDocument(url);
1640         XPath contextpath = new BaseXPath("/", nav);
1641         log("Initial Context :: " + contextpath);
1642         List list = contextpath.selectNodes(document);
1643         Iterator iter = list.iterator();
1644         while (iter.hasNext())
1645         {
1646             Object context = iter.next();
1647             assertCountXPath(3, context, "/foo/bar/text()");
1648             assertValueOfXPath("baz", context, "normalize-space(/foo/bar/text())");
1649         }
1650     }
1651 
1652     public void testNamespaceNodeCounts1() throws JaxenException
1653     {
1654         Navigator nav = getNavigator();
1655         String url = "xml/testNamespaces.xml";
1656         log("Document [" + url + "]");
1657         Object document = nav.getDocument(url);
1658         XPath contextpath = new BaseXPath("/", nav);
1659         log("Initial Context :: " + contextpath);
1660         List list = contextpath.selectNodes(document);
1661         Iterator iter = list.iterator();
1662         while (iter.hasNext())
1663         {
1664             Object context = iter.next();
1665             // the root is not an element, so no namespaces
1666             assertCountXPath(0, context, "namespace::*");
1667             assertCountXPath(0, context, "/namespace::*");
1668             // must count the default xml: prefix as well
1669             assertCountXPath(3, context, "/Template/Application1/namespace::*");
1670             assertCountXPath(3, context, "/Template/Application2/namespace::*");
1671             // every element has separate copies
1672             assertCountXPath(25, context, "//namespace::*");
1673         }
1674     }
1675 
1676     public void testNamespaceNodeCounts() throws JaxenException
1677     {
1678         Navigator nav = getNavigator();
1679         String url = "xml/testNamespaces.xml";
1680         log("Document [" + url + "]");
1681         Object document = nav.getDocument(url);
1682         XPath contextpath = new BaseXPath("/Template/Application1", nav);
1683         log("Initial Context :: " + contextpath);
1684         List list = contextpath.selectNodes(document);
1685         Iterator iter = list.iterator();
1686         while (iter.hasNext())
1687         {
1688             Object context = iter.next();
1689             // must count the default xml: prefix as well
1690             assertCountXPath(3, context, "namespace::*");
1691             assertCountXPath(0, context, "/namespace::*");
1692             assertCountXPath(3, context, "/Template/Application1/namespace::*");
1693             assertCountXPath(3, context, "/Template/Application2/namespace::*");
1694             assertCountXPath(25, context, "//namespace::*");
1695             assertCountXPath(8, context, "//namespace::xplt");
1696             /* the name test literally matches the prefix as given in the
1697               document, and does not use the URI */
1698             assertCountXPath(0, context, "//namespace::somethingelse");
1699         }
1700     }
1701 
1702     public void testNamespaceNodesHaveParent() throws JaxenException
1703     {
1704         Navigator nav = getNavigator();
1705         String url = "xml/testNamespaces.xml";
1706         log("Document [" + url + "]");
1707         Object document = nav.getDocument(url);
1708         XPath contextpath = new BaseXPath("/", nav);
1709         log("Initial Context :: " + contextpath);
1710         List list = contextpath.selectNodes(document);
1711         Iterator iter = list.iterator();
1712         while (iter.hasNext())
1713         {
1714             Object context = iter.next();
1715             // namespace nodes have their element as their parent
1716             assertCountXPath(1, context, "/Template/namespace::xml/parent::Template");
1717         }
1718     }
1719 
1720     /** 
1721      * namespace nodes can also be used as context nodes
1722      */
1723     public void testNamespaceNodeAsContext() throws JaxenException
1724     {
1725         Navigator nav = getNavigator();
1726         String url = "xml/testNamespaces.xml";
1727         log("Document [" + url + "]");
1728         Object document = nav.getDocument(url);
1729         XPath contextpath = new BaseXPath("/Template/namespace::xml", nav);
1730         log("Initial Context :: " + contextpath);
1731         List list = contextpath.selectNodes(document);
1732         Iterator iter = list.iterator();
1733         while (iter.hasNext())
1734         {
1735             Object context = iter.next();
1736             assertCountXPath(1, context, "parent::Template");
1737         }
1738     }
1739 }