За последние 24 часа нас посетили 26604 программиста и 1482 робота. Сейчас ищут 916 программистов ...

ремэйк xml2array()

Тема в разделе "Прочие вопросы по PHP", создана пользователем avm, 18 ноя 2006.

  1. avm

    avm Активный пользователь

    С нами с:
    21 сен 2006
    Сообщения:
    597
    Симпатии:
    0
    Адрес:
    Москва
    Отличное небольшое решение xml2array - (c) Vladson. Мне показалось, что можно было бы его чуть-чуть развить, и получилось:
    PHP:
    1.  
    2. <?php
    3. //
    4. // Parse XML data into an array
    5. //
    6. function xml2array($text) {
    7.     $reg_exp = "/<(\w+)([^>]*)>(.*?)<\/\\1>/s";
    8.     preg_match_all($reg_exp, $text, $match);
    9.     foreach ($match[1] as $key=>$val) {
    10.         $index = count($array[$val]);
    11.         if (strlen($all_args=trim($match[2][$key]))) {
    12.             preg_match_all("/[\s]*([^\=]+)\=[\"']*(.*?)[\"']+[\s]*/ms",$all_args,$arg);
    13.             for( $j=0; $j < count($arg[1]); $j++ )
    14.             $array[$val][$index]['arg'][ $arg[1][$j] ] = $arg[2][$j];
    15.         }
    16.         $data = trim($match[3][$key]);
    17.         $array[$val][$index]['data'] = (substr($data,0,9)=='<![CDATA[') || !preg_match($reg_exp,$data)
    18.                 ? preg_replace("/(^(\/\/|\/\*)\s*<!\[CDATA\[\s*|\s*(\/\/|\*\/)\s*\]\]>$)/mi",'',html_entity_decode($data))
    19.                 : xml2array($data);
    20.     }
    21.     return $array;
    22. }
    23. ?>
    24.  
    Внимание! этот код создает массив несколько другой структуры, и его нельзя использовать вместо оригинала не изменив обработку возвращаемого массива!

    К недостаткам можно отнести пожалуй то, что корректно обрабатывается только валидный код, а также некорректно будут обработаны параметры тегов у которых есть вложенные кавычки типа "двойная-одинарная-двойная" (понятно изъясняюсь?)

    К этому коду можно было бы еще приделать обработку тегов без закрывающей части (которые должны закрываться "/>" ), тогда эта крохотная функция могла бы стать довольно полезным инструментом.
     
  2. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Ты не первый кто делает ремейк (аналогов также много в каментах про XML в мануале на php.net)
    Однако твой вариант мне нравится больше так как он не перегружен излишествами...
     
  3. avm

    avm Активный пользователь

    С нами с:
    21 сен 2006
    Сообщения:
    597
    Симпатии:
    0
    Адрес:
    Москва
    я там крайне редко встречал что-либо интересное, зато там невероятно много ерунды и криворукости/кривоголовости.
     
  4. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Этого там БОЛЬШЕ чем можно представить...

    Даже моя функция xml2array там в немного другом виде (в ламерском), регулярку подправил один из первых людей кому эта функция понравилась
     
  5. NIKO

    NIKO Активный пользователь

    С нами с:
    10 фев 2006
    Сообщения:
    655
    Симпатии:
    0
    Адрес:
    Armenia
    А мож сделать функцию более глубоким, в смысле чтоб вместо xml2array($text) сделать xml2array($file) ? :) наверное поняли
     
  6. avm

    avm Активный пользователь

    С нами с:
    21 сен 2006
    Сообщения:
    597
    Симпатии:
    0
    Адрес:
    Москва
    NIKO, в этом нет необходимости, поскольку задача часто бывает не из файла (или url) данные брать, а из других источников. А сделать "обложку" вида:
    PHP:
    1. <?php $s = xml2array(file_get_contents("filename.xml")); ?>
    не так и сложно...
     
  7. NIKO

    NIKO Активный пользователь

    С нами с:
    10 фев 2006
    Сообщения:
    655
    Симпатии:
    0
    Адрес:
    Armenia
    ну как хотите :)
     
  8. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    А можно сделать так...
    Код (Text):
    1. function xml2array($text, $is_file=false) {
    2.     if ($is_file) $text = file_get_contents($text);
    Таким образом по дефолту функция не будет отличаться от оригинала
    Код (Text):
    1. $array = xml2array($string);
    а для парсинга файла достаточно будет добавит один параметр
    Код (Text):
    1. $array = xml2array($filename, true);
     
  9. avm

    avm Активный пользователь

    С нами с:
    21 сен 2006
    Сообщения:
    597
    Симпатии:
    0
    Адрес:
    Москва
    Чуть-чуть переделал. Теперь она нормально обрабатывает и "одиночные" узлы (тэги) типа <tagname aaa="bbb" />
    PHP:
    1. <?php
    2. function xml2array($text) {
    3.     $reg_exp = "/<(\w+)([\s]+([^>]*)\/|\/|([^>]*)>(.*?)<\/\\1)>/ms";
    4.     preg_match_all($reg_exp, $text, $match);
    5.     foreach ($match[1] as $key=>$val) {
    6.         $index = isset($array[$val]) ? count($array[$val]) : 0;
    7.         $n = ($hasChildren = strlen($data = trim($match[5][$key]))) ? 4 : 3;
    8.         if ($alen=strlen($all_args=trim($match[$n][$key]))) {
    9.             $array[$val][$index]['params'] = parse_args($all_args[$alen-1]=='/'?substr($all_args,0,$alen-1):$all_args);
    10.         } else $array[$val] = array();
    11.         if ($hasChildren) $array[$val][$index]['nodes'] = (substr($data,0,9)=='<![CDATA[') || !preg_match($reg_exp,$data)
    12.             ? preg_replace("/(^(\/\/|\/\*)\s*<!\[CDATA\[\s*|\s*(\/\/|\*\/)\s*\]\]>$)/mi",'',html_entity_decode($data))
    13.             : xml2array($data);
    14.     }
    15.     return $array;
    16. }
    17. ?>
    Я не привожу здесь используемую функцию преобразования строки аргументов в массив parse_args() - не о ней речь.

    Теперь у этой функции есть только один принципиальный недостаток - она неверно обрабатывает одинаковые вложенные узлы (тэги)