Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Преобразование XML в ассоциативный массив
Форумы портала PHP.SU » PHP » Напишите за меня, пожалуйста » Преобразование XML в ассоциативный массив

Страниц (1): [1]
 

1. Robotex - 07 Марта, 2009 - 18:19:23 - перейти к сообщению
Целый день бьюсь над этой задачей. Существующие решения не удовлетворяют (можно пользоваться только средствами встроенного в PHP парсера, бесплатные библиотеки начальство не уважает).

В общем проблема такая:

есть xml-документ, например:
CODE (text):
скопировать код в буфер обмена
  1.  
  2. <text>
  3.   Text3
  4.   <p>Text1</p>
  5.   <p>Text2</p>
  6.   Text4
  7. </text>
  8.  


Надо получить массив:

PHP:
скопировать код в буфер обмена
  1.  
  2. $a_xml = array(
  3.   0 => array(
  4.     'name' => 'text',
  5.     'attrib' => array(),
  6.     'content' => array(
  7.       0 => 'Text3',
  8.       1 => array(
  9.         0 => array(
  10.           'name' => 'p',
  11.           'attrib' => array(),
  12.           'content' => array(
  13.             0 => 'Text1'
  14.           )
  15.       ),
  16.       2 => array(
  17.         0 => array(
  18.           'name' => 'p',
  19.           'attrib' => array(),
  20.           'content' => array(
  21.             0 => 'Text2'
  22.           )
  23.       ),
  24.       3 => 'Text4'
  25.     )
  26.   )
  27. )
  28.  


Что-то наподобие этого.
Буду благодарен за любую помощь.

Вот основа, кстати:

PHP:
скопировать код в буфер обмена
  1.  
  2. <?PHP
  3.  
  4. $file = "d:/job/xml.xml";
  5.  
  6. $xml_parser = xml_parser_create('utf-8');
  7.  
  8. xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
  9.  
  10. $data = file_get_contents($file);
  11. $a_value=array();
  12. $a_index=array();
  13. if(!xml_parse_into_struct($xml_parser, $data, $a_value, $a_index))
  14.   debug_info('XML Error: '.xml_error_string(xml_get_error_code($xml_parser)).' at line '.xml_get_current_line_number($xml_parser));
  15.  
  16. // тут собственно и должен быть код. Свой набросок не даю, ибо по-любому собьет с верного пути
  17.  
  18. xml_parser_free($xml_parser);
  19.  
  20. ?>
  21.  

(Добавление)
Рекурсивное решение вертится в голове, но никак не могу его схватить...
(Добавление)
Вот хороший, код. Но не правильно отрабатывает приведенный выше пример (
PHP:
скопировать код в буфер обмена
  1. /*  
  2.     Working with XML. Usage:  
  3.     $xml=xml2ary(file_get_contents('1.xml'));  
  4.     $link=&$xml['ddd']['_c'];  
  5.     $link['twomore']=$link['onemore'];  
  6.     // ins2ary(); // dot not insert a link, and arrays with links inside!  
  7.     echo ary2xml($xml);  
  8. */  
  9.  
  10. // XML to Array  
  11. function xml2ary(&$string) {  
  12.     $parser = xml_parser_create();  
  13.     xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);  
  14.     xml_parse_into_struct($parser, $string, $vals, $index);  
  15.     xml_parser_free($parser);  
  16.  
  17.     $mnary=array();  
  18.     $ary=&$mnary;  
  19.     foreach ($vals as $r) {  
  20.         $t=$r['tag'];  
  21.         if ($r['type']=='open') {  
  22.             if (isset($ary[$t])) {  
  23.                 if (isset($ary[$t][0])) $ary[$t][]=array(); else $ary[$t]=array($ary[$t], array());  
  24.                 $cv=&$ary[$t][count($ary[$t])-1];  
  25.             } else $cv=&$ary[$t];  
  26.             if (isset($r['attributes'])) {foreach ($r['attributes'] as $k=>$v) $cv['_a'][$k]=$v;}  
  27.             $cv['_c']=array();  
  28.             $cv['_c']['_p']=&$ary;  
  29.             $ary=&$cv['_c'];  
  30.  
  31.         } elseif ($r['type']=='complete') {  
  32.             if (isset($ary[$t])) { // same as open  
  33.                 if (isset($ary[$t][0])) $ary[$t][]=array(); else $ary[$t]=array($ary[$t], array());  
  34.                 $cv=&$ary[$t][count($ary[$t])-1];  
  35.             } else $cv=&$ary[$t];  
  36.             if (isset($r['attributes'])) {foreach ($r['attributes'] as $k=>$v) $cv['_a'][$k]=$v;}  
  37.             $cv['_v']=(isset($r['value']) ? $r['value'] : '');  
  38.  
  39.         } elseif ($r['type']=='close') {  
  40.             $ary=&$ary['_p'];  
  41.         }  
  42.     }      
  43.        
  44.     _del_p($mnary);  
  45.     return $mnary;  
  46. }  
  47.  
  48. // _Internal: Remove recursion in result array  
  49. function _del_p(&$ary) {  
  50.     foreach ($ary as $k=>$v) {  
  51.         if ($k==='_p') unset($ary[$k]);  
  52.         elseif (is_array($ary[$k])) _del_p($ary[$k]);  
  53.     }  
  54. }  
  55.  
  56. // Array to XML  
  57. function ary2xml($cary, $d=0, $forcetag='') {  
  58.     $res=array();  
  59.     foreach ($cary as $tag=>$r) {  
  60.         if (isset($r[0])) {  
  61.             $res[]=ary2xml($r, $d, $tag);  
  62.         } else {  
  63.             if ($forcetag) $tag=$forcetag;  
  64.             $sp=str_repeat("\t", $d);  
  65.             $res[]="$sp<$tag";  
  66.             if (isset($r['_a'])) {foreach ($r['_a'] as $at=>$av) $res[]=" $at=\"$av\"";}  
  67.             $res[]=">".((isset($r['_c'])) ? "\n" : '');  
  68.             if (isset($r['_c'])) $res[]=ary2xml($r['_c'], $d+1);  
  69.             elseif (isset($r['_v'])) $res[]=$r['_v'];  
  70.             $res[]=(isset($r['_c']) ? $sp : '')."</$tag>\n";  
  71.         }  
  72.            
  73.     }  
  74.     return implode('', $res);  
  75. }  
  76.  
  77. // Insert element into array  
  78. function ins2ary(&$ary, $element, $pos) {  
  79.     $ar1=arrayarray_slice($ary, 0, $pos); $ar1[]=$element;  
  80.     $ary=arrayarray_merge($ar1, arrayarray_slice($ary, $pos));  
  81. }  
  82.  
  83.  
  84. //Example Convert XML to Array  
  85. $xml=xml2ary(file_get_contents('1.xml'));  
  86. print_r($xml);  
  87.  
  88. //Example Convert Array to XML  
  89. $xml=xml2ary(file_get_contents('1.xml'));  
  90. $xml['ddd']['_c']['twomore']=$xml['ddd']['_c']['onemore'];  
  91. $xml['ddd']['_c']['twomore']['_c']['tt'][0]['_v']='hello';  
  92. echo ary2xml($xml);  
2. Джур - 07 Марта, 2009 - 20:07:44 - перейти к сообщению
simplexml_load_string() вам в руки...
рекурсивно пробегаете по узлам и всего делов.

правда вот беда, это бесплатная часть, бесплатного РНР... начальство не одобрит. Ха-ха
3. Robotex - 07 Марта, 2009 - 20:12:42 - перейти к сообщению
Джур пишет:
правда вот беда, это бесплатная часть, бесплатного РНР... начальство не одобрит.

да это то начальство одобрит ))) но мне оно не нравится... Там же ж объекты вставляются ))) Если только вручную перебрать потом )

