0

我正在研究一个 Greasemonkey 脚本,该脚本需要在其他两个节点之间的每个节点上运行。目前,我正在使用(越来越复杂的)XPath 表达式获得第一个节点。我有另一个表达式来获取“中间”节点,但它包含两次初始表达式并且变得相当长。这是一个仅包含两个“子句”的早期版本:

var xpHeader   = "//h2[a/@name='section-References' or a/@name='References']";
var xpContents = "//h2[a/@name='section-References' or a/@name='References']/following-sibling::*[following-sibling::h2[1] = //h2[a/@name='section-References' or a/@name='References']/following-sibling::h2[1]]"

我正在寻找的是一种基于上下文节点选择“内容”的方法,而不是多次重新包含原始表达式——“标题”表达式将很快变得相当复杂。我知道这可以在 XSLT 中使用该current()函数来完成,但当然这在 vanilla XPath 中不可用:

<xsl:template match="//h2[a/@name='section-References' or a/@name='References']">
    <xsl:for-each select="following-sibling::*[following-sibling::h2[1] = current()/following-sibling::h2[1]]">
        <!-- do stuff -->
    </xsl:for-each>
</xsl:template>

当我键入此内容时,我突然想到,此时使用 DOM 收集内容可能比 XPath 更容易,但我仍然很想知道这是否可以完成。

该脚本的原始版本可在 UserScripts.org 上找到

4

3 回答 3

2

Although you're writing XPath expressions, to Javascript, they're just strings. You can concatenate strings.

var xpContents = xpHeader + "/following-sibling::*["
  + "following-sibling::h2[1] = " + xpHeader + "/following-sibling::h2[1]"
  + "]";

Now your header expression can get as complicated as you want without affecting the complexity of the assignment of content expression. The XPath evaluator will still have to parse the whole string, and if there is no optimization of the query, then it may get evaluated multiple times, but even that might be fast enough that it doesn't matter.

于 2009-03-26T02:57:24.527 回答
2

一旦您使用 XPath 在该级别收集内容,听起来使用 DOM 会更容易一些。假设您不使用任何框架,则类似于:

var nodes = document.evaluate("//h2[a/@name='section-References' or a/@name='References']/following-sibling::*", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var contents=[];
if (nodes.snapshotLength>0) contents.push(new Array());
var currentGroup=0;
for (var i=0;i<nodes.snapshotLength;i++) {
  if (nodes.shapshotItem(i)==<your favorite way to detect the right flavor of h2 element>) {
    currentGroup++;
    contents.push(new Array());
    continue;
  }
  contents[currentGroup].push(nodes.snapshotItem(i));
}

这有点冗长,但最终会在有趣的 h2 节点之间得到一组项目数组。

于 2009-03-26T19:14:07.643 回答
1

您可以使用 jQuery 或其他 JavaScript 框架来更轻松地使用 DOM。

例子:

// ==UserScript==
// @name           MyScript
// @namespace      http://example.com
// @description    Example
// @include        *
//
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js
// ==/UserScript==

$('h2[some crazy attributes...]').each(function() {
  // Do something
});

有关通过 XPath 属性选择和遍历 DOM 元素的更多信息,请查看 jQuery 参考。

jQuery 选择器

jQuery 遍历

jQuery 下一个()

jQuery nextAll()

于 2009-03-26T18:20:19.393 回答