Làm thế nào để chuyển đổi xml thành mảng trong php?


166

Tôi muốn chuyển đổi bên dưới XML sang mảng PHP. Bất kỳ đề xuất về làm thế nào tôi có thể làm điều này?

<aaaa Version="1.0">
   <bbb>
     <cccc>
       <dddd Id="id:pass" />
       <eeee name="hearaman" age="24" />
     </cccc>
   </bbb>
</aaaa>

3
Ngoài ra, câu hỏi đó khác với câu hỏi khác của bạn như thế nào? stackoverflow.com/questions/6578084/ Mạnh
Gordon

3
Vài điều đáng ghét như một OP chấp nhận trả lời sai cho câu hỏi của chính họ.
Giăng

Câu trả lời:


127

Một tùy chọn khác là tiện ích mở rộng SimpleXML (tôi tin rằng nó có tiêu chuẩn với hầu hết các cài đặt php.)

http://php.net/manual/en/book.simplexml.php

Cú pháp trông giống như ví dụ này

$xml = new SimpleXMLElement($xmlString);
echo $xml->bbb->cccc->dddd['Id'];
echo $xml->bbb->cccc->eeee['name'];
// or...........
foreach ($xml->bbb->cccc as $element) {
  foreach($element as $key => $val) {
   echo "{$key}: {$val}";
  }
}

82
Để công bằng, điều này không trả lời chính xác câu hỏi làm thế nào để có được một mảng.
sieppl

SimpleXML hút khi phân tích xml này: amazon.in/rss/bestseller/shoes?tag=dealslama-21 Ngay cả print_r cũng không nói đối tượng có chứa thực sự.
ravisoni

sử dụng var_dump, bạn sẽ thấy cấu trúc xml là các khóa bên trong đối tượng.
Magus

3
Tôi có một số [CDATA[TEXT]]bên trong một số yếu tố và họ không phân tích cú pháp với điều này. Nó phân tích nó như một SimpleXMLElement Object. Bất kỳ cách giải quyết cho điều đó?
masterFly

Điều này không trả lời câu hỏi
Bilaal Rashid

434

dễ dàng!

$xml = simplexml_load_string($xmlstring, "SimpleXMLElement", LIBXML_NOCDATA);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

20
Bạn có thể gặp rắc rối tại các phần CDATA (luôn luôn trả về null). Là một giải pháp, hãy thử $ xml = simplexml_load_opes ($ xmlopes, null, LIBXML_NOCDATA); $ json = json_encode ($ xml); $ mảng = json_decode ($ json, TRUE); (xem stackoverflow.com/a/2970701/413531 ) // e chết tiệt .. có cách nào để thêm dòng mới trong một nhận xét không?
Hirnhamster

4
Chúng tôi làm điều tương tự chính xác nhưng với Simplexml_load_file và nó hoạt động tốt. Cảm ơn
Thermech

2
Tham số thứ hai (TRUE) dùng để làm gì?
Mansour Fahad

3
@MansourFahad Trong json_decode, bạn có thể sử dụng tham số thứ hai tùy chọn là TRUE(thường mặc định là FALSE) để chuyển đổi đầu vào JSON thành một mảng kết hợp.
Jake Bathman

16
@Ismael Miguel quá nhiều mã? Chỉ vì bạn đặt tất cả các chức năng đó trên một dòng không có nghĩa là bạn đang sử dụng ít mã hơn. Nó có thể trông nhỏ gọn hơn nhưng nó có chi phí dễ đọc.
Jage

43

Chuyển đổi một chuỗi XML ( $buffer) thành một mảng được đơn giản hóa bỏ qua các thuộc tính và nhóm các phần tử con có cùng tên:

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

Kết quả:

Array
(
    [aaaa] => Array
        (
            [bbb] => Array
                (
                    [cccc] => Array
                        (
                            [dddd] => 
                            [eeee] => 
                        )

                )

        )

)

Nếu bạn cũng muốn có các thuộc tính, chúng có sẵn thông qua mã hóa / giải mã JSON của SimpleXMLEuity. Đây thường là giải pháp nhanh nhất dễ dàng nhất:

$xml   = simplexml_load_string($buffer);
$array = json_decode(json_encode((array) $xml), true);
$array = array($xml->getName() => $array);

Kết quả:

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
                                        )

                                )

                        )

                )

        )

)

Xin lưu ý rằng tất cả các phương thức này chỉ hoạt động trong không gian tên của tài liệu XML.


