XML探索后的PHP返回值

时间:2015-09-14 16:58:43

标签: php xml function

我有一个包含大量XML用户的PHP数组 - 文件URL:

$tab_users[0]=john.xml
$tab_users[1]=chris.xml
$tab_users[n...]=phil.xml

对于每个用户a< zoom>标签是否已填写,具体取决于用户是否填写:

john.xml = <zoom>Some content here</zoom>
chris.xml = <zoom/>
phil.xml = <zoom/>

我正在尝试浏览用户数据并显示第一个填充的&lt; zoom&gt; tag,但随机化:每次重新加载页面时,&lt; div id =“zoom”&gt;内容不同。

$rand=rand(0,$n); // $n is the number of users
$datas_zoom=zoom($n,$rand); 

我的PHP功能

function zoom($n,$rand) {   
    global $tab_users;

    $datas_user=new SimpleXMLElement($tab_users[$rand],null,true);
    $tag=$datas_user->xpath('/user');

    //if zoom found
    if($tag[0]->zoom !='') {
        $txt_zoom=$tag[0]->zoom;  
    }

    ... some other taff here

    // no "zoom" value found
    if ($txt_zoom =='') { 
       echo 'RAND='.$rand.' XML='.$tab_users[$rand].'<br />';
       $datas_zoom=zoom($r,$n,$rand); } // random zoom fct again and again till...
    }
    else {
       echo 'ZOOM='.$txt_zoom.'<br />';
       return $txt_zoom; // we got it!
    }

}

echo '<br />Return='.$datas_zoom;

问题是:当探索的第一个XML偶然包含一个“缩放”信息时,函数会返回它,但如果没有,则返回...当第一个偶然是好的时,结果的例子:

// for RAND=0, XML=john.xml
ZOOM=Anything here

Return=Some content here // we're lucky

不幸的:

RAND=1 XML=chris.xml

RAND=2 XML=phil.xml

// the for RAND=0 and XML=john.xml
ZOOM=Anything here 

// content founded but Return is empty

Return=

怎么了?

3 个答案:

答案 0 :(得分:1)

我建议将值导入数据库表,生成单个本地文件或类似的东西。这样您就不必为每个请求打开并解析所有XML文件。

读取多个文件比读取单个文件慢得多。使用数据库甚至可以将随机逻辑移动到SQL。

您目前正在使用SimpleXML,但使用DOM实际上从XML文档中获取单个值实际上更容易。 SimpleXMLElement::xpath()仅支持返回节点列表的Xpath表达式,但DOMXpath::evaluate()可以直接返回标量值:

$document = new DOMDocument();
$document->load($xmlFile);
$xpath = new DOMXpath($document);

$zoomValue = $xpath->evaluate('string(//zoom[1])');

//zoom[1]将获取节点列表中的第一个zoom元素节点。将列表转换为字符串将返回第一个节点的文本内容,如果列表为空(未找到节点),则返回空字符串。

为了这个例子,假设您生成了一个像这样的XML

<zooms>
  <zoom user="u1">z1</zoom>
  <zoom user="u2">z2</zoom>
</zooms>

在这种情况下,您可以使用Xpath获取所有缩放节点并从列表中获取随机节点。

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

$zooms = $xpath->evaluate('//zoom');
$zoom = $zooms->item(mt_rand(0, $zooms->length - 1));

var_dump(
  [
    'user' => $zoom->getAttribute('user'),
    'zoom' => $zoom->textContent
  ]
);

答案 1 :(得分:0)

您的主要问题是在没有找到缩放时您没有返回任何值。

$datas_zoom=zoom($r,$n,$rand); // no return keyword here!

当你使用递归时,你通常想要&#34;链&#34;返回值,直到找到你需要的值。 $datas_zoom不是一个全局变量,它不会泄漏出来#34;在你的功能之外。请阅读php's variable scope documentation了解更多信息。

然后,您再次使用三个参数(zoom)调用$r,$n,$rand函数,而该函数只能处理两个($n$rand)。此外,$r尚未确定,$n根本未被使用,您很可能会一次又一次地尝试使用相同的$rand值,这显然无效。

另请注意,代码中的结束括号太多了。

我认为解决问题的最佳方法是对数组进行洗牌,然后像FIFO一样使用它而不进行递归(这应该稍快一些):

function zoom($tab_users) {
    // shuffle an array once
    shuffle($tab_users);

    // init variable
    $txt_zoom = null;

    // repeat until zoom is found or there 
    // are no more elements in array
    do {
        $rand = array_pop($tab_users);
        $datas_user = new SimpleXMLElement($rand, null, true);
        $tag=$datas_user->xpath('/user');

        //if zoom found
        if($tag[0]->zoom !='') {
            $txt_zoom=$tag[0]->zoom;  
        }

    } while(!$txt_zoom && !empty($tab_users));

    return $txt_zoom;
}

$datas_zoom = zoom($tab_users); // your zoom is here!

请详细了解php scopesphp functionsrecursion

答案 2 :(得分:0)

没有理由进行递归。一个简单的循环就可以了。

$datas_user=new SimpleXMLElement($tab_users[$rand],null,true);
$tag=$datas_user->xpath('/user');

$max = $tag->length;
while(true) {
    $test_index = rand(0, $max);
    if ($tag[$test_index]->zoom != "") {
        break;
    }
}

当然,您可能需要添加更多逻辑来处理NO缩放设置了文本的情况,在这种情况下,上面将是无限循环。