Includes : XPath

xpath Function

// ==UserScript==
// @name           Includes : XPath
// @description    xpath Function
// @author         You
// @version        1.0
// @language       en
// @include        nowhere
// @namespace https://greasyfork.org/users/1385333
// ==/UserScript==

/**************************************************************************

    Author 's NOTE

    Original http://lowreal.net/blog/2007/11/17/1

***************************************************************************

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

**************************************************************************/

const XPath = Xpath = xpath = (...args) => {
    let [expression, context, type] = args;  // Destructuring arguments

    if (typeof context === "function") {
        type = context;
        context = null;
    }

    if (!context) context = document.documentElement || document;
    const documentInstance = context.ownerDocument || context;

    const evaluator = documentInstance.createExpression(expression, (prefix) => {
        const ns = documentInstance.createNSResolver(context).lookupNamespaceURI(prefix);
        if (ns) return ns;

        switch (context.contentType) {
            case "text/xhtml":
            case "application/xhtml+xml":
                return "http://www.w3.org/1999/xhtml";
            default:
                return "";
        }
    });

    switch (type) {
        case String:
            return evaluator.evaluate(context, XPathResult.STRING_TYPE, null).stringValue;
        case Number:
            return evaluator.evaluate(context, XPathResult.NUMBER_TYPE, null).numberValue;
        case Boolean:
            return evaluator.evaluate(context, XPathResult.BOOLEAN_TYPE, null).booleanValue;
        case Array: {
            const result = evaluator.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
            const resultArray = [];
            for (let i = 0; i < result.snapshotLength; i++) {
                resultArray.push(result.snapshotItem(i));
            }
            return resultArray;
        }
        case undefined: {
            const result = evaluator.evaluate(context, XPathResult.ANY_TYPE, null);
            switch (result.resultType) {
                case XPathResult.STRING_TYPE:
                    return result.stringValue;
                case XPathResult.NUMBER_TYPE:
                    return result.numberValue;
                case XPathResult.BOOLEAN_TYPE:
                    return result.booleanValue;
                case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
                    const nodes = [];
                    let node;
                    while ((node = result.iterateNext())) {
                        nodes.push(node);
                    }
                    return nodes;
                }
                default:
                    return null;
            }
        }
        default:
            throw new TypeError("xpath: specified type is not a valid type.");
    }
};