Liên quan: Mã hóa
Json

Trong PHP 7 tôi đã phải thêm điều này: && (is_countable($node) && 1 === count($node) ? $node = array($node) : 1)tuy nhiên tôi đã gặp lỗi ở dòng tiếp theo : [] operator not supported for strings.
andreshg112

@ andreshg112: Tôi không thể sao chép (hoạt động ổn định PHP 5.3.0 - 7.4.0), hành vi không thay đổi theo độ tuổi, vui lòng so sánh với hàng trăm phiên bản PHP khác nhau: 3v4l.org/l4nQN
hakre

có thể đó là do tệp KML của tôi (đó là XML). Tôi không thể chia sẻ nó. Tôi đã nhập nó nhưng tôi phải làm theo cách khác.
andreshg112

có lẽ bạn quan tâm đến không gian tên XML. Ví dụ này chỉ dành cho không gian tên w / oa (hoặc mặc định, đôi khi tôi trộn cái này).
hakre

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

1
nếu bạn chuyển sang mảng, bạn không cần json_encodejson_decode.
Ismael Miguel

11
@Ismael trên lý thuyết, đúc thành mảng nên là đủ. Trong thực tế chúng ta cũng cần phải đúc tất cả các nút lá, đó cũng là các đối tượng. Một diễn viên ngây thơ rời khỏi lá như các đối tượng SimpleXML. json_encode phôi đệ quy tiết kiệm rất nhiều công việc.
Peter Mellett

2
Nếu bạn không có giá trị văn bản vào $arraybiến của mình , có lẽ đó là do CDATA. Để giải quyết nó, hãy tải XML của bạn bằng : new SimpleXMLElement($xml, LIBXML_NOCDATA).
Jonathan Petitcolas

1
ps. $ xml = str numplace (mảng ('<! [CDATA [', ']]>'), '', $ xml);
dùng956584

1
Nó không hoạt động như thế. Mã đó sẽ không chuyển đổi ngay cả một XML đơn giản như thế này <?xml version="1.0" encoding="UTF-8"?><note a="b"><body c="d">Hello!</body></note>. Chạy mã và bạn sẽ thấy thuộc tính <body> c bị mất! Vui lòng kiểm tra mã đầy đủ ở đây nếu bạn không muốn có bất ngờ xấu nào github.com/gaarf/XML-opes-to-PHP-array/blob/master/iêu hoặc xem câu trả lời của tôi bên dưới stackoverflow.com/a/30234924/828366
Francesco Casula

7

Xem https://github.com/gaarf/XML-opes-to-PHP-array/blob/master/xmlstr_to_array.php

