我的目标是用PHP编写一个foreach循环,它可以搜索menu
中id
值最低(即5188)的食物name
(即鸡肉锅派),并找到一周内食物上桌的次数。例如,代码应按如下方式返回结果:
1.鸡肉锅派:3份
2.罗西尼巡回赛:1次
3.Beefsteak:1次
4.酒馆三明治:0次
5.鱼类;芯片:2倍
请注意,XML数据如下所示:
<foods total="5">
<food>
<id>5188</id>
<yourfood>
<name>Chicken Pot Pie</name>
</yourfood>
</food>
<food>
<id>5189</id>
<yourfood>
<name>Tournedos Rossini</name>
</yourfood>
</food>
<food>
<id>5190</id>
<yourfood>
<name>Beefsteak</name>
</yourfood>
</food>
<food>
<id>5191</id>
<yourfood>
<name>Tavern Sandwich</name>
</yourfood>
</food>
<food>
<id>5192</id>
<yourfood>
<name>Fish&Chips</name>
</yourfood>
</food>
</foods>
<weekdays total="7">
<day>
<date>01-16-2016</date>
<menu>We have served Beefsteak for today.</menu>
</day>
<day>
<date>01-17-2016</date>
<menu>We have served Fish&Chips for today.</menu>
</day>
<day>
<date>01-18-2016</date>
<menu>Today, there is Chicken Pot Pie for you.</menu>
</day>
<day>
<date>01-19-2016</date>
<menu>Fish&Chips is one of the best foods in our restaurant</menu>
</day>
<day>
<date>01-20-2016</date>
<menu>Welcome home! Tournedos Rossini!</menu>
</day>
<day>
<date>01-21-2016</date>
<menu>Chicken Pot Pie</menu>
</day>
<day>
<date>01-22-2016</date>
<menu>Chicken Pot Pie is one of our most delicious dishes.</menu>
</day>
</weekdays>
幸运的是,最低的ID先出现,然后完全按照最高ID的顺序出现。这是按照文档顺序,SimpleXML XPath是按照文档顺序出现的,所以要有所有名称:
/*/food//name
除此之外,您还需要查看所有工作日菜单中该术语的使用频率。对于那些需要从工作日XML文档中查看所有这些文本的人:
/*/day/menu
在PHP代码中,它简单到:
$foods = simplexml_load_string($foodsBuffer);
$weekdays = simplexml_load_string($weekdaysBuffer);
$names = $foods->xpath('/*/food//name');
$menus = $weekdays->xpath('/*/day/menu');
现在你关心的是查看每个名称:
foreach ($names as $i => $name) {
...
}
这可能是你要找的foreach
。但是它还没有完成,您需要检查$name
是$menus
条目的一部分的频率。
这是文本比较,PHP中的一个库是PCRE库,它能很好地处理文本并与SimpleXML中使用的UTF-8兼容。
它有一个名为preg_grep
的方便函数,可以过滤数组中的匹配项:
$pattern = sprintf('/%s/u', preg_quote($name));
$result = preg_grep($pattern, $menus);
这段小代码创建regex模式并根据它过滤数组。注意,如果$name
为空,您将获得所有命中。只是说说而已。
因此,完整的foreach
看起来像:
foreach ($names as $i => $name) {
$pattern = sprintf('/%s/u', preg_quote($name));
$result = preg_grep($pattern, $menus);
printf("%d.) %s: %d time(s)'n", $i + 1, $name, count($result));
}
下面是输出的示例(在线演示):
1.) Chicken Pot Pie: 3 time(s)
2.) Tournedos Rossini: 1 time(s)
3.) Beefsteak: 1 time(s)
4.) Tavern Sandwich: 0 time(s)
5.) Fish&Chips: 2 time(s)
因此,这个答案演示了如何将PHP中多个强大的基石结合在一起:XML解析器、XPath查询、数组处理和正则表达式。
这个答案中完整性的完整示例:
<?php
/**
* How to write a foreach loop in PHP that can count the values of an XML element with a different element?
*
* @link http://stackoverflow.com/a/29219339/367456
*/
$foodsBuffer = <<<XML
<foods total="5">
<food>
<id>5188</id>
<yourfood>
<name>Chicken Pot Pie</name>
</yourfood>
</food>
<food>
<id>5189</id>
<yourfood>
<name>Tournedos Rossini</name>
</yourfood>
</food>
<food>
<id>5190</id>
<yourfood>
<name>Beefsteak</name>
</yourfood>
</food>
<food>
<id>5191</id>
<yourfood>
<name>Tavern Sandwich</name>
</yourfood>
</food>
<food>
<id>5192</id>
<yourfood>
<name>Fish&Chips</name>
</yourfood>
</food>
</foods>
XML;
$weekdaysBuffer = <<<XML
<weekdays total="7">
<day>
<date>01-16-2016</date>
<menu>We have served Beefsteak for today.</menu>
</day>
<day>
<date>01-17-2016</date>
<menu>We have served Fish&Chips for today.</menu>
</day>
<day>
<date>01-18-2016</date>
<menu>Today, there is Chicken Pot Pie for you.</menu>
</day>
<day>
<date>01-19-2016</date>
<menu>Fish&Chips is one of the best foods in our restaurant</menu>
</day>
<day>
<date>01-20-2016</date>
<menu>Welcome home! Tournedos Rossini!</menu>
</day>
<day>
<date>01-21-2016</date>
<menu>Chicken Pot Pie</menu>
</day>
<day>
<date>01-22-2016</date>
<menu>Chicken Pot Pie is one of our most delicious dishes.</menu>
</day>
</weekdays>
XML;
$foods = simplexml_load_string($foodsBuffer);
$weekdays = simplexml_load_string($weekdaysBuffer);
$names = $foods->xpath('/*/food//name');
$menus = $weekdays->xpath('/*/day/menu');
foreach ($names as $i => $name) {
$pattern = sprintf('/%s/u', preg_quote($name));
$result = preg_grep($pattern, $menus);
printf("%d.) %s: %d time(s)'n", $i + 1, $name, count($result));
}