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