За последние 24 часа нас посетили 18215 программистов и 1640 роботов. Сейчас ищут 1145 программистов ...

Парсинг XML в двумерные ассоциативные массивы.

Тема в разделе "PHP для новичков", создана пользователем RHrum, 31 мар 2019.

  1. RHrum

    RHrum Новичок

    С нами с:
    31 мар 2019
    Сообщения:
    3
    Симпатии:
    0
    Суть- имеется огромное (более сотни) количество взаимосвязанных XML-файлов.
    Каждый файл хранит инфомацию об определенном числе объектов в виде атрибутов.
    Эти атрибуты добавлялись тем,кто заполнял XML не сразу,а по ходу разработки другого продукта (закрытого, т.е. доступ имеется только в информации в виде пар XML - CSV с одинаковым контентом).
    У каждого объекта есть заранее известный уникальный идентификатор в виде одного из атрибутов (условно ID="12345"). Остальные атрибуты неуникальны, смешанной природы (числа и строки).
    Требуется перегнать все файлы в условные массивы, либо любой аналог,позволяющий обратиться к ноде с нужным "ключевым" атрибутом, и выдрать нужный иной атрибут.
    Пример- условный Items.xml
    С контентом (помимо хедера)
    <Class ID="12222" Value="None" Price="2000" Amount="201"....>
    <Class ID="10022" Price="2001" Amount="201".....>
    И иной файл, условный Tools.xml
    <Class ID="2001111" ToolClass="None" Price="2001"...>

    Нужно иметь возможность обратиться к $Items[10022]['Price'] (результат- 2001) и $Tools[201111]['Price']- результат 2001.

    Что пытаюсь сделать (в условиях PHP 5.3):

    PHP:
    1. function SaXtA ($filenames, $ArrayName, $KeyAttrib)
    2. {   $list=explode(" ", $filenames);
    3.     foreach($list as $filename){
    4.  
    5.     $objector=simplexml_load_file($filename);
    6.  
    7.  
    8.  
    9.     foreach($objector->xpath('/idspace/Class') as $products)
    10.     {
    11.  
    12.         foreach ($products->attributes() as $CAtt => $CAttvalue)
    13.         {
    14.            
    15.            
    16.            ${(string)$ArrayName}[(string)$CAtt][(int)$products['ID']] =$CAttvalue;
    17.  
    18.         }
    19.         }
    20.     }
    21. }
    Однако либо получаю Illegal offset type, или , при иных попытках, массив просто не создаётся. Хотя при выводе в консоль $CAtt или отдельно $products['ID'] -всё окей.
    Понимаю,что такой вид динамического объявления через $$- фу,но... Руками перебирать всю сотню файлов-никак.

    После парсинга в массивы будет вывод в .HTML -файлы, где потребуется иметь возможность прямого обращения к элементам. В то же время чато придётся обращаться к содержимому одного файла через другой,так что листать огромные XML (десятки тысяч элементов) foreach`ами,как это делал прошлый разработчик- огромная потеря по времени,хотя и экономящая в итоге память.
     
    #1 RHrum, 31 мар 2019
    Последнее редактирование модератором: 31 мар 2019
  2. Павел Голубцов

    Павел Голубцов Активный пользователь

    С нами с:
    4 мар 2019
    Сообщения:
    183
    Симпатии:
    4
    Входные данные:
    HTML:
    1. Class ID="12222" Value="None" Price="2000" Amount="201"
    Обрабатываем:
    PHP:
    1. $pattern = '|(ID="[\d]+") .*(Price="([\d]+)")|';
    2. $str = file_get_contents('путь к файлу');
    3. $disa = preg_split($pattern, $str, -1, PREG_SPLIT_DELIM_CAPTURE);
    4. echo $disa[1] . ' равно: ' . $disa[3];
    Результат:
    ID="12222" равно: 2000
     
  3. RHrum

    RHrum Новичок

    С нами с:
    31 мар 2019
    Сообщения:
    3
    Симпатии:
    0
    Не вариант. Гонять регулярки по файлам,суммарное количество строк в которых измеряется десятками тысяч....
    Тут проблема не в том,что я не могу получить нужное поле из файла.
    Проблема в том,что я не совсем уловил синтаксис динамического объявления двумерных массивов, с ключами ,берущимися из других переменных.

    Т.е. условно массив $foo['Bar']['Baz'], задаваемый выражением типа ${$varfoo[$Varbar[$a]][$Varbaz[$b]]}
    Имеем:
    $ArrayName="Item";
    $CAtt="Name";
    $products['ID']= 1100;
    Проблема в том,что ${$ArrayName[$CAtt][products['ID]}="Foobarbaz"; - уже ловлю варнинг,и по факту массив не создаётся.
    Уже пробовал разные приведения переменных к (string), ключа к (int), даже трим для перевода в строку. Всё равно.
     
  4. Павел Голубцов

    Павел Голубцов Активный пользователь

    С нами с:
    4 мар 2019
    Сообщения:
    183
    Симпатии:
    4
    Это 2 одномерных массива.
    Я тебе предлагал парсить регуляркой первый блок с данными.
    Получать 2 переменные нужные.
    Имея 2 переменные с данными делай с ними что хочешь.
    Используя во втором блоке данных.
    Используй просто.
    Делай из них массив.
    ID останутся те же и Price.
     
  5. RHrum

    RHrum Новичок

    С нами с:
    31 мар 2019
    Сообщения:
    3
    Симпатии:
    0
    Эээ...Нет.
    Эти массивы двумерны.
    Первое измерение- это первый ключ. $Items[10022] и $Items[30000] -разные сущности
    Второе измерение- второй ключ. $Items[10022]['Name']-один атрибут исходной записи, а $Items[10022]['Value'],например- другой.
    И да,повторюсь, способ "достать" эти переменные я уже оформил, и двойным Foreach (первый- по листу нод,второй -по списку атрибутов каждой ноды) достаю я всё,что нужно. SimpleXML в этом плане меня целиком устраивает.
    Проблема именно в объявлении (инициализации и т.д.) двумерных массивов с заранее неизвестным списком ключей (которые парсятся на лету).
     
  6. Павел Голубцов

    Павел Голубцов Активный пользователь

    С нами с:
    4 мар 2019
    Сообщения:
    183
    Симпатии:
    4
    Двумерный да, сам уже запутался, пока смотрел, какие откуда массивы выходят ).
    Сделай функцию которая бы создавала массив, постепенно при парсинге.
    Получил переменные добавил в массив, а не сперва весь парсинг потом массив, может так ?