XPath中的不区分大小写匹配是什么?

95
例如,对于以下 XML:
<CATALOG>
    <CD title="Empire Burlesque"/>
    <CD title="empire burlesque"/>
    <CD title="EMPIRE BURLESQUE"/>
    <CD title="EmPiRe BuRLeSQuE"/>
    <CD title="Others"/>
<CATALOG>

如何使用XPath匹配前4条记录,就像//CD[@title='empire burlesque']。是否有XPath函数可以实现这个功能?其他解决方案,如PHP函数也是可以接受的。


1
请查看Ben Gripka的帖子,了解XPath 1.0。该帖子涉及将字符串转换为大写或小写的问题。 - user2237201
在这里,我还找到了另外两个解决方案,并附有说明:(非我的网站/推广)https://codingexplained.com/coding/php/solving-xpath-case-sensitivity-with-php - bharat
6个回答

132

XPath 2拥有小写(和大写)字符串函数。虽然这不完全等同于不区分大小写,但希望它足够接近:

//CD[lower-case(@title)='empire burlesque']

如果您使用XPath 1,则可以使用translate进行hack操作


甚至在 SQL Server 的 XML 列的 XPath 查询中也能正常工作。非常出色。 - T.J. Crowder

68

matches()是XPATH 2.0函数之一,可用于进行不区分大小写的正则表达式匹配。

标志之一是i,用于进行不区分大小写匹配。

以下XPATH使用了带有不区分大小写标志的matches()函数:

//CD[matches(@title,'empire burlesque','i')]

16
这是基于正则表达式的匹配,与基于文本的匹配有重要区别。 - usr
2
请注意,这也可能找到部分匹配项;如果不接受,请使用 ^$,例如 matches(@title, '^empire burlesque$', 'i') - Arjan

16

在Chrome开发者工具中无法定位元素,我想要找到屏幕上的“提交”按钮。

//input[matches(@value,'submit','i')]

然而,使用“translate”将所有大写字母替换为小写字母的方法如下:

//input[translate(@value,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz') = 'submit']

更新:我刚刚发现“matches”不起作用的原因。我正在使用带有xpath 1.0的Chrome浏览器,它不会理解“matches”的语法。应该使用xpath 2.0。


在国际化方面,似乎翻译概念被称为“不区分大小写排序”。 - neaumusic
请注意,此答案中的“translate”解决方案对于具有大写字母特殊规则的语言(例如德语)无效。 - Stephan

10

一个可能的PHP解决方案:

// load XML to SimpleXML
$x = simplexml_load_string($xmlstr);

// index it by title once
$index = array();
foreach ($x->CD as &$cd) {
  $title = strtolower((string)$cd['title']); 
  if (!array_key_exists($title, $index)) $index[$title] = array();
  $index[$title][] = &$cd;
}

// query the index 
$result = $index[strtolower("EMPIRE BURLESQUE")];

13
针对匿名的负分投票者:请仔细阅读原帖问题,特别是“也接受使用 PHP 函数等其他解决方案”这一部分。 - Tomalak

8

对于Selenium XPath ,小写字母不起作用,可以使用translate帮助实现大小写不敏感搜索。

情况1:
  1. 使用属性 //*[translate(@id,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='login_field']
  2. 使用任何属性 //[translate(@,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='login_field']
情况2:(包含contains函数)
//[contains(translate(@id,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz'),'login_field')]
情况3:对于文本属性
//*[contains(translate(text(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz'),'username')]

你帮了我很多,非常感谢! - Kamil

3

您提到PHP解决方案是可接受的,虽然PHP仅支持XPath v1.0,但它确实可以通过扩展XPath支持来允许调用PHP函数实现此目的。

$xpathObj = new DOMXPath($docObj);
$xpathObj->registerNamespace('php','http://php.net/xpath'); // (required)
$xpathObj->registerPhpFunctions("strtolower"); // (leave empty to allow *any* PHP function)
$xpathObj->query('//CD[php:functionString("strtolower",@title) = "empire burlesque"]');

请看PHP registerPhpFunctions文档以获取更多示例。它基本上表明,“php:function”用于布尔运算,而“php:functionString”用于字符串运算。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接