1 /**
2 * Phoebe DOM Implementation.
3 *
4 * This is a C++ approximation of the W3C DOM model, which follows
5 * fairly closely the specifications in the various .idl files, copies of
6 * which are provided for reference. Most important is this one:
7 *
8 * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
9 *
10 * Authors:
11 * Bob Jamison
12 *
13 * Copyright (C) 2006 Bob Jamison
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
32 #include "dom.h"
33 #include "lsimpl.h"
34 #include "xpathparser.h"
36 #include <stdio.h>
39 typedef org::w3c::dom::Node Node;
40 typedef org::w3c::dom::NodeList NodeList;
41 typedef org::w3c::dom::DOMString DOMString;
42 typedef org::w3c::dom::Document Document;
43 typedef org::w3c::dom::io::StdWriter StdWriter;
44 typedef org::w3c::dom::ls::DOMImplementationLSImpl DOMImplementationLSImpl;
45 typedef org::w3c::dom::ls::LSSerializer LSSerializer;
46 typedef org::w3c::dom::ls::LSOutput LSOutput;
47 typedef org::w3c::dom::ls::LSInput LSInput;
48 typedef org::w3c::dom::ls::LSParser LSParser;
49 typedef org::w3c::dom::xpath::XPathParser XPathParser;
53 typedef struct
54 {
55 char *xpathStr;
56 char *desc;
57 char *xml;
58 } XpathTest;
60 XpathTest xpathTests[] =
61 {
63 {
64 "/AAA",
65 "Select the root element AAA",
66 " <AAA>\n"
67 " <BBB/>\n"
68 " <CCC/>\n"
69 " <BBB/>\n"
70 " <BBB/>\n"
71 " <DDD>\n"
72 " <BBB/>\n"
73 " </DDD>\n"
74 " <CCC/>\n"
75 " </AAA>\n"
76 },
78 {
79 "/AAA/CCC",
80 "Select all elements CCC which are children of the root element AAA",
81 " <AAA>\n"
82 " <BBB/>\n"
83 " <CCC/>\n"
84 " <BBB/>\n"
85 " <BBB/>\n"
86 " <DDD>\n"
87 " <BBB/>\n"
88 " </DDD>\n"
89 " <CCC/>\n"
90 " </AAA>\n"
91 },
93 {
94 "/AAA/DDD/BBB",
95 "Select all elements BBB which are children of DDD which are children of the root element AAA",
96 " <AAA>\n"
97 " <BBB/>\n"
98 " <CCC/>\n"
99 " <BBB/>\n"
100 " <BBB/>\n"
101 " <DDD>\n"
102 " <BBB/>\n"
103 " </DDD>\n"
104 " <CCC/>\n"
105 " </AAA>\n"
106 },
108 {
109 "//BBB",
110 "Select all elements BBB",
111 " <AAA>\n"
112 " <BBB/>\n"
113 " <CCC/>\n"
114 " <BBB/>\n"
115 " <DDD>\n"
116 " <BBB/>\n"
117 " </DDD>\n"
118 " <CCC>\n"
119 " <DDD>\n"
120 " <BBB/>\n"
121 " <BBB/>\n"
122 " </DDD>\n"
123 " </CCC>\n"
124 " </AAA>\n"
125 },
127 {
128 "//DDD/BBB",
129 "Select all elements BBB which are children of DDD",
130 " <AAA>\n"
131 " <BBB/>\n"
132 " <CCC/>\n"
133 " <BBB/>\n"
134 " <DDD>\n"
135 " <BBB/>\n"
136 " </DDD>\n"
137 " <CCC>\n"
138 " <DDD>\n"
139 " <BBB/>\n"
140 " <BBB/>\n"
141 " </DDD>\n"
142 " </CCC>\n"
143 " </AAA>\n"
144 },
146 {
147 "/AAA/CCC/DDD/*",
148 "Select all elements enclosed by elements /AAA/CCC/DDD",
149 " <AAA>\n"
150 " <XXX>\n"
151 " <DDD>\n"
152 " <BBB/>\n"
153 " <BBB/>\n"
154 " <EEE/>\n"
155 " <FFF/>\n"
156 " </DDD>\n"
157 " </XXX>\n"
158 " <CCC>\n"
159 " <DDD>\n"
160 " <BBB/>\n"
161 " <BBB/>\n"
162 " <EEE/>\n"
163 " <FFF/>\n"
164 " </DDD>\n"
165 " </CCC>\n"
166 " <CCC>\n"
167 " <BBB>\n"
168 " <BBB>\n"
169 " <BBB/>\n"
170 " </BBB>\n"
171 " </BBB>\n"
172 " </CCC>\n"
173 " </AAA>\n"
174 },
176 {
177 "/*/*/*/BBB",
178 "Select all elements BBB which have 3 ancestors",
179 " <AAA>\n"
180 " <XXX>\n"
181 " <DDD>\n"
182 " <BBB/>\n"
183 " <BBB/>\n"
184 " <EEE/>\n"
185 " <FFF/>\n"
186 " </DDD>\n"
187 " </XXX>\n"
188 " <CCC>\n"
189 " <DDD>\n"
190 " <BBB/>\n"
191 " <BBB/>\n"
192 " <EEE/>\n"
193 " <FFF/>\n"
194 " </DDD>\n"
195 " </CCC>\n"
196 " <CCC>\n"
197 " <BBB>\n"
198 " <BBB>\n"
199 " <BBB/>\n"
200 " </BBB>\n"
201 " </BBB>\n"
202 " </CCC>\n"
203 " </AAA>\n"
204 },
206 {
207 "//*",
208 "Select all elements",
209 " <AAA>\n"
210 " <XXX>\n"
211 " <DDD>\n"
212 " <BBB/>\n"
213 " <BBB/>\n"
214 " <EEE/>\n"
215 " <FFF/>\n"
216 " </DDD>\n"
217 " </XXX>\n"
218 " <CCC>\n"
219 " <DDD>\n"
220 " <BBB/>\n"
221 " <BBB/>\n"
222 " <EEE/>\n"
223 " <FFF/>\n"
224 " </DDD>\n"
225 " </CCC>\n"
226 " <CCC>\n"
227 " <BBB>\n"
228 " <BBB>\n"
229 " <BBB/>\n"
230 " </BBB>\n"
231 " </BBB>\n"
232 " </CCC>\n"
233 " </AAA>\n"
234 },
236 {
237 "/AAA/BBB[1]",
238 "Select the first BBB child of element AAA",
239 " <AAA>\n"
240 " <BBB/>\n"
241 " <BBB/>\n"
242 " <BBB/>\n"
243 " <BBB/>\n"
244 " </AAA>\n"
245 },
247 {
248 "/AAA/BBB[last()]",
249 "Select the last BBB child of element AAA",
250 " <AAA>\n"
251 " <BBB/>\n"
252 " <BBB/>\n"
253 " <BBB/>\n"
254 " <BBB/>\n"
255 " </AAA>\n"
256 },
258 {
259 "//@id",
260 "Select all attributes @id",
261 " <AAA>\n"
262 " <BBB id = 'b1'/>\n"
263 " <BBB id = 'b2'/>\n"
264 " <BBB name = 'bbb'/>\n"
265 " <BBB/>\n"
266 " </AAA>\n"
267 },
269 {
270 "//BBB[@id]",
271 "Select BBB elements which have attribute id",
272 " <AAA>\n"
273 " <BBB id = 'b1'/>\n"
274 " <BBB id = 'b2'/>\n"
275 " <BBB name = 'bbb'/>\n"
276 " <BBB/>\n"
277 " </AAA>\n"
278 },
280 {
281 "//BBB[@name]",
282 "Select BBB elements which have attribute name",
283 " <AAA>\n"
284 " <BBB id = 'b1'/>\n"
285 " <BBB id = 'b2'/>\n"
286 " <BBB name = 'bbb'/>\n"
287 " <BBB/>\n"
288 " </AAA>\n"
289 },
291 {
292 "//BBB[@*]",
293 "Select BBB elements which have any attribute",
294 " <AAA>\n"
295 " <BBB id = 'b1'/>\n"
296 " <BBB id = 'b2'/>\n"
297 " <BBB name = 'bbb'/>\n"
298 " <BBB/>\n"
299 " </AAA>\n"
300 },
302 {
303 "//BBB[not(@*)]",
304 "Select BBB elements without an attribute",
305 " <AAA>\n"
306 " <BBB id = 'b1'/>\n"
307 " <BBB id = 'b2'/>\n"
308 " <BBB name = 'bbb'/>\n"
309 " <BBB/>\n"
310 " </AAA>\n"
311 },
313 {
314 "//BBB[@id='b1']",
315 "Select BBB elements which have attribute id with value b1",
316 " <AAA>\n"
317 " <BBB id = 'b1'/>\n"
318 " <BBB name = ' bbb '/>\n"
319 " <BBB name = 'bbb'/>\n"
320 " </AAA>\n"
321 },
323 {
324 "//BBB[@name='bbb']",
325 "Select BBB elements which have attribute name with value 'bbb'",
326 " <AAA>\n"
327 " <BBB id = 'b1'/>\n"
328 " <BBB name = ' bbb '/>\n"
329 " <BBB name = 'bbb'/>\n"
330 " </AAA>\n"
331 },
333 {
334 "//BBB[normalize-space(@name)='bbb']",
335 "Select BBB elements which have attribute name with value bbb, leading and trailing spaces are removed before comparison",
336 " <AAA>\n"
337 " <BBB id = 'b1'/>\n"
338 " <BBB name = ' bbb '/>\n"
339 " <BBB name = 'bbb'/>\n"
340 " </AAA>\n"
341 },
343 {
344 "//*[count(BBB)=2]",
345 "Select elements which have two children BBB",
346 " <AAA>\n"
347 " <CCC>\n"
348 " <BBB/>\n"
349 " <BBB/>\n"
350 " <BBB/>\n"
351 " </CCC>\n"
352 " <DDD>\n"
353 " <BBB/>\n"
354 " <BBB/>\n"
355 " </DDD>\n"
356 " <EEE>\n"
357 " <CCC/>\n"
358 " <DDD/>\n"
359 " </EEE>\n"
360 " </AAA>\n"
361 },
363 {
364 "//*[count(*)=2]",
365 "Select elements which have 2 children",
366 " <AAA>\n"
367 " <CCC>\n"
368 " <BBB/>\n"
369 " <BBB/>\n"
370 " <BBB/>\n"
371 " </CCC>\n"
372 " <DDD>\n"
373 " <BBB/>\n"
374 " <BBB/>\n"
375 " </DDD>\n"
376 " <EEE>\n"
377 " <CCC/>\n"
378 " <DDD/>\n"
379 " </EEE>\n"
380 " </AAA>\n"
381 },
383 {
384 "//*[count(*)=3]",
385 "Select elements which have 3 children",
386 " <AAA>\n"
387 " <CCC>\n"
388 " <BBB/>\n"
389 " <BBB/>\n"
390 " <BBB/>\n"
391 " </CCC>\n"
392 " <DDD>\n"
393 " <BBB/>\n"
394 " <BBB/>\n"
395 " </DDD>\n"
396 " <EEE>\n"
397 " <CCC/>\n"
398 " <DDD/>\n"
399 " </EEE>\n"
400 " </AAA>\n"
401 },
403 {
404 "//*[name()='BBB']",
405 "Select all elements with name BBB, equivalent with //BBB",
406 " <AAA>\n"
407 " <BCC>\n"
408 " <BBB/>\n"
409 " <BBB/>\n"
410 " <BBB/>\n"
411 " </BCC>\n"
412 " <DDB>\n"
413 " <BBB/>\n"
414 " <BBB/>\n"
415 " </DDB>\n"
416 " <BEC>\n"
417 " <CCC/>\n"
418 " <DBD/>\n"
419 " </BEC>\n"
420 " </AAA>\n"
421 },
423 {
424 "//*[starts-with(name(),'B')]",
425 "Select all elements name of which starts with letter B",
426 " <AAA>\n"
427 " <BCC>\n"
428 " <BBB/>\n"
429 " <BBB/>\n"
430 " <BBB/>\n"
431 " </BCC>\n"
432 " <DDB>\n"
433 " <BBB/>\n"
434 " <BBB/>\n"
435 " </DDB>\n"
436 " <BEC>\n"
437 " <CCC/>\n"
438 " <DBD/>\n"
439 " </BEC>\n"
440 " </AAA>\n"
441 },
443 {
444 "//*[contains(name(),'C')]",
445 "Select all elements name of which contain letter C",
446 " <AAA>\n"
447 " <BCC>\n"
448 " <BBB/>\n"
449 " <BBB/>\n"
450 " <BBB/>\n"
451 " </BCC>\n"
452 " <DDB>\n"
453 " <BBB/>\n"
454 " <BBB/>\n"
455 " </DDB>\n"
456 " <BEC>\n"
457 " <CCC/>\n"
458 " <DBD/>\n"
459 " </BEC>\n"
460 " </AAA>\n"
461 },
463 {
464 "//*[string-length(name()) = 3]",
465 "Select elements with three-letter name",
466 " <AAA>\n"
467 " <Q/>\n"
468 " <SSSS/>\n"
469 " <BB/>\n"
470 " <CCC/>\n"
471 " <DDDDDDDD/>\n"
472 " <EEEE/>\n"
473 " </AAA>\n"
474 },
476 {
477 "//*[string-length(name()) < 3]",
478 "Select elements name of which has one or two characters",
479 " <AAA>\n"
480 " <Q/>\n"
481 " <SSSS/>\n"
482 " <BB/>\n"
483 " <CCC/>\n"
484 " <DDDDDDDD/>\n"
485 " <EEEE/>\n"
486 " </AAA>\n"
487 },
489 {
490 "//*[string-length(name()) > 3]",
491 "Select elements with name longer than three characters",
492 " <AAA>\n"
493 " <Q/>\n"
494 " <SSSS/>\n"
495 " <BB/>\n"
496 " <CCC/>\n"
497 " <DDDDDDDD/>\n"
498 " <EEEE/>\n"
499 " </AAA>\n"
500 },
502 {
503 "//CCC | //BBB",
504 "Select all elements CCC and BBB",
505 " <AAA>\n"
506 " <BBB/>\n"
507 " <CCC/>\n"
508 " <DDD>\n"
509 " <CCC/>\n"
510 " </DDD>\n"
511 " <EEE/>\n"
512 " </AAA>\n"
513 },
515 {
516 "/AAA/EEE | //BBB",
517 "Select all elements BBB and elements EEE which are children of root element AAA",
518 " <AAA>\n"
519 " <BBB/>\n"
520 " <CCC/>\n"
521 " <DDD>\n"
522 " <CCC/>\n"
523 " </DDD>\n"
524 " <EEE/>\n"
525 " </AAA>\n"
526 },
528 {
529 "/AAA/EEE | //DDD/CCC | /AAA | //BBB",
530 "Number of combinations is not restricted",
531 " <AAA>\n"
532 " <BBB/>\n"
533 " <CCC/>\n"
534 " <DDD>\n"
535 " <CCC/>\n"
536 " </DDD>\n"
537 " <EEE/>\n"
538 " </AAA>\n"
539 },
541 {
542 "/AAA",
543 "Equivalent of /child::AAA",
544 " <AAA>\n"
545 " <BBB/>\n"
546 " <CCC/>\n"
547 " </AAA>\n"
548 },
550 {
551 "/child::AAA",
552 "Equivalent of /AAA",
553 " <AAA>\n"
554 " <BBB/>\n"
555 " <CCC/>\n"
556 " </AAA>\n"
557 },
559 {
560 "/AAA/BBB",
561 "Equivalent of /child::AAA/child::BBB",
562 " <AAA>\n"
563 " <BBB/>\n"
564 " <CCC/>\n"
565 " </AAA>\n"
566 },
568 {
569 "/child::AAA/child::BBB",
570 "Equivalent of /AAA/BBB",
571 " <AAA>\n"
572 " <BBB/>\n"
573 " <CCC/>\n"
574 " </AAA>\n"
575 },
577 {
578 "/child::AAA/BBB",
579 "Both possibilities can be combined",
580 " <AAA>\n"
581 " <BBB/>\n"
582 " <CCC/>\n"
583 " </AAA>\n"
584 },
586 {
587 "/descendant::*",
588 "Select all descendants of document root and therefore all elements",
589 " <AAA>\n"
590 " <BBB>\n"
591 " <DDD>\n"
592 " <CCC>\n"
593 " <DDD/>\n"
594 " <EEE/>\n"
595 " </CCC>\n"
596 " </DDD>\n"
597 " </BBB>\n"
598 " <CCC>\n"
599 " <DDD>\n"
600 " <EEE>\n"
601 " <DDD>\n"
602 " <FFF/>\n"
603 " </DDD>\n"
604 " </EEE>\n"
605 " </DDD>\n"
606 " </CCC>\n"
607 " </AAA>\n"
608 },
610 {
611 "/AAA/BBB/descendant::*",
612 "Select all descendants of /AAA/BBB",
613 " <AAA>\n"
614 " <BBB>\n"
615 " <DDD>\n"
616 " <CCC>\n"
617 " <DDD/>\n"
618 " <EEE/>\n"
619 " </CCC>\n"
620 " </DDD>\n"
621 " </BBB>\n"
622 " <CCC>\n"
623 " <DDD>\n"
624 " <EEE>\n"
625 " <DDD>\n"
626 " <FFF/>\n"
627 " </DDD>\n"
628 " </EEE>\n"
629 " </DDD>\n"
630 " </CCC>\n"
631 " </AAA>\n"
632 },
634 {
635 "//CCC/descendant::*",
636 "Select all elements which have CCC among its ancestors",
637 " <AAA>\n"
638 " <BBB>\n"
639 " <DDD>\n"
640 " <CCC>\n"
641 " <DDD/>\n"
642 " <EEE/>\n"
643 " </CCC>\n"
644 " </DDD>\n"
645 " </BBB>\n"
646 " <CCC>\n"
647 " <DDD>\n"
648 " <EEE>\n"
649 " <DDD>\n"
650 " <FFF/>\n"
651 " </DDD>\n"
652 " </EEE>\n"
653 " </DDD>\n"
654 " </CCC>\n"
655 " </AAA>\n"
656 },
658 {
659 "//CCC/descendant::DDD",
660 "Select elements DDD which have CCC among its ancestors",
661 " <AAA>\n"
662 " <BBB>\n"
663 " <DDD>\n"
664 " <CCC>\n"
665 " <DDD/>\n"
666 " <EEE/>\n"
667 " </CCC>\n"
668 " </DDD>\n"
669 " </BBB>\n"
670 " <CCC>\n"
671 " <DDD>\n"
672 " <EEE>\n"
673 " <DDD>\n"
674 " <FFF/>\n"
675 " </DDD>\n"
676 " </EEE>\n"
677 " </DDD>\n"
678 " </CCC>\n"
679 " </AAA>\n"
680 },
682 {
683 "//DDD/parent::*",
684 "Select all parents of DDD element",
685 " <AAA>\n"
686 " <BBB>\n"
687 " <DDD>\n"
688 " <CCC>\n"
689 " <DDD/>\n"
690 " <EEE/>\n"
691 " </CCC>\n"
692 " </DDD>\n"
693 " </BBB>\n"
694 " <CCC>\n"
695 " <DDD>\n"
696 " <EEE>\n"
697 " <DDD>\n"
698 " <FFF/>\n"
699 " </DDD>\n"
700 " </EEE>\n"
701 " </DDD>\n"
702 " </CCC>\n"
703 " </AAA>\n"
704 },
706 {
707 "/AAA/BBB/DDD/CCC/EEE/ancestor::*",
708 "Select all elements given in this absolute path",
709 " <AAA>\n"
710 " <BBB>\n"
711 " <DDD>\n"
712 " <CCC>\n"
713 " <DDD/>\n"
714 " <EEE/>\n"
715 " </CCC>\n"
716 " </DDD>\n"
717 " </BBB>\n"
718 " <CCC>\n"
719 " <DDD>\n"
720 " <EEE>\n"
721 " <DDD>\n"
722 " <FFF/>\n"
723 " </DDD>\n"
724 " </EEE>\n"
725 " </DDD>\n"
726 " </CCC>\n"
727 " </AAA>\n"
728 },
730 {
731 "//FFF/ancestor::*",
732 "Select ancestors of FFF element",
733 " <AAA>\n"
734 " <BBB>\n"
735 " <DDD>\n"
736 " <CCC>\n"
737 " <DDD/>\n"
738 " <EEE/>\n"
739 " </CCC>\n"
740 " </DDD>\n"
741 " </BBB>\n"
742 " <CCC>\n"
743 " <DDD>\n"
744 " <EEE>\n"
745 " <DDD>\n"
746 " <FFF/>\n"
747 " </DDD>\n"
748 " </EEE>\n"
749 " </DDD>\n"
750 " </CCC>\n"
751 " </AAA>\n"
752 },
754 {
755 "/AAA/BBB/following-sibling::*",
756 "The following-sibling axis contains all the following siblings of the context node.",
757 " <AAA>\n"
758 " <BBB>\n"
759 " <CCC/>\n"
760 " <DDD/>\n"
761 " </BBB>\n"
762 " <XXX>\n"
763 " <DDD>\n"
764 " <EEE/>\n"
765 " <DDD/>\n"
766 " <CCC/>\n"
767 " <FFF/>\n"
768 " <FFF>\n"
769 " <GGG/>\n"
770 " </FFF>\n"
771 " </DDD>\n"
772 " </XXX>\n"
773 " <CCC>\n"
774 " <DDD/>\n"
775 " </CCC>\n"
776 " </AAA>\n"
777 },
779 {
780 "//CCC/following-sibling::*",
781 "The following-sibling axis contains all the following siblings of the context node.",
782 " <AAA>\n"
783 " <BBB>\n"
784 " <CCC/>\n"
785 " <DDD/>\n"
786 " </BBB>\n"
787 " <XXX>\n"
788 " <DDD>\n"
789 " <EEE/>\n"
790 " <DDD/>\n"
791 " <CCC/>\n"
792 " <FFF/>\n"
793 " <FFF>\n"
794 " <GGG/>\n"
795 " </FFF>\n"
796 " </DDD>\n"
797 " </XXX>\n"
798 " <CCC>\n"
799 " <DDD/>\n"
800 " </CCC>\n"
801 " </AAA>\n"
802 },
804 {
805 "/AAA/XXX/preceding-sibling::*",
806 "The preceding-sibling axis contains all the preceding siblings of the context node.",
807 " <AAA>\n"
808 " <BBB>\n"
809 " <CCC/>\n"
810 " <DDD/>\n"
811 " </BBB>\n"
812 " <XXX>\n"
813 " <DDD>\n"
814 " <EEE/>\n"
815 " <DDD/>\n"
816 " <CCC/>\n"
817 " <FFF/>\n"
818 " <FFF>\n"
819 " <GGG/>\n"
820 " </FFF>\n"
821 " </DDD>\n"
822 " </XXX>\n"
823 " <CCC>\n"
824 " <DDD/>\n"
825 " </CCC>\n"
826 " </AAA>\n"
827 },
829 {
830 "//CCC/preceding-sibling::*",
831 "The preceding-sibling axis contains all the preceding siblings of the context node",
832 " <AAA>\n"
833 " <BBB>\n"
834 " <CCC/>\n"
835 " <DDD/>\n"
836 " </BBB>\n"
837 " <XXX>\n"
838 " <DDD>\n"
839 " <EEE/>\n"
840 " <DDD/>\n"
841 " <CCC/>\n"
842 " <FFF/>\n"
843 " <FFF>\n"
844 " <GGG/>\n"
845 " </FFF>\n"
846 " </DDD>\n"
847 " </XXX>\n"
848 " <CCC>\n"
849 " <DDD/>\n"
850 " </CCC>\n"
851 " </AAA>\n"
852 },
854 {
855 "/AAA/XXX/following::*",
856 "The following axis contains all nodes in the same document as the context "
857 "node that are after the context node in document order, "
858 "excluding any descendants and excluding attribute nodes and namespace nodes.",
859 " <AAA>\n"
860 " <BBB>\n"
861 " <CCC/>\n"
862 " <ZZZ>\n"
863 " <DDD/>\n"
864 " <DDD>\n"
865 " <EEE/>\n"
866 " </DDD>\n"
867 " </ZZZ>\n"
868 " <FFF>\n"
869 " <GGG/>\n"
870 " </FFF>\n"
871 " </BBB>\n"
872 " <XXX>\n"
873 " <DDD>\n"
874 " <EEE/>\n"
875 " <DDD/>\n"
876 " <CCC/>\n"
877 " <FFF/>\n"
878 " <FFF>\n"
879 " <GGG/>\n"
880 " </FFF>\n"
881 " </DDD>\n"
882 " </XXX>\n"
883 " <CCC>\n"
884 " <DDD/>\n"
885 " </CCC>\n"
886 " </AAA>\n"
887 },
889 {
890 "//ZZZ/following::*",
891 "The following axis contains all nodes in the same document as the context "
892 "node that are after the context node in document order, "
893 "excluding any descendants and excluding attribute nodes and namespace nodes.",
894 " <AAA>\n"
895 " <BBB>\n"
896 " <CCC/>\n"
897 " <ZZZ>\n"
898 " <DDD/>\n"
899 " <DDD>\n"
900 " <EEE/>\n"
901 " </DDD>\n"
902 " </ZZZ>\n"
903 " <FFF>\n"
904 " <GGG/>\n"
905 " </FFF>\n"
906 " </BBB>\n"
907 " <XXX>\n"
908 " <DDD>\n"
909 " <EEE/>\n"
910 " <DDD/>\n"
911 " <CCC/>\n"
912 " <FFF/>\n"
913 " <FFF>\n"
914 " <GGG/>\n"
915 " </FFF>\n"
916 " </DDD>\n"
917 " </XXX>\n"
918 " <CCC>\n"
919 " <DDD/>\n"
920 " </CCC>\n"
921 " </AAA>\n"
922 },
924 {
925 "/AAA/XXX/preceding::*",
926 "The preceding axis contains all nodes in the same document as the "
927 "context node that are before the context node in document order, "
928 "excluding any ancestors and excluding attribute nodes and namespace nodes",
929 " <AAA>\n"
930 " <BBB>\n"
931 " <CCC/>\n"
932 " <ZZZ>\n"
933 " <DDD/>\n"
934 " </ZZZ>\n"
935 " </BBB>\n"
936 " <XXX>\n"
937 " <DDD>\n"
938 " <EEE/>\n"
939 " <DDD/>\n"
940 " <CCC/>\n"
941 " <FFF/>\n"
942 " <FFF>\n"
943 " <GGG/>\n"
944 " </FFF>\n"
945 " </DDD>\n"
946 " </XXX>\n"
947 " <CCC>\n"
948 " <DDD/>\n"
949 " </CCC>\n"
950 " </AAA>\n"
951 },
953 {
954 "//GGG/preceding::*",
955 "The preceding axis contains all nodes in the same document as the "
956 "context node that are before the context node in document order, "
957 "excluding any ancestors and excluding attribute nodes and namespace nodes",
958 " <AAA>\n"
959 " <BBB>\n"
960 " <CCC/>\n"
961 " <ZZZ>\n"
962 " <DDD/>\n"
963 " </ZZZ>\n"
964 " </BBB>\n"
965 " <XXX>\n"
966 " <DDD>\n"
967 " <EEE/>\n"
968 " <DDD/>\n"
969 " <CCC/>\n"
970 " <FFF/>\n"
971 " <FFF>\n"
972 " <GGG/>\n"
973 " </FFF>\n"
974 " </DDD>\n"
975 " </XXX>\n"
976 " <CCC>\n"
977 " <DDD/>\n"
978 " </CCC>\n"
979 " </AAA>\n"
980 },
982 {
983 "/AAA/XXX/descendant-or-self::*",
984 "The descendant-or-self axis contains the "
985 "context node and the descendants of the context node",
986 " <AAA>\n"
987 " <BBB>\n"
988 " <CCC/>\n"
989 " <ZZZ>\n"
990 " <DDD/>\n"
991 " </ZZZ>\n"
992 " </BBB>\n"
993 " <XXX>\n"
994 " <DDD>\n"
995 " <EEE/>\n"
996 " <DDD/>\n"
997 " <CCC/>\n"
998 " <FFF/>\n"
999 " <FFF>\n"
1000 " <GGG/>\n"
1001 " </FFF>\n"
1002 " </DDD>\n"
1003 " </XXX>\n"
1004 " <CCC>\n"
1005 " <DDD/>\n"
1006 " </CCC>\n"
1007 " </AAA>\n"
1008 },
1010 {
1011 "//CCC/descendant-or-self::*",
1012 "The descendant-or-self axis contains the "
1013 "context node and the descendants of the context node",
1014 " <AAA>\n"
1015 " <BBB>\n"
1016 " <CCC/>\n"
1017 " <ZZZ>\n"
1018 " <DDD/>\n"
1019 " </ZZZ>\n"
1020 " </BBB>\n"
1021 " <XXX>\n"
1022 " <DDD>\n"
1023 " <EEE/>\n"
1024 " <DDD/>\n"
1025 " <CCC/>\n"
1026 " <FFF/>\n"
1027 " <FFF>\n"
1028 " <GGG/>\n"
1029 " </FFF>\n"
1030 " </DDD>\n"
1031 " </XXX>\n"
1032 " <CCC>\n"
1033 " <DDD/>\n"
1034 " </CCC>\n"
1035 " </AAA>\n"
1036 },
1038 {
1039 "/AAA/XXX/DDD/EEE/ancestor-or-self::*",
1040 "The ancestor-or-self axis contains the context node and the "
1041 "ancestors of the context node; thus, the ancestor-or-self axis "
1042 "will always include the root node.",
1043 " <AAA>\n"
1044 " <BBB>\n"
1045 " <CCC/>\n"
1046 " <ZZZ>\n"
1047 " <DDD/>\n"
1048 " </ZZZ>\n"
1049 " </BBB>\n"
1050 " <XXX>\n"
1051 " <DDD>\n"
1052 " <EEE/>\n"
1053 " <DDD/>\n"
1054 " <CCC/>\n"
1055 " <FFF/>\n"
1056 " <FFF>\n"
1057 " <GGG/>\n"
1058 " </FFF>\n"
1059 " </DDD>\n"
1060 " </XXX>\n"
1061 " <CCC>\n"
1062 " <DDD/>\n"
1063 " </CCC>\n"
1064 " </AAA>\n"
1065 },
1067 {
1068 "//GGG/ancestor-or-self::*",
1069 "The ancestor-or-self axis contains the context node and the "
1070 "ancestors of the context node; thus, the ancestor-or-self axis "
1071 "will always include the root node.",
1072 " <AAA>\n"
1073 " <BBB>\n"
1074 " <CCC/>\n"
1075 " <ZZZ>\n"
1076 " <DDD/>\n"
1077 " </ZZZ>\n"
1078 " </BBB>\n"
1079 " <XXX>\n"
1080 " <DDD>\n"
1081 " <EEE/>\n"
1082 " <DDD/>\n"
1083 " <CCC/>\n"
1084 " <FFF/>\n"
1085 " <FFF>\n"
1086 " <GGG/>\n"
1087 " </FFF>\n"
1088 " </DDD>\n"
1089 " </XXX>\n"
1090 " <CCC>\n"
1091 " <DDD/>\n"
1092 " </CCC>\n"
1093 " </AAA>\n"
1094 },
1096 {
1097 "//GGG/ancestor::*",
1098 "The ancestor, descendant, following, preceding and self axes partition a document",
1099 " <AAA>\n"
1100 " <BBB>\n"
1101 " <CCC/>\n"
1102 " <ZZZ/>\n"
1103 " </BBB>\n"
1104 " <XXX>\n"
1105 " <DDD>\n"
1106 " <EEE/>\n"
1107 " <FFF>\n"
1108 " <HHH/>\n"
1109 " <GGG>\n"
1110 " <JJJ>\n"
1111 " <QQQ/>\n"
1112 " </JJJ>\n"
1113 " <JJJ/>\n"
1114 " </GGG>\n"
1115 " <HHH/>\n"
1116 " </FFF>\n"
1117 " </DDD>\n"
1118 " </XXX>\n"
1119 " <CCC>\n"
1120 " <DDD/>\n"
1121 " </CCC>\n"
1122 " </AAA>\n"
1123 },
1125 {
1126 "//GGG/descendant::*",
1127 "The ancestor, descendant, following, preceding and self axes partition a document",
1128 " <AAA>\n"
1129 " <BBB>\n"
1130 " <CCC/>\n"
1131 " <ZZZ/>\n"
1132 " </BBB>\n"
1133 " <XXX>\n"
1134 " <DDD>\n"
1135 " <EEE/>\n"
1136 " <FFF>\n"
1137 " <HHH/>\n"
1138 " <GGG>\n"
1139 " <JJJ>\n"
1140 " <QQQ/>\n"
1141 " </JJJ>\n"
1142 " <JJJ/>\n"
1143 " </GGG>\n"
1144 " <HHH/>\n"
1145 " </FFF>\n"
1146 " </DDD>\n"
1147 " </XXX>\n"
1148 " <CCC>\n"
1149 " <DDD/>\n"
1150 " </CCC>\n"
1151 " </AAA>\n"
1152 },
1154 {
1155 "//GGG/following::*",
1156 "The ancestor, descendant, following, preceding and self axes partition a document",
1157 " <AAA>\n"
1158 " <BBB>\n"
1159 " <CCC/>\n"
1160 " <ZZZ/>\n"
1161 " </BBB>\n"
1162 " <XXX>\n"
1163 " <DDD>\n"
1164 " <EEE/>\n"
1165 " <FFF>\n"
1166 " <HHH/>\n"
1167 " <GGG>\n"
1168 " <JJJ>\n"
1169 " <QQQ/>\n"
1170 " </JJJ>\n"
1171 " <JJJ/>\n"
1172 " </GGG>\n"
1173 " <HHH/>\n"
1174 " </FFF>\n"
1175 " </DDD>\n"
1176 " </XXX>\n"
1177 " <CCC>\n"
1178 " <DDD/>\n"
1179 " </CCC>\n"
1180 " </AAA>\n"
1181 },
1183 {
1184 "//GGG/preceding::*",
1185 "The ancestor, descendant, following, preceding and self axes partition a document",
1186 " <AAA>\n"
1187 " <BBB>\n"
1188 " <CCC/>\n"
1189 " <ZZZ/>\n"
1190 " </BBB>\n"
1191 " <XXX>\n"
1192 " <DDD>\n"
1193 " <EEE/>\n"
1194 " <FFF>\n"
1195 " <HHH/>\n"
1196 " <GGG>\n"
1197 " <JJJ>\n"
1198 " <QQQ/>\n"
1199 " </JJJ>\n"
1200 " <JJJ/>\n"
1201 " </GGG>\n"
1202 " <HHH/>\n"
1203 " </FFF>\n"
1204 " </DDD>\n"
1205 " </XXX>\n"
1206 " <CCC>\n"
1207 " <DDD/>\n"
1208 " </CCC>\n"
1209 " </AAA>\n"
1210 },
1212 {
1213 "//GGG/self::*",
1214 "The ancestor, descendant, following, preceding and self axes partition a document",
1215 " <AAA>\n"
1216 " <BBB>\n"
1217 " <CCC/>\n"
1218 " <ZZZ/>\n"
1219 " </BBB>\n"
1220 " <XXX>\n"
1221 " <DDD>\n"
1222 " <EEE/>\n"
1223 " <FFF>\n"
1224 " <HHH/>\n"
1225 " <GGG>\n"
1226 " <JJJ>\n"
1227 " <QQQ/>\n"
1228 " </JJJ>\n"
1229 " <JJJ/>\n"
1230 " </GGG>\n"
1231 " <HHH/>\n"
1232 " </FFF>\n"
1233 " </DDD>\n"
1234 " </XXX>\n"
1235 " <CCC>\n"
1236 " <DDD/>\n"
1237 " </CCC>\n"
1238 " </AAA>\n"
1239 },
1241 {
1242 "//GGG/ancestor::* | //GGG/descendant::* | //GGG/following::* | //GGG/preceding::* | //GGG/self::*",
1243 "The ancestor, descendant, following, preceding and self axes partition a document",
1244 " <AAA>\n"
1245 " <BBB>\n"
1246 " <CCC/>\n"
1247 " <ZZZ/>\n"
1248 " </BBB>\n"
1249 " <XXX>\n"
1250 " <DDD>\n"
1251 " <EEE/>\n"
1252 " <FFF>\n"
1253 " <HHH/>\n"
1254 " <GGG>\n"
1255 " <JJJ>\n"
1256 " <QQQ/>\n"
1257 " </JJJ>\n"
1258 " <JJJ/>\n"
1259 " </GGG>\n"
1260 " <HHH/>\n"
1261 " </FFF>\n"
1262 " </DDD>\n"
1263 " </XXX>\n"
1264 " <CCC>\n"
1265 " <DDD/>\n"
1266 " </CCC>\n"
1267 " </AAA>\n"
1268 },
1270 {
1271 "//BBB[position() mod 2 = 0 ]",
1272 "Select even BBB elements",
1273 " <AAA>\n"
1274 " <BBB/>\n"
1275 " <BBB/>\n"
1276 " <BBB/>\n"
1277 " <BBB/>\n"
1278 " <BBB/>\n"
1279 " <BBB/>\n"
1280 " <BBB/>\n"
1281 " <BBB/>\n"
1282 " <CCC/>\n"
1283 " <CCC/>\n"
1284 " <CCC/>\n"
1285 " </AAA>\n"
1286 },
1288 {
1289 "//BBB[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5) ]",
1290 "Select middle BBB element(s)",
1291 " <AAA>\n"
1292 " <BBB/>\n"
1293 " <BBB/>\n"
1294 " <BBB/>\n"
1295 " <BBB/>\n"
1296 " <BBB/>\n"
1297 " <BBB/>\n"
1298 " <BBB/>\n"
1299 " <BBB/>\n"
1300 " <CCC/>\n"
1301 " <CCC/>\n"
1302 " <CCC/>\n"
1303 " </AAA>\n"
1304 },
1306 {
1307 "//CCC[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5) ]",
1308 "Select middle CCC element(s)",
1309 " <AAA>\n"
1310 " <BBB/>\n"
1311 " <BBB/>\n"
1312 " <BBB/>\n"
1313 " <BBB/>\n"
1314 " <BBB/>\n"
1315 " <BBB/>\n"
1316 " <BBB/>\n"
1317 " <BBB/>\n"
1318 " <CCC/>\n"
1319 " <CCC/>\n"
1320 " <CCC/>\n"
1321 " </AAA>\n"
1322 },
1324 { //end data
1325 NULL,
1326 NULL,
1327 NULL,
1328 }
1330 };
1334 bool doStringTest(char *str)
1335 {
1336 XPathParser xp;
1337 xp.setDebug(true);
1339 if (!xp.parse(str))
1340 return false;
1343 return true;
1344 }
1348 bool doStringTests()
1349 {
1350 for (XpathTest *xpt = xpathTests ; xpt->xpathStr ; xpt++)
1351 {
1352 if (!doStringTest(xpt->xpathStr))
1353 return false;
1354 }
1355 return true;
1356 }
1358 void dumpDoc(Document *doc)
1359 {
1360 DOMImplementationLSImpl domImpl;
1361 LSSerializer &serializer = domImpl.createLSSerializer();
1362 LSOutput output = domImpl.createLSOutput();
1363 StdWriter writer;
1364 output.setCharacterStream(&writer);
1365 serializer.write(doc, output);
1366 }
1369 bool doXmlTest(XpathTest *xpt)
1370 {
1371 printf("################################################################\n");
1373 //### READ
1374 DOMImplementationLSImpl domImpl;
1375 LSInput input = domImpl.createLSInput();
1376 LSParser &parser = domImpl.createLSParser(0, "");
1377 input.setStringData(xpt->xml);
1378 Document *doc = parser.parse(input);
1380 //### XPATH
1381 XPathParser xp;
1382 xp.setDebug(true);
1384 DOMString xpathStr = xpt->xpathStr;
1385 NodeList list = xp.evaluate(doc, xpathStr);
1386 for (unsigned int i=0 ; i<list.getLength() ; i++)
1387 {
1388 Node *n = list.item(i);
1389 printf("@@ node: %s\n", n->getNodeName().c_str());
1390 }
1392 //dumpDoc(doc);
1394 delete doc;
1395 return true;
1396 }
1398 bool doXmlTests()
1399 {
1400 for (XpathTest *xpt = xpathTests ; xpt->xpathStr ; xpt++)
1401 {
1402 if (!doXmlTest(xpt))
1403 return false;
1404 }
1405 return true;
1406 }
1408 bool doTests()
1409 {
1410 /*
1411 if (!doStringTests())
1412 {
1413 printf("## Failed string tests\n");
1414 return false;
1415 }
1416 */
1417 if (!doXmlTests())
1418 {
1419 printf("## Failed xml tests\n");
1420 return false;
1421 }
1422 return true;
1423 }
1427 int main(int argc, char **argv)
1428 {
1429 doTests();
1430 return 0;
1431 }