如何用XPath选取文本最长的锚点?求助lxml兼容XPath语法问题
为什么你的XPath表达式在lxml中无法生效?
嘿,这个问题我之前也踩过坑,来给你好好捋清楚原因!
核心问题:XPath版本差异
首先你要知道,Python的lxml库默认只支持XPath 1.0,而你的表达式是基于XPath 2.0的语法逻辑写的,这两者在节点集的处理规则上有本质区别。
你的表达式在两个版本中的不同表现
先看你的原表达式:
//a[not(string-length(.) < ancestor::li//a/string-length(.))]
- 在XPath 2.0中:当你在比较运算符右侧使用
ancestor::li//a/string-length(.)时,它会返回祖先li下所有a节点的长度组成的序列,然后<运算符会自动检查当前a的长度是否小于序列中的任意一个值——not(...)就表示当前a的长度不小于所有其他a的长度,也就是你要找的最长文本锚点。 - 在XPath 1.0中:XPath 1.0不支持序列的多值比较,当你在比较运算符中使用节点集时,它只会取节点集里第一个匹配到的节点的计算结果。也就是说
ancestor::li//a/string-length(.)只会返回祖先li下第一个a的长度,你的条件就变成了“当前a的长度不小于第一个a的长度”,这完全偏离了你要找最长锚点的需求,所以表达式自然无法生效。
适合lxml(XPath 1.0)的替代写法
要在XPath 1.0中实现“找祖先li下文本最长的a”,可以换一种思路:找没有其他同祖先li下的a比它文本更长的节点,写法如下:
//a[not(ancestor::li//a[string-length(.) > string-length(current())])]
这里用current()函数(XPath 1.0支持)指代当前正在判断的a节点,然后检查祖先li下是否存在任何一个a的文本长度比它大——如果不存在,那它就是最长的那个,这个逻辑在lxml里可以正常运行。
内容的提问来源于stack exchange,提问作者softwarevamp
相关产品推荐
相关产品推荐

