PHP SimpleXMLObject を再帰的に配列にキャストする必要があります。問題は、各サブ要素も PHP SimpleXMLElement であることです。
これは可能ですか?
json_decode(json_encode((array) simplexml_load_string($obj)), 1);
これをテストしませんでしたが、これで完了したようです。
function convertXmlObjToArr($obj, &$arr)
{
$children = $obj->children();
foreach ($children as $elementName => $node)
{
$nextIdx = count($arr);
$arr[$nextIdx] = array();
$arr[$nextIdx]['@name'] = strtolower((string)$elementName);
$arr[$nextIdx]['@attributes'] = array();
$attributes = $node->attributes();
foreach ($attributes as $attributeName => $attributeValue)
{
$attribName = strtolower(trim((string)$attributeName));
$attribVal = trim((string)$attributeValue);
$arr[$nextIdx]['@attributes'][$attribName] = $attribVal;
}
$text = (string)$node;
$text = trim($text);
if (strlen($text) > 0)
{
$arr[$nextIdx]['@text'] = $text;
}
$arr[$nextIdx]['@children'] = array();
convertXmlObjToArr($node, $arr[$nextIdx]['@children']);
}
return;
}
可能です。これは、親要素のタグと、子がなくなった要素のタグ+コンテンツを出力する再帰関数です。配列を構築するためにそれを変更することができます:
foreach( $simpleXmlObject as $element )
{
recurse( $element );
}
function recurse( $parent )
{
echo '<' . $parent->getName() . '>' . "\n";
foreach( $parent->children() as $child )
{
if( count( $child->children() ) > 0 )
{
recurse( $child );
}
else
{
echo'<' . $child->getName() . '>';
echo iconv( 'UTF-8', 'ISO-8859-1', $child );
echo '</' . $child->getName() . '>' . "\n";
}
}
echo'</' . $parent->getName() . '>' . "\n";
}
SimpleXMLObjectはとにかく配列と同じように脅威にさらされる可能性があるため、要点はわかりません...
しかし、本当にそれが必要な場合は、このスレッドまたはフォーラムのこの投稿で、 chassagnetteの回答を確認してください。
ここでは、配列への再帰キャストの反復的な (再帰的なデータを解析することでスタック爆発が発生するとは思わない場合でも) 実装を示します。これは、json_**decode 関数を介して渡すよりも直接的な方法です。
function xml2Array(SimpleXMLElement $el): stdClass {
$ret = $el;
$stack = [&$ret];
while (count($stack) > 0) {
$cur = &$stack[count($stack) - 1];
array_splice($stack, -1);
$cur = (object) (array) $cur;
foreach ($cur as $key => $child) {
$childRef = &$cur->{$key};
if ($child instanceof SimpleXMLElement)
$stack[count($stack) - 1] = &$childRef;
elseif(is_array($child))
foreach ($childRef as $ckey => $cell) {
if ($cell instanceof SimpleXMLElement)
$stack[count($stack) - 1] = &$childRef[$ckey];
}
}
}
return $ret;
}