在CasperJS

时间:2016-04-05 20:39:09

标签: javascript xml xpath casperjs

我正在尝试使用getElementXPath function from Firebug在CasperJS中工作,但我似乎找不到合适的地方来调用它来工作。这是我到目前为止,它只适用于已经有“id”标签的对象,但这没有多大帮助,因为我使用XPath代替id(大多数对象没有id)

casper.then(function () {
    var Element = this.evaluate(function(){
        var elm = document.querySelector('[class="h4"]');
        return getElementXPath(elm); //Set 1
        //return elm; //Set 2
    });

    console.log('xpath: '+ Element); //Set 1
    //console.log('xpath: '+ getElementXPath(Element)); //Set 2
});

Set 1始终输出“xpath:null”

如果元素已经具有“id”标记,则Set 2仅输出正确的路径。 “xpath:// * [id =”button“]”

Set 2否则将输出最后一个标签,即“xpath:/ a”或“xpath:/ span”

这是来自Firebug的getElementXPath函数,我刚刚粘贴在我的JS文件的顶部。

function getElementXPath(element)
{
    if (element && element.id)
        return '//*[@id="' + element.id + '"]';
    else
        return getElementTreeXPath(element);
};

function getElementTreeXPath(element)
{
    var paths = [];
    // Use nodeName (instead of localName) so namespace prefix is included (if any).
    for (; element && element.nodeType == Node.ELEMENT_NODE; element = element.parentNode)
    {
        var index = 0;
        var hasFollowingSiblings = false;
        for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
        {
            // Ignore document type declaration.
            if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
                continue;
            if (sibling.nodeName == element.nodeName)
                ++index;
        }

        for (var sibling = element.nextSibling; sibling && !hasFollowingSiblings;
            sibling = sibling.nextSibling)
        {
            if (sibling.nodeName == element.nodeName)
                hasFollowingSiblings = true;
        }
        var tagName = (element.prefix ? element.prefix + ":" : "") + element.localName;
        var pathIndex = (index || hasFollowingSiblings ? "[" + (index + 1) + "]" : "");
        paths.splice(0, 0, tagName + pathIndex);
    }
    return paths.length ? "/" + paths.join("/") : null;
};

1 个答案:

答案 0 :(得分:1)

当您收听"page.error"事件时,您会看到类似

的内容
  

错误:ReferenceError:找不到变量:getElementXPath

这与您在页面中包含该代码的方式有关。以下完整脚本适用于我:

var casper = require('casper').create();

// http://docs.casperjs.org/en/latest/events-filters.html#page-error
casper.on("page.error", function(msg, trace) {
    this.echo("Error: " + msg);
    // maybe make it a little fancier with the code from the PhantomJS equivalent
});

casper.start('http://example.com');

casper.then(function() {               
    this.evaluate(function(){
        window.getElementXPath = function(element)
        {
            if (element && element.id)
                return '//*[@id="' + element.id + '"]';
            else
                return getElementTreeXPath(element);
        };

        function getElementTreeXPath(element)
        {
            var paths = [];
            // Use nodeName (instead of localName) so namespace prefix is included (if any).
            for (; element && element.nodeType == Node.ELEMENT_NODE; element = element.parentNode)
            {
                var index = 0;
                var hasFollowingSiblings = false;
                for (var sibling = element.previousSibling; sibling; sibling = sibling.previousSibling)
                {
                    // Ignore document type declaration.
                    if (sibling.nodeType == Node.DOCUMENT_TYPE_NODE)
                        continue;
                    if (sibling.nodeName == element.nodeName)
                        ++index;
                }

                for (var sibling = element.nextSibling; sibling && !hasFollowingSiblings;
                    sibling = sibling.nextSibling)
                {
                    if (sibling.nodeName == element.nodeName)
                        hasFollowingSiblings = true;
                }
                var tagName = (element.prefix ? element.prefix + ":" : "") + element.localName;
                var pathIndex = (index || hasFollowingSiblings ? "[" + (index + 1) + "]" : "");
                paths.splice(0, 0, tagName + pathIndex);
            }
            return paths.length ? "/" + paths.join("/") : null;
        };
    });

    this.echo(this.evaluate(function(){
        return getElementXPath(document.querySelector("a"));
    }));
});

casper.run();

输出:

/html/body/div/p[2]/a

诀窍是在页面上下文中使getElementXPath在全局范围内可用。通过在window.getElementXPath上设置变量,可以轻松完成此操作。