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> 11 var 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 29 var ROOT = doc.documentElement; 30 var ITEM1 = ROOT.firstChild; 31 var ITEM2 = ITEM1.nextSibling; 32 var ITEM3 = ITEM2.nextSibling; 33 var ITEM4 = ITEM3.nextSibling; 34 var ITEM5 = ITEM4.nextSibling; 35 var REFA = ITEM5.nextSibling; 36 var REFC = REFA.nextSibling; 37 var REFE = REFC.nextSibling; 38 var NAMESPACE = REFE.nextSibling; 39 var ITEM6 = NAMESPACE.firstChild; 40 var ITEM7 = ITEM6.nextSibling; 41 42 test(doc, ROOT, '//item[@id=last()]', [ITEM5]); 43 test(doc, ROOT, '//item[position()=3]', [ITEM3]); 44 test(doc, ROOT, 'count(//item)', 5); 45 test(doc, ROOT, 'id("c")', [ITEM3]); 46 test(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>. 50 test(doc, ROOT, 'local-name(//self::node()[@id=7])', 'item'); 51 test(doc, ROOT, 'number(//self::node()[@id=7]/attribute::*[local-name()="value"])', 42); 52 test(doc, ROOT, 'local-name(/absent)', ''); 53 test(doc, ROOT, 'namespace-uri(//self::node()[@id>5])', 'http://www.example.com/a'); 54 test(doc, ROOT, '//self::node()[@id and namespace-uri()="http://www.example.com/b"]', [ITEM7]); 55 test(doc, ROOT, 'namespace-uri(/absent)', ''); 56 test(doc, ROOT, 'name(//self::node()[@id=7])', 'b:item'); 57 test(doc, ROOT, '//self::node()[name()="b:item"]', [ITEM7]); 58 test(doc, ROOT, 'name(/absent)', ''); 59 60 61 doc = (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 72 var ROOT = doc.documentElement; 73 var PARA1 = ROOT.firstChild; 74 var PARA2 = PARA1.nextSibling; 75 var PARA3 = PARA2.nextSibling; 76 var PARA4 = PARA3.nextSibling; 77 78 test(doc, doc, 'string(//para)', 'One'); 79 test(doc, doc, 'string(//inconceivable)', ''); 80 test(doc, doc, 'string(0 div 0)', 'NaN'); 81 test(doc, doc, 'string(1 div 0)', 'Infinity'); 82 test(doc, doc, 'string(-1 div 0)', '-Infinity'); 83 test(doc, doc, 'string(2.5 * 2)', '5'); 84 test(doc, doc, 'string(1 div -2)', '-0.5'); 85 test(doc, doc, 'string(1 = 2)', 'false'); 86 test(doc, doc, 'string("string")', 'string'); 87 test(doc, doc, '//para[string()="Two"]', [PARA2]); 88 test(doc, doc, 'concat(//para, ":", //para[2])', 'One:Two'); 89 test(doc, doc, 'starts-with("foo-bar", "foo")', true); 90 test(doc, doc, 'starts-with("foo-bar", "bar")', false); 91 test(doc, doc, 'contains("foo-bar", "o-b")', true); 92 test(doc, doc, 'contains("foo-bar", "b-o")', false); 93 test(doc, doc, 'substring-before("foo::bar", "::")', 'foo'); 94 test(doc, doc, 'substring-before("foo::bar", "--")', ''); 95 test(doc, doc, 'substring-after("foo::bar", "::")', 'bar'); 96 test(doc, doc, 'substring-after("foo::bar", "--")', ''); 97 test(doc, doc, 'substring("12345", 2)', '2345'); 98 test(doc, doc, 'substring("12345", 2, 3)', '234'); 99 test(doc, doc, 'substring("12345", 1.5, 2.6)', '234'); 100 test(doc, doc, 'substring("12345", 0, 3)', '12'); 101 test(doc, doc, 'substring("12345", 0 div 0, 3)', ''); 102 test(doc, doc, 'substring("12345", 1, 0 div 0)', ''); 103 test(doc, doc, 'substring("12345", -42, 1 div 0)', '12345'); 104 test(doc, doc, 'substring("12345", -1 div 0, 1 div 0)', ''); 105 test(doc, doc, 'substring("12345", 6, 1)', ''); 106 test(doc, doc, 'substring("12345", 1, 0)', ''); 107 test(doc, doc, 'string-length("12345")', 5); 108 test(doc, doc, '//para[string-length()=5]', [PARA3]); 109 test(doc, doc, 'normalize-space(" one two ")', 'one two'); 110 test(doc, doc, '//para[normalize-space() = "Four"]', [PARA4]); 111 test(doc, doc, 'translate("abcdef", "abcde", "xyz")', 'xyzf'); 112 113 doc = (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 136 var ROOT = doc.documentElement; 137 var PARA1 = ROOT.firstChild; 138 var PARA2 = PARA1.nextSibling; 139 var ITEM3 = PARA2.firstChild; 140 var SECTION4 = ITEM3.nextSibling.nextSibling; 141 var ITEM5 = SECTION4.firstChild; 142 var PARA6 = PARA2.nextSibling; 143 var PARA7 = PARA6.nextSibling; 144 var PARA8 = PARA7.nextSibling; 145 146 test(doc, doc, 'boolean(1)', true); 147 test(doc, doc, 'boolean(0)', false); 148 test(doc, doc, 'boolean(0 div 0)', false); 149 test(doc, doc, 'boolean(cod)', false); 150 test(doc, doc, 'boolean(doc)', true); 151 test(doc, doc, 'boolean("")', false); 152 test(doc, doc, 'boolean("foo")', true); 153 test(doc, doc, 'not(1 = 1)', false); 154 test(doc, doc, 'true()', true); 155 test(doc, doc, 'false()', false); 156 test(doc, doc, '//*[lang("en")]', [PARA2, ITEM3, PARA6, PARA7, PARA8]); 157 test(doc, doc, '//*[lang("EN-US")]', [PARA7]); 158 test(doc, doc, 'normalize-space((//text()[lang("jp")])[normalize-space()])', 'Nihongo'); 159 160 doc = (new DOMParser).parseFromString( 161 '<doc>' + 162 '<item>1</item>' + 163 '<item>2</item>' + 164 '<item>3</item>' + 165 '</doc>', 166 'application/xml'); 167 168 test(doc, doc, 'string(number("-1e5"))', 'NaN'); // This test originally checked for successful parsing, but -1e5 is not a valid XPath number. 169 test(doc, doc, 'number(true())', 1); 170 test(doc, doc, 'number(false())', 0); 171 test(doc, doc, 'number(//item)', 1); 172 test(doc, doc, 'string(//item[number()=4 div 2])', '2'); 173 test(doc, doc, 'sum(//item)', 6); 174 test(doc, doc, 'floor(1.99)', 1); 175 test(doc, doc, 'floor(-1.99)', -2); 176 test(doc, doc, 'ceiling(1.99)', 2); 177 test(doc, doc, 'ceiling(-1.99)', -1); 178 test(doc, doc, 'round(1.5)', 2); 179 test(doc, doc, 'round(-1.5)', -1); 180 test(doc, doc, 'string(round(0 div 0))', 'NaN'); 181 test(doc, doc, 'round(1 div 0)', 1 / 0); 182 test(doc, doc, 'round(-1 div 0)', -1 / 0); 183 184 // The below tests are added for WebKit to complement the -1e5 test above. 185 test(doc, doc, 'number(".1")', 0.1); 186 test(doc, doc, 'number("1.")', 1); 187 test(doc, doc, 'string(number(".1."))', 'NaN'); 188 test(doc, doc, 'string(number("..1"))', 'NaN'); 189 test(doc, doc, 'string(number("1.."))', 'NaN'); 190 test(doc, doc, 'string(number(".-1"))', 'NaN'); 191 192 193 var successfullyParsed = true; 194 195 </script> 196 <script src="../../js/resources/js-test-post.js"></script> 197 </body> 198 </html> 199