为什么XPath选择上下文节点之外的节点?

时间:2017-02-22 18:24:42

标签: html node.js xml xpath

我正在使用带有Node.js的XPath,我有以下HTML文档,我想要选择所有文章节点,然后在第二步中使用类"abc"的所有div:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
    <article>
        <div>123456</div>
        <div class="abc">Hello0!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello1!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello2!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello3!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello4!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello5!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello6!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello7!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello8!</div>
    </article>
    <article>
        <div>123456</div>
        <div class="abc">Hello9!</div>
    </article>
</body>
</html>

我使用以下代码来选择节点:

var xpath = require('xpath');
var DOMParser = require('xmldom').DOMParser;

let parser: DOMParser = new DOMParser();
let doc = parser.parseFromString("HTML-document","text/xml");
let nodes: Node[] = xpath.select("//article", doc);
console.log("NODES: ", nodes.length);
let divs: Node[] = xpath.select("//div[@class='abc']", nodes[0]);
console.log("DIVS: ", divs.length);

我的问题是,在检查两个控制台日志时,第一个显示"NODES: 10"

到目前为止,我有十个文章节点。但是,当我再次选择十个文章节点中的第一个时,控制台会显示"DIVS: 10"。所以XPath选择了一篇文章中的所有10个div,我只期望一个div

我做错了什么?

2 个答案:

答案 0 :(得分:2)

Andersson已经提供了correct direct answer to your question(+1),但这只是另一种选择:你可以将两个XPath合并为一个:这个XPath,

//article[0]/div[@class='abc']

将选择与您的两步流程相同的div元素。

你甚至可以在路径的任何一步更精细。此XPath将在div个元素中选择@class='abc'article元素,其中div子元素的字符串值为123456

//article[div='123456']/div[@class='abc']

对于显示的特定XML文档,article上的谓词选择所有articles,但这种优化的可能性通常存在。

答案 1 :(得分:1)

您应该注意//表示从根元素开始在页面上搜索,而.//表示从当前节点开始搜索页面上的任何位置。因此,如果您想从已找到的article元素开始搜索,则需要替换

"//div[@class='abc']"

".//div[@class='abc']"

"./div[@class='abc']"

由于divarticle

的直接子女