Web

Как преобразовать XML в массив PHP

Я хочу преобразовать XML в массив PHP. Есть предложения, как я могу это сделать?

<aaaa Version="1.0">

   <bbb>

     <cccc>

       <dddd Id="id:pass" />

       <eeee name="hearaman" age="24" />

     </cccc>

   </bbb>

</aaaa>

 

Ответ 1

Используя расширение SimpleXML (я считаю, что оно входит в стандартную комплектацию большинства установок php).

Синтаксис для вашего примера выглядит примерно так:

$xml = new SimpleXMLElement($xmlString);

echo $xml->bbb->cccc->dddd['Id'];

echo $xml->bbb->cccc->eeee['name'];

// или...........

foreach ($xml->bbb->cccc as $element) {

  foreach($element as $key => $val) {

   echo "{$key}: {$val}";

  }

}

 

Ответ 2

Преобразование строки XML($buffer) в упрощенный массив без учета атрибутов и группировки дочерних элементов с одинаковыми именами:

function XML2Array(SimpleXMLElement $parent) {

    $array = array();

    foreach ($parent as $name => $element) {

        ($node = & $array[$name])

            && (1 === count($node) ? $node = array($node) : 1)

            && $node = & $node[];

        $node = $element->count() ? XML2Array($element) : trim($element);

    }

    return $array;

}

xml   = simplexml_load_string($buffer);

$array = XML2Array($xml);

$array = array($xml->getName() => $array);

 

Результат:

Array (

    [aaaa] => Array  (

            [bbb] => Array  (

                    [cccc] => Array  (

                            [dddd] => 

                            [eeee] => 

                        )

                )

        )

)

 

Если вам также нужны атрибуты, они доступны через JSON-кодирование/декодирование SimpleXMLElement. Это часто является наиболее простым и быстрым решением: 

$xml   = simplexml_load_string($buffer);

$array = json_decode(json_encode((array) $xml), true);

$array = array($xml->getName() => $array);

 

Результат:

Array (

    [aaaa] => Array  (

            [@attributes] => Array  (

                    [Version] => 1.0

                )

            [bbb] => Array  (

                    [cccc] => Array  (

                            [dddd] => Array  (

                                    [@attributes] => Array  (

                                            [Id]        => id:pass

                                        )

                                )

                            [eeee] => Array  (

                                    [@attributes] => Array  (

                                            [name]   => hearaman

                                            [age]      => 24

                                        )

                                )

                        )

                )

        )

)

 

Обратите внимание, что все эти методы работают только в пространстве имен XML-документа.

 

Ответ 3

Метод, используемый в принятом ответе, отбрасывающий атрибуты при встрече с дочерними элементами, имеющими только текстовый узел. Например: 

$xml = '<container><element attribute="123">abcd</element></container>';

print_r(json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)),1));

Array (

    [element] => abcd

)

 

Мое решение:

function XMLtoArray($xml) {

    $previous_value = libxml_use_internal_errors(true);

    $dom = new DOMDocument('1.0', 'UTF-8');

    $dom->preserveWhiteSpace = false; 

    $dom->loadXml($xml);

    libxml_use_internal_errors($previous_value);

    if (libxml_get_errors()) {

        return [];

    }

    return DOMtoArray($dom);

}

function DOMtoArray($root) {

    $result = array();

    if ($root->hasAttributes()) {

        $attrs = $root->attributes;

        foreach ($attrs as $attr) {

            $result['@attributes'][$attr->name] = $attr->value;

        }

    }

    if ($root->hasChildNodes()) {

        $children = $root->childNodes;

        if ($children->length == 1) {

            $child = $children->item(0);

            if (in_array($child->nodeType,[XML_TEXT_NODE,XML_CDATA_SECTION_NODE])) {

                $result['_value'] = $child->nodeValue;

                return count($result) == 1

                    ? $result['_value']

                    : $result;

            }

        }

        $groups = array();

        foreach ($children as $child) {

            if (!isset($result[$child->nodeName])) {

                $result[$child->nodeName] = DOMtoArray($child);

            } else {

                if (!isset($groups[$child->nodeName])) {

                    $result[$child->nodeName]   = array($result[$child->nodeName]);

                    $groups[$child->nodeName] = 1;

                }

                $result[$child->nodeName][] = DOMtoArray($child);

            }

        }

    }

    return $result;

}

 

