假设我有这个例子:
<div>
<p>some text <em>emphasized text</em> some other text</p>
<p><em>The paragraph I want to capture</em></p>
<p>some text <em>emphasized text</em> some other text and <em>other em text</em> until the end.</p>
</div>
我要选择的是第二段(但也可能是第三段或第一段)。问题是这里
p
和 em
是相邻的。 <p>
和 <em>
之间没有任何文字,开头和结尾都没有。所有文字都在里面<em>xyz</em>
。
如何通过 XPath 查询获取它?
我尝试了
//p/em
,//p/child:em
,//em/parent:p
,所有这些都选择了三个段落,因为所有em
都是p
的子级。
//p[starts-with(.,'./em')]
也没有帮助。
根据评论,OP 澄清:
是的,我想捕获仅包含强调文本的任何段落,它是否包含在一个或多个
标签中。em
因此,这次更新了 XPath,
//p[em][not(node()[not(self::em)])]
将选择带有一个或多个
p
子元素的所有 em
元素,但不选择任何类型的其他子元素 — 仅选择完全强调的段落。
这个 XPath,
//p[count(node())=1][em]
将选择具有单个子节点(即
p
元素)的所有 em
元素。
//p
选择文档中的所有 p
元素。[count(node())=1]
仅过滤那些具有单个子 p
的 node()
元素。由于 node()
匹配 any 类型的节点(包括元素节点和文本节点),因此它将确保仅选择具有任何类型的单个子代的 p
元素。[em]
仅过滤那些具有 p
子元素的单子 em
元素。因此,对于您输入的XML/HTML,只有目标
p
,
<p><em>The paragraph I want to capture</em></p>
将被选中。如果还有另一个
p
带着三个 em
孩子,
<p><em>Do</em><em>not</em><em>select</em></p>
或一个
em
子元素和其他元素子元素,
<p><em>Do</em><sup>not</sup><sub>select!</sub><span> or else!</span></p>
此类
p
元素将不会被选择。
警告:当前接受的答案中的XPath,
//p[not(text())][em]
,然而,会选择这样的p
元素,这在我看来并不是您的意图。