views:

199

answers:

2

Hello,

I am using arrays in PHP to modify xml data and write it back. This is the xml structure (simplified for demonstration purpose):

<docs>
  <folder>
    <name>Folder name</name>
    <date>20.06.2009</date>
    <folder>
      <name>Subfolder1</name>
      <date></date>
    </folder>
    <folder>
      <name>Subfolder1</name>
      <date></date>
    </folder>
    <file>
      <name></name>
    </file>
  </folder>
  <name></name>
  <date></date>
</docs>

Using this code, this is then parsed and transformed into a multidimensional array:

Array
(
    [docs] => Array
        (
            [_c] => Array
                (
                    [folder] => Array
                        (
                            [_c] => Array
                                (
                                    [name] => Array
                                        (
                                            [_v] => Folder name
                                        )

                                    [date] => Array
                                        (
                                            [_v] => 20.06.2009
                                        )

                                    [folder] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [_c] => Array
                                                        (
                                                            [name] => Array
                                                                (
                                                                    [_v] => Subfolder1
                                                                )

                                                            [date] => Array
                                                                (
                                                                    [_v] => 
                                                                )

                                                        )

                                                )

                                            [1] => Array
                                                (
                                                    [_c] => Array
                                                        (
                                                            [name] => Array
                                                                (
                                                                    [_v] => Subfolder1
                                                                )

                                                            [date] => Array
                                                                (
                                                                    [_v] => 
                                                                )

                                                        )

                                                )

                                        )

                                    [file] => Array
                                        (
                                            [_c] => Array
                                                (
                                                    [name] => Array
                                                        (
                                                            [_v] => 
                                                        )

                                                )

                                        )

                                )

                        )

                    [name] => Array
                        (
                            [_v] => 
                        )

                    [date] => Array
                        (
                            [_v] => 
                        )

                )

        )

)

Lengthy, I know. But now to the actual issue. If I want to add another file to a sub folder called Subfolder2 in this case, it's not a problem to do it by hand when u see the structure:

array_push($array['docs']['_c']['folder']['_c']['folder'][1], $newfile);

Now when I want to do it via the function that only knows a path to the folder (like docs/Folder name/Subfolder2), the algorithm has to analyze the array structure (check the name of each [folder], check if there is one or more folders ['_c'] or [number]) - all good, but I cannot find a way to create a variable that would have an "array" path for that new file.

I was thinking somewhere along these lines:

$writepath = "['docs']['_c']['folder']...[1]"; // path string
array_push($array{$writepath}, $newfile);

Of course this is not a valid syntax.

So, how can I make a variable that contains a path through the array elements? I did a bit of research on w3c and php.net finding no helpful info on multidimensional arrays...

If anyone has any other suggestions regarding structure, xml transformation/manipulation etc. by all means, I know it is far from sufficient way of data handling.

Thanks for any input,

Erik


Edit: Regarding the reference, is it possible to reference the reference? As that would be the way to move the 'pointer' through a set of arrays? Something as such:

$pointer = &$array['docs'];
if (key($pointer) == '_c') { $pointer = &$pointer['_c']; }
else (
  // create an array with '_c' key instead of empty '_v' array
)

This syntax does not work.

Edit: The syntax works, never mind... Thanks for all your help guys!

+2  A: 

Using references might help.

You could firstly write a function that returns a reference to the given part of the array for a path string. For example, get_path_array("Documents") would return $array['docs']['_c']['folder']['_c']['folder'][1], $newfile)

<?php
function &get_path_array($path_str)
{
    // your code to seek to seek the path in the array
    return $result;
}
>?php

Now to add an element, you could just do

array_push(get_path_array("docs/Folder name/Subfolder2"), $newfile);

Is that what you were looking for?

(See php references for more info)

Edit: In reply to Eric's comment (a bit too hard to fit into a comment)

I think you may be confused about how arrays work. There isn't really any such thing as multidimentional arrays in php, just arrays that are storing other arrays. For example,

<?php
$a = array(array(1,2,3), array(4,5,6));
$b = $a[1];
echo $b[0];
?>

Will output "4".

Note that in the above code, $b is a copy of $a[1], changing $b won't affect $a[1]. However, using references, this can be made to work:

<?php
$a = array(array(1,2,3), array(4,5,6));
$b = &$a[1]; // the & make $b a reference to $a[1]
$b[0] = 4242;
print_r($a);
?>

Outputs:

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

    [1] => Array
        (
            [0] => 4242
            [1] => 5
            [2] => 6
        )

)

So there is never a need to generate the string $array['doc']['path'], you just use a loop to seek the right array.

nanothief
I'm not sure, how can I generate this 'string' $array['docs']['c'] to be executed? The point is I don't understand how to store square brackets as a variable that would be executed? Can you elaborate?
Erik
@Eric: See the addition to my answer. Does that help?
nanothief
Perfect! The light bulb just lit! :) Thank you for your time nanothief, and what a great community stackoverflow is!Regards
Erik
Could you comment on my addition to my original question? Thanks
Erik
+4  A: 
VolkerK
Using xpath is a very nice solution to this problem. It takes a bit longer to learn than just using a xml -> array solution, but I think it would pay off in the long run.
nanothief
Great answer! I guess I can start exploring the SimpleXML extension as it is a lot simpler to manage. It does however <a href="http://us2.php.net/manual/en/simplexml.requirements.php">require PHP 5</a>. Thanks a lot!
Erik