$xml = '

    <aaaa Version="1.0">

       <bbb>

         <cccc>

           <dddd id="123" />

           <eeee name="john" age="24" />

           <ffff type="employee">Supervisor</ffff>

         </cccc>

       </bbb>

    </aaaa>

';

print_r(XMLtoArray($xml));

Array (

    [aaaa] => Array (

            [@attributes] => Array (

                    [Version] => 1.0

                )

            [bbb] => Array (

                    [cccc] => Array (

                            [dddd] => Array (

                                    [@attributes] => Array (

                                            [id]         => 123

                                        )

                                )

                            [eeee] => Array (

                                    [@attributes] => Array (

                                            [name]  => john

                                            [age]     => 24

                                        )

                                )

                            [ffff] => Array (

                                    [@attributes] => Array (

                                            [type]    => employee

                                        )

                                    [_value] => Supervisor

                                )

                        )

                )

        )

)

 

Ответ 4

<?php

/**

  * преобразование xml-строки в php-массив - для получения сериализуемого значения

  *

  * @param string $xmlstr

  * @return array

  *

*/

function xmlstr_to_array($xmlstr) {

  $doc = new DOMDocument();

  $doc->loadXML($xmlstr);

  $root = $doc->documentElement;

  $output = domnode_to_array($root);

  $output['@root'] = $root->tagName;

  return $output;

}

function domnode_to_array($node) {

  $output = array();

  switch ($node->nodeType) {

    case XML_CDATA_SECTION_NODE:

    case XML_TEXT_NODE:

      $output = trim($node->textContent);

    break;

    case XML_ELEMENT_NODE:

      for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {

        $child = $node->childNodes->item($i);

        $v      = domnode_to_array($child);

        if(isset($child->tagName)) {

          $t = $child->tagName;

          if(!isset($output[$t])) {

            $output[$t] = array();

          }

          $output[$t][] = $v;

        }

        elseif($v || $v === '0') {

          $output = (string) $v;

        }

      }

      if($node->attributes->length && !is_array($output)) { // Имеет атрибуты, но не является массивом

        $output = array('@content'=>$output); //Измените вывод в массив.

      }

      if(is_array($output)) {

        if($node->attributes->length) {

          $a = array();

          foreach($node->attributes as $attrName => $attrNode) {

            $a[$attrName] = (string) $attrNode->value;

          }

          $output['@attributes'] = $a;

        }

        foreach ($output as $t => $v) {

          if(is_array($v) && count($v)==1 && $t!='@attributes') {

            $output[$t] = $v[0];

          }

        }

      }

    break;

  }

  return $output;

}

 

Ответ 5

Мне понравился этот вопрос, и некоторые ответы были мне полезны, но мне нужно преобразовать xml в один доминирующий массив, поэтому я опубликую свое решение, возможно, оно кому-то понадобится позже:

<?php

$xml = json_decode(json_encode((array)simplexml_load_string($xml)),1);

$finalItem = getChild($xml);

var_dump($finalItem);

 function getChild($xml, $finalItem = []){

    foreach($xml as $key=>$value){

        if(!is_array($value)){

            $finalItem[$key] = $value;

        }else{

            $finalItem = getChild($value, $finalItem);

        }

    }

    return $finalItem;

}

?>   

Схожие статьи

Web

Как вставить новый элемент в массив в любую позицию на PHP

Что такое Флаттер от Google, как им пользоваться и зачем он создан?
Web

Что такое Флаттер от Google, как им пользоваться и зачем он создан?

Web

Простейшее двустороннее шифрование с использованием PHP

Как стать веб-разработчиком и что нужно знать веб-разработчику
Web

Как стать веб-разработчиком и что нужно знать веб-разработчику