我有一个包含大量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=
怎么了?
答案 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 scopes,php functions和recursion。
答案 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缩放设置了文本的情况,在这种情况下,上面将是无限循环。