到目前为止,我已经得到了一个非常简单的类,名为Menu.php,其中包含以下内容:
<?php
class Menu
{
private $_dom;
private $categoryItems;
function __construct()
{
if(file_exists('Menu.xml'))
{
$this->_dom = simplexml_load_file('Menu.xml');
}
}
public function retrieveMenu($category)
{
$products = $this->_dom->xpath('/menu/category[@name="'.$category.'"]');
return $products;
}
} // end of class Menu
非常基本,我知道,只是为了测试的目的。现在,我还有一个如下所示的XML文件:
<?xml version="1.0" encoding="UTF-8" ?>
<menu>
<category name="pizza">
<item name="Tomato and Cheese">
<type>Regular</type>
<available>true</available>
<size name="Small">
<price>5.50</price>
</size>
<size name="Large">
<price>9.75</price>
</size>
</item>
</category>
<category name="pizza">
<item name="Pepperoni">
<type>Regular</type>
<available>true</available>
<size name="Small">
<price>6.85</price>
</size>
<size name="Large">
<price>10.85</price>
</size>
</item>
</category>
适用于多个产品。我们的想法是通过类访问这个文件,为了实现这一点,我在index.php中做了以下操作:
<?php
require 'Menu.php';
$menu = new Menu();
$tests = $menu->retrieveMenu('pizza');
foreach($tests as $test) {
echo $test->attributes();
echo '<br />';
foreach($test->item as $item) {
echo $item->attributes();
echo '<br />';
echo $item->type;
echo '<br />';
echo $item->available;
echo '<br />';
foreach($item->size as $price) {
echo $price->attributes();
echo '<br />';
echo $price->price;
echo '<br />';
echo '<br />';
echo $price->price;
echo '<br />';*/
}
//echo $item->size->attributes();
echo '<br /><br /><br /><br />';
}
}
返回我所期望的结果:
>pizza
>Tomato and Cheese
>Regular
>true
>Small
>5.50
>Large
>9.75
现在,我的问题是:既然我使用3嵌套的for循环,如果我没有错,复杂性是n^3,这是相当可怕的,原来的XML包含了很多产品,有没有更好的方式来访问它?我做错了什么吗?
顺便说一下,是的,我必须使用XML和XPATH
在这种情况下嵌套循环没有问题。您可以访问并输出单个资源上的所有子元素。但是,确实可以使用Xpath从不同级别获取节点到列表中。
Xpath表达式可以使用|来组合多个位置路径。所以它实际上是三个位置路径表达式返回所有匹配的节点:
-
name
属性节点从所有元素://*/@name
-
item/size
的price
子元素://item/size/price
item
除size
外的子元素://item/*[not(self::size)]
这个例子使用了DOM:
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$expression = '//*/@name|//item/*[not(self::size)]|//item/size/price';
foreach ($xpath->evaluate($expression) as $node) {
echo trim($node->nodeValue), "<br/>'n";
}
输出:pizza<br/>
Tomato and Cheese<br/>
Regular<br/>
true<br/>
Small<br/>
5.50<br/>
Large<br/>
9.75<br/>
pizza<br/>
Pepperoni<br/>
Regular<br/>
true<br/>
Small<br/>
6.85<br/>
Large<br/>
10.85<br/>
Xpath中的位置路径类似于过滤器,节点根据其在文档中的位置按顺序返回。
它也适用于SimpleXML:
$element = simplexml_load_string($xml);
$expression = '//*/@name|//item/*[not(self::size)]|//item/size/price';
foreach ($element->xpath($expression) as $node) {
echo trim($node), "<br/>'n";
}
演示:https://eval.in/156266