简单 xml 元素上的 foreach 中的无限循环
Infinite loop in foreach on a simplexmlelement
我遇到了一个特殊的问题,因为我没有找到太多参考资料。我发现 simpleXMLElement attributes and foreach 描述了同样的问题,但是已经一年没有答案了,也没有任何答案。
对于一些上下文,我正在尝试使用 PHPOffice/PHPExcel
,并且在加载 xlsx
文件时,此框架在第 364 至 376 行的 simplexmlelement
上循环Excel2007.php
,可在 https://github.com/PHPOffice/PHPExcel/blob/1.8/Classes/PHPExcel/Reader/Excel2007.php 获得,其中几行摘自此处(我添加了 var_dump 和 echo):
foreach ( $colourScheme as $k => $xmlColour ) {
var_dump ( $xmlColour ); echo 'NEWVAR';
$themePos = array_search ( $k, $themeOrderArray );
if (! $themePos) {
$themePos = $themeOrderAdditional ++;
}
if (isset ( $xmlColour->sysClr )) {
$xmlColourData = $xmlColour->sysClr->attributes ();
$themeColours [$themePos] = $xmlColourData ['lastClr'];
} elseif (isset ( $xmlColour->srgbClr )) {
$xmlColourData = $xmlColour->srgbClr->attributes ();
$themeColours [$themePos] = $xmlColourData ['val'];
}
}
$colourScheme
var 是一个 SimpleXMLElement
,其中包含 12 个 SimpleXMLElements
,所有这 12 个都有一个 SimpleXMLElement
0 作为子级,除了一个 "srgbClr"
.
当我尝试调试它时,$k
var 在循环的 2 次迭代中得到更新,然后不再更改($colorScheme
中出现 12 次),因此循环无限(或至少直到时间限制,我尝试了一个很长的值)。
如果我评论我的 php.ini
的以下几行(我正在使用 wampServer
的 64b 版本,在 Windows 7 上,使用 eclisePDT 调试图标作为 web 开始调试应用程序),死循环似乎没有发生,并且文件似乎转换得很好。
; XDEBUG Extension
zend_extension = "D:/path/to/wamp/bin/php/php5.5.12/zend_ext/php_xdebug-2.2.5-5.5-vc11-x86_64.dll"
;
[xdebug]
xdebug.remote_enable = on
xdebug.remote_host = "localhost"
xdebug.remote_port = 9000
xdebug.remote_handler = "dbgp"
xdebug.remote_mode = req
xdebug.profiler_enable = On
xdebug.profiler_enable_trigger = off
xdebug.profiler_output_name = cachegrind.out.%t.%p
xdebug.profiler_output_dir = "D:/path/to/tmp/tmp"
xdebug.show_local_vars = on
xdebug.collect_params = on
编辑:更多信息。
一切似乎都工作正常(php.ini
评论与否),直到我在 eclipse 中添加断点并要求调试我的页面。一旦我添加断点,就会发生无限循环,并且我会因最大执行时间或最大内存限制而停止。我用一个小文件 (20KB) 测试了它,它似乎工作,调试与否,以及一个更大的文件 (750KB),但它失败了。
在步进时,我可以肯定地看到我的密钥 $k
在第二次迭代后没有得到更新。
如果有人有想法,或者任何可以帮助我调试而无需无限循环的东西,那就太好了!
非常感谢您的宝贵时间和帮助!
我最近刚刚在同一个文件中完成了一些类似的工作。我花了很长时间才意识到的一件事是 SimpleXML 扩展中有一个错误可能会导致此问题:https://bugs.php.net/bug.php?id=55098
似乎对我有用的是:
foreach ($colourScheme as $k => $xmlColour) {
...
}
尝试使用 children()
方法:
foreach ($colourScheme->children() as $k => $xmlColour) {
...
}
要尝试的另一件事是在尝试循环之前用计数包装它:
if ($colourScheme->count() > 0) {
...
}
这里的问题是 SimpleXML 对象不是数组,并不总是像您想象的那样工作。即使是 children()
的文档,这可能与 foreach
循环中发生的转换行为相同,也说无论是否有子元素,都将返回一个 SimpleXML 元素。因此你一遍又一遍地迭代同一个对象(无限循环):
如果一切都失败了,你可以convert it to a real array并这样处理:
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
参考文献:
http://php.net/manual/en/simplexmlelement.children.php
http://php.net/manual/en/simplexmlelement.count.php
我遇到了一个特殊的问题,因为我没有找到太多参考资料。我发现 simpleXMLElement attributes and foreach 描述了同样的问题,但是已经一年没有答案了,也没有任何答案。
对于一些上下文,我正在尝试使用 PHPOffice/PHPExcel
,并且在加载 xlsx
文件时,此框架在第 364 至 376 行的 simplexmlelement
上循环Excel2007.php
,可在 https://github.com/PHPOffice/PHPExcel/blob/1.8/Classes/PHPExcel/Reader/Excel2007.php 获得,其中几行摘自此处(我添加了 var_dump 和 echo):
foreach ( $colourScheme as $k => $xmlColour ) {
var_dump ( $xmlColour ); echo 'NEWVAR';
$themePos = array_search ( $k, $themeOrderArray );
if (! $themePos) {
$themePos = $themeOrderAdditional ++;
}
if (isset ( $xmlColour->sysClr )) {
$xmlColourData = $xmlColour->sysClr->attributes ();
$themeColours [$themePos] = $xmlColourData ['lastClr'];
} elseif (isset ( $xmlColour->srgbClr )) {
$xmlColourData = $xmlColour->srgbClr->attributes ();
$themeColours [$themePos] = $xmlColourData ['val'];
}
}
$colourScheme
var 是一个 SimpleXMLElement
,其中包含 12 个 SimpleXMLElements
,所有这 12 个都有一个 SimpleXMLElement
0 作为子级,除了一个 "srgbClr"
.
当我尝试调试它时,$k
var 在循环的 2 次迭代中得到更新,然后不再更改($colorScheme
中出现 12 次),因此循环无限(或至少直到时间限制,我尝试了一个很长的值)。
如果我评论我的 php.ini
的以下几行(我正在使用 wampServer
的 64b 版本,在 Windows 7 上,使用 eclisePDT 调试图标作为 web 开始调试应用程序),死循环似乎没有发生,并且文件似乎转换得很好。
; XDEBUG Extension
zend_extension = "D:/path/to/wamp/bin/php/php5.5.12/zend_ext/php_xdebug-2.2.5-5.5-vc11-x86_64.dll"
;
[xdebug]
xdebug.remote_enable = on
xdebug.remote_host = "localhost"
xdebug.remote_port = 9000
xdebug.remote_handler = "dbgp"
xdebug.remote_mode = req
xdebug.profiler_enable = On
xdebug.profiler_enable_trigger = off
xdebug.profiler_output_name = cachegrind.out.%t.%p
xdebug.profiler_output_dir = "D:/path/to/tmp/tmp"
xdebug.show_local_vars = on
xdebug.collect_params = on
编辑:更多信息。
一切似乎都工作正常(php.ini
评论与否),直到我在 eclipse 中添加断点并要求调试我的页面。一旦我添加断点,就会发生无限循环,并且我会因最大执行时间或最大内存限制而停止。我用一个小文件 (20KB) 测试了它,它似乎工作,调试与否,以及一个更大的文件 (750KB),但它失败了。
在步进时,我可以肯定地看到我的密钥 $k
在第二次迭代后没有得到更新。
如果有人有想法,或者任何可以帮助我调试而无需无限循环的东西,那就太好了!
非常感谢您的宝贵时间和帮助!
我最近刚刚在同一个文件中完成了一些类似的工作。我花了很长时间才意识到的一件事是 SimpleXML 扩展中有一个错误可能会导致此问题:https://bugs.php.net/bug.php?id=55098
似乎对我有用的是:
foreach ($colourScheme as $k => $xmlColour) {
...
}
尝试使用 children()
方法:
foreach ($colourScheme->children() as $k => $xmlColour) {
...
}
要尝试的另一件事是在尝试循环之前用计数包装它:
if ($colourScheme->count() > 0) {
...
}
这里的问题是 SimpleXML 对象不是数组,并不总是像您想象的那样工作。即使是 children()
的文档,这可能与 foreach
循环中发生的转换行为相同,也说无论是否有子元素,都将返回一个 SimpleXML 元素。因此你一遍又一遍地迭代同一个对象(无限循环):
如果一切都失败了,你可以convert it to a real array并这样处理:
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
参考文献:
http://php.net/manual/en/simplexmlelement.children.php http://php.net/manual/en/simplexmlelement.count.php