0

我正在尝试从包含类别和子类别+图像的现有 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);

    ?>
4

1 回答 1

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]);

我已将该示例作为演示放到网上。

我的输出与带有缩进的文本一样,但是由于有了foreachs ,将其转换为 HTML 应该非常简单。我把它留作练习。

于 2012-11-02T00:00:24.593 回答