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