case insensitive xpath searching in php
我有一个这样的 xml 文件:
1 2 3 4 5 6 7 8 9 | <volume name="Early"> <book name="School Years"> <chapter number="1"> <line number="1">Here's the first line with Chicago in it.</line> <line number="2">Here's a line that talks about Atlanta</line> <line number="3">Here's a line that says chicagogo </line> </chapter> </book> </volume> |
我正在尝试使用 PHP 进行简单的关键字搜索,以找到单词并显示它所在的行。我有这个工作
1 2 3 4 5 6 | $xml = simplexml_load_file($data); $keyword = $_GET['keyword']; $kw=$xml->xpath("//line[contains(text(),'$keyword')]"); ...snip... echo $kw[0]." is the first returned item"; |
但是,使用这种技术,用户必须搜索"Chicago"而不是"chicago",否则搜索将不会返回任何内容。
我知道我需要使用翻译功能,但我所有的尝试和错误都是徒劳的。
我试过了:
1 2 3 | $upper ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $lower ="abcdefghijklmnopqrstuvwxyz"; $kw = $xml->xpath("line[contains(text(),'translate('$keyword','$upper','$lower'))]"); |
但似乎没有任何效果。有小费吗?
如果您选择使用 XPath 中的 PHP 函数,Gordon 的建议将证明更加灵活。然而,与他的回答相反,
首先,查尔斯在对问题的评论中指出了明显的错字。然后是您如何尝试匹配文本值的逻辑。
在 word 形式中,您目前在问,"文本是否包含关键字的小写形式?"这不是你真正想要问的。相反,问,"小写文本是否包含小写关键字?"翻译(原谅双关语)回到 XPath 领域将是:
(注意:为了便于阅读,字母被截断)
1 | //line[contains(translate(text(),'ABC...Z','abc...z'),'chicago')] |
上面将
现在是强制性的代码片段(但实际上,上面的想法是你真正需要带回家的):
1 2 3 4 5 6 7 8 | $xml = simplexml_load_file($data); $search = strtolower($keyword); $nodes = $xml->xpath("//line[contains(translate(text(), 'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz'), '$search')]"); echo 'Got ' . count($nodes) . ' matches!' . PHP_EOL; foreach ($nodes as $node){ echo $node . PHP_EOL; } |
在第戎的评论后编辑
在 foreach 中,您可以访问如下所示的行号、章节号和书名。
行号——这只是
章节编号——正如你所说的那样,为了解决这个问题,我们需要遍历树。如果我们使用 DOM 类,我们将有一个方便的
由于
1 2 | // In the near future we can use: current(...)['number'] but not yet $chapter = current($node->xpath('./parent::chapter'))->attributes()->number; |
书名——这个过程与访问章节号的过程相同。来自
请参阅 salathe 的回答,了解如何使用 SimpleXml 和 translate()。
作为使用 XPath 函数的替代/添加选项,您可以在使用 DOM 时在 XPath 表达式中使用 PHP5.3 起的任何 PHP 函数,包括自定义函数。我不确定 SimpleXml 中是否有相同的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // create a DOMDocument and load your XML string into it $dom = new DOMDocument; $dom->loadXML($xml); // create a new Xpath and register PHP functions as XPath functions $xPath = new DOMXPath($dom); $xPath->registerNamespace("php","http://php.net/xpath"); $xPath->registerPHPFunctions(); // Setup the query $keyword = 'chicago'; $q ="//line[php:functionString('stripos', text(), '$keyword')]"; $nodes = $xPath->query($q); // Iterate the resulting NodeList foreach($nodes as $node) { echo $node->nodeValue, PHP_EOL; } |
这将输出
1 2 | Here's the first line with Chicago in it. Here's a line that says chicagogo |
有关更多详细信息,请参阅@salathes 博客条目和 PHP 手册。
我可能遗漏了一些东西......但恕我直言,这是另一种方法 - 更简单。
在通过
IE
1 2 3 | $xml = simplexml_load_string(strtolower(file_get_contents($xml_file_path))); $keyword = strtolower($_GET['keyword']); //Make sure you sanitize this! $kw = $xml->xpath("//line[contains(text(),'$keyword')]"); |
这样,你是在比较小写::小写