标记示例:
<div class="post-content">
<p>
<moredepth>
<...>
<span class="image-container float_right">
<div class="some_element">
image1
</div>
<p>do not need this</p>
</span>
<div class="image-container float_right">
image2
</div>
<p>text1</p>
<li>text2</li>
</...>
</moredepth>
</p>
</div>
最糟糕的是“图像容器”的深度可以在任何级别上。
我尝试使用的 Xpath:
//div[contains(@class, 'post-content')]//*[not(contains(@class, 'image-container'))]
我应该使用什么 Xpath 来排除“some_element”和任何深度的“image-container”的任何其他子元素以及“image-container”元素本身?
此示例中的输出应为:
<p>
<moredepth>
<...>
<p>text1</p>
<li>text2</li>
</...>
</moredepth>
</p>
附言是否可以使用 CSS 进行这样的选择?
最佳答案
您可以应用 Kaysian 方法来获取集合的交集。你有两组:
A: //div[contains(@class, 'post-content')]
的元素,不包括当前元素(因为你不想要根 分区
):
//*[ancestor::div[contains(@class, 'post-content')]]
B: //*[not(contains(@class, 'image-container'))]
的元素,包括当前元素(因为你想排除整个树, 包括 div
和 span
):
//*[not(ancestor-or-self::*[contains(@class, 'image-container')])]
这两组的交集就是您问题的解决方案。 Kaysian 方法的公式为:A [ count(. | B) = count(B) ]
。将其应用于您的问题,您需要的结果是:
//*[ancestor::div[contains(@class, 'post-content')]]
[ count(. | //*[not(ancestor-or-self::*[contains(@class, 'image-container')])])
=
count(//*[not(ancestor-or-self::*[contains(@class, 'image-container')])]) ]
这将从您的示例代码中选择以下元素:
/div/p
/div/p/moredepth
/div/p/moredepth/...
/div/p/moredepth/.../p
/div/p/moredepth/.../li
排除匹配不需要的类及其后代的 span
和 div
。
然后您可以向表达式添加额外的步骤以准确过滤出您需要的文本或节点。
关于html - xpath 通过包含值的父属性排除元素及其所有子元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28738431/