<?php
/**
  * convert xml string to php array - useful to get a serializable value
  *
  * @param string $xmlstr
  * @return array
  *
  * @author Adrien aka Gaarf & contributors
  * @see http://gaarf.info/2009/08/13/xml-string-to-php-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)) { //Has attributes but isn't an array
        $output = array('@content'=>$output); //Change output into an array.
      }
      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;
}

7

Ngạc nhiên không ai nhắc đến xml_parse_into_struct:

$simple = "<para><note>simple note</note></para>";
$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);
echo "Index array\n";
print_r($index);
echo "\nVals array\n";
print_r($vals);

Đôi khi tôi tự hỏi nhà phát triển đã tạo ra triển khai PHP XML đã nghĩ gì khi xml_parse_into_struct được thiết kế ...
Anibal Sanchez

7

Phương thức được sử dụng trong các thuộc tính thả câu trả lời được chấp nhận khi gặp các phần tử con chỉ có một nút văn bản. Ví dụ:

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

Giải pháp của tôi (và tôi ước tôi có thể cung cấp tín dụng ở đây vì tôi chắc chắn rằng tôi đã điều chỉnh điều này từ một cái gì đó):

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
                                )

                        )

                )

        )

)

2

XML thành mảng

Thêm chi tiết Truy cập https://github.com/sapankumarmohanty/lamp/blob/master/Crate-XML-2-Array

// Chuyển đổi XML thành mảng và SOAP XML thành mảng

function xml2array($contents, $get_attributes = 1, $priority = 'tag')
    {
        if (!$contents) return array();
        if (!function_exists('xml_parser_create')) {
            // print "'xml_parser_create()' function not found!";
            return array();
        }
        // Get the XML parser of PHP - PHP must have this module for the parser to work
        $parser = xml_parser_create('');
        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); // http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, trim($contents) , $xml_values);
        xml_parser_free($parser);
        if (!$xml_values) return; //Hmm...
        // Initializations
        $xml_array = array();
        $parents = array();
        $opened_tags = array();
        $arr = array();
        $current = & $xml_array; //Refference
        // Go through the tags.
        $repeated_tag_index = array(); //Multiple tags with same name will be turned into an array
        foreach($xml_values as $data) {
            unset($attributes, $value); //Remove existing values, or there will be trouble
            // This command will extract these variables into the foreach scope
            // tag(string), type(string), level(int), attributes(array).
            extract($data); //We could use the array by itself, but this cooler.
            $result = array();
            $attributes_data = array();
            if (isset($value)) {
                if ($priority == 'tag') $result = $value;
                else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode
            }
            // Set the attributes too.
            if (isset($attributes) and $get_attributes) {
                foreach($attributes as $attr => $val) {                                   
                                    if ( $attr == 'ResStatus' ) {
                                        $current[$attr][] = $val;
                                    }
                    if ($priority == 'tag') $attributes_data[$attr] = $val;
                    else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
                }
            }
            // See tag status and do the needed.
                        //echo"<br/> Type:".$type;
            if ($type == "open") { //The starting of the tag '<tag>'
                $parent[$level - 1] = & $current;
                if (!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                    $current[$tag] = $result;
                    if ($attributes_data) $current[$tag . '_attr'] = $attributes_data;
                                        //print_r($current[$tag . '_attr']);
                    $repeated_tag_index[$tag . '_' . $level] = 1;
                    $current = & $current[$tag];
                }
                else { //There was another element with the same tag name
                    if (isset($current[$tag][0])) { //If there is a 0th element it is already an array
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
                        $repeated_tag_index[$tag . '_' . $level]++;
                    }
                    else { //This section will make the value an array if multiple tags with the same name appear together
                        $current[$tag] = array(
                            $current[$tag],
                            $result
                        ); //This will combine the existing item and the new item together to make an array
                        $repeated_tag_index[$tag . '_' . $level] = 2;
                        if (isset($current[$tag . '_attr'])) { //The attribute of the last(0th) tag must be moved as well
                            $current[$tag]['0_attr'] = $current[$tag . '_attr'];
                            unset($current[$tag . '_attr']);
                        }
                    }
                    $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
                    $current = & $current[$tag][$last_item_index];
                }
            }
            elseif ($type == "complete") { //Tags that ends in 1 line '<tag />'
                // See if the key is already taken.
                if (!isset($current[$tag])) { //New Key
                    $current[$tag] = $result;
                    $repeated_tag_index[$tag . '_' . $level] = 1;
                    if ($priority == 'tag' and $attributes_data) $current[$tag . '_attr'] = $attributes_data;
                }
                else { //If taken, put all things inside a list(array)
                    if (isset($current[$tag][0]) and is_array($current[$tag])) { //If it is already an array...
                        // ...push the new element into that array.
                        $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
                        if ($priority == 'tag' and $get_attributes and $attributes_data) {
                            $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
                        }
                        $repeated_tag_index[$tag . '_' . $level]++;
                    }
                    else { //If it is not an array...
                        $current[$tag] = array(
                            $current[$tag],
                            $result
                        ); //...Make it an array using using the existing value and the new value
                        $repeated_tag_index[$tag . '_' . $level] = 1;
                        if ($priority == 'tag' and $get_attributes) {
                            if (isset($current[$tag . '_attr'])) { //The attribute of the last(0th) tag must be moved as well
                                $current[$tag]['0_attr'] = $current[$tag . '_attr'];
                                unset($current[$tag . '_attr']);
                            }
                            if ($attributes_data) {
                                $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
                            }
                        }
                        $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken
                    }
                }
            }
            elseif ($type == 'close') { //End of tag '</tag>'
                $current = & $parent[$level - 1];
            }
        }
        return ($xml_array);
    }
    
    // Let's call the this above function xml2array
    
    xml2array($xmlContent, $get_attributes = 3, $priority = 'tag'); // it will work 100% if not ping me @skype: sapan.mohannty
    
//  Enjoy coding

0

Tôi thích câu hỏi này và một số câu trả lời hữu ích cho tôi, nhưng tôi cần chuyển đổi xml thành một mảng thống trị, vì vậy tôi sẽ đăng giải pháp của mình có thể ai đó cần nó sau:

<?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;
}
?>  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.