Блин, как я сам до этого не додумался )
(Добавление)
Попробовал...
Оно болеет той же болезнью, что и приведенный выше исходник.

Вот код:
PHP:
скопировать код в буфер обмена
  1. <text style='strong'>
  2.   Bla
  3.   <p>This is <b>p1</b></p>
  4.   <div>This is p4</div>
  5.   Bla-bla
  6. </text>
  7.  


вот результат обработки
PHP:
скопировать код в буфер обмена
  1. object(SimpleXMLElement)#1 (3) {
  2.  ["@attributes"]=>
  3.   array(1) {
  4.     ["style"]=>
  5.     string(6) "strong"
  6.   }
  7.   ["p"]=>
  8.   string(8) "This is "
  9.   ["div"]=>
  10.   string(10) "This is p4"
  11. }

Теги b и текст в теге text бесследно исчезли
4. Джур - 07 Марта, 2009 - 22:21:54 - перейти к сообщению
опять 25. Ха-ха
ну вообщето они никуда не делись...
просто метод __toString данной штуки возращает на глубину в 1-н еденицу...
вам достаточно по найденым элементам пройтись...



Кстати... где-то на этом форуме я уже кому-то такую штуку писал...
Там больше подробностей
5. Robotex - 08 Марта, 2009 - 22:01:16 - перейти к сообщению
Блин, оно их еще и в группы собирает (
Как узнать какой тег за каким идет?

Форум называется "Напишите за меня пожалуйста", а не "Поржите с ленивого дурака"
6. Robotex - 09 Марта, 2009 - 18:22:28 - перейти к сообщению
В общем я уже сам все сделал. Правда структура не такая, как в первом сообщении. Как оказалось, та что приведена ниже намного удобнее для меня.
Если кому нибудь нужно - ловите...

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. function doc_xml_para($s_xml, $level)
  4. {
  5.         $xml_parser = xml_parser_create('utf-8');
  6.         xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
  7.  
  8.         $a_values = array();
  9.         $a_index = array();
  10.  
  11.         if (!xml_parse_into_struct($xml_parser, $s_xml, $a_values, $a_index))
  12.             trigger_error('XML Error: '.xml_error_string(xml_get_error_code($xml_parser)).' at line '.xml_get_current_line_number($xml_parser));
  13.  
  14.         xml_parser_free($xml_parser);
  15.  
  16.         $a_para = array();
  17.         $para = array();
  18.  
  19.         $i_level = 0;
  20.         $b_open = false;
  21.   $a_stack = array();
  22.  
  23.         for($i=0;$i<count($a_values);$i++)
  24.         {
  25.           if($a_values[$i]['level'] >= $level)
  26.           {
  27.             if($a_values[$i]['type'] === 'open')
  28.             {
  29.               if(!$b_open)
  30.               {
  31.                       $b_open = true;
  32.                       $i_level = $a_values[$i]['level'];
  33.                       $para = array(
  34.                         'text' => isset($a_values[$i]['value'])?trim($a_values[$i]['value']):'',
  35.                         'tag' => $a_values[$i]['tag'],
  36.                         'attributes' => isset($a_values[$i]['attributes'])?$a_values[$i]['attributes']:array()
  37.                       );
  38.               }
  39.               else
  40.               {
  41.           $a_style = array();
  42.           $a_style['tag'] = $a_values[$i]['tag'];
  43.           $a_style['cpStart'] = strlen($para['text']);
  44.           if($a_style['cpStart']>0)
  45.             $a_style['cpStart']++;
  46.           if(isset($a_values[$i]['value']))
  47.                 {
  48.                   $value = trim($a_values[$i]['value']);
  49.                   if(!empty($para['text']))
  50.                     $space = ' ';
  51.                   else
  52.                     $space = '';
  53.             $para['text'] = $para['text']./*' <'.$a_values[$i]['tag'].'>'.*/((!empty($value))?($space.$value):'');
  54.           }
  55.           $a_style['cpLast'] = 0;
  56.           $a_style['attributes'] = isset($a_values[$i]['attributes'])?$a_values[$i]['attributes']:array();
  57.           $para['style'][] = $a_style;
  58.  
  59.           $a_stack[] = array(
  60.             'tag' => $a_values[$i]['tag'],
  61.             'index' => count($para['style'])-1
  62.           );
  63.               }
  64.             }
  65.             elseif($a_values[$i]['type'] === 'complete')
  66.             {
  67.               $value = '';
  68.               if(isset($a_values[$i]['value']))
  69.               {
  70.                   $value = trim($a_values[$i]['value']);
  71.               }
  72.               if($b_open && $a_values[$i]['level'] > $i_level && !empty($value))
  73.               {
  74.                 $a_style = array();
  75.                 $a_style['tag'] = $a_values[$i]['tag'];
  76.                 $a_style['cpStart'] = strlen($para['text']);
  77.                 if($a_style['cpStart']>0)
  78.             $a_style['cpStart']++;
  79.  
  80.           if(!empty($para['text']))
  81.             $space = ' ';
  82.           else
  83.             $space = '';
  84.           $para['text'] = $para['text']./*' <'.$a_values[$i]['tag'].'>'.*/((!empty($value))?($space.$value):'')/*.'</'.$a_values[$i]['tag'].'>'*/;
  85.  
  86.                 $a_style['cpLast'] = strlen($para['text'])-1;
  87.                 $a_style['attributes'] = isset($a_values[$i]['attributes'])?$a_values[$i]['attributes']:array();
  88.                 $para['style'][] = $a_style;
  89.               }
  90.               elseif(!$b_open)
  91.               {
  92.                 $a_para[] = array(
  93.                   'text' => isset($a_values[$i]['value'])?trim($a_values[$i]['value']):'',
  94.                   'tag' => $a_values[$i]['tag'],
  95.                   'attributes' => isset($a_values[$i]['attributes'])?$a_values[$i]['attributes']:array()
  96.                 );
  97.               }
  98.             }
  99.             elseif($a_values[$i]['type'] === 'cdata' && isset($a_values[$i]['value']))
  100.             {
  101.               $value = trim($a_values[$i]['value']);
  102.               if(!empty($para['text']))
  103.                 $space = ' ';
  104.               else
  105.                 $space = '';
  106.               $para['text'] = $para['text'].(!empty($value)?($space.$value):'');
  107.             }
  108.             elseif($b_open && $a_values[$i]['type'] === 'close')
  109.             {
  110.               if($a_values[$i]['level'] === $i_level)
  111.               {
  112.                       $b_open = false;
  113.                       $a_para[] = $para;
  114.         }
  115.         else
  116.         {
  117.                 $tag = array_pop($a_stack);
  118.           if($tag['tag'] === $a_values[$i]['tag'])
  119.           {
  120.                   //$para['text'] = $para['text'].'</'.$a_values[$i]['tag'].'>';
  121.                   $para['style'][$tag['index']]['cpLast'] = strlen($para['text'])-1;
  122.                 }
  123.                 else
  124.                 {
  125.                   trigger_error('doc_xml_para: Internal error');
  126.                 }
  127.               }
  128.             }
  129.           }
  130.         }
  131.  
  132.   return $a_para;
  133. }
  134.  
  135. ?>

 

Powered by ExBB FM 1.0 RC1