UNPKG

xpath2

Version:

DOM 3 XPath implementation (with XPath 2.0 language support)

195 lines (173 loc) 6.35 kB
<!doctype html> <html> <head> </head> <body> <script src="xpath2.min.js"></script> <script src="node_modules/xpath/xpath.js"></script> <script src="node_modules/wicked-good-xpath/dist/wgxpath.install.js"></script> <script> var xpathwg = {document:{}}; wgxpath.install(xpathwg); </script> <script type="text/javascript"> function testPerf(func) { var date = new Date, times = 1000, res = []; for (var n = 0; n < times; n++) res.push(func()); return (new Date() - date); } function lookupNamespaceURI(prefix) { if (prefix == "a") { return "http://example.com/book"; } if (prefix == "b") { return "http://www.w3.org/1999/xhtml"; } if (prefix == "c") { return "http://localhost"; } } var resolver = { lookupNamespaceURI: lookupNamespaceURI }; function evaluateN(expression, doc, res) { try { return document.evaluate(expression, doc, res || resolver).numberValue; } catch(e) { return e.message; } }; function evaluate(expression, doc, res) { try { return xpath.evaluate(expression, doc, res || resolver, xpath.XPathResult.ANY_TYPE).numberValue; } catch(e) { return e.message; } }; function evaluate2(expression, doc, res) { try { return xpath2.evaluate(expression, doc, res || resolver).numberValue; } catch(e) { return e.message; } }; function evaluateG(expression, doc, res) { try { return xpathwg.document.evaluate(expression, doc, res || resolver, xpath.XPathResult.ANY_TYPE).numberValue; } catch(e) { return e.message; } }; var doc = new DOMParser().parseFromString("<books xmlns='http://example.com/book' xmlns:attr='http://example.com/book'><book id='1' isbn='12'><title attr:id='Rowling'>Harry Potter</title><content>Once upon a time</content></book><book id='2' isbn='22'><title attr:id='Someone'>Other Book</title></book></books>", 'text/xml'); var testCases = [ ['--5', 5, document], ['1+2', 3, document], ['0.1+0.2', 0.3, document], ['count(. | .)', 1, document], ['count(id("1"))', 1, doc], ['count(//*)', 6, doc], ['count(//*/attribute::*)', 6, doc], ['count(//@*)', 6, doc], ['count(//*/attribute::id)', 2, doc], ['count(//*/attribute::ID)', 0, doc], ['count(//*/attribute::a:id)', 2, doc], ['count(//book)', 0, doc], ['count(//BOOK)', 0, doc], ['count(//c:book)', 0, doc], ['count(//a:title/ancestor-or-self::a:book[a:content])', 1, doc], ['count(//a:book/descendant-or-self::*[a:content])', 1, doc], ['count(id("1")/@id/preceding-sibling::node())', 0, doc], ['count(id("1")/@id/following-sibling::node())', 0, doc], ['count(id("1")/preceding::*)', 0, doc], ['count(id("1")/following::*)', 2, doc], ['count(id("1")/preceding-sibling::*)', 0, doc], ['count(id("1")/following-sibling::*)', 1, doc], ['count(//*)', 8, document], ['count(//* | //*)', 8, document], ['count(//*/ancestor::*/ancestor-or-self::*)', 2, document], ['count(//*/attribute::*)', 4, document], ['count(//SCRIPT)', 0, document], ['count(//script)', 5, document], ['count(//b:script)', 5, document], ['count(//@src)', 3, document], ['count(//@SRC)', 0, document], ['count(//*[ancestor::b:html])', 7, document], ['count(//unknown:title)', 1, doc], ['count(//unknown:title)', 1, document], ['', 3, document], ['1+', 3, document], ['1+2', 3, {}], ['count(unknown-axis::*)', 1, document], ['count(.)', 1], ['count(. + 1)', 1, document], ['count(fun())', 1, document], ['count($var)', 1, document], ['count("str""ing")', 1, document], ['count("str\"\"ing")', 1, document], ]; var engines = ['evaluateN', 'evaluate', 'evaluate2', 'evaluateG']; var table = []; table.push('<table border="1" width="100%">'); table.push('<thead>'); table.push('<tr>'); table.push('<th rowspan="3">DOM</th>'); table.push('<th rowspan="3">Query</th>'); table.push('<th rowspan="3">Expected</th>'); table.push('<th colspan="8" width="60%">Engine</th>'); table.push('</tr>'); table.push('<tr>'); table.push('<th colspan="2">native</th>'); table.push('<th colspan="2">xpath</th>'); table.push('<th colspan="2">xpath2</th>'); table.push('<th colspan="2">google</th>'); table.push('</tr>'); table.push('<tr>'); table.push('<th>result</th>'); table.push('<th width="50">ms/op</th>'); table.push('<th>result</th>'); table.push('<th width="50">ms/op</th>'); table.push('<th>result</th>'); table.push('<th width="50">ms/op</th>'); table.push('<th>result</th>'); table.push('<th width="50">ms/op</th>'); table.push('</tr>'); table.push('</thead>'); table.push('<tbody>'); var engineTimeTotal = engines.map(function() {return 0}); for (var n = 0, testCase, result, perf, engineTime, totalTime; n < testCases.length; n++) { table.push('<tr>'); testCase = testCases[n]; table.push('<td>' + (testCase[2] === document ? "HTML" : testCase[2] === doc ? "XML" : "---") + '</td>'); table.push('<td>' + testCase[0] + '</td>'); table.push('<td>' + testCase[1] + '</td>'); engineTime = engines.map(function() {return 0}); totalTime = 0; for (var e = 0; e < engines.length; e++) { perf = testPerf(function(){window[engines[e]](testCase[0], testCase[2])}); engineTime[e] = perf; totalTime += perf; engineTimeTotal[e] += perf; } for (var e = 0; e < engines.length; e++) { result = window[engines[e]](testCase[0], testCase[2]); table.push('<td style="' + (result !== testCase[1] ? 'color:red;' : '') + (perf ) + '">' + result + '</td>'); table.push('<td style="' + (engineTime[e] / totalTime > .33 ? 'background-color:pink' : engineTime[e] / totalTime < .2 ? 'background-color:lightgreen' : '') + '">' + engineTime[e] + '</td>'); } table.push('</tr>'); } table.push('</tbody>'); table.push('<tfoot style="font-weight:bold">'); table.push('<td colspan="3"></td>'); table.push('<td></td><td>' + engineTimeTotal[0] + '</td>'); table.push('<td></td><td>' + engineTimeTotal[1] + '</td>'); table.push('<td></td><td>' + engineTimeTotal[2] + '</td>'); table.push('<td></td><td>' + engineTimeTotal[3] + '</td>'); table.push('</tfoot>'); table.push('</table>'); document.write(table.join('')); </script> </body> </html>