~ubuntu-branches/ubuntu/precise/xom/precise

« back to all changes in this revision

Viewing changes to src/nu/xom/tests/XPathTest.java

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2007-11-25 15:50:40 UTC
  • Revision ID: james.westby@ubuntu.com-20071125155040-r75ikcqf1vu0cei7
Tags: upstream-1.1
ImportĀ upstreamĀ versionĀ 1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2005 Elliotte Rusty Harold
 
2
   
 
3
   This library is free software; you can redistribute it and/or modify
 
4
   it under the terms of version 2.1 of the GNU Lesser General Public 
 
5
   License as published by the Free Software Foundation.
 
6
   
 
7
   This library is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 
10
   GNU Lesser General Public License for more details.
 
11
   
 
12
   You should have received a copy of the GNU Lesser General Public
 
13
   License along with this library; if not, write to the 
 
14
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 
15
   Boston, MA 02111-1307  USA
 
16
   
 
17
   You can contact Elliotte Rusty Harold by sending e-mail to
 
18
   elharo@metalab.unc.edu. Please include the word "XOM" in the
 
19
   subject line. The XOM home page is located at http://www.xom.nu/
 
20
*/
 
21
 
 
22
package nu.xom.tests;
 
23
 
 
24
import java.io.ByteArrayOutputStream;
 
25
import java.io.File;
 
26
import java.io.IOException;
 
27
import java.io.PrintStream;
 
28
import java.net.MalformedURLException;
 
29
 
 
30
import nu.xom.Attribute;
 
31
import nu.xom.Builder;
 
32
import nu.xom.Comment;
 
33
import nu.xom.DocType;
 
34
import nu.xom.Document;
 
35
import nu.xom.Element;
 
36
import nu.xom.Elements;
 
37
import nu.xom.Namespace;
 
38
import nu.xom.NamespaceConflictException;
 
39
import nu.xom.Node;
 
40
import nu.xom.Nodes;
 
41
import nu.xom.ParsingException;
 
42
import nu.xom.ProcessingInstruction;
 
43
import nu.xom.Text;
 
44
import nu.xom.XPathContext;
 
45
import nu.xom.XPathException;
 
46
import nu.xom.XPathTypeException;
 
47
 
 
48
/**
 
49
 * <p>
 
50
 * Unit tests for XPath functionality
 
51
 * </p>
 
52
 * 
 
53
 * @author Elliotte Rusty Harold
 
54
 * @version 1.1b4
 
55
 *
 
56
 */
 
