For example, for the XML below
开发者_如何学Go<CATALOG>
<CD title="Empire Burlesque"/>
<CD title="empire burlesque"/>
<CD title="EMPIRE BURLESQUE"/>
<CD title="EmPiRe BuRLeSQuE"/>
<CD title="Others"/>
<CATALOG>
How to match the first 4 records with xpath like //CD[@title='empire burlesque']
. Is there xpath function to do this? Other solutions like PHP function are also accepted.
XPath 2 has a lower-case (and upper-case) string function. That's not quite the same as case-insensitive, but hopefully it will be close enough:
//CD[lower-case(@title)='empire burlesque']
If you are using XPath 1, there is a hack using translate.
matches() is an XPATH 2.0 function that allows for case-insensitive regex matching.
One of the flags is i
for case-insensitive matching.
The following XPATH using the matches() function with the case-insensitive flag:
//CD[matches(@title,'empire burlesque','i')]
This does not work in Chrome Developer tools to locate a element, i am looking to locate the 'Submit' button in the screen
//input[matches(@value,'submit','i')]
However, using 'translate' to replace all caps to small works as below
//input[translate(@value,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz') = 'submit']
Update: I just found the reason why 'matches' doesnt work. I am using Chrome with xpath 1.0 which wont understand the syntax 'matches'. It should be xpath 2.0
One possible PHP solution:
// 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")];
for selenium xpath lower-case will not work ... Translate will help Case 1 :
- using Attribute //*[translate(@id,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='login_field']
- Using any attribute //[translate(@,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='login_field']
Case 2 : (with contains) //[contains(translate(@id,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz'),'login_field')]
case 3 : for Text property //*[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'username')]
You mentioned that PHP solutions were acceptable, and PHP does offer a way to accomplish this even though it only supports XPath v1.0. You can extend the XPath support to allow PHP function calls.
$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"]');
See the PHP registerPhpFunctions documentation for more examples. It basically demonstrates that "php:function" is for boolean evaluation and "php:functionString" is for string evaluation.
精彩评论