| <html> |
| <head> |
| <script src="../../../resources/js-test-pre.js"></script> |
| <script src="../xpath-test-pre.js"></script> |
| </head> |
| <body> |
| <div id="console"></div> |
| |
| <script> |
| var doc = (new DOMParser).parseFromString( |
| '<!DOCTYPE doc [<!ATTLIST item identifier ID #IMPLIED>]>' + |
| '<doc>' + |
| '<item id="1" identifier="a" />' + |
| '<item id="2" identifier="b" />' + |
| '<item id="3" identifier="c" />' + |
| '<item id="4" identifier="d" />' + |
| '<item id="5" identifier="e" />' + |
| '<reference>a</reference>' + |
| '<reference>c</reference>' + |
| '<reference>e</reference>' + |
| '<namespace xmlns="http://www.example.com/a" xmlns:b="http://www.example.com/b">' + |
| '<item id="6" />' + |
| '<b:item id="7" b:value="42" />' + |
| '</namespace>' + |
| '</doc>', |
| 'application/xml'); |
| |
| var ROOT = doc.documentElement; |
| var ITEM1 = ROOT.firstChild; |
| var ITEM2 = ITEM1.nextSibling; |
| var ITEM3 = ITEM2.nextSibling; |
| var ITEM4 = ITEM3.nextSibling; |
| var ITEM5 = ITEM4.nextSibling; |
| var REFA = ITEM5.nextSibling; |
| var REFC = REFA.nextSibling; |
| var REFE = REFC.nextSibling; |
| var NAMESPACE = REFE.nextSibling; |
| var ITEM6 = NAMESPACE.firstChild; |
| var ITEM7 = ITEM6.nextSibling; |
| |
| test(doc, ROOT, '//item[@id=last()]', [ITEM5]); |
| test(doc, ROOT, '//item[position()=3]', [ITEM3]); |
| test(doc, ROOT, 'count(//item)', 5); |
| test(doc, ROOT, 'id("c")', [ITEM3]); |
| test(doc, ROOT, 'id(//reference)', [ITEM1, ITEM3, ITEM5]); |
| // The below test is wrong, it has an invalid expression. |
| //test(doc, ROOT, '//reference/id("a")', [ITEM1]); |
| // Several tests below originally used predicates with an abbreviated step, which is formally invalid, see <https://bugs.webkit.org/show_bug.cgi?id=12632>. |
| test(doc, ROOT, 'local-name(//self::node()[@id=7])', 'item'); |
| test(doc, ROOT, 'number(//self::node()[@id=7]/attribute::*[local-name()="value"])', 42); |
| test(doc, ROOT, 'local-name(/absent)', ''); |
| test(doc, ROOT, 'namespace-uri(//self::node()[@id>5])', 'http://www.example.com/a'); |
| test(doc, ROOT, '//self::node()[@id and namespace-uri()="http://www.example.com/b"]', [ITEM7]); |
| test(doc, ROOT, 'namespace-uri(/absent)', ''); |
| test(doc, ROOT, 'name(//self::node()[@id=7])', 'b:item'); |
| test(doc, ROOT, '//self::node()[name()="b:item"]', [ITEM7]); |
| test(doc, ROOT, 'name(/absent)', ''); |
| |
| |
| doc = (new DOMParser).parseFromString( |
| '<doc>' + |
| '<para id="1">One</para>' + |
| '<para id="2">Two</para>' + |
| '<para id="3">Three</para>' + |
| '<para id="4">' + |
| 'Four' + |
| '</para>' + |
| '</doc>', |
| 'application/xml'); |
| |
| var ROOT = doc.documentElement; |
| var PARA1 = ROOT.firstChild; |
| var PARA2 = PARA1.nextSibling; |
| var PARA3 = PARA2.nextSibling; |
| var PARA4 = PARA3.nextSibling; |
| |
| test(doc, doc, 'string(//para)', 'One'); |
| test(doc, doc, 'string(//inconceivable)', ''); |
| test(doc, doc, 'string(0 div 0)', 'NaN'); |
| test(doc, doc, 'string(1 div 0)', 'Infinity'); |
| test(doc, doc, 'string(-1 div 0)', '-Infinity'); |
| test(doc, doc, 'string(2.5 * 2)', '5'); |
| test(doc, doc, 'string(1 div -2)', '-0.5'); |
| test(doc, doc, 'string(1 = 2)', 'false'); |
| test(doc, doc, 'string("string")', 'string'); |
| test(doc, doc, '//para[string()="Two"]', [PARA2]); |
| test(doc, doc, 'concat(//para, ":", //para[2])', 'One:Two'); |
| test(doc, doc, 'starts-with("foo-bar", "foo")', true); |
| test(doc, doc, 'starts-with("foo-bar", "bar")', false); |
| test(doc, doc, 'contains("foo-bar", "o-b")', true); |
| test(doc, doc, 'contains("foo-bar", "b-o")', false); |
| test(doc, doc, 'substring-before("foo::bar", "::")', 'foo'); |
| test(doc, doc, 'substring-before("foo::bar", "--")', ''); |
| test(doc, doc, 'substring-after("foo::bar", "::")', 'bar'); |
| test(doc, doc, 'substring-after("foo::bar", "--")', ''); |
| test(doc, doc, 'substring("12345", 2)', '2345'); |
| test(doc, doc, 'substring("12345", 2, 3)', '234'); |
| test(doc, doc, 'substring("12345", 1.5, 2.6)', '234'); |
| test(doc, doc, 'substring("12345", 0, 3)', '12'); |
| test(doc, doc, 'substring("12345", 0 div 0, 3)', ''); |
| test(doc, doc, 'substring("12345", 1, 0 div 0)', ''); |
| test(doc, doc, 'substring("12345", -42, 1 div 0)', '12345'); |
| test(doc, doc, 'substring("12345", -1 div 0, 1 div 0)', ''); |
| test(doc, doc, 'substring("12345", 6, 1)', ''); |
| test(doc, doc, 'substring("12345", 1, 0)', ''); |
| test(doc, doc, 'string-length("12345")', 5); |
| test(doc, doc, '//para[string-length()=5]', [PARA3]); |
| test(doc, doc, 'normalize-space(" one two ")', 'one two'); |
| test(doc, doc, '//para[normalize-space() = "Four"]', [PARA4]); |
| test(doc, doc, 'translate("abcdef", "abcde", "xyz")', 'xyzf'); |
| |
| doc = (new DOMParser).parseFromString( |
| '<doc id="0">' + |
| '<para id="1" />' + |
| '<para id="2" xml:lang="en">' + |
| '<item id="3" />' + |
| 'English' + |
| '<section id="4" xml:lang="jp">' + |
| '<item id="5" />' + |
| 'Nihongo' + |
| '</section>' + |
| '</para>' + |
| '<para id="6" xml:lang="EN">' + |
| 'ENGLISH' + |
| '</para>' + |
| '<para id="7" xml:lang="en-us">' + |
| 'US English' + |
| '</para>' + |
| '<para id="8" xml:lang="EN-UK">' + |
| 'UK English' + |
| '</para>' + |
| '</doc>', |
| 'application/xml'); |
| |
| var ROOT = doc.documentElement; |
| var PARA1 = ROOT.firstChild; |
| var PARA2 = PARA1.nextSibling; |
| var ITEM3 = PARA2.firstChild; |
| var SECTION4 = ITEM3.nextSibling.nextSibling; |
| var ITEM5 = SECTION4.firstChild; |
| var PARA6 = PARA2.nextSibling; |
| var PARA7 = PARA6.nextSibling; |
| var PARA8 = PARA7.nextSibling; |
| |
| test(doc, doc, 'boolean(1)', true); |
| test(doc, doc, 'boolean(0)', false); |
| test(doc, doc, 'boolean(0 div 0)', false); |
| test(doc, doc, 'boolean(cod)', false); |
| test(doc, doc, 'boolean(doc)', true); |
| test(doc, doc, 'boolean("")', false); |
| test(doc, doc, 'boolean("foo")', true); |
| test(doc, doc, 'not(1 = 1)', false); |
| test(doc, doc, 'true()', true); |
| test(doc, doc, 'false()', false); |
| test(doc, doc, '//*[lang("en")]', [PARA2, ITEM3, PARA6, PARA7, PARA8]); |
| test(doc, doc, '//*[lang("EN-US")]', [PARA7]); |
| test(doc, doc, 'normalize-space((//text()[lang("jp")])[normalize-space()])', 'Nihongo'); |
| |
| doc = (new DOMParser).parseFromString( |
| '<doc>' + |
| '<item>1</item>' + |
| '<item>2</item>' + |
| '<item>3</item>' + |
| '</doc>', |
| 'application/xml'); |
| |
| test(doc, doc, 'string(number("-1e5"))', 'NaN'); // This test originally checked for successful parsing, but -1e5 is not a valid XPath number. |
| test(doc, doc, 'number(true())', 1); |
| test(doc, doc, 'number(false())', 0); |
| test(doc, doc, 'number(//item)', 1); |
| test(doc, doc, 'string(//item[number()=4 div 2])', '2'); |
| test(doc, doc, 'sum(//item)', 6); |
| test(doc, doc, 'floor(1.99)', 1); |
| test(doc, doc, 'floor(-1.99)', -2); |
| test(doc, doc, 'ceiling(1.99)', 2); |
| test(doc, doc, 'ceiling(-1.99)', -1); |
| test(doc, doc, 'round(1.5)', 2); |
| test(doc, doc, 'round(-1.5)', -1); |
| test(doc, doc, 'string(round(0 div 0))', 'NaN'); |
| test(doc, doc, 'round(1 div 0)', 1 / 0); |
| test(doc, doc, 'round(-1 div 0)', -1 / 0); |
| |
| // The below tests are added for WebKit to complement the -1e5 test above. |
| test(doc, doc, 'number(".1")', 0.1); |
| test(doc, doc, 'number("1.")', 1); |
| test(doc, doc, 'string(number(".1."))', 'NaN'); |
| test(doc, doc, 'string(number("..1"))', 'NaN'); |
| test(doc, doc, 'string(number("1.."))', 'NaN'); |
| test(doc, doc, 'string(number(".-1"))', 'NaN'); |
| |
| </script> |
| <script src="../../../resources/js-test-post.js"></script> |
| </body> |
| </html> |