Case insensitive XPath contains() possible?

I'm running over all textnodes of my DOM and check if the nodeValue contains a certain string.

/html/body//text()[contains(.,'test')]

This is case sensitive. However, I also want to catch Test, TEST or TesT. Is that possible with XPath (in JavaScript)?

102486 次浏览

如果您的环境支持 XPath 2.0,请参阅 给你


Yes. Possible, but not beautiful.

/html/body//text()[
contains(
translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
'test'
)
]

这种方法适用于事先知道字母表的搜索字符串。添加您希望看到的任何重音字符。


如果可以,用其他方法标记您感兴趣的文本,比如在构建 HTML 时将其包含在具有某个类的 <span>中。使用 XPath 比在元素文本中使用子字符串更容易找到这些内容。

If that's not an option, you can let JavaScript (or any other host language that you are using to execute XPath) help you with building an dynamic XPath expression:

function xpathPrepare(xpath, searchString) {
return xpath.replace("$u", searchString.toUpperCase())
.replace("$l", searchString.toLowerCase())
.replace("$s", searchString.toLowerCase());
}


xp = xpathPrepare("//text()[contains(translate(., '$u', '$l'), '$s')]", "Test");
// -> "//text()[contains(translate(., 'TEST', 'test'), 'test')]"

(给 @ KirillPolishchuk 的回答的帽子提示——当然你只需要翻译那些你实际上是为 寻找翻译的字符。)

这种方法适用于任何搜索字符串,而不需要事先了解字母表,这是一个很大的优势。

当搜索字符串可以包含单引号时,上述两种方法都会失败,在这种情况下,将得到 更复杂

我一直使用的方法是在 XPath 中使用“ trans”函数。我不会说它很漂亮,但它的工作原理是正确的。

/html/body//text()[contains(translate(.,'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),'TEST')]

希望这能有所帮助,

可以。您可以使用 translate将要匹配的文本转换为小写,如下所示:

/html/body//text()[contains(translate(.,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'),
'test')]

不区分大小写的 contains

/html/body//text()[contains(translate(., 'EST', 'est'), 'test')]

如果使用的是 XPath 2.0,那么可以将排序规则指定为要包含()的第三个参数。但是,排序规则 URI 没有标准化,因此细节取决于您所使用的产品。

请注意,前面的使用 trans ()给出的解决方案都假设您只使用了26个字母的英文字母。

更新: XPath 3.1为区分大小写匹配定义了一个标准排序 URI。

XPath 2.0 Solutions

  1. 使用 < strong > 小写() :

    /html/body//text()[contains(lower-case(.),'test')]

  2. 使用不区分大小写的 火柴()正则表达式匹配 旗帜:

    /html/body//text()[matches(.,'test', 'i')]