1

I'm using jsTree and I need to convert this HTML tag tree code <ul> <li> to a PHP array. The jsTree HTML tag will be passed to PHP to be parsed and store in a structured tree PHP array(see below for the PHP array structure).

Additional question: Is my desired PHP array structure good or you can suggest a good structure? I'm open for suggestions.

Thanks in advance :)

Cheers, Mark

jsTree Screenshot:

alt text

HTML Tree String:

<ul class="ltr">
<li id="phtml_1" class="  open">
    <a style="" class=" " href="#"><ins>&nbsp;</ins>Folder 1</a>
    <ul>
    <li class="leaf" id="phtml_2">
        <a style="" class=" " href="#"><ins>&nbsp;</ins>Child 1.1</a>
    </li>
    <li class="open" id="phtml_3">
        <a style="" class=" " href="#"><ins>&nbsp;</ins>Folder 1.1</a>
        <ul>
        <li class="leaf last" rel="default">
            <a href="" style="" class=" "><ins>&nbsp;</ins>Child 1.1.1</a>
        </li>
        </ul>
    </li>
    <li class="last open" rel="default">
        <a href="" style="" class=" "><ins>&nbsp;</ins>Folder 1.2</a>
        <ul>
        <li class="leaf" rel="default">
            <a href="" style="" class=" "><ins>&nbsp;</ins>Child 1.2.1</a>
        </li>
        <li class="leaf last" rel="default">
            <a href="" style="" class=" "><ins>&nbsp;</ins>Child 1.2.2</a>
        </li>
        </ul>
    </li>
    </ul>
</li>
<li id="phtml_5" class="file open">
    <a style="" class=" " href="#"><ins>&nbsp;</ins>Folder 2</a>
    <ul>
    <li class="leaf" rel="default">
        <a href="" style="" class=" "><ins>&nbsp;</ins>Child 2.1</a>
    </li>
    <li class="leaf last" rel="default">
        <a href="" style="" class="clicked"><ins>&nbsp;</ins>Child 2.2</a>
    </li>
    </ul>
</li>
<li class="leaf last" rel="default">
    <a href="" style="" class=" "><ins>&nbsp;</ins>Outer Child</a>
</li>
</ul>

PHP Array Structure:

<?php
$tree_array = array(
    'Folder 1' => array(
        'Child 1.1',
        'Folder 1.1' => array(
            'Child 1.1.1'
        ),
        'Folder 1.2' => array(
            'Child 1.2.1',
            'Child 1.2.2'
        ),
    ),
    'Folder 2' => array(
        'Child 2.1',
        'Child 2.2'
    ),
    'Outer Child'
);

echo '<pre>',print_r($tree_array),'</pre>';
?>

PHP print_r Output:

Array
(
    [Folder 1] => Array
        (
            [0] => Child 1.1
            [Folder 1.1] => Array
                (
                    [0] => Child 1.1.1
                )

            [Folder 1.2] => Array
                (
                    [0] => Child 1.2.1
                    [1] => Child 1.2.2
                )

        )

    [Folder 2] => Array
        (
            [0] => Child 2.1
            [1] => Child 2.2
        )

    [0] => Outer Child
)
2
  • I.e. you start with a fragment of HTML and want to end up with a PHP array? Commented May 12, 2010 at 9:08
  • @Salman: Yes. I'm creating a jsTree editor with buttons to add, edit, delete, move, copy, paste and rename functionalities. After the edit of the user, I need to save the HTML tag tree structure. My problem I'm having a hard time parsing the string HTML tag and save it in a PHP array. Commented May 13, 2010 at 6:34

4 Answers 4

3

Regarding:

My problem I'm having a hard time parsing the string HTML tag and save it in a PHP array.

I suggest that you use an HTML parser, such as simplehtmldom. This will allow you to traverse over HTML DOM just the way you want.

Here is a quick and dirty UL walking script:

