我有一个像这样的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>
我正在尝试使用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";
但是,使用此技术,用户 必须 搜索“芝加哥”而不是“芝加哥”,否则搜索将不会返回任何内容。
我了解我需要使用翻译功能,但是我所有的尝试和错误都是徒劳的。
我试过了:
$upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $lower = "abcdefghijklmnopqrstuvwxyz"; $kw = $xml->xpath("line[contains(text(),'translate('$keyword','$upper','$lower'))]");
但似乎没有任何效果。有小费吗?
如果您选择使用Gordon在XPath中使用PHP函数的建议,将会更加灵活。然而,出乎他的回答中,translate字符串函数 是 XPath 1.0中可用,因此,这意味着你可以使用它; 你的问题是 如何 。
translate
首先,查尔斯在对问题的评论中指出了明显的错别字。然后是您尝试匹配文本值的逻辑。
在单词形式中,您当前正在问:“ 文本是否包含关键字的小写形式? ”这并不是您真正要问的。相反,问:“ 小写文本是否包含小写关键字? ”将其翻译回XPath-land(请原谅):
(注意:为了便于阅读,截断了字母)
//line[contains(translate(text(),'ABC...Z','abc...z'),'chicago')]
上面的小写字母包含在line节点内的文本,然后检查它(小写字母的文本)是否包含关键字chicago。
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; }
在 第戎评论后编辑
在foreach中,您可以访问行号,章号和书名,如下所示。
行号 -这只是<line>元素上的一个属性,使访问它变得非常容易。使用SimpleXML,有两种方法可以访问它:$node['number']或$node->attributes()->number(我更喜欢前者)。
<line>
$node['number']
$node->attributes()->number
章节编号 -要做到这一点,正如您正确地说的那样,我们需要遍历树。如果我们使用DOM类,我们将拥有一个方便的$node->parentNode属性,可直接将我们引向<chapter>(因为它是我们的直接祖先<line>)。SimpleXML没有这种方便的属性,但是我们可以使用相对的XPath查询来获取它。该父轴允许我们遍历了树。
$node->parentNode
<chapter>
由于xpath()返回数组,我们可以作弊并current()用来访问从数组返回的数组中的第一个(也是唯一的)项目。然后,只需访问上述number属性即可。
xpath()
current()
number
// In the near future we can use: current(...)['number'] but not yet $chapter = current($node->xpath('./parent::chapter'))->attributes()->number;
书籍名称 -这样做的过程与访问章号的过程相同。来自的相对XPath查询<line>可以利用祖先轴,例如./ancestor::book(或./parent:chapter/parent::book)。希望您能弄清楚如何访问其name属性。
./ancestor::book
./parent:chapter/parent::book
name