Answer the question
In order to leave comments, you need to log in
What is the correct way to write a recursive function to create a menu tree from a multidimensional associative array?
Hello.
Given: XML file.
Required: process the XML file and output HTML based on it.
The structure of an XML file starts with <params>
, nested in <systems>
. Next come the groups <group>
, which can have any number of attachments. And the last level is <parameter>
c <value>
inside.
That is, the differences are only in the nesting of tags <group>
. And these groups should be displayed as menu items. The text must come from the textid
tag attribute <group>
.
At first, I made the option with one level, but, alas, groups can have an unknown number of nesting levels and my solution did not fit at all.
I translate XML into an array and I'm already trying to build a tree from it.
To be honest, I am a teapot and swim in elementary things so far. And if working with an array could somehow be mastered, then, coupled with a recursive function, I got stuck tightly.
At the moment there is one of the wrong solutions. The tree is displayed without nesting levels and not in order.
Can someone help me rewrite my function (in procedural style) so that the correct tree is displayed?
I put an example of my "code" in one file for convenience:
$string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<system>
<params>
<group id="a08150" txtid="Item A Level 1">
<parameter id="a08151" type="1" txtid="A Parameter 1-1">
<value>true</value>
</parameter>
<parameter id="a08152" type="1" txtid="A Parameter 1-2">
<value>false</value>
</parameter>
<parameter id="a08153" type="3" txtid="A Parameter 1-3">
<value>1100</value>
</parameter>
<parameter id="a08154" type="0" txtid="A Parameter 1-4">
<value>Text</value>
</parameter>
</group>
<group id="a08200" txtid="Item B Level 1">
<group id="a08210" txtid="Subitem B Level 2">
<group id="a08220" txtid="Subitem B Level 3">
<parameter id="a08221" type="0" txtid="B Parameter 3-1">
<value>Example Text</value>
</parameter>
</group>
</group>
</group>
<group id="a08300" txtid="Item C Level 1">
<group id="a08310" txtid="Subitem C Level 2">
<group id="a08320" txtid="Subitem C Level 3-1">
<parameter id="a08321" type="0" txtid="C Parameter 3-1-1">
<value>Example Text</value>
</parameter>
<parameter id="a08322" type="0" txtid="C Parameter 3-1-2">
<value>Example Text</value>
</parameter>
<parameter id="a08322" type="0" txtid="C Parameter 3-1-3">
<value>Example Text</value>
</parameter>
</group>
<group id="a08330" txtid="Subitem C Level 3-2">
<group id="a08340" txtid="Subitem C Level 4-1">
<group id="a08350" txtid="Subitem C Level 5-1">
<parameter id="a08331" type="0" txtid="C Parameter 5-1">
<value>Example Text</value>
</parameter>
<parameter id="a08332" type="0" txtid="C Parameter 5-2">
<value>Example Text</value>
</parameter>
<parameter id="a08332" type="0" txtid="C Parameter 5-3">
<value>Example Text</value>
</parameter>
</group>
</group>
</group>
<parameter id="a08311" type="0" txtid="C Parameter 2-1">
<value>Example Text</value>
</parameter>
</group>
<parameter id="a08301" type="0" txtid="C Parameter 1-1">
<value>Example Text</value>
</parameter>
<parameter id="a08302" type="0" txtid="C Parameter 1-2">
<value>Example Text</value>
</parameter>
</group>
<group id="a08160" txtid="Item D Level 1">
<parameter id="a08161" type="0" txtid="Text Input">
<value>Example Text</value>
</parameter>
<parameter id="a08162" type="1" txtid="Checkbox (Boolean) unchecked">
<value>false</value>
</parameter>
<parameter id="a08163" type="1" txtid="Checkbox (Boolean) checked">
<value>true</value>
</parameter>
<parameter id="a08164" type="2" txtid="Float">
<value>25.75</value>
</parameter>
<parameter id="a08165" type="3" txtid="Integer">
<value>1979</value>
</parameter>
<parameter id="a08166" type="4" txtid="IP4">
<value>127.0.0.1</value>
</parameter>
<parameter id="a08167" type="5" txtid="IP6">
<value>0:0:0:0:0:ffff:7f00:1</value>
</parameter>
<parameter id="a08168" type="7" txtid="List">
<value>3</value>
<range>
<row txtid="List1">1</row>
<row txtid="List2">2</row>
<row txtid="List3">3</row>
<row txtid="List4">4</row>
<row txtid="List5">5</row>
</range>
</parameter>
</group>
</params>
</system>
XML;
$xml = simplexml_load_string( $string );
$json_string = json_encode( $xml );
$input_array = json_decode( $json_string, TRUE );
function build_tree( $input_array, $tree = '' )
{
if( !is_array( $input_array ) )
{
return '';
}
foreach( $input_array as $key => $value )
{
if( $key === 'group' )
{
$branch = '';
if( isset( $value[ '@attributes' ][ 'txtid' ] ) )
{
$title = $value[ '@attributes' ][ 'txtid' ];
if( $title )
{
$branch .= '<li>' . $title . '</li>';
}
}
else
{
foreach( $value as $inner_values )
{
$title = '';
if( isset( $inner_values[ '@attributes' ] ) )
{
$title = $inner_values[ '@attributes' ][ 'txtid' ];
}
if( $title )
{
$branch .= '<li>' . $title . '</li>';
}
}
}
if( $branch )
{
$tree .= '<ul>' . $branch . '</ul>';
}
}
$tree .= build_tree( $value );
}
return $tree;
}
echo build_tree( $input_array );
Answer the question
In order to leave comments, you need to log in
I will answer myself, maybe it will be useful to someone. The final solution turned out to be something like this:
function build_tree( $input_array, $output = '' )
{
if( !is_array( $input_array ) )
{
return '';
}
if( array_key_exists( 'group', $input_array ) )
{
$output .= '<ul>';
}
foreach( $input_array as $key => $value )
{
if( ( isset( $value[ '@attributes' ][ 'txtid' ] ) ) && ( $key !== 'parameter' ) )
{
$id = $value[ '@attributes' ][ 'id' ];
$title = $value[ '@attributes' ][ 'txtid' ];
$output .= '<li>' . $title;
if( array_key_exists( 'group', $value ) )
{
$output .= build_tree( $value );
}
$output .= '</li>';
}
elseif( $key !== 'parameter' )
{
$output .= build_tree( $value );
}
}
if( array_key_exists( 'group', $input_array ) )
{
$output .= '</ul>';
}
return $output;
}
I did not work with php, but perhaps this article will shed light on the truth.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question