【发布时间】:2012-01-18 10:19:26
【问题描述】:
我正在遍历我的 DOM 的所有文本节点并检查 nodeValue 是否包含某个字符串。
/html/body//text()[contains(.,'test')]
这是区分大小写的。但是,我也想抓住Test、TEST 或TesT。使用 XPath(在 JavaScript 中)可以做到这一点吗?
【问题讨论】:
标签: javascript html xml xslt xpath
我正在遍历我的 DOM 的所有文本节点并检查 nodeValue 是否包含某个字符串。
/html/body//text()[contains(.,'test')]
这是区分大小写的。但是,我也想抓住Test、TEST 或TesT。使用 XPath(在 JavaScript 中)可以做到这一点吗?
【问题讨论】:
标签: javascript html xml xslt xpath
这适用于 XPath 1.0。如果您的环境支持 XPath 2.0,请参阅 here。
是的。可能,但不漂亮。
/html/body//text()[
contains(
translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
'test'
)
]
这适用于预先知道字母表的搜索字符串。添加您希望看到的任何重音字符。
如果可以,请使用其他方式标记您感兴趣的文本,例如在构建 HTML 时将其包含在具有特定类的 <span> 中。使用 XPath 比元素文本中的子字符串更容易找到此类内容。
如果这不是一个选项,您可以让 JavaScript(或您用来执行 XPath 的任何其他宿主语言)帮助您构建动态 XPath 表达式:
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's answer 的提示 - 当然,您只需要翻译您实际搜索的那些字符。)
这种方法适用于任何搜索字符串,无需事先了解字母表,这是一大优势。
当搜索字符串可以包含单引号时,上述两种方法都会失败,在这种情况下会得到more complicated。
【讨论】:
translate() 本身并不关心您重复每个字符的频率 - translate(., 'EE', 'ee') 绝对等同于 translate(., 'E', 'e')。 P.S.:别忘了给@KirillPolishchuk 投票,这个想法是他的。
不区分大小写contains
/html/body//text()[contains(translate(., 'EST', 'est'), 'test')]
【讨论】:
TEST 转换为test 并保留Test 原样吗?
translate(., 'TES', 'tes') 可能更清楚。这样人们就会意识到这不是单词翻译,而是字母翻译。
使用lower-case():
/html/body//text()[contains(lower-case(.),'test')]
使用matches() 正则表达式匹配其不区分大小写 标志:
/html/body//text()[matches(.,'test', 'i')]
【讨论】:
是的。您可以使用translate将要匹配的文本转换为小写,如下所示:
/html/body//text()[contains(translate(.,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'),
'test')]
【讨论】:
如果您使用的是 XPath 2.0,那么您可以将排序规则指定为 contains() 的第三个参数。但是,排序规则 URI 不是标准化的,因此详细信息取决于您使用的产品。
请注意,前面使用 translate() 给出的解决方案都假设您只使用 26 个字母的英文字母表。
更新: XPath 3.1 为区分大小写匹配定义了标准排序规则 URI。
【讨论】:
我一直这样做的方式是使用 XPath 中的“翻译”功能。我不会说它非常漂亮,但它可以正常工作。
/html/body//text()[contains(translate(.,'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),'TEST')]
希望这会有所帮助,
【讨论】: