对我上一个问题的某种跟进:for loop - move deeper on numeric key in multidimensional array
我将此数组作为输入:
Array
(
[0] => apl_struct Object
(
[funcname] => say
[args] => Array
(
[0] => Array
(
[0] => apl_struct Object
(
[funcname] => text
[args] => Array
(
[value] => hello
)
)
)
)
)
)
我现在有两个功能为我工作。 一个是仅用于获取关联数组中的下一个键/值的函数。 next(),prev()等都不像索引数组那样对我有用:
function getnext($array, $key) {
$keys = array_keys($array);
if ((false !== ($p = array_search($key, $keys))) && ($p < count($keys) - 1)) {
return array('key' => $keys[++$p], 'value' => $array[$keys[$p]]);
} else {return false;}
}
下一个功能是我的执行者或构造者。他为我创造了一个半xmlstruct。 我试图添加递归来跳过数字键。他们显然是胡说八道,可以跳过。
然后我想检查非数字键的所有值是否都是数组。 如果它是一个数组,则表示要遵循的参数,输出应如下所示:INPUT。
如果没有,它可以是函数名(funcname),也可能是我们的实际值,例如&#34;你好&#34;。
function arr2xml($array, $level = 1, $pos = 1) {
$xml = '';
foreach ($array as $key => $value) {
if (is_object($value)) {$value = get_object_vars($value);}// convert object to array
if (is_numeric($key)) {
$xml .= arr2xml($value);
} else {
if (!is_array($value)) {
switch ($key) {
case 'funcname':
$nextkey = getnext($array, $key);
$xml .= str_repeat("\t", $level) . "<apl:$value>\n";
$xml .= arr2xml($nextkey['value'], $level++);
$xml .= str_repeat("\t", $level) . "</apl:$value>\n";
break;
case 'value':
$xml .= str_repeat("\t", $level) . "\t$value\n";
break;
}
} else {
$xml .= str_repeat("\t", $level) . "<$key pos='$pos'>\n\t";
$xml .= arr2xml($value, $level++, $pos++);
$xml .= str_repeat("\t", $level) . "</$key>\n";
}
}
}
return $xml;
}
但到目前为止我得出的是: 功能名称插入正确。 这是说和文字。 另外,在某些狂野的情况下,-tag和值都可以正确执行。
<apl:say>
<apl:text>
hello
</apl:text>
<args pos='1'>
hello
</args>
</apl:say>
<args pos='1'>
<apl:text>
hello
</apl:text>
<args pos='1'>
hello
</args>
</args>
</xml>
对我而言,看起来递归并不是真的有效。我错过了什么吗?
我试图从之前提到的帖子重建它。
我也想知道我在这里得到的多重输出。 标签似乎正确填充,但实际安排对我来说非常混乱。
我期待输出看起来像这样:
<apl:say>
<args pos='1'>
<apl:text>
<args pos='1'>
hello
</args>
</apl:text>
</args>
</apl:say>
提前致谢
答案 0 :(得分:1)
它是(完全多余的函数)getnext()
的组合,以及你的arr2xml()
如何递归。我在这里提供了一个arr2xml()
替换函数,它可以执行您想要的操作,而无需getnext()
。
详细说明了代码中出了什么问题,以及我建议如何修复它。
function arr2xml($array, $level = 0, $pos = 1) {
$xml = '';
foreach ($array as $key => $value) {
if (is_object($value)) {
$value = get_object_vars($value);
}
if (is_numeric($key)) {
$xml .= arr2xml($value, $level+1);
continue;
} else {
if (!is_array($value)) {
switch ($key) {
case 'funcname':
array_shift($array);
$xml .= str_repeat(" ", $level) . "<apl:$value>\n";
$xml .= arr2xml($array, $level+1);
$xml .= str_repeat(" ", $level) . "</apl:$value>\n";
return $xml;
case 'value':
$xml .= str_repeat(" ", $level) . " $value\n";
return $xml;
}
} else {
$xml .= str_repeat(" ", $level) . "<$key pos='$pos'>\n ";
$xml .= arr2xml($value, $level+1, $pos+1);
$xml .= str_repeat(" ", $level) . "</$key>\n";
return $xml;
}
}
}
return $xml;
}
Here是一个eval.in,显示在您提供的相同数据结构上使用的这个新函数,为您提供或多或少的所需输出(空格可能不是您想要的,我会离开这对你来说是锻炼。)
当funcname
为'say'
时,条件case 'funcname':
调用getnext()
,$key
设置为'funcname'
,$array
设置为:
array(2) {
["funcname"]=>
string(3) "say"
["args"]=>
array(1) {
[0]=>
array(1) {
[0]=>
object(apl_struct)#1 (2) {
["funcname"]=>
string(4) "text"
["args"]=>
array(1) {
["value"]=>
string(5) "hello"
}
}
}
}
}
然后在该数组('funcname'
)中找到$p = array_search($key, $keys)
并创建一个仅包含数组中下一项值的新数组:
return array('key' => $keys[++$p], 'value' => $array[$keys[$p]]);
结果是一个不再包含'args'
键的数组:
array(2) {
["key"]=>
string(4) "args"
["value"]=>
array(1) {
[0]=>
array(1) {
[0]=>
object(apl_struct)#1 (2) {
["funcname"]=>
string(4) "text"
["args"]=>
array(1) {
["value"]=>
string(5) "hello"
}
}
}
}
}
因此,您永远不会得到您希望的标记,因为数据结构已被getnext()
损坏,以删除您希望找到的密钥以构建它。
可以通过先前从内部递归返回来解决重复值。现在,您正在递归,处理“内部”节点,然后返回到顶部并再次处理它们。
相反,我们可以完全删除getnext
(因为它甚至不能做你想要的),我们可以使用array_shift代替丢弃数组的最左边的值。然后我们继续正常处理$array
。
答案 1 :(得分:0)
function apl2xml($array, $tlevel = 0) {
$ret = '';
$ret .= str_repeat("\t", $tlevel) . "<apl>\n";
foreach ($array as $key => $value) {
$ret .= $this->aplstruct2xml($value, $tlevel + 1);
}
$ret .= str_repeat("\t", $tlevel) . "</apl>\n";
return $ret;
}
function aplstruct2xml($apl_struct, $tlevel = 0) {
$ret = '';
if ($apl_struct->funcname == 'text') {
$ret .= str_repeat("\t", $tlevel) . "<text>\n";
$ret .= str_repeat("\t", $tlevel);
$ret .= $apl_struct->args[0] . "\n";
$ret .= str_repeat("\t", $tlevel) . "</text>\n";
} else {
$ret .= str_repeat("\t", $tlevel) . "<aplfunc:{$apl_struct->funcname}>\n";
foreach ($apl_struct->args as $key => $value) {
$ret .= str_repeat("\t", $tlevel + 1) . "<arg pos='$key'>\n";
$ret .= $this->apl2xml($value, $tlevel + 2);
$ret .= str_repeat("\t", $tlevel + 1) . "</arg>\n";
}
$ret .= str_repeat("\t", $tlevel) . "</aplfunc:{$apl_struct->funcname}>\n";
}
return $ret;
}
原来我根本不需要任何递归..
所谓的apl只包含一个apl_struct,它可能包含更多apl / apl_struct的