1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri.model;
18
19 import org.apache.commons.jxpath.AbstractFactory;
20 import org.apache.commons.jxpath.IdentityManager;
21 import org.apache.commons.jxpath.JXPathContext;
22 import org.apache.commons.jxpath.JXPathException;
23 import org.apache.commons.jxpath.JXPathTestCase;
24 import org.apache.commons.jxpath.Pointer;
25 import org.apache.commons.jxpath.Variables;
26 import org.apache.commons.jxpath.xml.DocumentContainer;
27
28
29
30
31
32
33
34
35
36
37 public abstract class XMLModelTestCase extends JXPathTestCase {
38 protected JXPathContext context;
39
40 public void setUp() {
41 if (context == null) {
42 DocumentContainer docCtr = createDocumentContainer();
43 context = createContext();
44 Variables vars = context.getVariables();
45 vars.declareVariable("document", docCtr.getValue());
46 vars.declareVariable("container", docCtr);
47 vars.declareVariable("element", context.getPointer("vendor/location/address/street").getNode());
48 }
49 }
50
51 protected abstract String getModel();
52
53 protected DocumentContainer createDocumentContainer() {
54 return new DocumentContainer(
55 JXPathTestCase.class.getResource("Vendor.xml"),
56 getModel());
57 }
58
59 protected abstract AbstractFactory getAbstractFactory();
60
61 protected JXPathContext createContext() {
62 JXPathContext context =
63 JXPathContext.newContext(createDocumentContainer());
64 context.setFactory(getAbstractFactory());
65 context.registerNamespace("product", "productNS");
66 return context;
67 }
68
69
70
71
72
73
74 protected abstract String getXMLSignature(
75 Object node,
76 boolean elements,
77 boolean attributes,
78 boolean text,
79 boolean pi);
80
81 protected void assertXMLSignature(
82 JXPathContext context,
83 String path,
84 String signature,
85 boolean elements,
86 boolean attributes,
87 boolean text,
88 boolean pi)
89 {
90 Object node = context.getPointer(path).getNode();
91 String sig = getXMLSignature(node, elements, attributes, text, pi);
92 assertEquals("XML Signature mismatch: ", signature, sig);
93 }
94
95
96
97 public void testDocumentOrder() {
98 assertDocumentOrder(
99 context,
100 "vendor/location",
101 "vendor/location/address/street",
102 -1);
103
104 assertDocumentOrder(
105 context,
106 "vendor/location[@id = '100']",
107 "vendor/location[@id = '101']",
108 -1);
109
110 assertDocumentOrder(
111 context,
112 "vendor//price:amount",
113 "vendor/location",
114 1);
115 }
116
117
118 public void testSetValue() {
119 assertXPathSetValue(
120 context,
121 "vendor/location[@id = '100']",
122 "New Text");
123
124 assertXMLSignature(
125 context,
126 "vendor/location[@id = '100']",
127 "<E>New Text</E>",
128 false,
129 false,
130 true,
131 false);
132
133 assertXPathSetValue(
134 context,
135 "vendor/location[@id = '101']",
136 "Replacement Text");
137
138 assertXMLSignature(
139 context,
140 "vendor/location[@id = '101']",
141 "<E>Replacement Text</E>",
142 false,
143 false,
144 true,
145 false);
146 }
147
148
149
150
151 public void testCreatePath() {
152
153 assertXPathCreatePath(
154 context,
155 "/vendor[1]/location[3]",
156 "",
157 "/vendor[1]/location[3]");
158
159
160 assertXPathCreatePath(
161 context,
162 "/vendor[1]/location[3]/address/street",
163 "",
164 "/vendor[1]/location[3]/address[1]/street[1]");
165
166
167 assertXPathCreatePath(
168 context,
169 "/vendor[1]/location[2]/@manager",
170 "",
171 "/vendor[1]/location[2]/@manager");
172
173 assertXPathCreatePath(
174 context,
175 "/vendor[1]/location[1]/@name",
176 "local",
177 "/vendor[1]/location[1]/@name");
178
179 assertXPathCreatePathAndSetValue(
180 context,
181 "/vendor[1]/location[4]/@manager",
182 "",
183 "/vendor[1]/location[4]/@manager");
184
185 context.registerNamespace("price", "priceNS");
186
187
188 assertXPathCreatePath(
189 context,
190 "/vendor[1]/price:foo/price:bar",
191 "",
192 "/vendor[1]/price:foo[1]/price:bar[1]");
193 }
194
195
196
197
198 public void testCreatePathAndSetValue() {
199
200 assertXPathCreatePathAndSetValue(
201 context,
202 "vendor/location[3]",
203 "",
204 "/vendor[1]/location[3]");
205
206
207 assertXPathCreatePathAndSetValue(
208 context,
209 "vendor/location[3]/address/street",
210 "Lemon Circle",
211 "/vendor[1]/location[3]/address[1]/street[1]");
212
213
214 assertXPathCreatePathAndSetValue(
215 context,
216 "vendor/location[2]/@manager",
217 "John Doe",
218 "/vendor[1]/location[2]/@manager");
219
220 assertXPathCreatePathAndSetValue(
221 context,
222 "vendor/location[1]/@manager",
223 "John Doe",
224 "/vendor[1]/location[1]/@manager");
225
226 assertXPathCreatePathAndSetValue(
227 context,
228 "/vendor[1]/location[4]/@manager",
229 "James Dow",
230 "/vendor[1]/location[4]/@manager");
231
232 assertXPathCreatePathAndSetValue(
233 context,
234 "vendor/product/product:name/attribute::price:language",
235 "English",
236 "/vendor[1]/product[1]/product:name[1]/@price:language");
237
238 context.registerNamespace("price", "priceNS");
239
240
241 assertXPathCreatePathAndSetValue(
242 context,
243 "/vendor[1]/price:foo/price:bar",
244 "123.20",
245 "/vendor[1]/price:foo[1]/price:bar[1]");
246 }
247
248
249
250
251 public void testRemovePath() {
252
253 context.removePath("vendor/location[@id = '101']//street/text()");
254 assertEquals(
255 "Remove DOM text",
256 "",
257 context.getValue("vendor/location[@id = '101']//street"));
258
259 context.removePath("vendor/location[@id = '101']//street");
260 assertEquals(
261 "Remove DOM element",
262 new Double(0),
263 context.getValue("count(vendor/location[@id = '101']//street)"));
264
265 context.removePath("vendor/location[@id = '100']/@name");
266 assertEquals(
267 "Remove DOM attribute",
268 new Double(0),
269 context.getValue("count(vendor/location[@id = '100']/@name)"));
270 }
271
272 public void testID() {
273 context.setIdentityManager(new IdentityManager() {
274 public Pointer getPointerByID(JXPathContext context, String id) {
275 NodePointer ptr = (NodePointer) context.getPointer("/");
276 ptr = ptr.getValuePointer();
277 return ptr.getPointerByID(context, id);
278 }
279 });
280
281 assertXPathValueAndPointer(
282 context,
283 "id(101)//street",
284 "Tangerine Drive",
285 "id('101')/address[1]/street[1]");
286
287 assertXPathPointerLenient(
288 context,
289 "id(105)/address/street",
290 "id(105)/address/street");
291 }
292
293 public void testAxisChild() {
294 assertXPathValue(
295 context,
296 "vendor/location/address/street",
297 "Orchard Road");
298
299
300 assertXPathValue(
301 context,
302 "vendor/location/address/city",
303 "Fruit Market");
304
305
306 assertXPathValue(
307 context,
308 "local-name(vendor/product/price:amount)",
309 "amount");
310
311
312 assertXPathValue(context, "local-name(vendor/location)", "location");
313
314
315 assertXPathValue(
316 context,
317 "name(vendor/product/price:amount)",
318 "value:amount");
319
320
321 assertXPathValue(
322 context,
323 "name(vendor/location)",
324 "location");
325
326
327 assertXPathValue(
328 context,
329 "namespace-uri(vendor/product/price:amount)",
330 "priceNS");
331
332
333 assertXPathValue(context, "vendor/product/prix", "934.99");
334
335 assertXPathValue(context, "/vendor/contact[@name='jim']", "Jim");
336
337 boolean nsv = false;
338 try {
339 context.setLenient(false);
340 context.getValue("/vendor/contact[@name='jane']");
341 }
342 catch (JXPathException ex) {
343 nsv = true;
344 }
345 assertTrue("No such value: /vendor/contact[@name='jim']", nsv);
346
347 nsv = false;
348 try {
349 context.setLenient(false);
350 context.getValue("/vendor/contact[@name='jane']/*");
351 }
352 catch (JXPathException ex) {
353 nsv = true;
354 }
355 assertTrue("No such value: /vendor/contact[@name='jane']/*", nsv);
356
357
358 assertXPathValue(
359 context,
360 "count(vendor/product/price:*)",
361 new Double(2));
362
363
364 assertXPathValue(context, "count(vendor/product/*)", new Double(4));
365
366
367 assertXPathValue(context, "vendor/product/price:amount", "45.95");
368
369
370 context.registerNamespace("x", "temp");
371 assertXPathValue(context, "vendor/x:pos//number", "109");
372 }
373
374 public void testAxisChildIndexPredicate() {
375 assertXPathValue(
376 context,
377 "vendor/location[2]/address/street",
378 "Tangerine Drive");
379 }
380
381 public void testAxisDescendant() {
382
383 assertXPathValue(context, "//street", "Orchard Road");
384
385
386 assertXPathValue(context, "count(//price:*)", new Double(2));
387
388 assertXPathValueIterator(context, "vendor//saleEnds", list("never"));
389
390 assertXPathValueIterator(context, "vendor//promotion", list(""));
391
392 assertXPathValueIterator(
393 context,
394 "vendor//saleEnds[../@stores = 'all']",
395 list("never"));
396
397 assertXPathValueIterator(
398 context,
399 "vendor//promotion[../@stores = 'all']",
400 list(""));
401 }
402
403
404
405
406
407
408
409
410 public void testAxisParent() {
411
412 assertXPathPointer(
413 context,
414 "//street/..",
415 "/vendor[1]/location[1]/address[1]");
416
417
418 assertXPathPointerIterator(
419 context,
420 "//street/..",
421 list(
422 "/vendor[1]/location[2]/address[1]",
423 "/vendor[1]/location[1]/address[1]"));
424
425
426 assertXPathValue(
427 context,
428 "vendor/product/price:sale/saleEnds/parent::price:*" + "/saleEnds",
429 "never");
430 }
431
432 public void testAxisFollowingSibling() {
433
434 assertXPathValue(
435 context,
436 "vendor/location[.//employeeCount = 10]/"
437 + "following-sibling::location//street",
438 "Tangerine Drive");
439
440
441 assertXPathPointer(
442 context,
443 "vendor/location[.//employeeCount = 10]/"
444 + "following-sibling::location//street",
445 "/vendor[1]/location[2]/address[1]/street[1]");
446 }
447
448 public void testAxisPrecedingSibling() {
449
450 assertXPathPointer(
451 context,
452 "//location[2]/preceding-sibling::location//street",
453 "/vendor[1]/location[1]/address[1]/street[1]");
454 }
455
456 public void testAxisPreceding() {
457
458 assertXPathPointer(
459 context,
460 "//location[2]/preceding-sibling::location//street",
461 "/vendor[1]/location[1]/address[1]/street[1]");
462 assertXPathPointer(context, "//location[2]/preceding::*[1]", "/vendor[1]/location[1]/employeeCount[1]");
463 assertXPathPointer(context, "//location[2]/preceding::node()[3]", "/vendor[1]/location[1]/employeeCount[1]/text()[1]");
464 assertXPathPointer(context, "//location[2]/preceding::node()[4]", "/vendor[1]/location[1]/employeeCount[1]");
465 }
466
467 public void testAxisAttribute() {
468
469 assertXPathValue(context, "vendor/location/@id", "100");
470
471
472 assertXPathPointer(
473 context,
474 "vendor/location/@id",
475 "/vendor[1]/location[1]/@id");
476
477
478 assertXPathValueIterator(
479 context,
480 "vendor/location/@id",
481 list("100", "101"));
482
483
484 assertXPathValue(
485 context,
486 "vendor/product/price:amount/@price:discount",
487 "10%");
488
489
490 assertXPathValue(
491 context,
492 "namespace-uri(vendor/product/price:amount/@price:discount)",
493 "priceNS");
494
495
496 assertXPathValue(
497 context,
498 "local-name(vendor/product/price:amount/@price:discount)",
499 "discount");
500
501
502 assertXPathValue(
503 context,
504 "name(vendor/product/price:amount/@price:discount)",
505 "price:discount");
506
507
508 assertXPathValue(
509 context,
510 "vendor/product/price:amount/@discount",
511 "20%");
512
513
514 assertXPathValue(
515 context,
516 "namespace-uri(vendor/product/price:amount/@discount)",
517 "");
518
519
520 assertXPathValue(
521 context,
522 "local-name(vendor/product/price:amount/@discount)",
523 "discount");
524
525
526 assertXPathValue(
527 context,
528 "name(vendor/product/price:amount/@discount)",
529 "discount");
530
531
532 assertXPathValueIterator(
533 context,
534 "vendor/product/price:amount/@price:*",
535 list("10%"));
536
537
538 assertXPathValueIterator(
539 context,
540 "vendor/location[1]/@*",
541 set("100", "", "local"));
542
543
544 assertXPathValueIterator(
545 context,
546 "vendor/product/price:amount/@*",
547
548 set("10%", "20%"));
549
550
551 assertXPathValueIterator(
552 context,
553 "vendor/product/price:amount/attribute::node()",
554
555 set("10%", "20%"));
556
557
558 assertXPathValueIterator(
559 context,
560 "vendor/product/price:amount/@*[namespace-uri() = '']",
561 list("20%"));
562
563
564 assertXPathValue(context, "vendor/location/@manager", "");
565
566
567 assertXPathValueLenient(context, "vendor/location/@missing", null);
568
569
570 assertXPathValueLenient(context, "vendor/location/@miss:missing", null);
571
572
573 assertXPathValue(
574 context,
575 "vendor/location[@id='101']//street",
576 "Tangerine Drive");
577
578 assertXPathValueIterator(
579 context,
580 "/vendor/location[1]/@*[name()!= 'manager']", list("100",
581 "local"));
582 }
583
584 public void testAxisNamespace() {
585
586 assertXPathValueAndPointer(
587 context,
588 "vendor/product/prix/namespace::price",
589 "priceNS",
590 "/vendor[1]/product[1]/prix[1]/namespace::price");
591
592
593 assertXPathValue(
594 context,
595 "count(vendor/product/namespace::*)",
596 new Double(3));
597
598
599 assertXPathValue(
600 context,
601 "name(vendor/product/prix/namespace::price)",
602 "price");
603
604
605 assertXPathValue(
606 context,
607 "local-name(vendor/product/prix/namespace::price)",
608 "price");
609 }
610
611 public void testAxisAncestor() {
612
613 assertXPathValue(
614 context,
615 "vendor/product/price:sale/saleEnds/"
616 + "ancestor::price:sale/saleEnds",
617 "never");
618
619
620 assertXPathValue(
621 context,
622 "vendor/product/price:sale/saleEnds/ancestor::price:*"
623 + "/saleEnds",
624 "never");
625 }
626
627 public void testAxisAncestorOrSelf() {
628
629 assertXPathValue(
630 context,
631 "vendor/product/price:sale/"
632 + "ancestor-or-self::price:sale/saleEnds",
633 "never");
634 }
635
636 public void testAxisFollowing() {
637 assertXPathValueIterator(
638 context,
639 "vendor/contact/following::location//street",
640 list("Orchard Road", "Tangerine Drive"));
641
642
643 assertXPathValue(
644 context,
645 "//location/following::price:sale/saleEnds",
646 "never");
647 assertXPathPointer(context, "//location[2]/following::node()[2]", "/vendor[1]/product[1]");
648 }
649
650 public void testAxisSelf() {
651
652 assertXPathValue(
653 context,
654 "//price:sale/self::price:sale/saleEnds",
655 "never");
656
657
658 assertXPathValueLenient(context, "//price:sale/self::x/saleEnds", null);
659 }
660
661 public void testNodeTypeComment() {
662
663 assertXPathValue(
664 context,
665 "//product/comment()",
666 "We are not buying this product, ever");
667 }
668
669 public void testNodeTypeText() {
670
671
672 assertXPathValue(
673 context,
674 "//product/text()[. != '']",
675 "We love this product.");
676
677
678 assertXPathPointer(
679 context,
680 "//product/text()",
681 "/vendor[1]/product[1]/text()[1]");
682
683 }
684
685 public void testNodeTypeProcessingInstruction() {
686
687 assertXPathValue(
688 context,
689 "//product/processing-instruction()",
690 "do not show anybody");
691
692
693 assertXPathValue(
694 context,
695 "//product/processing-instruction('report')",
696 "average only");
697
698
699 assertXPathPointer(
700 context,
701 "//product/processing-instruction('report')",
702 "/vendor[1]/product[1]/processing-instruction('report')[1]");
703
704
705 assertXPathValue(
706 context,
707 "name(//product/processing-instruction()[1])",
708 "security");
709 }
710
711 public void testLang() {
712
713 assertXPathValue(context, "//product/prix/@xml:lang", "fr");
714
715
716 assertXPathValue(context, "//product/prix[lang('fr')]", "934.99");
717
718
719 assertXPathValue(
720 context,
721 "//product/price:sale[lang('en')]/saleEnds",
722 "never");
723 }
724
725 public void testDocument() {
726 assertXPathValue(
727 context,
728 "$document/vendor/location[1]//street",
729 "Orchard Road");
730
731 assertXPathPointer(
732 context,
733 "$document/vendor/location[1]//street",
734 "$document/vendor[1]/location[1]/address[1]/street[1]");
735
736 assertXPathValue(context, "$document/vendor//street", "Orchard Road");
737 }
738
739 public void testContainer() {
740 assertXPathValue(context, "$container/vendor//street", "Orchard Road");
741
742 assertXPathValue(context, "$container//street", "Orchard Road");
743
744 assertXPathPointer(
745 context,
746 "$container//street",
747 "$container/vendor[1]/location[1]/address[1]/street[1]");
748
749
750 assertXPathValue(
751 context,
752 "number(vendor/location/employeeCount)",
753 new Double(10));
754 }
755
756 public void testElementInVariable() {
757 assertXPathValue(context, "$element", "Orchard Road");
758 }
759
760 public void testTypeConversions() {
761
762 assertXPathValue(
763 context,
764 "vendor/location/employeeCount + 1",
765 new Double(11));
766
767
768 assertXPathValue(
769 context,
770 "vendor/location/employeeCount and true()",
771 Boolean.TRUE);
772 }
773
774 public void testBooleanFunction() {
775 assertXPathValue(
776 context,
777 "boolean(vendor//saleEnds[../@stores = 'all'])",
778 Boolean.TRUE);
779
780 assertXPathValue(
781 context,
782 "boolean(vendor//promotion[../@stores = 'all'])",
783 Boolean.TRUE);
784
785 assertXPathValue(
786 context,
787 "boolean(vendor//promotion[../@stores = 'some'])",
788 Boolean.FALSE);
789 }
790
791 public void testFunctionsLastAndPosition() {
792 assertXPathPointer(
793 context,
794 "vendor//location[last()]",
795 "/vendor[1]/location[2]");
796 }
797
798 public void testNamespaceMapping() {
799 context.registerNamespace("rate", "priceNS");
800 context.registerNamespace("goods", "productNS");
801
802 assertEquals("Context node namespace resolution",
803 "priceNS",
804 context.getNamespaceURI("price"));
805
806 assertEquals("Registered namespace resolution",
807 "priceNS",
808 context.getNamespaceURI("rate"));
809
810
811 assertXPathValue(context,
812 "count(vendor/product/rate:*)",
813 new Double(2));
814
815 assertXPathValue(context,
816 "vendor[1]/product[1]/rate:amount[1]/@rate:discount", "10%");
817 assertXPathValue(context,
818 "vendor[1]/product[1]/rate:amount[1]/@price:discount", "10%");
819 assertXPathValue(context,
820 "vendor[1]/product[1]/price:amount[1]/@rate:discount", "10%");
821 assertXPathValue(context,
822 "vendor[1]/product[1]/price:amount[1]/@price:discount", "10%");
823
824
825 assertXPathValueAndPointer(context,
826 "//product:name",
827 "Box of oranges",
828 "/vendor[1]/product[1]/goods:name[1]");
829
830
831 JXPathContext childCtx =
832 JXPathContext.newContext(context, context.getContextBean());
833 assertXPathValueAndPointer(childCtx,
834 "//product:name",
835 "Box of oranges",
836 "/vendor[1]/product[1]/goods:name[1]");
837
838
839 JXPathContext relativeCtx =
840 context.getRelativeContext(context.getPointer("/vendor"));
841 assertXPathValueAndPointer(relativeCtx,
842 "product/product:name",
843 "Box of oranges",
844 "/vendor[1]/product[1]/goods:name[1]");
845 }
846
847 public void testUnion() {
848 assertXPathValue(context, "/vendor[1]/contact[1] | /vendor[1]/contact[4]", "John");
849 assertXPathValue(context, "/vendor[1]/contact[4] | /vendor[1]/contact[1]", "John");
850 }
851
852 public void testNodes() {
853 Pointer pointer = context.getPointer("/vendor[1]/contact[1]");
854 assertFalse(pointer.getNode().equals(pointer.getValue()));
855 }
856 }