xpath中选择不包含某子元素的节点需用not()函数判断子元素是否存在://div[not(span)]选无span子元素的div,//div[not(descendant::span)]选子孙中不含span的div,not()内表达式匹配成功则整体为假。

用XPath选择不包含某个子元素的节点,核心是使用 not() 函数配合子节点存在性判断。关键不在“排除内容”,而在“验证子元素不存在”。
基础写法:用 not(child::tag) 或 not(tag)
要选那些**没有特定子元素**的父节点,比如选取所有不含 <span></span> 的 <div>,写法是:
<ul>
<li>
<code>//div[not(span)] —— 最常用,简洁明了,等价于 //div[not(child::span)]
//div[not(*)] —— 选完全不含任何子元素(无子标签)的 <div>(但可能含文本)
<li>
<code>//div[not(node())] —— 选不含任何子节点(包括文本、注释、元素)的空 <div>
<h3>注意:text() 和其他节点类型要单独处理</h3>
<p><code>not(span) 只检查是否存在 <span></span> 元素,不影响文本节点。如果想排除“有 span 或纯文本”的情况,需组合判断:
- 选有文字但无
<span></span>的<div>:<code>//div[text() and not(span)] - 选既无
<span></span>也无其他子元素,且含非空白文本://div[not(span) and normalize-space(text())] -
//div[not(descendant::span)]—— 整个子树都不含<span></span> -
//div[not(.//span)]—— 等价写法,.//span表示当前节点下任意深度的<span></span> -
//div[span]—— 这是选「包含 span」的 div,和需求相反 -
//div[not(*/span)]—— 语法错误,*/span不合法;想查孙元素应写.//span或descendant::span -
//div[not(text())]—— 排除含文本的 div,和是否含子元素无关
进阶:排除含某子元素的任意后代(不止直接子)
若要排除的是“子孙中任意位置出现”,不是仅直接子元素,改用 descendant:::
常见误区提醒
以下写法是错的或效果不符预期:
不复杂但容易忽略:XPath 的 not(X) 判断的是 X 是否能选出节点,X 为真(即至少匹配一个节点)时整体为假。抓住这点,组合就清晰了。










