PHP和XML。使用PHP循环XML文件

时间:2011-07-26 22:40:11

标签: php xml foreach performance

我现在正处于foreach炼狱之中,试图想出一种方法来使用PHP遍历这个XML文件(下面的实际XML文本)(遵循XML文件内容)。 我想要做的是以下几点:

  1. 获取所有文件夹元素名称
  2. 如果文件夹元素具有yes作为子文件夹属性,则向下移动级别并获取该文件夹元素的名称
  3. 如果没有转到下一个文件夹元素
  4. gallerylist.xml:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <gallerylisting exists="yes">
    <folder subfolder="yes">
    Events
       <folder subfolder="yes">
       Beach_Clean_2010
            <folder subfolder="no">
            Onna_Village
            </folder>
                <folder subfolder="no">
                Sunabe_Sea_Wall
            </folder>
            </folder>
      </folder>
      <folder subfolder="no">
      Food_And_Drink
      </folder>
      <folder subfolder="no">
      Inside
      </folder>
      <folder subfolder="no">
      Location
      </folder>
      <folder subfolder="no">
      NightLife
      </folder>
    </gallerylisting>
    

    gallerylisting.php

    <?php
    $xmlref = simplexml_load_file("gallerylisting.xml");
    foreach($xmlref->children() as $child) {
        foreach($child->attributes() as $attr => $attrVal) {
            print $child;
            if($attrVal == "yes") {
                foreach($child->children() as $child) {
                    echo $child;
                    foreach($child->attributes() as $attr => $attrVal) {
                        if($attrVal == "yes") {
                            foreach($child->children() as $child) {
                                echo $child;
                            }
                        }                   
                    }
                }
            }
        }
    }
    

    我...计数... 5个foreach循环深入到这个PHP脚本中我根本不喜欢它,加上如果我的文件夹有另一个子文件夹,我将不得不添加相同的

    $if(attrVal=="yes")...etc.
    
    再次,好吧......不!无论如何,我可以避免这种情况。我是PHP的新手,特别是PHP和XML。

    感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

递归可能对你有益。

<?php

function display_entities( $xml )
{
    foreach($xml->children() as $child) {
        foreach($child->attributes() as $attr => $attrVal) {
            print $child;
            if($attrVal == "yes") {
              display_entities( $child->children() );
            }
        }
    }
}

$xmlref = simplexml_load_file("gallerylisting.xml");

display_entities($xmlref->children());

答案 1 :(得分:2)

使用XPath:

如果subfolder = no在叶子中不可靠(即可能不总是设置'no'):

foreach($xmlref->xpath('//folder[not(@subfolder) or @subfolder!="yes"]') as $node){

如果是:

foreach($xmlref->xpath('//folder[@subfolder="no"]') as $node){

或者即使你想要检查没有文件夹子项的文件夹,也不管属性:

foreach($xmlref->xpath('//folder[not(folder)]') as $node){

答案 2 :(得分:0)

您可以尝试使用xpath而不是嵌套循环方法..

运行查询

gallerylisting//folder[@subfolder="yes"]/text() 
使用this xpath tester在上面给出的xml doc上的

给出了结果Events和Beach_Clean_2010,这是我认为你想要的。查询将查找根节点gallerylisting下的所有文件夹元素,如果它们的子文件夹属性等于“yes”,则将返回节点中的文本。

所以,在PHP中,我们有

<?php
    $xmldoc = new DOMDocument();
    $xmldoc->load('gallerylisting.xml');

    $xpathvar = new Domxpath($xmldoc);

    $queryResult = $xpathvar->query('gallerylisting//folder[@subfolder="yes"]/text()');
    foreach($queryResult as $result){
            echo $result->textContent;
    }
?>

我不是PHP人,所以我相信this StackOverflow question中的代码。需要注意的一点是,在xpath中使用// name意味着找到与当前位置匹配的所有节点。这在大型文档上可能非常慢。

似乎有多种方法可以用PHP处理xpath。来自this page的示例执行查询,如下所示:     

   $result = $xml->xpath("gallerylisting//folder[@subfolder="yes"]/text()");

   print_r($result);
?>