【问题标题】:PHP and XML. Looping through an XML file with PHPPHP 和 XML。使用 PHP 循环遍历 XML 文件
【发布时间】:2011-10-13 19:52:31
【问题描述】:

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

  1. 获取所有文件夹元素名称
  2. 如果文件夹元素具有“是”作为子文件夹属性,则向下移动一个级别并获取该文件夹元素的名称
  3. 如果不移动到下一个文件夹元素

画廊列表.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。

感谢您的帮助。

【问题讨论】:

  • 当你用效率标记这个问题时,我会提出这一点。您的 xml 中不需要“子文件夹”属性。 PHP-Library 将帮助您了解该节点是否有子节点。如果有,请递归使用@Matt 的函数。您不应该将“文本”元素(例如您的文件夹名称)与节点混合。这看起来有点恶心。尝试使用“名称”属性。
  • 注意以备将来参考!谢谢你的坦率! (badump ch!)

标签: php xml foreach performance


【解决方案1】:

您可以尝试使用xpath 代替嵌套循环方法..

运行查询

gallerylisting//folder[@subfolder="yes"]/text() 

在上面给出的 xml 文档中,使用 this xpath tester 会给出结果事件和 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);
?> 

【讨论】:

    【解决方案2】:

    递归在这里可能对你有益。

    <?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());
    

    【讨论】:

    • 我将不得不尝试你的交易,这个 xpath Wrikken 在下面谈论。到时我会给出我的答案。这似乎是我会在 Javascript 中做的事情,所以是的,它还很遥远。
    • 是的!是的!这就是它兄弟,这完全是它。我在实际调用它时在 display_entities 参数中做了一些小改动,我只使用了 $xmlref。这让我得到了一切!你是邪恶的兄弟。
    • 您应该使用一个标志并将 if 移出内部 foreach 循环,否则内部 display_entitties 可能会被多次调用,而只有真的需要每个孩子一次。
    【解决方案3】:

    使用 XPath:

    如果 subfolder=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){
    

    【讨论】:

    • 我将不得不研究 xpath 的考验。它看起来很合法。
    猜你喜欢
    • 2021-11-12
    • 2020-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多