57
public class XPathTest extends XOMTestCase {
 
58
    
 
59
    public XPathTest(String name) {
 
60
        super(name);
 
61
    }
 
62
    
 
63
    
 
64
    // This class tests error conditions, which Xerces
 
65
    // annoyingly logs to System.err. This hides System.err 
 
66
    // before each test and restores it after each test.
 
67
    private PrintStream systemErr = System.err;
 
68
    
 
69
    protected void setUp() {
 
70
        System.setErr(new PrintStream(new ByteArrayOutputStream()));
 
71
    }
 
72
    
 
73
    
 
74
    protected void tearDown() {
 
75
        System.setErr(systemErr);
 
76
    }
 
77
    
 
78
    public void testAllNodesQuery() {
 
79
        
 
80
        Document doc = new Document(new Element("doc"));
 
81
        Nodes subset = doc.query("//. | /");
 
82
        assertEquals(2, subset.size());
 
83
        
 
84
    }
 
85
    
 
86
    
 
87
    /* <a>
 
88
<x>1</x>
 
89
<b>
 
90
<x>2</x>
 
91
<x>3</x>
 
92
</b>
 
93
<x>4</x>
 
94
</a> */
 
95
    public void testDescendantAxisOrder() {
 
96
        
 
97
        Element a = new Element("a");
 
98
        Document doc = new Document(a);
 
99
        Element x1 = new Element("x");
 
100
        x1.appendChild("a1");
 
101
        Element x2 = new Element("x");
 
102
        x2.appendChild("b2");
 
103
        Element x3 = new Element("x");
 
104
        x3.appendChild("c3");
 
105
        Element x4 = new Element("x");
 
106
        x4.appendChild("d4");
 
107
        a.appendChild(x1);
 
108
        Element b = new Element("b");
 
109
        b.appendChild(x2);
 
110
        b.appendChild(x3);
 
111
        a.appendChild(b);
 
112
        a.appendChild(x4);
 
113
        Nodes result = doc.query("//x");
 
114
        assertEquals(4, result.size());
 
115
        assertTrue(result.get(0) instanceof Element);
 
116
        assertTrue(result.get(1) instanceof Element);
 
117
        assertTrue(result.get(2) instanceof Element);
 
118
        assertTrue(result.get(3) instanceof Element);
 
119
        assertEquals(x1, result.get(0));   
 
120
        assertEquals(x2, result.get(1));
 
121
        assertEquals(x3, result.get(2));
 
122
        assertEquals(x4, result.get(3));
 
123
        
 
124
    }
 
125
    
 
126
 
 
127
    public void testSimpleQuery() {
 
128
        
 
129
        Element parent = new Element("Test");
 
130
        Element child = new Element("child");
 
131
        parent.appendChild(child);
 
132
        
 
133
        Nodes result = parent.query("*");
 
134
        assertEquals(1, result.size());
 
135
        assertEquals(child, result.get(0));   
 
136
        
 
137
    }
 
138
    
 
139
    
 
140
    public void testChildWildCard() {
 
141
     
 
142
        Element a = new Element("a");
 
143
        Element b = new Element("b");
 
144
        Element c = new Element("c");
 
145
        Element d = new Element("d");
 
146
        
 
147
        a.appendChild(b);
 
148
        b.appendChild(c);
 
149
        c.appendChild(d);
 
150
        
 
151
        Nodes result = a.query("/a/b/*/d");
 
152
        assertEquals(1, result.size());
 
153
        assertEquals(d, result.get(0));
 
154
        
 
155
    }
 
156
    
 
157
 
 
158
    public void testSimpleChild() {
 
159
     
 
160
        Element a = new Element("a");
 
161
        Nodes result = a.query("/a");
 
162
        assertEquals(1, result.size());
 
163
        
 
164
    }
 
165
    
 
166
 
 
167
    public void testSimpleWildCard() {
 
168
     
 
169
        Element a = new Element("a");
 
170
        Nodes result = a.query("/*");
 
171
        assertEquals(1, result.size());
 
172
        
 
173
    }
 
174
    
 
175
 
 
176
    public void testLongs() {
 
177
        
 
178
        Document doc = new Document(new Element("root"));
 
179
        
 
180
        Nodes result = doc.query("/*[5000000000=5000000000]");
 
181
        assertEquals(1, result.size());
 
182
        
 
183
        result = doc.query("/*[5000000000 < 5000000001]");
 
184
        assertEquals(1, result.size());
 
185
        result = doc.query("/*[5000000000 > 5000000001]");
 
186
        assertEquals(0, result.size());
 
187
        result = doc.query("/*[5000000001 >= 5000000001]");
 
188
        assertEquals(1, result.size());
 
189
        result = doc.query("/*[5000000001 > 5000000001]");
 
190
        assertEquals(0, result.size());
 
191
        
 
192
    }
 
193
    
 
194
 
 
195
    public void testNamespaceNodeParent() {
 
196
        
 
197
        Element root = new Element("root");
 
198
        Document doc = new Document(root);
 
199
        Element child = new Element("pre:child", "http://www.ietf.org");
 
200
        root.appendChild(child);
 
201
        
 
202
        Nodes result = doc.query("/root/*/namespace::*/parent::*");
 
203
        assertEquals(1, result.size());
 
204
        assertEquals(child, result.get(0));
 
205
        
 
206
    }
 
207
    
 
208
 
 
209
    public void testNamespaceNodeChild() {
 
210
        
 
211
        Element root = new Element("root");
 
212
        Document doc = new Document(root);
 
213
        Element child = new Element("pre:child", "http://www.ietf.org");
 
214
        root.appendChild(child);
 
215
        
 
216
        Nodes result = doc.query("/root/*/namespace::*/child::*");
 
217
        assertEquals(0, result.size());
 
218
        
 
219
    }
 
220
    
 
221
 
 
222
    // JAXEN-46: http://jira.codehaus.org/browse/JAXEN-46
 
223
    public void testHashInAttributeValue() {
 
224
        
 
225
        Element root = new Element("test");
 
226
        Document doc = new Document(root);
 
227
        Attribute test = new Attribute("test", "SUBSCRIBER");
 
228
        Attribute test1 = new Attribute("test1", "SUBSCRIBER#");
 
229
        root.addAttribute(test);
 
230
        root.addAttribute(test1);
 
231
        
 
232
        Nodes result = doc.query("test[@test='SUBSCRIBER']");
 
233
        assertEquals(1, result.size());
 
234
        assertEquals(root, result.get(0));
 
235
        
 
236
        result = doc.query("test[@test1='SUBSCRIBER#']");
 
237
        assertEquals(1, result.size());
 
238
        assertEquals(root, result.get(0));
 
239
        
 
240
    }
 
241
    
 
242
 
 
243
    public void testUseRootNodeWhenQueryingDocumentLessElements() {
 
244
        
 
245
        Element test = new Element("Test");
 
246
        
 
247
        Nodes result = test.query("/*");
 
248
        assertEquals(1, result.size());
 
249
        assertEquals(test, result.get(0));   
 
250
        
 
251
        try {
 
252
            test.query("/");
 
253
            fail("Did not throw exception when querying rootless document for root");
 
254
        }
 
255
        catch (XPathException success) {
 
256
            assertNotNull(success.getMessage());
 
257
        }
 
258
        
 
259
    }
 
260
    
 
261
 
 
262
    public void testUseRootNodeWhenQueryingDocumentLessElements2() {
 
263
        
 
264
        Element test = new Element("Test");
 
265
        Nodes result = test.query("/None");
 
266
        assertEquals(0, result.size());
 
267
        
 
268
    }
 
269
    
 
270
 
 
271
    public void testUseRootNodeWhenQueryingDocumentLessElements3() {
 
272
        
 
273
        Element test = new Element("Test");  
 
274
        
 
275
        Nodes result = test.query("//*");
 
276
        assertEquals(1, result.size());
 
277
        
 
278
    }
 
279
    
 
280
 
 
281
    public void testUseRootNodeWhenQueryingDocumentLessElements4() {
 
282
        
 
283
        Element test = new Element("Test");  
 
284
        
 
285
        Nodes result = test.query("//* | /");
 
286
        assertEquals(1, result.size());
 
287
        
 
288
    }
 
289
    
 
290
 
 
291
    public void testUnionOfNodesWithInts() {
 
292
        
 
293
        Element parent = new Element("Test");
 
294
        Element child = new Element("child");
 
295
        parent.appendChild(child);
 
296
        
 
297
        try {
 
298
            parent.query("* | count(/*)");
 
299
            fail("Allowed query returning non-node-set");
 
300
        }
 
301
        catch (XPathException success) {
 
302
            assertNotNull(success.getMessage());
 
303
        }
 
304
        
 
305
    }
 
306
    
 
307
    
 
308
    public void testFranceschet1() throws ParsingException, IOException {
 
309
     
 
310
        Builder builder = new Builder();
 
311
        Document doc = builder.build(
 
312
          "http://staff.science.uva.nl/~francesc/xpathmark/benchmark_canon.xml"
 
313
        );
 
314
        Element root = doc.getRootElement();
 
315
        Elements inputs = root.getChildElements("document");
 
316
        Element input = inputs.get(0).getFirstChildElement("site");
 
317
        input.detach();
 
318
        
 
319
        Nodes doc1Queries = root.query("child::query[starts-with(@id, 'Q')]");
 
320
        
 
321
        for (int i = 0; i < doc1Queries.size(); i++) {
 
322
            Element query = (Element) doc1Queries.get(i);
 
323
            String xpath = query.getFirstChildElement("syntax").getValue();
 
324
            String id = query.getAttributeValue("id");
 
325
            // this query needs special comparison code due to 
 
326
            // adjacent text nodes
 
327
            if ("Q21".equals(id)) continue;
 
328
            // test suite bug relating to id() function
 
329
            else if (xpath.indexOf("id(") >= 0) continue;
 
330
            Nodes result = input.query(xpath);
 
331
            Element answer = query.getFirstChildElement("answer");
 
332
            Nodes expected = new Nodes();
 
333
            for (int j = 0; j < answer.getChildCount(); j++) {
 
334
                Node node = answer.getChild(j);
 
335
                if (node instanceof Text) {
 
336
                    if (!("".equals(node.getValue().trim()))) {
 
337
                        expected.append(node);
 
338
                    }
 
339
                }
 
340
                else {
 
341
                    expected.append(node);
 
342
                }
 
343
            }
 
344
            assertEquals("Failed query " + id, expected.size(), result.size());
 
345
            for (int j = 0; j < result.size(); j++) {
 
346
                Node expectedNode = expected.get(j);
 
347
                Node actualNode = result.get(j);                
 
348
                assertEquals(id + " " + expectedNode.toXML() + " " + actualNode.toXML(), expectedNode, actualNode);
 
349
            }
 
350
        }
 
351
        
 
352
    }
 
353
    
 
354
 
 
355
    public void testFranceschet2() throws ParsingException, IOException {
 
356
     
 
357
        Builder builder = new Builder();
 
358
        Document doc = builder.build(
 
359
          "http://staff.science.uva.nl/~francesc/xpathmark/benchmark_canon.xml"
 
360
        );
 
361
        Element root = doc.getRootElement();
 
362
        Elements inputs = root.getChildElements("document");
 
363
        Element input = inputs.get(1);
 
364
        Document html = new Document(new Element("fake"));
 
365
        int p = 0;
 
366
        while (true) {
 
367
            Node node = input.getChild(0);
 
368
            if (node instanceof Element) break;
 
369
            else {
 
370
                node.detach();
 
371
                if (node instanceof Text) continue;
 
372
                html.insertChild(node, p++);
 
373
            }
 
374
        }    
 
375
        Node newroot = input.getChild(0);
 
376
        newroot.detach();
 
377
        html.setRootElement((Element) newroot);
 
378
        while (input.getChildCount() > 0) {
 
379
            Node node = input.getChild(0);
 
380
            node.detach();
 
381
            if (node instanceof Text) continue;
 
382
            html.appendChild(node);
 
383
        }    
 
384
        
 
385
        Nodes doc2Queries = root.query("child::query[starts-with(@id, 'A')]");
 
386
        
 
387
        XPathContext context = new XPathContext();
 
388
        context.addNamespace("svg", "http://www.w3.org/2000/svg");
 
389
        context.addNamespace("xlink", "http://www.w3.org/1999/xlink");
 
390
        
 
391
        for (int i = 0; i < doc2Queries.size(); i++) {
 
392
            Element query = (Element) doc2Queries.get(i);
 
393
            String xpath = query.getFirstChildElement("syntax").getValue();
 
394
            String id = query.getAttributeValue("id");
 
395
 
 
396
            Nodes result = html.query(xpath, context);
 
397
            Element answer = query.getFirstChildElement("answer");
 
398
            Nodes expected = new Nodes();
 
399
            for (int j = 0; j < answer.getChildCount(); j++) {
 
400
                Node node = answer.getChild(j);
 
401
                if (node instanceof Text) {
 
402
                    if (!("".equals(node.getValue().trim()))) {
 
403
                        expected.append(node);
 
404
                    }
 
405
                }
 
406
                else {
 
407
                    expected.append(node);
 
408
                }
 
409
            }
 
410
            assertEquals("Failed query " + id, expected.size(), result.size());
 
411
            for (int j = 0; j < result.size(); j++) {
 
412
                Node expectedNode = expected.get(j);
 
413
                Node actualNode = result.get(j);                
 
414
                assertEquals(id + " " + expectedNode.toXML() + " " 
 
415
                  + actualNode.toXML(), expectedNode, actualNode);
 
416
            }
 
417
        }
 
418
        
 
419
    }
 
420
    
 
421
 
 
422
    public void testQueryThatReturnsNumber() {
 
423
        
 
424
        Element parent = new Element("Test");
 
425
        Element child = new Element("child");
 
426
        parent.appendChild(child);
 
427
        
 
428
        try {
 
429
            parent.query("count(*)");
 
430
            fail("Allowed query to return number");
 
431
        }
 
432
        catch (XPathTypeException success) {
 
433
            assertNotNull(success.getMessage());
 
434
            assertEquals(new Double(1), success.getReturnValue());
 
435
            assertEquals("count(*)", success.getXPath());
 
436
        }
 
437
        
 
438
    }
 
439
    
 
440
 
 
441
    public void testStartsWith() {
 
442
        
 
443
        Element parent = new Element("Test");
 
444
        Element child = new Element("child");
 
445
        child.addAttribute(new Attribute("foo", "bar"));
 
446
        parent.appendChild(child);
 
447
        Element child2 = new Element("child");
 
448
        child2.addAttribute(new Attribute("foo", "big"));
 
449
        parent.appendChild(child2);
 
450
        
 
451
        Nodes result = parent.query(".//*[starts-with(@foo, 'ba')]");
 
452
        assertEquals(1, result.size());
 
453
        assertEquals(child, result.get(0));
 
454
        
 
455
    }
 
456
    
 
457
 
 
458
    // a jaxen extension function
 
459
    public void testEndsWith() {
 
460
        
 
461
        Element parent = new Element("Test");
 
462
        Element child = new Element("child");
 
463
        child.addAttribute(new Attribute("foo", "bar"));
 
464
        parent.appendChild(child);
 
465
        
 
466
        try {
 
467
            parent.query(".//*[ends-with(@foo, 'ar')]");
 
468
            fail("Allowed Jaxen extension function");
 
469
        }
 
470
        catch (XPathException success) {
 
471
            assertTrue(success.getMessage().indexOf("ends-with") >= 0);
 
472
        }
 
473
        
 
474
    }
 
475
    
 
476
 
 
477
    public void testEmptyTextNodesDontCount() {
 
478
        
 
479
        Element parent = new Element("Test");
 
480
        Element child1 = new Element("child1");
 
481
        parent.appendChild(child1);
 
482
        parent.appendChild(new Text(""));
 
483
        parent.appendChild(new Text(""));
 
484
        Element child2 = new Element("child2");
 
485
        parent.appendChild(child2);
 
486
        
 
487
        Nodes result = parent.query("*");
 
488
        assertEquals(2, result.size());
 
489
        assertEquals(child1, result.get(0));   
 
490
        
 
491
        result = parent.query("*[2]");
 
492
        assertEquals(1, result.size());
 
493
        assertEquals(child2, result.get(0));
 
494
        
 
495
    }
 
496
    
 
497
 
 
498
    public void testEmptyTextNodesDontCount2() {
 
499
        
 
500
        Element parent = new Element("Test");
 
501
        parent.appendChild(new Text(""));
 
502
        Element child1 = new Element("child1");
 
503
        parent.appendChild(child1);
 
504
        Element child2 = new Element("child2");
 
505
        parent.appendChild(child2);
 
506
        
 
507
        Nodes result = parent.query("node()");
 
508
        assertEquals(2, result.size());
 
509
        assertEquals(child1, result.get(0));   
 
510
        assertEquals(child2, result.get(1));   
 
511
        
 
512
        result = parent.query("node()[1]");
 
513
        assertEquals(1, result.size());
 
514
        assertEquals(child1, result.get(0));
 
515
        
 
516
    }
 
517
    
 
518
 
 
519
    public void testEmptyTextNodesAtEndOfParent() {
 
520
        
 
521
        Element parent = new Element("Test");
 
522
        Element child1 = new Element("child1");
 
523
        parent.appendChild(child1);
 
524
        Element child2 = new Element("child2");
 
525
        parent.appendChild(child2);
 
526
        parent.appendChild(new Text(""));
 
527
        parent.appendChild(new Text(""));
 
528
        parent.appendChild(new Text(""));
 
529
        
 
530
        Nodes result = parent.query("node()");
 
531
        assertEquals(2, result.size());
 
532
        assertEquals(child1, result.get(0));   
 
533
        assertEquals(child2, result.get(1));   
 
534
        
 
535
        result = parent.query("node()[1]");
 
536
        assertEquals(1, result.size());
 
537
        assertEquals(child1, result.get(0));
 
538
        
 
539
    }
 
540
    
 
541
 
 
542
    public void testEmptyTextNodeNextToNonEmptyTextNode() {
 
543
        
 
544
        Element parent = new Element("Test");
 
545
        Text empty = new Text("");
 
546
        parent.appendChild(empty);
 
547
        Text nonempty = new Text("value");
 
548
        parent.appendChild(nonempty);
 
549
        Element child1 = new Element("child1");
 
550
        parent.appendChild(child1);
 
551
        Element child2 = new Element("child2");
 
552
        parent.appendChild(child2);
 
553
        
 
554
        Nodes result = parent.query("node()");
 
555
        assertEquals(4, result.size());
 
556
        assertEquals(empty, result.get(0));   
 
557
        assertEquals(nonempty, result.get(1));   
 
558
        
 
559
        result = parent.query("node()[1]");
 
560
        assertEquals(2, result.size());
 
561
        assertEquals(empty, result.get(0));
 
562
        
 
563
    }
 
564
    
 
565
 
 
566
    public void testBasicPredicate() {
 
567
        
 
568
        Element parent = new Element("Test");
 
569
        Element child1 = new Element("child");
 
570
        child1.appendChild("1");
 
571
        parent.appendChild(child1);
 
572
        Element child2 = new Element("child");
 
573
        child2.appendChild("2");
 
574
        parent.appendChild(child2);
 
575
        Element child3 = new Element("child");
 
576
        child3.appendChild("3");
 
577
        parent.appendChild(child3);
 
578
        
 
579
        Nodes result = parent.query("*[.='2']");
 
580
        assertEquals(1, result.size());
 
581
        assertEquals(child2, result.get(0));   
 
582
        
 
583
    }
 
584
    
 
585
 
 
586
    public void testXMLLang() {
 
587
        
 
588
        Element parent = new Element("Test");
 
589
        Element child1 = new Element("child");
 
590
        child1.addAttribute(new Attribute("xml:lang", 
 
591
          "http://www.w3.org/XML/1998/namespace", "en"));
 
592
        parent.appendChild(child1);
 
593
        Element child2 = new Element("child");
 
594
        child2.appendChild("2");
 
595
        child2.addAttribute(new Attribute("xml:lang", 
 
596
          "http://www.w3.org/XML/1998/namespace", "fr"));
 
597
        parent.appendChild(child2);
 
598
        Element child3 = new Element("child");
 
599
        child3.appendChild("3");
 
600
        parent.appendChild(child3);
 
601
        Element child4 = new Element("child");
 
602
        child4.appendChild("4");
 
603
        child4.addAttribute(new Attribute("xml:lang", 
 
604
          "http://www.w3.org/XML/1998/namespace", "en-US"));
 
605
        parent.appendChild(child4);
 
606
        
 
607
        Nodes result = parent.query("child::*[lang('en')]");
 
608
        assertEquals(2, result.size());
 
609
        assertEquals(child1, result.get(0));   
 
610
        assertEquals(child4, result.get(1));   
 
611
        
 
612
    }
 
613
    
 
614
 
 
615
    public void testXMLPrefixIsAlwaysBound() {
 
616
        
 
617
        Element parent = new Element("Test");
 
618
        Element child1 = new Element("child");
 
619
        child1.addAttribute(new Attribute("xml:lang", 
 
620
          "http://www.w3.org/XML/1998/namespace", "en"));
 
621
        parent.appendChild(child1);
 
622
        Element child2 = new Element("child");
 
623
        child2.appendChild("2");
 
624
        child2.addAttribute(new Attribute("xml:lang", 
 
625
          "http://www.w3.org/XML/1998/namespace", "fr"));
 
626
        parent.appendChild(child2);
 
627
        Element child3 = new Element("child");
 
628
        child3.appendChild("3");
 
629
        parent.appendChild(child3);
 
630
        Element child4 = new Element("child");
 
631
        child4.appendChild("4");
 
632
        child4.addAttribute(new Attribute("xml:lang", 
 
633
          "http://www.w3.org/XML/1998/namespace", "en-US"));
 
634
        parent.appendChild(child4);
 
635
        
 
636
        Nodes result = parent.query("child::*/@xml:lang");
 
637
        assertEquals(3, result.size());   
 
638
        
 
639
    }
 
640
    
 
641
    
 
642
    public void testCantRebindXMLPrefix() {
 
643
        
 
644
        XPathContext context = new XPathContext();
 
645
        try {
 
646
            context.addNamespace("xml", "http://www.example.org");
 
647
            fail("Rebound xml prefix");
 
648
        }
 
649
        catch (NamespaceConflictException success) {
 
650
            assertNotNull(success.getMessage());
 
651
        }
 
652
        
 
653
    }
 
654
    
 
655
 
 
656
    public void testParentAxis() {
 
657
        
 
658
        Element parent = new Element("Test");
 
659
        Element child = new Element("child");
 
660
        parent.appendChild(child);
 
661
        
 
662
        Nodes result = child.query("parent::*");
 
663
        assertEquals(1, result.size());
 
664
        assertEquals(parent, result.get(0));   
 
665
        
 
666
    }
 
667
    
 
668
 
 
669
    public void testAncestorAxis() {
 
670
        
 
671
        Element grandparent = new Element("Test");
 
672
        new Document(grandparent);
 
673
        Element parent = new Element("Test");
 
674
        Element child = new Element("child");
 
675
        parent.appendChild(child);
 
676
        grandparent.appendChild(parent);
 
677
        
 
678
        Nodes result = child.query("ancestor::*");
 
679
        assertEquals(2, result.size());
 
680
        assertEquals(grandparent, result.get(0));   
 
681
        assertEquals(parent, result.get(1));
 
682
        
 
683
    }
 
684
    
 
685
 
 
686
    public void testParentAxisWithDocument() {
 
687
        
 
688
        Element root = new Element("Test");
 
689
        new Document(root);
 
690
        
 
691
        Nodes result = root.query("parent::*");
 
692
        assertEquals(0, result.size());
 
693
        
 
694
    }
 
695
    
 
696
    
 
697
    public void testParentAxisWithNodeMatchingDocument() {
 
698
        
 
699
        Element root = new Element("Test");
 
700
        Document doc = new Document(root);
 
701
        
 
702
        Nodes result = root.query("parent::node()");
 
703
        assertEquals(1, result.size());
 
704
        assertEquals(doc, result.get(0));
 
705
        
 
706
    }
 
707
    
 
708
    
 
709
    public void testSubstringFunction() {
 
710
        
 
711
        Element root = new Element("Test");
 
712
        new Document(root);
 
713
        
 
714
        Nodes result = root.query("/*[substring('12345', 0, 3)='12']");
 
715
        assertEquals(1, result.size());
 
716
        assertEquals(root, result.get(0));
 
717
        
 
718
    }
 
719
    
 
720
    
 
721
    public void testPrecedingAxisWithElementName() {
 
722
        
 
723
        Element root = new Element("Test");
 
724
        Document doc = new Document(root);
 
725
        
 
726
        Nodes result = doc.query("/descendant::*/preceding::x");
 
727
        assertEquals(0, result.size());
 
728
        
 
729
    }
 
730
    
 
731
    
 
732
    
 
733
    
 
734
    public void testDocTypeIsNotAnXPathNode() {
 
735
     
 
736
        Element root = new Element("root");
 
737
        Document doc = new Document(root);
 
738
        DocType doctype = new DocType("root");
 
739
        doc.setDocType(doctype);
 
740
        
 
741
        Nodes result = doc.query("child::node()[1]");
 
742
        assertEquals(1, result.size());
 
743
        assertEquals(root, result.get(0));
 
744
        
 
745
    }
 
746
    
 
747
 
 
748
    public void testGetNodeBeforeDocType() {
 
749
     
 
750
        Element root = new Element("root");
 
751
        Document doc = new Document(root);
 
752
        DocType doctype = new DocType("root");
 
753
        doc.setDocType(doctype);
 
754
        Comment c = new Comment("test");
 
755
        doc.insertChild(c, 0);
 
756
        
 
757
        Nodes result = doc.query("child::node()[1]");
 
758
        assertEquals(1, result.size());
 
759
        assertEquals(c, result.get(0));
 
760
        
 
761
    }
 
762
    
 
763
 
 
764
    public void testCantUseDocTypeAsXPathContextNode() {
 
765
     
 
766
        Element root = new Element("root");
 
767
        Document doc = new Document(root);
 
768
        DocType doctype = new DocType("root");
 
769
        doc.setDocType(doctype);
 
770
        
 
771
        try {
 
772
            doctype.query("/");
 
773
            fail("Allowed DocType as context node");
 
774
        }
 
775
        catch (XPathException success) {
 
776
            assertNotNull(success.getMessage());
 
777
        }
 
778
        
 
779
    }
 
780
    
 
781
 
 
782
    public void testDescendantAxis() {
 
783
        
 
784
        Element grandparent = new Element("Test");
 
785
        Document doc = new Document(grandparent);
 
786
        Element parent = new Element("Test");
 
787
        Element child = new Element("child");
 
788
        parent.appendChild(child);
 
789
        grandparent.appendChild(parent);
 
790
        
 
791
        Nodes result = doc.query("descendant::*");
 
792
        assertEquals(3, result.size());
 
793
        assertEquals(grandparent, result.get(0));   
 
794
        assertEquals(parent, result.get(1));
 
795
        assertEquals(child, result.get(2));
 
796
        
 
797
    }
 
798
  
 
799
    
 
800
    public void testGetElementQName() {
 
801
        
 
802
        Element grandparent = new Element("Test");
 
803
        Document doc = new Document(grandparent);
 
804
        Element parent = new Element("Test");
 
805
        Element child1 = new Element("pre:child", "http://www.example.org/");
 
806
        Element child2 = new Element("pre:child", "http://www.example.com/");
 
807
        parent.appendChild(child1);
 
808
        parent.appendChild(child2);
 
809
        grandparent.appendChild(parent);
 
810
        
 
811
        Nodes result = doc.query("descendant::*[name(.)='pre:child']");
 
812
        assertEquals(2, result.size());
 
813
        assertEquals(child1, result.get(0));   
 
814
        assertEquals(child2, result.get(1));
 
815
        
 
816
    }
 
817
    
 
818
 
 
819
    // This does not actually hit the method I was aiming at. 
 
820
    // Apparently, Jaxen never actually invokes
 
821
    // getElementStringValue()
 
822
    public void testGetElementStringValue() {
 
823
        
 
824
        Element grandparent = new Element("Test");
 
825
        Document doc = new Document(grandparent);
 
826
        Element parent = new Element("Test");
 
827
        Element child1 = new Element("child");
 
828
        child1.appendChild("foo");
 
829
        Element child2 = new Element("child");
 
830
        child2.appendChild("bar");
 
831
        parent.appendChild(child1);
 
832
        parent.appendChild(child2);
 
833
        grandparent.appendChild(parent);
 
834
        
 
835
        Nodes result = doc.query("descendant::*[.='foo']");
 
836
        assertEquals(1, result.size());
 
837
        assertEquals(child1, result.get(0)); 
 
838
        
 
839
    }
 
840
    
 
841
 
 
842
    public void testGetNonExistentNode() {
 
843
        
 
844
        Element grandparent = new Element("Test");
 
845
        Document doc = new Document(grandparent);
 
846
        Element parent = new Element("Test");
 
847
        Element child1 = new Element("child");
 
848
        child1.appendChild("foo");
 
849
        Element child2 = new Element("child");
 
850
        child2.appendChild("bar");
 
851
        parent.appendChild(child1);
 
852
        parent.appendChild(child2);
 
853
        grandparent.appendChild(parent);
 
854
        
 
855
        Nodes result = doc.query("/Test/Test/*[12]");
 
856
        assertEquals(0, result.size()); 
 
857
        
 
858
    }
 
859
    
 
860
 
 
861
    public void testGetAttributeQName() {
 
862
        
 
863
        Element grandparent = new Element("Test");
 
864
        Document doc = new Document(grandparent);
 
865
        Element parent = new Element("Test");
 
866
        Attribute a1 = new Attribute("pre:attribute", "http://www.example.org/", "test");
 
867
        Attribute a2 = new Attribute("pre:attribute", "http://www.example.com/", "test");
 
868
        parent.addAttribute(a2);
 
869
        grandparent.addAttribute(a1);
 
870
        grandparent.appendChild(parent);
 
871
        
 
872
        Nodes result = doc.query("descendant::*/attribute::*[name(.)='pre:attribute']");
 
873
        assertEquals(2, result.size());
 
874
        assertTrue(result.contains(a1));   
 
875
        assertTrue(result.contains(a2));
 
876
        
 
877
    }
 
878
    
 
879
    
 
880
    public void testGetNamespaceStringValue() {
 
881
        
 
882
        Element test = new Element("Test", "http://www.example.com/");
 
883
        
 
884
        Nodes result = test.query("self::*[contains(namespace::*, 'http://')]");
 
885
        assertEquals(1, result.size());
 
886
        assertEquals(test, result.get(0));
 
887
        
 
888
    }
 
889
    
 
890
    
 
891
    private File inputDir = new File("data");
 
892
 
 
893
    
 
894
    public void testGetDocument() throws MalformedURLException {
 
895
        
 
896
        Element element = new Element("test");
 
897
        File f = new File(inputDir, "prettyxml.xml");
 
898
        String url = f.toURL().toExternalForm();
 
899
        try {
 
900
            element.query("document('" + url + "')/*");
 
901
            fail("allowed document() function");
 
902
        }
 
903
        catch(XPathException success) {
 
904
            assertTrue(success.getMessage().indexOf("document") >= 0);
 
905
        }
 
906
        
 
907
    }
 
908
    
 
909
 
 
910
    public void testGetMultipleNodesViaDocumentFunction() 
 
911
      throws MalformedURLException {
 
912
        
 
913
        Element element = new Element("test");
 
914
        File f = new File(inputDir, "prettyxml.xml");
 
915
        String url = f.toURL().toExternalForm();
 
916
        try {
 
917
            element.query("document('" + url + "')//*");
 
918
            fail("allowed document() function");
 
919
        }
 
920
        catch(XPathException success) {
 
921
            assertTrue(success.getMessage().indexOf("document") >= 0);
 
922
        }
 
923
        
 
924
    }
 
925
    
 
926
 
 
927
    public void testDoubleDocument() throws MalformedURLException {
 
928
        
 
929
        Element element = new Element("test");
 
930
        File f1 = new File(inputDir, "prettyxml.xml");
 
931
        String url1 = f1.toURL().toExternalForm();
 
932
        File f2 = new File(inputDir, "test.xml");
 
933
        String url2 = f2.toURL().toExternalForm();
 
934
        try {
 
935
            element.query("document('" + url1 + "')/* | " 
 
936
              + "document('" + url2 + "')/*");
 
937
            fail("allowed document() function");
 
938
        }
 
939
        catch(XPathException success) {
 
940
            assertTrue(success.getMessage().indexOf("document") >= 0);
 
941
        }
 
942
        
 
943
    }
 
944
    
 
945
 
 
946
    public void testGetNonExistentDocument() {
 
947
        
 
948
        Element element = new Element("test");
 
949
        try {
 
950
            element.query("document('http://www.ibiblio.org/aksdjhk/')/*");
 
951
            fail("That file doesn't exist!");
 
952
        }
 
953
        catch (XPathException success) {
 
954
            assertNotNull(success.getMessage());
 
955
        }
 
956
        
 
957
    }
 
958
    
 
959
 
 
960
    public void testMalformedDocument() {
 
961
        
 
962
        Element element = new Element("test");
 
963
        try {
 
964
            element.query("document('http://www.cafeaulait.org/formatter/Formatter.java')/*");
 
965
            fail("Queried malformed document!");
 
966
        }
 
967
        catch (XPathException success) {
 
968
            assertNotNull(success.getMessage());
 
969
        }
 
970
        
 
971
    }
 
972
    
 
973
 
 
974
    public void testGetDocumentNode() {
 
975
        
 
976
        Element element = new Element("test");
 
977
        Document doc = new Document(element);
 
978
        Nodes result = element.query("/");
 
979
        assertEquals(1, result.size());
 
980
        assertEquals(doc, result.get(0));
 
981
        
 
982
    }
 
983
    
 
984
 
 
985
    public void testCommentNodeTest() {
 
986
        
 
987
        Element grandparent = new Element("Test");
 
988
        Document doc = new Document(grandparent);
 
989
        Element parent = new Element("Test");
 
990
        Element child = new Element("child");
 
991
        parent.appendChild(child);
 
992
        grandparent.appendChild(parent);
 
993
        
 
994
        Comment c1 = new Comment("c1");
 
995
        Comment c2 = new Comment("c2");
 
996
        Comment c3 = new Comment("c3");
 
997
        Comment c4 = new Comment("c4");
 
998
        
 
999
        doc.insertChild(c1, 0);
 
1000
        grandparent.insertChild(c2, 0);
 
1001
        parent.insertChild(c3, 0);
 
1002
        child.insertChild(c4, 0);
 
1003
        
 
1004
        Nodes result = doc.query("descendant::comment()");
 
1005
        assertEquals(4, result.size());
 
1006
        assertEquals(c1, result.get(0));   
 
1007
        assertEquals(c2, result.get(1));
 
1008
        assertEquals(c3, result.get(2));
 
1009
        assertEquals(c4, result.get(3));
 
1010
        
 
1011
    }
 
1012
    
 
1013
 
 
1014
    public void testCommentStringValue() {
 
1015
        
 
1016
        Element grandparent = new Element("Test");
 
1017
        Document doc = new Document(grandparent);
 
1018
        Element parent = new Element("Test");
 
1019
        Element child = new Element("child");
 
1020
        parent.appendChild(child);
 
1021
        grandparent.appendChild(parent);
 
1022
        
 
1023
        Comment c1 = new Comment("c1");
 
1024
        Comment c2 = new Comment("c2");
 
1025
        Comment c3 = new Comment("c3");
 
1026
        Comment c4 = new Comment("c4");
 
1027
        
 
1028
        doc.insertChild(c1, 0);
 
1029
        grandparent.insertChild(c2, 0);
 
1030
        parent.insertChild(c3, 0);
 
1031
        child.insertChild(c4, 0);
 
1032
        
 
1033
        Nodes result = doc.query("descendant::comment()[.='c3']");
 
1034
        assertEquals(1, result.size());
 
1035
        assertEquals(c3, result.get(0));
 
1036
        
 
1037
    }
 
1038
    
 
1039
    
 
1040
    public void testGetProcessingInstructionData() {
 
1041
        
 
1042
        Element grandparent = new Element("Test");
 
1043
        Document doc = new Document(grandparent);
 
1044
        Element parent = new Element("Test");
 
1045
        Element child = new Element("child");
 
1046
        parent.appendChild(child);
 
1047
        grandparent.appendChild(parent);
 
1048
        
 
1049
        ProcessingInstruction p1 = new ProcessingInstruction("c1", "1");
 
1050
        ProcessingInstruction p2 = new ProcessingInstruction("c1", "2");
 
1051
        ProcessingInstruction p3 = new ProcessingInstruction("c1", "3");
 
1052
        ProcessingInstruction p4 = new ProcessingInstruction("c1", "4");
 
1053
        
 
1054
        doc.insertChild(p1, 0);
 
1055
        grandparent.insertChild(p2, 0);
 
1056
        parent.insertChild(p3, 0);
 
1057
        child.insertChild(p4, 0);
 
1058
        
 
1059
        Nodes result = doc.query("descendant::processing-instruction()[.='3']");
 
1060
        assertEquals(1, result.size());
 
1061
        assertEquals(p3, result.get(0));
 
1062
        
 
1063
    }
 
1064
    
 
1065
    
 
1066
    public void testProcessingInstructionNodeTest() {
 
1067
        
 
1068
        Element grandparent = new Element("Test");
 
1069
        Document doc = new Document(grandparent);
 
1070
        Element parent = new Element("Test");
 
1071
        Element child = new Element("child");
 
1072
        parent.appendChild(child);
 
1073
        grandparent.appendChild(parent);
 
1074
        
 
1075
        Comment c1 = new Comment("c1");
 
1076
        Comment c2 = new Comment("c2");
 
1077
        Comment c3 = new Comment("c3");
 
1078
        Comment c4 = new Comment("c4");
 
1079
        
 
1080
        doc.insertChild(c1, 0);
 
1081
        grandparent.insertChild(c2, 0);
 
1082
        parent.insertChild(c3, 0);
 
1083
        child.insertChild(c4, 0);
 
1084
        ProcessingInstruction pi = new ProcessingInstruction("appendix", "text");
 
1085
        doc.appendChild(pi);
 
1086
        ProcessingInstruction pi2 = new ProcessingInstruction("test", "text");
 
1087
        parent.appendChild(pi2);
 
1088
        
 
1089
        Nodes result = doc.query("descendant::processing-instruction('test')");
 
1090
        assertEquals(1, result.size());
 
1091
        assertEquals(pi2, result.get(0));
 
1092
        
 
1093
    }
 
1094
    
 
1095
 
 
1096
    public void testDescendantOrSelfAxis() {
 
1097
        
 
1098
        Element grandparent = new Element("Test");
 
1099
        Element parent = new Element("Test");
 
1100
        Element child = new Element("child");
 
1101
        parent.appendChild(child);
 
1102
        grandparent.appendChild(parent);
 
1103
        
 
1104
        Nodes result = grandparent.query("descendant-or-self::*");
 
1105
        assertEquals(3, result.size());
 
1106
        assertEquals(grandparent, result.get(0));   
 
1107
        assertEquals(parent, result.get(1));
 
1108
        assertEquals(child, result.get(2));
 
1109
        
 
1110
    }
 
1111
    
 
1112
 
 
1113
    public void testAncestorOrSelfAxis() {
 
1114
        
 
1115
        Element grandparent = new Element("Test");
 
1116
        new Document(grandparent);
 
1117
        Element parent = new Element("Test");
 
1118
        Element child = new Element("child");
 
1119
        parent.appendChild(child);
 
1120
        grandparent.appendChild(parent);
 
1121
        
 
1122
        Nodes result = child.query("ancestor-or-self::*");
 
1123
        assertEquals(3, result.size());
 
1124
        assertEquals(child, result.get(2));   
 
1125
        assertEquals(parent, result.get(1));   
 
1126
        assertEquals(grandparent, result.get(0));
 
1127
        
 
1128
    }
 
1129
    
 
1130
 
 
1131
    public void testSelfAxis() {
 
1132
        
 
1133
        Element parent = new Element("Test");
 
1134
        Element child = new Element("child");
 
1135
        parent.appendChild(child);
 
1136
        
 
1137
        Nodes result = child.query("self::*");
 
1138
        assertEquals(1, result.size());
 
1139
        assertEquals(child, result.get(0));   
 
1140
        result = parent.query("self::*");
 
1141
        assertEquals(1, result.size());
 
1142
        assertEquals(parent, result.get(0));   
 
1143
        
 
1144
    }
 
1145
    
 
1146
 
 
1147
    public void testSelfAxisWithUnparentedText() {
 
1148
        
 
1149
        Text text = new Text("test");
 
1150
        Nodes result = text.query("self::text()");
 
1151
        assertEquals(1, result.size());
 
1152
        assertEquals(text, result.get(0));  
 
1153
        
 
1154
    }
 
1155
    
 
1156
    public void testSelfAxisWithAttribute() {
 
1157
        
 
1158
        Element e = new Element("child");
 
1159
        e.addAttribute(new Attribute("test", "value"));
 
1160
        Nodes result = e.query("@*[self::test]");
 
1161
        assertEquals(0, result.size());
 
1162
        
 
1163
    }
 
1164
    
 
1165
 
 
1166
    public void testSelfAxisWithTextChild() {
 
1167
        
 
1168
        Element parent = new Element("parent");
 
1169
        Node child = new Text("child");
 
1170
        parent.appendChild(child);
 
1171
        Nodes result = child.query("self::text()");
 
1172
        assertEquals(1, result.size());
 
1173
        assertEquals(child, result.get(0));
 
1174
        
 
1175
    }
 
1176
    
 
1177
 
 
1178
    public void testSelfAxisWithTextChildren() {
 
1179
        
 
1180
        Element parent = new Element("parent");
 
1181
        Node child1 = new Text("1");
 
1182
        Node child2 = new Text("2");
 
1183
        Node child3 = new Text("3");
 
1184
        Node child4 = new Text("4");
 
1185
        parent.appendChild(child1);
 
1186
        parent.appendChild(child2);
 
1187
        parent.appendChild(child3);
 
1188
        parent.appendChild(child4);
 
1189
        Nodes result = child1.query("self::text()");
 
1190
        assertEquals(4, result.size());
 
1191
        assertEquals(child1, result.get(0));
 
1192
        assertEquals(child2, result.get(1));
 
1193
        assertEquals(child3, result.get(2));
 
1194
        assertEquals(child4, result.get(3));  
 
1195
        
 
1196
    }
 
1197
    
 
1198
 
 
1199
    public void testSelfAxisWithTextChildren2() {
 
1200
        
 
1201
        Element parent = new Element("parent");
 
1202
        Node child1 = new Text("1");
 
1203
        Node child2 = new Text("2");
 
1204
        Node child3 = new Text("3");
 
1205
        Node child4 = new Text("4");
 
1206
        parent.appendChild(child1);
 
1207
        parent.appendChild(child2);
 
1208
        parent.appendChild(child3);
 
1209
        parent.appendChild(child4);
 
1210
        Nodes result = child3.query("self::text()");
 
1211
        assertEquals(4, result.size());
 
1212
        assertEquals(child1, result.get(0));
 
1213
        assertEquals(child2, result.get(1));
 
1214
        assertEquals(child3, result.get(2));
 
1215
        assertEquals(child4, result.get(3));
 
1216
        
 
1217
    }
 
1218
    
 
1219
 
 
1220
    public void testSelfAxisWithTextChildAndNoParent() {
 
1221
        
 
1222
        Node child = new Text("child");
 
1223
        Nodes result = child.query("self::text()");
 
1224
        assertEquals(1, result.size());
 
1225
        assertEquals(child, result.get(0));
 
1226
        
 
1227
    }
 
1228
    
 
1229
 
 
1230
    public void testAttributeAxis() {
 
1231
        
 
1232
        Element parent = new Element("Test");
 
1233
        Element child = new Element("child");
 
1234
        parent.appendChild(child);
 
1235
        parent.addAttribute(new Attribute("name", "value"));
 
1236
        parent.addAttribute(new Attribute("name2", "value"));
 
1237
        
 
1238
        Nodes result = child.query("attribute::*");
 
1239
        assertEquals(0, result.size());
 
1240
        result = parent.query("attribute::*");
 
1241
        assertEquals(2, result.size());
 
1242
        result = parent.query("attribute::name");
 
1243
        assertEquals(1, result.size()); 
 
1244
        
 
1245
    }
 
1246
    
 
1247
 
 
1248
    public void testAttributeAxisOnNonElement() {
 
1249
        
 
1250
        Text text = new Text("Test");
 
1251
        Nodes result = text.query("attribute::*");
 
1252
        assertEquals(0, result.size());
 
1253
        
 
1254
    }
 
1255
    
 
1256
 
 
1257
    public void testEmptyParentAxis() {
 
1258
        
 
1259
        Element parent = new Element("Test");
 
1260
        Element child = new Element("child");
 
1261
        parent.appendChild(child);
 
1262
        
 
1263
        Nodes result = parent.query("parent::*");
 
1264
        assertEquals(0, result.size());   
 
1265
        
 
1266
    }
 
1267
    
 
1268
 
 
1269
    public void testPrecedingSiblingAxis() {
 
1270
        
 
1271
        Element parent = new Element("Test");
 
1272
        Element child1 = new Element("child1");
 
1273
        Element child2 = new Element("child2");
 
1274
        Element child3 = new Element("child3");
 
1275
        parent.appendChild(child1);
 
1276
        parent.appendChild(child2);
 
1277
        parent.appendChild(child3);
 
1278
        
 
1279
        Nodes result = child1.query("preceding-sibling::*");
 
1280
        assertEquals(0, result.size());   
 
1281
        result = child2.query("preceding-sibling::*");
 
1282
        assertEquals(1, result.size());   
 
1283
        assertEquals(child1, result.get(0));   
 
1284
        result = child3.query("preceding-sibling::*");
 
1285
        assertEquals(2, result.size());    
 
1286
        
 
1287
    }
 
1288
    
 
1289
 
 
1290
    public void testAttributeHasNoSiblings() {
 
1291
        
 
1292
        Element parent = new Element("Test");
 
1293
        Element child1 = new Element("child1");
 
1294
        Element child2 = new Element("child2");
 
1295
        Element child3 = new Element("child3");
 
1296
        parent.appendChild(child1);
 
1297
        parent.appendChild(child2);
 
1298
        parent.appendChild(child3);
 
1299
        Attribute a1 = new Attribute("a1", "value");
 
1300
        Attribute a2 = new Attribute("a2", "value");
 
1301
        Attribute a3 = new Attribute("a3", "value");
 
1302
        child2.addAttribute(a1);
 
1303
        child2.addAttribute(a2);
 
1304
        child2.addAttribute(a3);
 
1305
        
 
1306
        Nodes result = a2.query("preceding-sibling::node()");
 
1307
        assertEquals(0, result.size());   
 
1308
        result = a2.query("following-sibling::node()");
 
1309
        assertEquals(0, result.size());    
 
1310
        
 
1311
    }
 
1312
    
 
1313
 
 
1314
    public void testIDFunction() {
 
1315
        
 
1316
        Element parent = new Element("Test");
 
1317
        Element child1 = new Element("child1");
 
1318
        Element child2 = new Element("child2");
 
1319
        Element child3 = new Element("child3");
 
1320
        Attribute id = new Attribute("a", "anchor");
 
1321
        id.setType(Attribute.Type.ID);
 
1322
        child2.addAttribute(id);
 
1323
        
 
1324
        parent.appendChild(child1);
 
1325
        parent.appendChild(child2);
 
1326
        parent.appendChild(child3);
 
1327
        
 
1328
        Nodes result = parent.query("id('anchor')");
 
1329
        assertEquals(1, result.size());     
 
1330
        assertEquals(child2, result.get(0));
 
1331
        
 
1332
    }
 
1333
    
 
1334
 
 
1335
    public void testIDQueryOnDocumentNode() {
 
1336
        
 
1337
        Element parent = new Element("Test");
 
1338
        Element child1 = new Element("child1");
 
1339
        Element child2 = new Element("child2");
 
1340
        Element child3 = new Element("child3");
 
1341
        Attribute id = new Attribute("a", "anchor");
 
1342
        id.setType(Attribute.Type.ID);
 
1343
        child2.addAttribute(id);
 
1344
        
 
1345
        parent.appendChild(child1);
 
1346
        parent.appendChild(child2);
 
1347
        parent.appendChild(child3);
 
1348
        Document doc = new Document(parent);
 
1349
        
 
1350
        Nodes result = doc.query("id('anchor')");
 
1351
        assertEquals(1, result.size());     
 
1352
        assertEquals(child2, result.get(0));
 
1353
        
 
1354
    }
 
1355
    
 
1356
 
 
1357
    public void testIDFunctionWithoutType() {
 
1358
        
 
1359
        Element parent = new Element("Test");
 
1360
        Element child1 = new Element("child1");
 
1361
        Element child2 = new Element("child2");
 
1362
        Element child3 = new Element("child3");
 
1363
        Attribute id = new Attribute("id", "anchor");
 
1364
        child2.addAttribute(id);
 
1365
        
 
1366
        parent.appendChild(child1);
 
1367
        parent.appendChild(child2);
 
1368
        parent.appendChild(child3);
 
1369
        
 
1370
        Nodes result = parent.query("id('anchor')");
 
1371
        assertEquals(0, result.size());
 
1372
        
 
1373
    }
 
1374
    
 
1375
 
 
1376
    public void testIDFunctionFromTextNode() {
 
1377
        
 
1378
        Element parent = new Element("Test");
 
1379
        Element child1 = new Element("child1");
 
1380
        Element child2 = new Element("child2");
 
1381
        Element child3 = new Element("child3");
 
1382
        Text text = new Text("test");
 
1383
        child3.appendChild(text);
 
1384
        Attribute id = new Attribute("a", "anchor");
 
1385
        id.setType(Attribute.Type.ID);
 
1386
        child2.addAttribute(id);
 
1387
        
 
1388
        parent.appendChild(child1);
 
1389
        parent.appendChild(child2);
 
1390
        parent.appendChild(child3);
 
1391
        
 
1392
        Nodes result = text.query("id('anchor')");
 
1393
        assertEquals(1, result.size());     
 
1394
        assertEquals(child2, result.get(0));
 
1395
        
 
1396
    }
 
1397
    
 
1398
 
 
1399
    public void testIDFunctionFromUnparentedTextNode() {
 
1400
        
 
1401
        Text text = new Text("test");
 
1402
        Nodes result = text.query("id('anchor')");
 
1403
        assertEquals(0, result.size());
 
1404
        
 
1405
    }
 
1406
    
 
1407
 
 
1408
    public void testIDFunctionFromDisconnectedTextNode() {
 
1409
        
 
1410
        Text text = new Text("test");       
 
1411
        Nodes result = text.query("id('anchor')");
 
1412
        assertEquals(0, result.size());
 
1413
        
 
1414
    }
 
1415
    
 
1416
 
 
1417
    public void testFollowingSiblingAxis() {
 
1418
        
 
1419
        Element parent = new Element("Test");
 
1420
        Element child1 = new Element("child1");
 
1421
        Element child2 = new Element("child2");
 
1422
        Element child3 = new Element("child3");
 
1423
        parent.appendChild(child1);
 
1424
        parent.appendChild(child2);
 
1425
        parent.appendChild(child3);
 
1426
        
 
1427
        Nodes result = child3.query("following-sibling::*");
 
1428
        assertEquals(0, result.size());   
 
1429
        result = child2.query("following-sibling::*");
 
1430
        assertEquals(1, result.size());   
 
1431
        assertEquals(child3, result.get(0));   
 
1432
        result = child1.query("following-sibling::*");
 
1433
        assertEquals(2, result.size());    
 
1434
        
 
1435
    }
 
1436
    
 
1437
 
 
1438
    public void testNamespaceQuery() {
 
1439
        
 
1440
        Element parent = new Element("Test", "http://www.example.org");
 
1441
        Element child = new Element("child", "http://www.example.org");
 
1442
        parent.appendChild(child);
 
1443
        
 
1444
        XPathContext context = new XPathContext("pre", "http://www.example.org");
 
1445
        Nodes result = parent.query("child::pre:child", context);
 
1446
        assertEquals(1, result.size());
 
1447
        assertEquals(child, result.get(0));   
 
1448
        
 
1449
    }
 
1450
    
 
1451
    
 
1452
    public void testNamespaceAxis() {
 
1453
        
 
1454
        Element parent = new Element("Test", "http://www.example.org");
 
1455
        
 
1456
        Nodes result = parent.query("namespace::*");
 
1457
        assertEquals(2, result.size());
 
1458
        Namespace n1 = (Namespace) result.get(0);
 
1459
        Namespace n2 = (Namespace) result.get(1);
 
1460
        assertTrue(n1.getPrefix().equals("") || n2.getPrefix().equals(""));
 
1461
        assertTrue(n1.getPrefix().equals("xml") || n2.getPrefix().equals("xml"));
 
1462
        assertTrue(n1.getValue().equals("http://www.example.org") 
 
1463
          || n2.getValue().equals("http://www.example.org"));
 
1464
        assertTrue(n1.getValue().equals(Namespace.XML_NAMESPACE) 
 
1465
          || n2.getValue().equals(Namespace.XML_NAMESPACE));
 
1466
        
 
1467
    }
 
1468
    
 
1469
    
 
1470
    public void testNamespaceAxisFromNonElement() {
 
1471
        
 
1472
        Text text = new Text("test");
 
1473
        
 
1474
        Nodes result = text.query("namespace::*");
 
1475
        assertEquals(0, result.size()); 
 
1476
        
 
1477
    }
 
1478
    
 
1479
    
 
1480
    public void testPredicateWithNamespaceAxis() {
 
1481
        
 
1482
        Element parent = new Element("Test");
 
1483
        Element child = new Element("child", "http://www.example.com");
 
1484
        Element grandchild = new Element("child", "http://www.example.com");
 
1485
        grandchild.addNamespaceDeclaration("pre", "http://www.w3.org/");
 
1486
        parent.appendChild(child);
 
1487
        child.appendChild(grandchild);
 
1488
        
 
1489
        // Every node has at least a mapping for xml prefix.
 
1490
        Nodes result = parent.query("self::*[count(namespace::*)=0]");
 
1491
        assertEquals(0, result.size());   
 
1492
        
 
1493
        result = parent.query("self::*[count(namespace::*)=1]");
 
1494
        assertEquals(1, result.size());   
 
1495
        assertEquals(parent, result.get(0));
 
1496
        
 
1497
        result = child.query("self::*[count(namespace::*)=2]");
 
1498
        assertEquals(1, result.size());   
 
1499
        assertEquals(child, result.get(0));
 
1500
        
 
1501
        result = grandchild.query("self::*[count(namespace::*)=3]");
 
1502
        assertEquals(1, result.size());   
 
1503
        assertEquals(grandchild, result.get(0));
 
1504
        
 
1505
    }
 
1506
    
 
1507
    
 
1508
    public void testPredicateWithNamespaceAxis2() {
 
1509
        
 
1510
        Element parent = new Element("Test");
 
1511
        Element child = new Element("child", "http://www.example.com");
 
1512
        Element grandchild = new Element("child", "http://www.example.com");
 
1513
        grandchild.addNamespaceDeclaration("pre", "http://www.w3.org/");
 
1514
        parent.appendChild(child);
 
1515
        child.appendChild(grandchild);
 
1516
        
 
1517
        // Every node has at least a mapping for xml prefix.
 
1518
        Nodes result = parent.query("*[count(namespace::*)=0]");
 
1519
        assertEquals(0, result.size());   
 
1520
        
 
1521
        result = parent.query(".//self::*[count(namespace::*)=1]");
 
1522
        assertEquals(1, result.size());   
 
1523
        assertEquals(parent, result.get(0));
 
1524
        
 
1525
        result = parent.query(".//*[count(namespace::*)=2]");
 
1526
        assertEquals(1, result.size());   
 
1527
        assertEquals(child, result.get(0));
 
1528
        
 
1529
        result = parent.query(".//*[count(namespace::*)=3]");
 
1530
        assertEquals(1, result.size());   
 
1531
        assertEquals(grandchild, result.get(0));
 
1532
        
 
1533
    }
 
1534
    
 
1535
    
 
1536
    public void testNamespaceQueryWithNullPrefix() {
 
1537
        
 
1538
        try {
 
1539
            XPathContext context = new XPathContext("pre", "http://www.example.org");
 
1540
            context.addNamespace(null, "http://www.w3.org");
 
1541
            fail("Allowed null prefix");
 
1542
        }
 
1543
        catch (NullPointerException success) {
 
1544
            assertNotNull(success.getMessage());
 
1545
        }
 
1546
        
 
1547
    }
 
1548
    
 
1549
    
 
1550
    public void testNamespaceQueryWithNullPrefix2() {
 
1551
        
 
1552
        try {
 
1553
            new XPathContext(null, "http://www.example.org");
 
1554
            fail("Allowed null prefix");
 
1555
        }
 
1556
        catch (NullPointerException success) {
 
1557
            assertNotNull(success.getMessage());
 
1558
        }
 
1559
        
 
1560
    }
 
1561
    
 
1562
    
 
1563
    public void testNamespaceQueryWithEmptyPrefix() {
 
1564
        
 
1565
        try {
 
1566
            XPathContext context = new XPathContext("pre", "http://www.example.org");
 
1567
            context.addNamespace("", "http://www.w3.org");
 
1568
        }
 
1569
        catch (NamespaceConflictException success) {
 
1570
            assertTrue(success.getMessage().length() > 1);
 
1571
        }
 
1572
        
 
1573
    }
 
1574
    
 
1575
    
 
1576
    public void testNamespaceQueryWithEmptyPrefix2() {
 
1577
        
 
1578
        try {
 
1579
            new XPathContext("", "http://www.example.org");
 
1580
        }
 
1581
        catch (NamespaceConflictException success) {
 
1582
            assertTrue(success.getMessage().length() > 1);
 
1583
        }
 
1584
        
 
1585
    }
 
1586
    
 
1587
    
 
1588
    public void testNamespaceQueryWithNullURI() {
 
1589
        
 
1590
        Element parent = new Element("Test", "http://www.example.org");
 
1591
        Element child = new Element("child", "http://www.example.org");
 
1592
        parent.appendChild(child);
 
1593
        
 
1594
        XPathContext context = new XPathContext("pre", null);
 
1595
        try {
 
1596
            parent.query("child::pre:child", context);
 
1597
            fail("Allowed null URI");
 
1598
        }
 
1599
        catch (XPathException success) {
 
1600
            assertNotNull(success.getCause());
 
1601
            assertNotNull(success.getMessage());
 
1602
        }
 
1603
        
 
1604
    }
 
1605
    
 
1606
    
 
1607
    public void testNamespaceQueryWithEmptyURI() {
 
1608
        
 
1609
        Element parent = new Element("Test", "http://www.example.org");
 
1610
        Element child = new Element("child", "http://www.example.org");
 
1611
        parent.appendChild(child);
 
1612
        
 
1613
        XPathContext context = new XPathContext("pre", "");
 
1614
        try {
 
1615
            parent.query("child::pre:child", context);
 
1616
            fail("Allowed empty string as namespace URI");
 
1617
        }
 
1618
        catch (XPathException success) {
 
1619
            assertNotNull(success.getCause());
 
1620
            assertNotNull(success.getMessage());
 
1621
        }
 
1622
        
 
1623
    }
 
1624
    
 
1625
    
 
1626
    public void testNamespaceQueryWithReboundPrefix() {
 
1627
        
 
1628
        Element parent = new Element("Test", "http://www.example.org");
 
1629
        Element child = new Element("child", "http://www.example.org");
 
1630
        parent.appendChild(child);
 
1631
        
 
1632
        XPathContext context = new XPathContext("pre", "http://www.example.com");
 
1633
        Nodes result = parent.query("child::pre:child", context);
 
1634
        assertEquals(0, result.size());
 
1635
        
 
1636
        context.addNamespace("pre", "http://www.example.org");
 
1637
        result = parent.query("child::pre:child", context);
 
1638
        assertEquals(1, result.size());
 
1639
        assertEquals(child, result.get(0));   
 
1640
        
 
1641
    }
 
1642
    
 
1643
    
 
1644
    public void testNamespaceQueryWithUnboundPrefix() {
 
1645
        
 
1646
        Element parent = new Element("Test", "http://www.example.org");
 
1647
        Element child = new Element("child", "http://www.example.org");
 
1648
        parent.appendChild(child);
 
1649
        
 
1650
        XPathContext context = new XPathContext("not", "http://www.example.com");
 
1651
        try {
 
1652
            parent.query("child::pre:child", context);
 
1653
            fail("Queried with unbound prefix");
 
1654
        }
 
1655
        catch (XPathException success) {
 
1656
            assertNotNull(success.getMessage());
 
1657
            assertNotNull(success.getCause());
 
1658
        }
 
1659
        
 
1660
        try {
 
1661
            parent.query("child::pre:child");
 
1662
            fail("Queried with unbound prefix");
 
1663
        }
 
1664
        catch (XPathException success) {
 
1665
            assertNotNull(success.getMessage());
 
1666
            assertNotNull(success.getCause());
 
1667
        }
 
1668
        
 
1669
    }
 
1670
    
 
1671
    
 
1672
    public void testElementBasedNamespaceContext() {
 
1673
        
 
1674
        Element parent = new Element("Test", "http://www.example.org");
 
1675
        Element child = new Element("child", "http://www.example.org");
 
1676
        parent.appendChild(child);
 
1677
        
 
1678
        Element test = new Element("pre:test", "http://www.example.org");
 
1679
        XPathContext context = XPathContext.makeNamespaceContext(test);
 
1680
        Nodes result = parent.query("child::pre:child", context);
 
1681
        assertEquals(1, result.size());
 
1682
        assertEquals(child, result.get(0));   
 
1683
        
 
1684
    }
 
1685
    
 
1686
    
 
1687
    public void testAttributeBasedNamespaceContext() {
 
1688
        
 
1689
        Element parent = new Element("Test", "http://www.example.org");
 
1690
        Element child = new Element("child", "http://www.example.org");
 
1691
        parent.appendChild(child);
 
1692
        
 
1693
        Element test = new Element("test");
 
1694
        test.addAttribute(new Attribute("pre:test", "http://www.example.org", "value"));
 
1695
        XPathContext context = XPathContext.makeNamespaceContext(test);
 
1696
        Nodes result = parent.query("child::pre:child", context);
 
1697
        assertEquals(1, result.size());
 
1698
        assertEquals(child, result.get(0));   
 
1699
        
 
1700
    }
 
1701
    
 
1702
    
 
1703
    public void testAdditionalNamespaceBasedNamespaceContext() {
 
1704
        
 
1705
        Element parent = new Element("Test", "http://www.example.org");
 
1706
        Element child = new Element("child", "http://www.example.org");
 
1707
        parent.appendChild(child);
 
1708
        
 
1709
        Element test = new Element("test");
 
1710
        test.addNamespaceDeclaration("pre", "http://www.example.org");
 
1711
        XPathContext context = XPathContext.makeNamespaceContext(test);
 
1712
        Nodes result = parent.query("child::pre:child", context);
 
1713
        assertEquals(1, result.size());
 
1714
        assertEquals(child, result.get(0));   
 
1715
        
 
1716
    }
 
1717
    
 
1718
    
 
1719
    public void testAncestorElementBasedNamespaceContext() {
 
1720
        
 
1721
        Element parent = new Element("Test", "http://www.example.org");
 
1722
        Element child = new Element("child", "http://www.example.org");
 
1723
        parent.appendChild(child);
 
1724
        
 
1725
        Element test = new Element("pre:test", "http://www.example.org");
 
1726
        Element testChild = new Element("testchild");
 
1727
        test.appendChild(testChild);
 
1728
        XPathContext context = XPathContext.makeNamespaceContext(testChild);
 
1729
        Nodes result = parent.query("child::pre:child", context);
 
1730
        assertEquals(1, result.size());
 
1731
        assertEquals(child, result.get(0));   
 
1732
        
 
1733
    }
 
1734
    
 
1735
    
 
1736
    public void testAncestorAttributeBasedNamespaceContext() {
 
1737
        
 
1738
        Element parent = new Element("Test", "http://www.example.org");
 
1739
        Element child = new Element("child", "http://www.example.org");
 
1740
        parent.appendChild(child);
 
1741
        
 
1742
        Element test = new Element("test");
 
1743
        test.addAttribute(new Attribute("pre:test", "http://www.example.org", "value"));
 
1744
        Element testChild = new Element("testchild");
 
1745
        test.appendChild(testChild);
 
1746
        XPathContext context = XPathContext.makeNamespaceContext(testChild);
 
1747
        Nodes result = parent.query("child::pre:child", context);
 
1748
        assertEquals(1, result.size());
 
1749
        assertEquals(child, result.get(0));   
 
1750
        
 
1751
    }
 
1752
    
 
1753
    
 
1754
    public void testAncestorAdditionalNamespaceBasedNamespaceContext() {
 
1755
        
 
1756
        Element parent = new Element("Test", "http://www.example.org");
 
1757
        Element child = new Element("child", "http://www.example.org");
 
1758
        parent.appendChild(child);
 
1759
        
 
1760
        Element test = new Element("test");
 
1761
        test.addNamespaceDeclaration("pre", "http://www.example.org");
 
1762
        Element testChild = new Element("testchild");
 
1763
        test.appendChild(testChild);
 
1764
        XPathContext context = XPathContext.makeNamespaceContext(testChild);
 
1765
        Nodes result = parent.query("child::pre:child", context);
 
1766
        assertEquals(1, result.size());
 
1767
        assertEquals(child, result.get(0));   
 
1768
        
 
1769
    }
 
1770
    
 
1771
    
 
1772
    public void testPrefixedNamespaceQuery() {
 
1773
        
 
1774
        Element parent = new Element("a:Test", "http://www.example.org");
 
1775
        Element child = new Element("b:child", "http://www.example.org");
 
1776
        Attribute att = new Attribute("c:dog", "http://www.cafeconleche.org/", "test");
 
1777
        parent.appendChild(child);
 
1778
        child.addAttribute(att);
 
1779
        
 
1780
        XPathContext context = new XPathContext("pre", "http://www.example.org");
 
1781
        context.addNamespace("c", "http://www.cafeconleche.org/");
 
1782
        Nodes result = parent.query("child::pre:child", context);
 
1783
        assertEquals(1, result.size());
 
1784
        assertEquals(child, result.get(0)); 
 
1785
        
 
1786
        result = child.query("@c:*", context);
 
1787
        assertEquals(1, result.size());
 
1788
        assertEquals(att, result.get(0)); 
 
1789
        
 
1790
    }
 
1791
    
 
1792
    
 
1793
    public void testBradley() {
 
1794
     
 
1795
        Element element = new Element("root");
 
1796
        Text t1 = new Text("makes ");
 
1797
        Text t2 = new Text("a");
 
1798
        Text t3 = new Text(" good");
 
1799
        Text t4 = new Text(" point.");
 
1800
        Element child = new Element("someElement");
 
1801
        Text t5 = new Text("  Yes");
 
1802
        Text t6 = new Text(" he");
 
1803
        Text t7 = new Text(" does!");
 
1804
        element.appendChild(t1);
 
1805
        element.appendChild(t2);
 
1806
        element.appendChild(t3);
 
1807
        element.appendChild(t4);
 
1808
        element.appendChild(child);
 
1809
        element.appendChild(t5);
 
1810
        element.appendChild(t6);
 
1811
        element.appendChild(t7);
 
1812
        
 
1813
        Nodes result = element.query("./text()[contains(., 'o')]");
 
1814
        assertEquals(7, result.size());
 
1815
        assertEquals(t1, result.get(0));
 
1816
        assertEquals(t2, result.get(1));
 
1817
        assertEquals(t3, result.get(2));
 
1818
        assertEquals(t4, result.get(3));
 
1819
        assertEquals(t5, result.get(4));
 
1820
        assertEquals(t6, result.get(5));
 
1821
        assertEquals(t7, result.get(6));
 
1822
        
 
1823
        
 
1824
    }
 
1825
    
 
1826
 
 
1827
    public void testNamespaceQueryWithAdjacentTextNodes() {
 
1828
        
 
1829
        Element parent = new Element("Test", "http://www.example.org");
 
1830
        Element child = new Element("child", "http://www.example.org");
 
1831
        parent.appendChild(child);
 
1832
        child.appendChild("1");
 
1833
        child.appendChild("2");
 
1834
        
 
1835
        XPathContext context = new XPathContext("pre", "http://www.example.org");
 
1836
        Nodes result = parent.query("descendant::text()", context);
 
1837
        assertEquals(2, result.size());
 
1838
        assertEquals("1", result.get(0).getValue());   
 
1839
        assertEquals("2", result.get(1).getValue());   
 
1840
        
 
1841
    }
 
1842
    
 
1843
 
 
1844
    public void testNamespaceQueryWithoutPrefixMapping() {
 
1845
        
 
1846
        Element parent = new Element("Test", "http://www.example.org");
 
1847
        Element child = new Element("child", "http://www.example.org");
 
1848
        parent.appendChild(child);
 
1849
        
 
1850
        Nodes result = parent.query("child");
 
1851
        assertEquals(0, result.size());   
 
1852
        
 
1853
    }
 
1854
    
 
1855
 
 
1856
    public void testAdjacentTextObjects() {
 
1857
        
 
1858
        Element parent = new Element("Test");
 
1859
        parent.appendChild("test");
 
1860
        parent.appendChild("again");
 
1861
        
 
1862
        Nodes result = parent.query("text()");
 
1863
        assertEquals(2, result.size());
 
1864
        assertEquals("test", result.get(0).getValue());   
 
1865
        assertEquals("again", result.get(1).getValue());   
 
1866
        
 
1867
    }
 
1868
    
 
1869
 
 
1870
    public void testQueryCrossesAdjacentTextObjects() {
 
1871
        
 
1872
        Element parent = new Element("Test");
 
1873
        parent.appendChild("test");
 
1874
        parent.appendChild("again");
 
1875
        
 
1876
        Nodes result = parent.query("node()[contains(., 'tag')]");
 
1877
        assertEquals(2, result.size());
 
1878
        assertEquals("test", result.get(0).getValue());   
 
1879
        assertEquals("again", result.get(1).getValue());   
 
1880
        
 
1881
    }
 
1882
    
 
1883
 
 
1884
    // According to section 5.7 of the XPath 1.0 spec,
 
1885
    // "As much character data as possible is grouped into each text 
 
1886
    // node: a text node never has an immediately following or 
 
1887
    // preceding sibling that is a text node."
 
1888
    public void testAdjacentTextNodes2() {
 
1889
        
 
1890
        Element parent = new Element("Test");
 
1891
        parent.appendChild("test");
 
1892
        parent.appendChild("again");
 
1893
        
 
1894
        Nodes result = parent.query("child::text()[1]");
 
1895
        assertEquals(2, result.size());
 
1896
        assertEquals("test", result.get(0).getValue());   
 
1897
        assertEquals("again", result.get(1).getValue());   
 
1898
        
 
1899
    }
 
1900
    
 
1901
 
 
1902
    // According to section 5.7 of the XPath 1.0 spec,
 
1903
    // "A text node always has at least one character of data."
 
1904
    public void testEmptyTextNodes() {
 
1905
        
 
1906
        Element parent = new Element("Test");
 
1907
        parent.appendChild("");
 
1908
        
 
1909
        Nodes result = parent.query("child::text()");
 
1910
        assertEquals(0, result.size());  
 
1911
        
 
1912
    }
 
1913
    
 
1914
 
 
1915
    public void testEmptyTextFollowsNonEmptyText() {
 
1916
        
 
1917
        Element parent = new Element("parent");
 
1918
        Text empty = new Text("");
 
1919
        Text nonempty = new Text("value");
 
1920
        parent.appendChild(nonempty);
 
1921
        parent.appendChild(empty);
 
1922
        Nodes result = parent.query("node()");
 
1923
        assertEquals(2, result.size());
 
1924
        
 
1925
    }
 
1926
    
 
1927
    
 
1928
    public void testCountAdjacentEmptyAndNonEmptyTextNodes() {
 
1929
        
 
1930
        Element parent = new Element("parent");
 
1931
        Text empty = new Text("");
 
1932
        Text nonempty = new Text("value");
 
1933
        parent.appendChild(nonempty);
 
1934
        parent.appendChild(empty);
 
1935
 
 
1936
        Nodes result2 = parent.query("/*[count(node())=1]");
 
1937
        assertEquals(1, result2.size());
 
1938
        assertEquals(parent, result2.get(0));
 
1939
        
 
1940
        Nodes nodes1 = parent.query("node()[1]");
 
1941
        assertEquals(2, nodes1.size());
 
1942
        Nodes nodes2 = parent.query("node()[2]");
 
1943
        assertEquals(0, nodes2.size());
 
1944
        
 
1945
    }
 
1946
    
 
1947
    
 
1948
    public void testAdjacentEmptyAndNonEmptyTextNodes() {
 
1949
        
 
1950
        Element parent = new Element("parent");
 
1951
        Text empty = new Text("");
 
1952
        Text nonempty = new Text("value");
 
1953
        Text nonempty2 = new Text("value2");
 
1954
        parent.appendChild(empty);
 
1955
        parent.appendChild(nonempty);
 
1956
        parent.appendChild(nonempty2);
 
1957
        
 
1958
        Nodes result = parent.query("node()");
 
1959
        assertEquals(3, result.size());
 
1960
 
 
1961
        Nodes result2 = parent.query("/*[count(node())=1]");
 
1962
        assertEquals(1, result2.size());
 
1963
        assertEquals(parent, result2.get(0));
 
1964
        
 
1965
        Nodes nodes1 = parent.query("node()[1]");
 
1966
        assertEquals(3, nodes1.size());
 
1967
        
 
1968
        Nodes nodes2 = parent.query("node()[2]");
 
1969
        assertEquals(0, nodes2.size());
 
1970
        
 
1971
    }
 
1972
 
 
1973
 
 
1974
    public void testBadXPathExpression() {
 
1975
        
 
1976
        Element parent = new Element("Test");
 
1977
        
 
1978
        try {
 
1979
            parent.query("This is not an XPath expression");
 
1980
            fail("Allowed malformed query");
 
1981
        }
 
1982
        catch (XPathException success) {
 
1983
            assertNotNull(success.getMessage());
 
1984
        }  
 
1985
        
 
1986
    }
 
1987
    
 
1988
    
 
1989
    public void testNaNEvaluatesToFalse() {
 
1990
        
 
1991
        Element root = new Element("root");
 
1992
        Document doc = new Document(root);
 
1993
        
 
1994
        Nodes result = doc.query("/*[boolean(0 div 0)]");
 
1995
        assertEquals(0, result.size());
 
1996
        
 
1997
    }
 
1998
    
 
1999
    
 
2000
    /* <body>
 
2001
<p>
 
2002
  <span></span>
 
2003
</p>
 
2004
<div></div>
 
2005
</body> */
 
2006
     public void testPrecedingAxis() {
 
2007
      
 
2008
         Element body = new Element("body");
 
2009
         Element p = new Element("p");
 
2010
         body.appendChild(p);
 
2011
         Element span = new Element("span");
 
2012
         p.appendChild(span);
 
2013
         Element div = new Element("div");
 
2014
         body.appendChild(div);
 
2015
         
 
2016
         Nodes result = div.query("preceding::*[1]");
 
2017
         assertEquals(1, result.size());
 
2018
         assertEquals(span, result.get(0));
 
2019
         
 
2020
     }
 
2021
    
 
2022
    
 
2023
     public void testRootNodeValueIsNonEmpty() {
 
2024
      
 
2025
         Element root = new Element("html");
 
2026
         Document doc = new Document(root);
 
2027
         root.appendChild("test");
 
2028
         
 
2029
         Nodes result = doc.query("/*[string(/) != '']");
 
2030
         assertEquals(1, result.size());
 
2031
         assertEquals(root, result.get(0));
 
2032
         
 
2033
     }
 
2034
    
 
2035
    
 
2036
     public void testContextPositionForParaentlessNodeIs1() {
 
2037
      
 
2038
         Element root = new Element("html");
 
2039
         
 
2040
         Nodes result = root.query("self::*[1]");
 
2041
         assertEquals(1, result.size());
 
2042
         assertEquals(root, result.get(0));
 
2043
         
 
2044
     }
 
2045
    
 
2046
    
 
2047
     public void testContextSizeForParaentlessNodeIs1() {
 
2048
      
 
2049
         Element root = new Element("html");
 
2050
         
 
2051
         Nodes result = root.query("self::*[last()=1]");
 
2052
         assertEquals(1, result.size());
 
2053
         assertEquals(root, result.get(0));
 
2054
         
 
2055
     }
 
2056
    
 
2057
    
 
2058
     public void testLastFunction() {
 
2059
      
 
2060
         Element root = new Element("html");
 
2061
         Element child1 = new Element("child1");
 
2062
         Element child2 = new Element("child2");
 
2063
         root.appendChild(child1);
 
2064
         root.appendChild(child2);
 
2065
         new Document(root);
 
2066
         
 
2067
         Nodes result = child2.query("self::*[position()=last()]");
 
2068
         assertEquals(1, result.size());
 
2069
         assertEquals(child2, result.get(0));
 
2070
         
 
2071
     }
 
2072
     
 
2073
     
 
2074
     public void testJaxen51() throws ParsingException, IOException {
 
2075
 
 
2076
         String data = "<root>\n <servlet-mapping>\n" 
 
2077
             + "  <servlet-name>DeviceInfoServlet</servlet-name>\n"
 
2078
             + "  <url-pattern>/tools/*</url-pattern>\n"
 
2079
             + "</servlet-mapping>\n</root>";
 
2080
         
 
2081
         Builder builder = new Builder();
 
2082
         Document doc = builder.build(data, null);
 
2083
         
 
2084
         Nodes result = doc.query("//*[./../servlet-name = 'DeviceInfoServlet']");
 
2085
         assertEquals(2, result.size());
 
2086
       
 
2087
     }         
 
2088
 
 
2089
 
 
2090
    public void testXPathNamespaceParentage() 
 
2091
      throws ParsingException, IOException {
 
2092
        
 
2093
        String input = "<!DOCTYPE doc [\n"
 
2094
            + "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
 
2095
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
2096
            + "]>\n"
 
2097
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
2098
            + "   <e1>\n"
 
2099
            + "      <e2 xmlns=\"\">\n"
 
2100
            + "         <e3 id=\"E3\"/>\n"
 
2101
            + "      </e2>\n"
 
2102
            + "   </e1>\n"
 
2103
            + "</doc>";
 
2104
        
 
2105
        Document doc = (new Builder()).build(input, null);
 
2106
        String xpath = "(/*/* | /*/*/namespace::*)\n";
 
2107
        Nodes result = doc.query(xpath);
 
2108
        assertEquals(4, result.size());
 
2109
        Element parent = (Element) result.get(0);
 
2110
        for (int i = 1; i < 4; i++) {
 
2111
            Namespace namespace = (Namespace) result.get(i); 
 
2112
            assertEquals(parent, namespace.getParent());
 
2113
        }
 
2114
        
 
2115
    }
 
2116
    
 
2117
 
 
2118
    public void testAttributesFollowElementsInDocumentOrder() 
 
2119
      throws ParsingException, IOException {
 
2120
        
 
2121
        String input = "<document>\n"
 
2122
            + "   <e1 a='b' c='d' e='f'>\n"
 
2123
            + "      <e2>\n"
 
2124
            + "         <e3 id=\"E3\"/>\n"
 
2125
            + "      </e2>\n"
 
2126
            + "   </e1>\n"
 
2127
            + "</document>";
 
2128
        
 
2129
        Document doc = (new Builder()).build(input, null);
 
2130
        String xpath = "(/*/* | /*/*/attribute::*)\n";
 
2131
        Nodes result = doc.query(xpath);
 
2132
        assertEquals(4, result.size());
 
2133
        Element parent = (Element) result.get(0);
 
2134
        for (int i = 1; i < 4; i++) {
 
2135
            Attribute attribute = (Attribute) result.get(i); 
 
2136
            assertEquals(parent, attribute.getParent());
 
2137
        }
 
2138
        
 
2139
    }
 
2140
    
 
2141
    
 
2142
    public void testDoubleSlashIsIncorrect() {
 
2143
        
 
2144
        Element root = new Element("root", "http://www.example.org");
 
2145
        Document doc = new Document(root);
 
2146
        root.appendChild(new Element("child"));
 
2147
        root.appendChild("test");
 
2148
        root.addAttribute(new Attribute("test", "test"));
 
2149
        
 
2150
        try {
 
2151
            doc.query("//");
 
2152
            fail("Queried //");
 
2153
        }
 
2154
        catch (XPathException success) {
 
2155
            assertNotNull(success.getMessage());
 
2156
        }
 
2157
        
 
2158
    }
 
2159
    
 
2160
 
 
2161
    public void testDoubleSlashIsIncorrect2() {
 
2162
        
 
2163
        Element root = new Element("root", "http://www.example.org");
 
2164
        Document doc = new Document(root);
 
2165
        root.appendChild(new Element("child"));
 
2166
        root.appendChild("test");
 
2167
        root.addAttribute(new Attribute("test", "test"));
 
2168
        
 
2169
        try {
 
2170
            doc.query("// ");
 
2171
            fail("Queried // ");
 
2172
        }
 
2173
        catch (XPathException success) {
 
2174
            assertNotNull(success.getMessage());
 
2175
        }
 
2176
        
 
2177
    }
 
2178
    
 
2179
 
 
2180
    public void testWhiteSpaceIsAllowedBetweenTokens() {
 
2181
        
 
2182
        Element root = new Element("root", "http://www.example.org");
 
2183
        Document doc = new Document(root);
 
2184
        root.appendChild(new Element("child"));
 
2185
        root.appendChild("test");
 
2186
        root.addAttribute(new Attribute("test", "test"));
 
2187
        
 
2188
        Nodes nodes = doc.query("// a");
 
2189
        assertEquals(0, nodes.size());
 
2190
        
 
2191
    }
 
2192
    
 
2193
    
 
2194
/*    public void testMassimo() throws ParsingException, IOException {
 
2195
        
 
2196
        Builder builder = new Builder();
 
2197
        Document doc = builder.build("http://staff.science.uva.nl/~francesc/xpathmark/benchmark_canon.xml");
 
2198
        Element root = doc.getRootElement();
 
2199
        Element input_1 = root.getFirstChildElement("document_1");
 
2200
        Element input_2 = root.getFirstChildElement("document_2");
 
2201
        
 
2202
        Nodes queries = root.query("child::query[starts-with('@id', 'Q')]");
 
2203
        for (int i = 0; i < queries.size(); i++) {
 
2204
            Element query = (Element) queries.get(i);
 
2205
            String xpath = query.getFirstChildElement("syntax").getValue();
 
2206
            Nodes actual = input_1.query(xpath);
 
2207
            Elements expected = query.getChildElements();
 
2208
        }
 
2209
        
 
2210
    } */
 
2211
    
 
2212
    
 
2213
    public void testJaxenIntegrationTest() throws ParsingException, IOException {
 
2214
        
 
2215
        Builder builder = new Builder();
 
2216
        Document testDoc = builder.build(
 
2217
          "http://cvs.jaxen.codehaus.org/viewrep/~raw,r=HEAD/jaxen/jaxen/xml/test/tests.xml");
 
2218
        Elements documents = testDoc.getRootElement().getChildElements("document");
 
2219
        for (int i = 0; i < documents.size(); i++) {
 
2220
            Element documentElement = documents.get(i);
 
2221
            String url = documentElement.getAttributeValue("url");
 
2222
            Document source = builder.build(
 
2223
              "http://cvs.jaxen.codehaus.org/viewrep/~raw,r=HEAD/jaxen/jaxen/" 
 
2224
              + url);
 
2225
            Elements contextElements = documentElement.getChildElements("context");
 
2226
            for (int j = 0; j < contextElements.size(); j++) {
 
2227
                Element contextElement = contextElements.get(j);
 
2228
                    
 
2229
                // skip tests that use variables
 
2230
                // because XOM doesn't support variables in 
 
2231
                // XPath expressions
 
2232
                if (queryUsesVars(contextElement)) continue;
 
2233
                
 
2234
                String xpath = contextElement.getAttributeValue("select");
 
2235
                XPathContext namespaces = getXPathContext(contextElement);
 
2236
                Node context = source.query(xpath).get(0);
 
2237
                
 
2238
                // process counts
 
2239
                Elements tests = contextElement.getChildElements("test");
 
2240
                for (int k = 0; k < tests.size(); k++) {
 
2241
                    Element test = tests.get(k);
 
2242
                    
 
2243
                    String select = test.getAttributeValue("select");
 
2244
                    Attribute countAttribute = test.getAttribute("count");
 
2245
                    int count = -1;
 
2246
                    if (countAttribute != null) {
 
2247
                        count = Integer.parseInt(countAttribute.getValue());
 
2248
                    }
 
2249
                    
 
2250
                    boolean exceptional = false;
 
2251
                    String exception = test.getAttributeValue("exception");
 
2252
                    if ("true".equals(exception)) {
 
2253
                        exceptional = true;
 
2254
                    }
 
2255
                    
 
2256
                    if (exceptional) {
 
2257
                        try {
 
2258
                            context.query(select, namespaces);
 
2259
                            fail("Evaluated " + select);
 
2260
                        }
 
2261
                        catch (XPathException success) {
 
2262
                            assertNotNull(success.getMessage());
 
2263
                        }
 
2264
                    }
 
2265
                    else {
 
2266
                        try {
 
2267
                            Nodes results = context.query(select, namespaces);
 
2268
                            if (count != -1) {
 
2269
                                assertEquals(select, count, results.size());
 
2270
                            }
 
2271
                            Elements valueOfs = test.getChildElements("valueOf");
 
2272
                            for (int v = 0; v < valueOfs.size(); v++) {
 
2273
                                Element vo = valueOfs.get(v);
 
2274
                                checkValueOf(results.get(0), vo, namespaces);
 
2275
                            }
 
2276
                        }
 
2277
                        catch (XPathException ex) {
 
2278
                            if (ex.getMessage().equalsIgnoreCase("XPath error: No such function document")
 
2279
                              || ex.getMessage().equalsIgnoreCase("XPath error: No such function evaluate")) {
 
2280
                                continue;
 
2281
                            }
 
2282
                            throw ex;
 
2283
                        }
 
2284
 
 
2285
                    }
 
2286
                }
 
2287
                
 
2288
                // process valueOfs
 
2289
                Elements valueOfs = contextElement.getChildElements("valueOf");
 
2290
                for (int k = 0; k < valueOfs.size(); k++) {
 
2291
                    checkValueOf(context, valueOfs.get(k), namespaces);
 
2292
                }
 
2293
                
 
2294
            }
 
2295
        }
 
2296
    }
 
2297
 
 
2298
 
 
2299
    private void checkValueOf(Node context, Element valueOf, XPathContext namespaces) {
 
2300
 
 
2301
        String select = valueOf.getAttributeValue("select");
 
2302
        try {
 
2303
            Nodes nodes = context.query(select, namespaces);
 
2304
            String result = nodes.get(0).getValue();
 
2305
            assertEquals(valueOf.getValue(), result);
 
2306
        }
 
2307
        catch (XPathTypeException ex) {
 
2308
            assertNotNull(ex.getMessage());
 
2309
        }
 
2310
        catch (XPathException ex) {
 
2311
            if (ex.getMessage().equalsIgnoreCase("XPath error: No such function document")
 
2312
              || ex.getMessage().equalsIgnoreCase("XPath error: No such function upper-case")
 
2313
              || ex.getMessage().equalsIgnoreCase("XPath error: No such function lower-case")              
 
2314
              || ex.getMessage().equalsIgnoreCase("XPath error: No such function ends-with")              
 
2315
            ) {
 
2316
                return;
 
2317
            }
 
2318
            throw ex;
 
2319
        }
 
2320
        
 
2321
    }
 
2322
 
 
2323
 
 
2324
    private XPathContext getXPathContext(Element contextElement) {
 
2325
 
 
2326
        XPathContext context = new XPathContext();
 
2327
        for (int i = 0; i < contextElement.getNamespaceDeclarationCount(); i++) {
 
2328
            String prefix = contextElement.getNamespacePrefix(i);
 
2329
            if (! "".equals(prefix)) {
 
2330
                context.addNamespace(prefix, contextElement.getNamespaceURI(prefix));
 
2331
            }
 
2332
        }
 
2333
        return context;
 
2334
    }
 
2335
 
 
2336
 
 
2337
    private boolean queryUsesVars(Element testElement) {
 
2338
 
 
2339
        for (int i = 0; i < testElement.getAttributeCount(); i++) {
 
2340
            Attribute a = testElement.getAttribute(i);
 
2341
            if ("http://jaxen.org/test-harness/var".equals(a.getNamespaceURI())) {
 
2342
                return true;
 
2343
            }
 
2344
        }
 
2345
        return false;
 
2346
    }
 
2347
    
 
2348
    
 
2349
    public void testTextChildInPredicate() {
 
2350
        
 
2351
        Element item = new Element("item");
 
2352
        Document doc = new Document(item);
 
2353
        Element name = new Element("name");
 
2354
        name.appendChild("a");
 
2355
        item.appendChild(name);
 
2356
        Element value = new Element("value");
 
2357
        value.appendChild("b");
 
2358
        item.appendChild(value);
 
2359
        Nodes result = doc.query("/item[name/text()='a']/value");
 
2360
        assertEquals(1, result.size());
 
2361
        assertEquals("b", result.get(0).getValue());
 
2362
        
 
2363
    }
 
2364
 
 
2365
    
 
2366
    public void testSimpleTextChildInPredicate() {
 
2367
        
 
2368
        Element item = new Element("item");
 
2369
        Document doc = new Document(item);
 
2370
        item.appendChild("a");
 
2371
        Nodes result = doc.query("/item[text()='a']");
 
2372
        assertEquals(1, result.size());
 
2373
        
 
2374
    }
 
2375
    
 
2376
    
 
2377
    public void testPrecedingAxisInDocumentOrder() {
 
2378
    
 
2379
        Element root = new Element("root");
 
2380
        new Document(root);
 
2381
        
 
2382
        Element a = new Element("a");
 
2383
        root.appendChild(a);
 
2384
        Element b = new Element("b");
 
2385
        root.appendChild(b);
 
2386
        Element c = new Element("c");
 
2387
        a.appendChild(c);
 
2388
        
 
2389
        Nodes result = b.query("preceding::*");
 
2390
        assertEquals(2, result.size());
 
2391
        assertEquals(a, result.get(0));
 
2392
        assertEquals(c, result.get(1));
 
2393
        
 
2394
    }
 
2395
    
 
2396
    
 
2397
    public void testAttributeWithUnderscore() {
 
2398
     
 
2399
        Element a = new Element("a");
 
2400
        Attribute foo = new Attribute("_foo", "bar");
 
2401
        a.addAttribute(foo);
 
2402
        Nodes results = a.query("//@_foo");
 
2403
        assertEquals(1, results.size());
 
2404
        assertEquals(foo, results.get(0));
 
2405
        
 
2406
    }
 
2407
    
 
2408
    
 
2409
}