使用XML从XML数据集创建嵌套列表

时间:2012-11-01 21:08:36

标签: php xml arrays xpath simplexml

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

    ?>

1 个答案:

答案 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。我把它留作练习。