Как использовать переменную для доступа к определенному элементу в многомерном массиве? - PullRequest
1 голос
/ 20 июня 2009

Я использую массивы в PHP, чтобы изменить данные XML и записать их обратно. Это структура xml (упрощенная для демонстрации):

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

Используя этот код , он затем анализируется и преобразуется в многомерный массив:

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] => 
                        )

                )

        )

)

Длинна, я знаю. Но теперь к актуальному вопросу. Если в этом случае я хочу добавить другой файл в подпапку с именем Subfolder2 , это не проблема сделать вручную, когда вы увидите структуру:

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

Теперь, когда я хочу сделать это с помощью функции, которая знает только путь к папке (например, docs / Имя папки / Subfolder2 ), алгоритм должен проанализировать структуру массива (проверить имя каждая [папка], проверьте, есть ли одна или несколько папок ['_c'] или [число]) - все хорошо, но я не могу найти способ создать переменную, которая будет иметь " массив " путь к этому новому файлу.

Я думал где-то так:

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

Конечно, это неправильный синтаксис.

Итак, как я могу создать переменную, которая содержит путь через элементы массива? Я провел небольшое исследование по w3c и php.net, не обнаружив полезной информации о многомерных массивах ...

Если у кого-либо есть какие-либо предложения относительно структуры, преобразования / манипуляции с XML и т. Д. Всеми средствами, я знаю, что это далеко не достаточный способ обработки данных.

Спасибо за любой вклад,

Эрик


Редактировать: Что касается ссылки, можно ли ссылаться на ссылку? Как это будет способ перемещения «указателя» через набор массивов? Нечто подобное:

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

Этот синтаксис не работает.

Редактировать: Синтаксис работает, неважно ... Спасибо за вашу помощь, ребята!

Ответы [ 2 ]

4 голосов
/ 20 июня 2009

Хотя это не точно ответ на ваш вопрос: вместо кода массива xml <-> вы могли бы использовать SimpleXML и его возможности XPath ,

<?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>';</p>

<p>$doc = new SimpleXMLElement($xml);
$pathToParentelement = '//folder[name="Subfolder3"]';
$element = $doc->xpath($pathToParentelement);
isset($element[0]) or die('not found');<br>
$newFolder = $element[0]->addChild("folder");
$newFolder->name = "Subfolder4.1";
$newFolder->date = date(DATE_RFC822);<br>
// let's see the result
echo $doc->asxml();
$ pathToParentelement является более или менее вашим $ writepath.
2 голосов
/ 20 июня 2009

Использование ссылок может помочь.

Вы могли бы сначала написать функцию, которая возвращает ссылку на заданную часть массива для строки пути. Например, get_path_array("Documents") вернет $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

Теперь, чтобы добавить элемент, вы можете просто сделать

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

Это то, что вы искали?

(см. php ссылки для дополнительной информации)

Редактировать: В ответ на комментарий Эрика (слишком сложно вписать в комментарий)

Думаю, вы не понимаете, как работают массивы. На самом деле в php нет такой вещи, как многомерные массивы, просто массивы, которые хранят другие массивы. Например,

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

Выводит "4".

Обратите внимание, что в приведенном выше коде $b является копией $a[1], изменение $b не повлияет на $a[1]. Однако, используя ссылки, это можно заставить работать:

<?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);
?>

Выходы:

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

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

)

Так что вам не нужно генерировать строку $array['doc']['path'], вы просто используете цикл для поиска нужного массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...