1

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 Answers 2

4

Although this isn't exactly an answer to your question: Instead of the xml<->array code you could use SimpleXML and its XPath capabilities.

<?php
$xml = '<docs>
  <folder>
    <name>Folder name</name>
    <date>20.06.2009</date>
    <folder>
      <name>Subfolder1</name>
      <date></date>
    </folder>
    <folder>
      <name>Subfolder2</name>
      <date></date>
      <folder>
        <name>Subfolder3</name>
        <date></date>
      </folder>
    </folder>
  </folder>
</docs>';

$doc = new SimpleXMLElement($xml); $pathToParentelement = '//folder[name="Subfolder3"]'; $element = $doc->xpath($pathToParentelement); isset($element[0]) or die('not found');
$newFolder = $element[0]->addChild("folder"); $newFolder->name = "Subfolder4.1"; $newFolder->date = date(DATE_RFC822);
// let's see the result echo $doc->asxml();

$pathToParentelement is more or less your $writepath.

Sign up to request clarification or add additional context in comments.

2 Comments

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.
Great answer! I guess I can start exploring the SimpleXML extension as it is a lot simpler to manage. It does however <a href="us2.php.net/manual/en/… PHP 5</a>. Thanks a lot!
2

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.

4 Comments

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?
@Eric: See the addition to my answer. Does that help?
Perfect! The light bulb just lit! :) Thank you for your time nanothief, and what a great community stackoverflow is! Regards
Could you comment on my addition to my original question? Thanks

Your Answer

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