我正在尝试从包含类别和子类别+图像的现有XML文件构建无序列表。我需要将每个子类别作为无序列表中的项目,并在嵌套列表中包含每个相关图像。子类别应仅显示一次(如果相同,则不得重复)。我相信我正在寻找的是一个递归循环,但这就是我迷失的地方。
基本上,我正在努力实现与此类似的外观:
-------------- DOGS -------------
[..........小..........]
[图片] [图片]
[..........大..........]
[图象]
-------------- CATS -------------
[..........介质..........]
[图象]
[..........大..........]
[图片] [图片]
我的XML文件结构:
<root>
<animal>
<category>DOGS</category>
<subcategory>small</subcategory>
<name>Terrier</name>
<image>aaa.jpg</image>
</animal>
<animal>
<category>-</category>
<subcategory>small</subcategory>
<name>Havanese</name>
<image>bbb.jpg</image>
</animal>
<animal>
<category>-</category>
<subcategory>large</subcategory>
<name>Dalmatian</name>
<image>ccc.jpg</image>
</animal>
<animal>
<category>CATS</category>
<subcategory>medium</subcategory>
<name>Abyssinian</name>
<image>ddd.jpg</image>
</animal>
<animal>
<category>-</category>
<subcategory>large</subcategory>
<name>Birman</name>
<image>eee.jpg</image>
</animal>
<animal>
<category>-</category>
<subcategory>large</subcategory>
<name>American Shorthair</name>
<image>fff.jpg</image>
</animal>
</root>
这是我到目前为止所做的尝试:
<?php
$xml = simplexml_load_file("file.xml");
$categories = array();
$subcategories = array();
$names = array();
$image = array();
foreach($xml->animal as $animals) {
$category = $animals->category;
$subcategory = $animals->subcategory;
$name = $animals->name;
$image = $animals->image;
$categories[] = $category;
$subcategories[] = $subcategory;
$names[] = $name;
$images[] = $image
}
function getMenu($xml, $categories, $subcategories, $names, $images) {
$output = '<ul>';
foreach(array_keys($images) as $n) {
$output .= '<li class="animals" data-tags="'.$names[$n].'">';
$output .= '<img src="xml/'.$images[$n].'" width="75" height="75" alt="'.$names[$n].'" />';
$output .= '</li>';
}
$output.= '</ul>';
return array($output);
}
$result = getMenu($xml, $categories, $subcategories, $names, $images);
echo json_encode($result);
?>
答案 0 :(得分:2)
你可以通过千种方式做到这一点。最直接的可能是xpath()
。它是一种值得学习的强大的XML查询语言。您的$xml
simplexmlelement示例:
foreach ($xml->xpath('//category[not(. = following::category)]') as $category) {
echo "=== $category === \n";
foreach ($xml->xpath("//animal[category = '$category']/subcategory[not(. = following::animal[category = '$category']/subcategory)]") as $subcategory) {
echo " = $subcategory =\n";
foreach ($xml->xpath("//animal[category = '$category' and subcategory = '$subcategory']") as $animal) {
echo " * $animal->name ($animal->image)\n";
}
}
}
输出:
=== DOGS ===
= small =
* Terrier (aaa.jpg)
* Havanese (bbb.jpg)
= large =
* Dalmatian (ccc.jpg)
你可能还想在那里替换冗长的xpath字符串。在闭包和迭代器聚合的帮助下,甚至可以将代码简化为:
foreach ($categories as $category) {
echo "=== $category === \n";
foreach ($subcategories as $subcategory) {
echo " = $subcategory =\n";
foreach ($animals as $animal) {
echo " * $animal->name ($animal->image)\n";
}
}
}
这将允许稍后更改XML结构并在中心位置配置xpath:
$categories = $vpath('//category[not(. = following::category)]');
$subcategories = $vpath('//animal[category = "%1$s"]/subcategory[not(. = following::animal[category = "%1$s"]/subcategory)]', [&$category]);
$animals = $vpath("//animal[category = '%s' and subcategory = '%s']", [&$category, &$subcategory]);
我已将该示例放在网上demo。
我的输出就像带有缩进的文本一样,但是由于foreach
,它应该非常直接地将其转换为HTML。我把它留作练习。