<?php
    require_once( "simplehtmldom/simple_html_dom.php" );
    $DOM = file_get_html( "test.htm" );
    $ARR = array( );
    function WalkUL( $ul, &$ar )
    {
        foreach( $ul->children as $li )
        {
            if ( $li->tag != "li" )
            {
                continue;
            }
            $arar = array( );
            foreach( $li->children as $ulul )
            {
                if ( $ulul->tag != "ul" )
                {
                    continue;
                }
                WalkUL( $ulul, $arar );
            }
            $ar[ $li->find( "a", 0 )->plaintext ] = $arar;
        }
    }
    WalkUL( $DOM->find( "ul", 0 ), $ARR );
    print_r( $ARR );
?>

Its output, not exactly as you wanted it but close:

Array
(
    [Folder 1] => Array
        (
            [Child 1.1] => Array
                (
                )
            [Folder 1.1] => Array
                (
                    [Child 1.1.1] => Array
                        (
                        )
                )
            [Folder 1.2] => Array
                (
                    [Child 1.2.1] => Array
                        (
                        )
                    [Child 1.2.2] => Array
                        (
                        )
                )
        )
    [Folder 2] => Array
        (
            [Child 2.1] => Array
                (
                )
            [Child 2.2] => Array
                (
                )
        )
    [Outer Child] => Array
        (
        )
)
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Salman. I'm currently testing simplehtmldom I downloaded in phpclasses.org when I read your answer. Thanks for your WalkUL function, it will help :) Cheers
I will just need to edit the PHP array structure to cater my needs. Thanks again :>
The only problem in the array structure is that if there are multiple same folder name then it will overwrite the array key. But I will find a way to put it in value instead in the key.
Complicated but possible. Your "child arrays" can be associative arrays: array( "label" => "Folder 1", "children" => array( ) );. Gets tricky!
3

Instead of messing with html you should submit the tree data in a more programmer-friendly format.

$('#saveButton').click(function() {
    var treeData = $.tree.reference($('#sortableTree')).get(undefined, 'json');
    var tmp = serializeTree(treeData, 0);
    // now json-encode tmp and submit it
});

function serializeTree(nodes, parent)
{
    var parents = {};
    var childOrder = []
    var childOrders = {};
    for(var i = 0; i < nodes.length; i++)
    {
        var node = nodes[i];
        var id = node.attributes.id.substr(5); // assuming the id looks like 'abcd-ID'
        parents[id] = parent;
        childOrder.push(id);
        if(node.children)
        {
            var tmp = serializeTree(node.children, id);
            for(var id in tmp[0])
                parents[id] = tmp[0][id];
            for(var id in tmp[1])
                childOrders[id] = tmp[1][id]
        }
    }

    childOrders[parent] = childOrder;

    return [parents, childOrders];
}

2 Comments

Nice! :) A fast reply. You're good sir. I will try it now. Thanks! :D
Um I javascript alert tmp and this is the output: [{_1:0, _2:"_1", _3:"_1", _5:0}, {_1:["_2", "_3"], 0:["_1", "_5"]}] I don't get it? Hhmm... Can you elaborate please? Thanks again :)
0

Just for referecence: there's also a jQuery plugin for serializing a HTML DOM Tree of <ol> and <ul> lists: http://www.drakedata.com/serializetree/sampleTree.html - it converts a nested structure of <ol> and <ul> lists to a string which can be used as an associated php array.

Comments

0

If you have a UL that does not contain any href elements (e.g. just plain text nexted ul).. I've adjusted Salman's simplehtmldom code to work with that:

$DOM = str_get_html( $catshtml );
$ARR = array( );
function WalkUL( $ul, &$ar )
{
    foreach( $ul->children as $li )
    {
        if ( $li->tag != "li" )
        {
            continue;
        }
        $arar = array( );
        foreach( $li->children as $ulul )
        {
            if ( $ulul->tag != "ul" )
            {
                continue;
            }
            WalkUL( $ulul, $arar );
        }
        $ar[ trim(preg_replace("#</?[a-z]+[^>]*>(.+</[a-z]+[^>]*>|)#is","",$li->innertext)) ] = $arar;
    }
}
WalkUL( $DOM->find( "ul", 0 ), $ARR );
echo "<pre>"; print_r( $ARR );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.