【发布时间】:2012-02-09 19:11:50
【问题描述】:
我一直在编写一些从网页中提取主要文本内容的代码。一个有用的策略是定位内容的第一段,然后选择以下所有同级元素,直到但不包括第一个不是 p、ul、ol 或blockquote 元素。在 Perl 中,代码如下所示:
my ($firstpara) = $document->findnodes('//p[whatever]');
my @content = ($firstpara);
for my $sibling ($firstpara->findnodes('following-sibling::*')) {
last if $sibling->tag !~ /^(?:p|ol|ul|blockquote)\z/;
push @content, $sibling;
}
这还不错,但如果能够只使用 XPath 来获取我想要的节点,那就太酷了,所以我可以写这样的东西:
my ($firstpara) = $document->findnodes('//p[whatever]');
my @content = ($firstpara, $firstpara->findnodes('<query>'));
我做了很多实验,但还没有弄清楚如何编写最后一个查询。我能找到的最接近有效的解决方案是:
$firstpara->findnodes('following-sibling::*[position() < $EXPR]');
...其中$EXPR 是一些表达式,它返回标签不是p、ul、ol 或blockquote 的下一个兄弟的位置,但我无法确定这样的表达式是否可以在 XPath 中表达。
有什么方法可以做我在 XPath 中描述的事情吗?
例子:
假设我的文档如下所示:
<h1>Header</h1>
<p>Paragraph 1</p>
<p id="first">Paragraph 2</p>
<p>Paragraph 3</p>
<ul><li>Item 1</li><li>Item 2</li></ul>
<p>Paragraph 4</p>
<hr>
<p>Paragraph 5</p>
<blockquote>Blockquote 1</blockquote>
...
我引用了 ID 为 first 的 <p> 元素。我正在寻找一个 XPath 表达式,使用该 first 元素作为内容节点,这将为我提供以下兄弟姐妹 Paragraph 3、无序列表和 Paragraph 4。 <hr> 元素不在我想要的元素中(<p>、<ul>、<ol> 和 <blockquote>),因此该元素和之后的所有同级元素不应成为返回节点集的一部分。
【问题讨论】:
-
冗长而令人困惑。请提供一个简单的 XML 作为示例,并指明您要选择的确切节点——解释每个节点必须满足的规则。
-
“以下所有兄弟元素,直到但不包括第一个不是 p、ul、ol 或 blockquote 元素的元素”冗长且令人困惑?
-
请编辑问题——没有多少人会阅读评论。
标签: xpath