如何在PHP中编写一个foreach循环,可以使用不同的元素计算XML元素的值?

时间:2015-03-23 14:21:18

标签: php xml

我的目标是在PHP中编写一个foreach循环,可以在name中搜索id值(即5188)最低的食物menu(即鸡罐饼),并查找如何很多时候,食物已在一周内送达。例如,代码应该按如下方式回显结果:

1。鸡肉馅饼:3次

2。 Tournedos Rossini:1次

3。牛排:1次

4。酒馆三明治:0次

5。 Fish& Chips: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&amp;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&amp;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&amp;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>

1 个答案:

答案 0 :(得分:3)

幸运的是,最低的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中的一个文库很好,与SimpleXML中使用的UTF-8兼容的是PCRE库。

它有一个名为preg_grep的便捷函数,可以过滤匹配的数组:

$pattern = sprintf('/%s/u', preg_quote($name));
$result  = preg_grep($pattern, $menus);

这段代码创建了正则表达式模式并根据它过滤数组。如果$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));
}

这是示例输出(online demo):

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&amp;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&amp;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&amp;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));
}