Search code examples
javascriptxpathgreasemonkey

getting XPath result from another XPath result


I can't seem to get this to work at all. I'm trying to use an xPath result as my base query for the page from within a greasemonkey script.

The code I'm using is:

var select=$tag('select');
this.basePath=xpath.single("/html/body/div/div/div/div",document);
// - /html/body/div/div/div/div/div[2]/div/div[2]/div[2]/table/tbody/tr/th[2]/a
if(select.length>0){
    this.location=xpath.single("/div[2]/div/div[2]/div[2]/table/tbody/tr/th[2]/a",this.basePath);
    console.log('location: '+this.location.singleNodeValue.textContent);
}

The xPath functions are:

var xpath=function(){
    return {
    single:function easyXPath(path,baseNode){
        if(baseNode===undefined||!isHTML(baseNode)){
                baseNode=document;
        }
        return document.evaluate(path,baseNode,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
    },
    count:function easyXPathCount(path,baseNode){
        if(baseNode===undefined||!isHTML(baseNode)){
            baseNode=document;
        }
        return document.evaluate("count("+path+")",baseNode,null,XPathResult.NUMBER_TYPE,null).numberValue;
    },
    number:function easyXPathNumber(path,baseNode){
        if(baseNode===undefined||!isHTML(baseNode)){
            baseNode=document;
        }
        return document.evaluate(path,baseNode,null,XPathResult.NUMBER_TYPE,null).numberValue;
    },
    multi:function easyXPathMultiNode(path,baseNode){
        if(baseNode==undefined||!isHTML(baseNode)){
            baseNode=document;
        }
        return document.evaluate(path,baseNode,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
    }
};
}();
function isHTML(node){
    return node instanceof HTMLElement || node instanceof Element;
}

I've left the full path to the element I'm trying to reach and at last resort I will just prepend the base path to the following paths


Solution

  • Found a way to do it. Probably not the most efficient but it works.

    let select=$tag('select');
    this.basePath=xpath.single("/html/body/div/div/div/div");
    // - /html/body/div/div/div/div/div[2]/div/div[2]/div[2]/table/tbody/tr/th[2]/a
    let fragment=document.createDocumentFragment();
    let d=this.basePath.singleNodeValue.cloneNode(true);
    fragment=fragment.appendChild(d);
    if(select.length>0){
        this.location=xpath.single("/div[2]/div/div[2]/div[2]/table/tbody/tr/th[2]/a",fragment);
        console.log('location: '+this.location.singleNodeValue.textContent);
    }
    

    It seems like xPath requires a document base to work and will not work on anything that is not already a document type, or document fragment.

    Hopefully this also helps someone else.