在php中搜索不区分大小写的xpath

dij*_*jon 6 php xpath

我有一个像这样的xml文件:

<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>
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用PHP进行简单的关键字搜索,找到该单词并显示它所在的行.我有这个工作

$xml = simplexml_load_file($data);
$keyword = $_GET['keyword'];
$kw=$xml->xpath("//line[contains(text(),'$keyword')]");
...snip...

echo $kw[0]." is the first returned item";
Run Code Online (Sandbox Code Playgroud)

但是,使用此技术,用户必须搜索"芝加哥"而不是"芝加哥",否则搜索将不返回任何内容.

我知道我需要使用翻译功能,但我的所有试验和错误都是徒劳的.

我试过了:

$upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$lower = "abcdefghijklmnopqrstuvwxyz";
$kw = $xml->xpath("line[contains(text(),'translate('$keyword','$upper','$lower'))]");
Run Code Online (Sandbox Code Playgroud)

但似乎没什么用.有小费吗?

sal*_*the 8

如果您选择使用,那么Gordon建议在XPath中使用PHP函数将更加灵活.然而,出乎他的回答中,translate字符串函数可用的XPath 1.0中,这样意味着你可以使用它; 你的问题是怎么回事.

首先,查尔斯在对这个问题的评论中指出了明显的错字.然后就是你如何尝试匹配文本值的逻辑.


在单词形式中,您当前会问," 文本是否包含关键字的小写形式? "这不是您想要的.相反,问一下," 小写文本是否包含小写关键字? "翻译(原谅双关语)回到XPath-land将是:

(注意:截断的字母表是为了便于阅读)

//line[contains(translate(text(),'ABC...Z','abc...z'),'chicago')]
Run Code Online (Sandbox Code Playgroud)

上面的小写包含line节点中包含的文本,然后检查它(小写文本)是否包含关键字chicago.


现在为强制性代码片段(但实际上,上述想法是你真正需要带回家的):

$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;
}
Run Code Online (Sandbox Code Playgroud)

第戎评论编辑

在foreach中,您可以访问下面的行号,章节号和书名.

行号 - 这只是<line>元素的一个属性,使得访问它非常容易.使用SimpleXML有两种方法可以访问它:$node['number']或者$node->attributes()->number(我更喜欢前者).

章节编号 - 正如你正确地说的那样,我们需要遍历树.如果我们使用DOM类,我们将有一个方便的$node->parentNode属性直接引导我们<chapter>(因为它是我们的直接祖先<line>).SimpleXML没有这么方便的属性,但是我们可以使用相对的XPath查询来获取它.该父轴允许我们遍历了树.

因为xpath()返回一个数组,我们可以欺骗并使用它current()来访问从它返回的数组中的第一个(也是唯一的)项.然后,只需访问上述number属性即可.

// In the near future we can use: current(...)['number'] but not yet
$chapter = current($node->xpath('./parent::chapter'))->attributes()->number;
Run Code Online (Sandbox Code Playgroud)

书名 - 此过程与访问章节号的过程相同.来自的相对XPath查询<line>可以使用像(或)那样的祖先轴.希望你能弄明白如何访问它的属性../ancestor::book./parent:chapter/parent::bookname