3 <script src=
"../../../resources/js-test.js"></script>
4 <script src=
"../xpath-test-pre.js"></script>
7 <div id=
"console"></div>
10 var doc
= (new DOMParser
).parseFromString(
11 '<!DOCTYPE doc [<!ATTLIST item identifier ID #IMPLIED>]>' +
13 '<item id="1" identifier="a" />' +
14 '<item id="2" identifier="b" />' +
15 '<item id="3" identifier="c" />' +
16 '<item id="4" identifier="d" />' +
17 '<item id="5" identifier="e" />' +
18 '<reference>a</reference>' +
19 '<reference>c</reference>' +
20 '<reference>e</reference>' +
21 '<namespace xmlns="http://www.example.com/a" xmlns:b="http://www.example.com/b">' +
23 '<b:item id="7" b:value="42" />' +
28 var ROOT
= doc
.documentElement
;
29 var ITEM1
= ROOT
.firstChild
;
30 var ITEM2
= ITEM1
.nextSibling
;
31 var ITEM3
= ITEM2
.nextSibling
;
32 var ITEM4
= ITEM3
.nextSibling
;
33 var ITEM5
= ITEM4
.nextSibling
;
34 var REFA
= ITEM5
.nextSibling
;
35 var REFC
= REFA
.nextSibling
;
36 var REFE
= REFC
.nextSibling
;
37 var NAMESPACE
= REFE
.nextSibling
;
38 var ITEM6
= NAMESPACE
.firstChild
;
39 var ITEM7
= ITEM6
.nextSibling
;
41 test(doc
, ROOT
, '//item[@id=last()]', [ITEM5
]);
42 test(doc
, ROOT
, '//item[position()=3]', [ITEM3
]);
43 test(doc
, ROOT
, 'count(//item)', 5);
44 test(doc
, ROOT
, 'id("c")', [ITEM3
]);
45 test(doc
, ROOT
, 'id(//reference)', [ITEM1
, ITEM3
, ITEM5
]);
46 // The below test is wrong, it has an invalid expression.
47 //test(doc, ROOT, '//reference/id("a")', [ITEM1]);
48 // Several tests below originally used predicates with an abbreviated step, which is formally invalid, see <https://bugs.webkit.org/show_bug.cgi?id=12632>.
49 test(doc
, ROOT
, 'local-name(//self::node()[@id=7])', 'item');
50 test(doc
, ROOT
, 'number(//self::node()[@id=7]/attribute::*[local-name()="value"])', 42);
51 test(doc
, ROOT
, 'local-name(/absent)', '');
52 test(doc
, ROOT
, 'namespace-uri(//self::node()[@id>5])', 'http://www.example.com/a');
53 test(doc
, ROOT
, '//self::node()[@id and namespace-uri()="http://www.example.com/b"]', [ITEM7
]);
54 test(doc
, ROOT
, 'namespace-uri(/absent)', '');
55 test(doc
, ROOT
, 'name(//self::node()[@id=7])', 'b:item');
56 test(doc
, ROOT
, '//self::node()[name()="b:item"]', [ITEM7
]);
57 test(doc
, ROOT
, 'name(/absent)', '');
60 doc
= (new DOMParser
).parseFromString(
62 '<para id="1">One</para>' +
63 '<para id="2">Two</para>' +
64 '<para id="3">Three</para>' +
71 var ROOT
= doc
.documentElement
;
72 var PARA1
= ROOT
.firstChild
;
73 var PARA2
= PARA1
.nextSibling
;
74 var PARA3
= PARA2
.nextSibling
;
75 var PARA4
= PARA3
.nextSibling
;
77 test(doc
, doc
, 'string(//para)', 'One');
78 test(doc
, doc
, 'string(//inconceivable)', '');
79 test(doc
, doc
, 'string(0 div 0)', 'NaN');
80 test(doc
, doc
, 'string(1 div 0)', 'Infinity');
81 test(doc
, doc
, 'string(-1 div 0)', '-Infinity');
82 test(doc
, doc
, 'string(2.5 * 2)', '5');
83 test(doc
, doc
, 'string(1 div -2)', '-0.5');
84 test(doc
, doc
, 'string(1 = 2)', 'false');
85 test(doc
, doc
, 'string("string")', 'string');
86 test(doc
, doc
, '//para[string()="Two"]', [PARA2
]);
87 test(doc
, doc
, 'concat(//para, ":", //para[2])', 'One:Two');
88 test(doc
, doc
, 'starts-with("foo-bar", "foo")', true);
89 test(doc
, doc
, 'starts-with("foo-bar", "bar")', false);
90 test(doc
, doc
, 'contains("foo-bar", "o-b")', true);
91 test(doc
, doc
, 'contains("foo-bar", "b-o")', false);
92 test(doc
, doc
, 'substring-before("foo::bar", "::")', 'foo');
93 test(doc
, doc
, 'substring-before("foo::bar", "--")', '');
94 test(doc
, doc
, 'substring-after("foo::bar", "::")', 'bar');
95 test(doc
, doc
, 'substring-after("foo::bar", "--")', '');
96 test(doc
, doc
, 'substring("12345", 2)', '2345');
97 test(doc
, doc
, 'substring("12345", 2, 3)', '234');
98 test(doc
, doc
, 'substring("12345", 1.5, 2.6)', '234');
99 test(doc
, doc
, 'substring("12345", 0, 3)', '12');
100 test(doc
, doc
, 'substring("12345", 0 div 0, 3)', '');
101 test(doc
, doc
, 'substring("12345", 1, 0 div 0)', '');
102 test(doc
, doc
, 'substring("12345", -42, 1 div 0)', '12345');
103 test(doc
, doc
, 'substring("12345", -1 div 0, 1 div 0)', '');
104 test(doc
, doc
, 'substring("12345", 6, 1)', '');
105 test(doc
, doc
, 'substring("12345", 1, 0)', '');
106 test(doc
, doc
, 'string-length("12345")', 5);
107 test(doc
, doc
, '//para[string-length()=5]', [PARA3
]);
108 test(doc
, doc
, 'normalize-space(" one two ")', 'one two');
109 test(doc
, doc
, '//para[normalize-space() = "Four"]', [PARA4
]);
110 test(doc
, doc
, 'translate("abcdef", "abcde", "xyz")', 'xyzf');
112 doc
= (new DOMParser
).parseFromString(
115 '<para id="2" xml:lang="en">' +
118 '<section id="4" xml:lang="jp">' +
123 '<para id="6" xml:lang="EN">' +
126 '<para id="7" xml:lang="en-us">' +
129 '<para id="8" xml:lang="EN-UK">' +
135 var ROOT
= doc
.documentElement
;
136 var PARA1
= ROOT
.firstChild
;
137 var PARA2
= PARA1
.nextSibling
;
138 var ITEM3
= PARA2
.firstChild
;
139 var SECTION4
= ITEM3
.nextSibling
.nextSibling
;
140 var ITEM5
= SECTION4
.firstChild
;
141 var PARA6
= PARA2
.nextSibling
;
142 var PARA7
= PARA6
.nextSibling
;
143 var PARA8
= PARA7
.nextSibling
;
145 test(doc
, doc
, 'boolean(1)', true);
146 test(doc
, doc
, 'boolean(0)', false);
147 test(doc
, doc
, 'boolean(0 div 0)', false);
148 test(doc
, doc
, 'boolean(cod)', false);
149 test(doc
, doc
, 'boolean(doc)', true);
150 test(doc
, doc
, 'boolean("")', false);
151 test(doc
, doc
, 'boolean("foo")', true);
152 test(doc
, doc
, 'not(1 = 1)', false);
153 test(doc
, doc
, 'true()', true);
154 test(doc
, doc
, 'false()', false);
155 test(doc
, doc
, '//*[lang("en")]', [PARA2
, ITEM3
, PARA6
, PARA7
, PARA8
]);
156 test(doc
, doc
, '//*[lang("EN-US")]', [PARA7
]);
157 test(doc
, doc
, 'normalize-space((//text()[lang("jp")])[normalize-space()])', 'Nihongo');
159 doc
= (new DOMParser
).parseFromString(
167 test(doc
, doc
, 'string(number("-1e5"))', 'NaN'); // This test originally checked for successful parsing, but -1e5 is not a valid XPath number.
168 test(doc
, doc
, 'number(true())', 1);
169 test(doc
, doc
, 'number(false())', 0);
170 test(doc
, doc
, 'number(//item)', 1);
171 test(doc
, doc
, 'string(//item[number()=4 div 2])', '2');
172 test(doc
, doc
, 'sum(//item)', 6);
173 test(doc
, doc
, 'floor(1.99)', 1);
174 test(doc
, doc
, 'floor(-1.99)', -2);
175 test(doc
, doc
, 'ceiling(1.99)', 2);
176 test(doc
, doc
, 'ceiling(-1.99)', -1);
177 test(doc
, doc
, 'round(1.5)', 2);
178 test(doc
, doc
, 'round(-1.5)', -1);
179 test(doc
, doc
, 'string(round(0 div 0))', 'NaN');
180 test(doc
, doc
, 'round(1 div 0)', 1 / 0);
181 test(doc
, doc
, 'round(-1 div 0)', -1 / 0);
183 // The below tests are added for WebKit to complement the -1e5 test above.
184 test(doc
, doc
, 'number(".1")', 0.1);
185 test(doc
, doc
, 'number("1.")', 1);
186 test(doc
, doc
, 'string(number(".1."))', 'NaN');
187 test(doc
, doc
, 'string(number("..1"))', 'NaN');
188 test(doc
, doc
, 'string(number("1.."))', 'NaN');
189 test(doc
, doc
, 'string(number(".-1"))', 'NaN');