Як конвертувати масив у SimpleXML


Відповіді:


209

короткий:

<?php

$test_array = array (
  'bla' => 'blub',
  'foo' => 'bar',
  'another_array' => array (
    'stack' => 'overflow',
  ),
);
$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

призводить до

<?xml version="1.0"?>
<root>
  <blub>bla</blub>
  <bar>foo</bar>
  <overflow>stack</overflow>
</root>

ключі та значення змінюються - ви можете це виправити array_flip()перед початком масиву. array_walk_recursiveвимагає PHP 5. array_walkзамість цього ви можете використовувати , але ви не ввійдете 'stack' => 'overflow'в xml.


53
Це не спрацює, якщо $ test_array має "more_another_array", як "Another_array", тому що ключ "else_array" не перетворений. Отже, у вас буде кілька "<overflow> стеків </overflow>".
understack

11
Не array_flipбуде працювати, оскільки він не може перевернути масиви (як, наприклад, another_arrayвсередині основного масиву).
Лод

14
Де елемент xml «ще_аррай»? Все
згладжено

2
Чудово працював, коли я додав array_flip перед array_walk_recursive. Дякую.
Майк Перселл

12
Нахил, тому що array_flipпрацює лише тоді, коли масив не містить однакових значень.
Martijn

386

Ось код PHP 5.2, який перетворить масив будь-якої глибини в XML-документ:

Array
(
    ['total_stud']=> 500
    [0] => Array
        (
            [student] => Array
                (
                    [id] => 1
                    [name] => abc
                    [address] => Array
                        (
                            [city]=>Pune
                            [zip]=>411006
                        )                       
                )
        )
    [1] => Array
        (
            [student] => Array
                (
                    [id] => 2
                    [name] => xyz
                    [address] => Array
                        (
                            [city]=>Mumbai
                            [zip]=>400906
                        )   
                )

        )
)

згенерований XML буде таким:

<?xml version="1.0"?>
<student_info>
    <total_stud>500</total_stud>
    <student>
        <id>1</id>
        <name>abc</name>
        <address>
            <city>Pune</city>
            <zip>411006</zip>
        </address>
    </student>
    <student>
        <id>1</id>
        <name>abc</name>
        <address>
            <city>Mumbai</city>
            <zip>400906</zip>
        </address>
    </student>
</student_info>

Фрагмент PHP

<?php
// function defination to convert array to xml
function array_to_xml( $data, &$xml_data ) {
    foreach( $data as $key => $value ) {
        if( is_array($value) ) {
            if( is_numeric($key) ){
                $key = 'item'.$key; //dealing with <0/>..<n/> issues
            }
            $subnode = $xml_data->addChild($key);
            array_to_xml($value, $subnode);
        } else {
            $xml_data->addChild("$key",htmlspecialchars("$value"));
        }
     }
}

// initializing or creating array
$data = array('total_stud' => 500);

// creating object of SimpleXMLElement
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');

// function call to convert array to xml
array_to_xml($data,$xml_data);

//saving generated xml file; 
$result = $xml_data->asXML('/file/path/name.xml');

?>

Документація на SimpleXMLElement::asXMLвикористаний у цьому фрагменті


40
Це, ІМО, є набагато кращим рішенням, ніж прийнята відповідь. Однак це обмеження полягає в тому, що за допомогою цифрових ключів вони генерують неправильно сформований XML. <0> <1> <2> недійсні імена вузлів.
KOGI

2
Однак, якщо ваш масив з цифровими ключами містить лише інший масив, який не є цифровим ключем, він не буде.
Брайан Петті

15
@KOGI Я змінив відповідь Hanmant. Тепер його підтримують багаторівневі масиви. pastebin.com/pYuXQWee
Mifas

1
Цей приклад явно уникає спеціальних символів у текстових даних елементів, використовуючи htmlspecialchars, але SimpleXMLElement :: addChild автоматично переводить xml спеціальні символи до їхніх суттєвих об'єктів, щоб htmlspecialchars можна було залишити. Цікаво, що це, здається, не призводить до подвійних даних.
mbaynton

3
@ Алекс, ваш редактор №5 робить приклад невдалим. Він вставляє <item $ x> перед кожним записом <student>, роблячи вихід XML не таким, як задумав автор. Можливо, наведіть приклад проблеми, яку ви намагаєтеся виправити, і ми можемо знайти інше рішення для обох випадків. Зайняв мене деякий час, перш ніж я зрозумів, що авторський код був змінений.
Ніколас Бласген

124

Надані тут відповіді лише перетворюють масив у XML з вузлами, ви не можете встановити атрибути. Я написав функцію php, яка дозволяє перетворити масив у php, а також встановити атрибути для конкретних вузлів у xml. Недоліком тут є те, що ви повинні побудувати масив по-особливому з кількома умовами (лише якщо ви хочете використовувати атрибути)

Наступний приклад дозволить вам також встановлювати атрибути в XML.

Джерело можна знайти тут: https://github.com/digitickets/lalit/blob/master/src/Array2XML.php

<?php    
$books = array(
    '@attributes' => array(
        'type' => 'fiction'
    ),
    'book' => array(
        array(
            '@attributes' => array(
                'author' => 'George Orwell'
            ),
            'title' => '1984'
        ),
        array(
            '@attributes' => array(
                'author' => 'Isaac Asimov'
            ),
            'title' => 'Foundation',
            'price' => '$15.61'
        ),
        array(
            '@attributes' => array(
                'author' => 'Robert A Heinlein'
            ),
            'title' => 'Stranger in a Strange Land',
            'price' => array(
                '@attributes' => array(
                    'discount' => '10%'
                ),
                '@value' => '$18.00'
            )
        )
    )
);
/* creates 
<books type="fiction">
  <book author="George Orwell">
    <title>1984</title>
  </book>
  <book author="Isaac Asimov">
    <title>Foundation</title>
    <price>$15.61</price>
  </book>
  <book author="Robert A Heinlein">
    <title>Stranger in a Strange Land</title>
    <price discount="10%">$18.00</price>
  </book>
</books>
*/
?>

9
Мені здається, що ніхто на це не відреагував. Цей клас дуже корисний, оскільки робить протилежне тому, що буде генерувати simpleXMLElement. Це дає вам можливість використовувати SimpleXMLElement обома способами.
FMaz008

4
Я б позначив це як відповідь замість поточної. Поточна відповідь не будує рекурсивних масивів
Олександр ІЙ

2
Гарний клас. Я змінив лінію 128 , if(!is_array($arr)) {щоб if(!is_array($arr) && $arr !== '') {таким чином , що вона не буде додавати новий текстовий вузол для порожніх рядків і , отже , зберігає скорочену порожній формат тегів тобто 'tag'=>''це <tag/>замість<tag></tag>
user1433150

Це найкраща відповідь поки що. Також це має правильну структуру декількох елементів з одним ключем: 1-й - це ключ імені вузла, потім він містить масив з цифровими ключами. (навпаки відповіді Хантанта)
Василь Попов

1
Знайдено github від автора @Legionar github.com/digitickets/lalit/blob/master/src/Array2XML.php
Дарил Тео

57

Я знайшов усі відповіді, щоб використовувати занадто багато коду. Ось простий спосіб зробити це:

function to_xml(SimpleXMLElement $object, array $data)
{   
    foreach ($data as $key => $value) {
        if (is_array($value)) {
            $new_object = $object->addChild($key);
            to_xml($new_object, $value);
        } else {
            // if the key is an integer, it needs text with it to actually work.
            if ($key == (int) $key) {
                $key = "key_$key";
            }

            $object->addChild($key, $value);
        }   
    }   
}   

Тоді це проста справа надсилання масиву у функцію, яка використовує рекурсію, тому він буде обробляти багатовимірний масив:

$xml = new SimpleXMLElement('<rootTag/>');
to_xml($xml, $my_array);

Тепер $ xml містить прекрасний XML-об’єкт на основі вашого масиву саме так, як ви його написали.

print $xml->asXML();

9
Я люблю це рішення найбільше. Хоча, було б непогано додати тест на цифрові клавіші, як: if ( is_numeric( $key ) ) $key = "numeric_$key"; .
wout

@wout Хороший улов. Додано. Я зробив перевірку int cast замість is_numeric, тому що is_numeric може дати деякі, хоча технічно очікувані, результати, які б справді відкинули вас.
Френсіс Льюїс

Я використовую цю функцію, але змінена $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" ?><rootTag/>');для дійсного кодування UTF-8.
Даандже

Мені подобається цей розчин найбільш , як добре, просто робить це :-) Одне зауваження: Ви можете змінити , $object->addChild($key, $value);щоб $object->addChild($key, htmlspecialchars($value));запобігти його від падіння , якщо $ значення містить символи , такі як «і» , які потребують в XML-кодуванні.
лео

38
<? php
функція array_to_xml (масив $ arr, SimpleXMLElement $ xml)
{
    foreach ($ arr як $ k => $ v) {
        is_array ($ v)
            ? array_to_xml ($ v, $ xml-> addChild ($ k))
            : $ xml-> addChild ($ k, $ v);
    }
    повернути $ xml;
}

$ test_array = масив (
    'bla' => 'blub',
    'foo' => 'бар',
    'else_array' => масив (
        'stack' => 'переповнення',
    ),
);

echo array_to_xml ($ test_array, новий SimpleXMLElement ('<root />')) -> asXML ();

1
це не вдається, якщо ваш масив містить внутрішній масив з числовими індексами. <0> ... </0> недійсний XML.
Адріано Варолі П'яцца

@AdrianoVaroliPiazza просто додайте щось на зразок $k = (is_numeric($k)) ? 'item' : $k;всерединіforeach()
AlienWebguy

Якщо один з ключів у масиві названий "body", він не працює - точніше, ключ ігнорується та проходить. Намагаюся розібратися, чому.
Bambax

@Bambax Єдиною причиною, про яку я можу подумати, є те, що XML аналізується як HTML в якийсь пізній момент.
Brilliand

16

Від PHP 5.4

function array2xml($data, $root = null){
    $xml = new SimpleXMLElement($root ? '<' . $root . '/>' : '<root/>');
    array_walk_recursive($data, function($value, $key)use($xml){
        $xml->addChild($key, $value);
    });
    return $xml->asXML();
}

Здається, що це пряма копія вибраної відповіді, просто поставлена ​​у функцію.
фаберест

Я б додав htmlspecialchars () до частини addChild, як-от так: $ xml-> addChild ($ ключ, htmlspecialchars ($ значення));
Tyreal

15

Ще одне поліпшення:

/**
* Converts an array to XML
*
* @param array $array
* @param SimpleXMLElement $xml
* @param string $child_name
*
* @return SimpleXMLElement $xml
*/
public function arrayToXML($array, SimpleXMLElement $xml, $child_name)
{
    foreach ($array as $k => $v) {
        if(is_array($v)) {
            (is_int($k)) ? $this->arrayToXML($v, $xml->addChild($child_name), $v) : $this->arrayToXML($v, $xml->addChild(strtolower($k)), $child_name);
        } else {
            (is_int($k)) ? $xml->addChild($child_name, $v) : $xml->addChild(strtolower($k), $v);
        }
    }

    return $xml->asXML();
}

Використання:

$this->arrayToXML($array, new SimpleXMLElement('<root/>'), 'child_name_to_replace_numeric_integers');

Дякую! Ваша функція повертає точний вміст будь-якого n-мірного масиву.
besciualex

12

Ось мій запис, простий і чистий ..

function array2xml($array, $xml = false){
    if($xml === false){
        $xml = new SimpleXMLElement('<root/>');
    }
    foreach($array as $key => $value){
        if(is_array($value)){
            array2xml($value, $xml->addChild($key));
        }else{
            $xml->addChild($key, $value);
        }
    }
    return $xml->asXML();
}


header('Content-type: text/xml');
print array2xml($array);

8

Так чи інакше ... Я взяв код onokazu (спасибі!) Та додав можливість повторних тегів у XML, він також підтримує атрибути, сподіваюся, хтось вважає це корисним!

 <?php

function array_to_xml(array $arr, SimpleXMLElement $xml) {
        foreach ($arr as $k => $v) {

            $attrArr = array();
            $kArray = explode(' ',$k);
            $tag = array_shift($kArray);

            if (count($kArray) > 0) {
                foreach($kArray as $attrValue) {
                    $attrArr[] = explode('=',$attrValue);                   
                }
            }

            if (is_array($v)) {
                if (is_numeric($k)) {
                    array_to_xml($v, $xml);
                } else {
                    $child = $xml->addChild($tag);
                    if (isset($attrArr)) {
                        foreach($attrArr as $attrArrV) {
                            $child->addAttribute($attrArrV[0],$attrArrV[1]);
                        }
                    }                   
                    array_to_xml($v, $child);
                }
            } else {
                $child = $xml->addChild($tag, $v);
                if (isset($attrArr)) {
                    foreach($attrArr as $attrArrV) {
                        $child->addAttribute($attrArrV[0],$attrArrV[1]);
                    }
                }
            }               
        }

        return $xml;
    }

        $test_array = array (
          'bla' => 'blub',
          'foo' => 'bar',
          'another_array' => array (
            array('stack' => 'overflow'),
            array('stack' => 'overflow'),
            array('stack' => 'overflow'),
          ),
          'foo attribute1=value1 attribute2=value2' => 'bar',
        );  

        $xml = array_to_xml($test_array, new SimpleXMLElement('<root/>'))->asXML();

        echo "$xml\n";
        $dom = new DOMDocument;
        $dom->preserveWhiteSpace = FALSE;
        $dom->loadXML($xml);
        $dom->formatOutput = TRUE;
        echo $dom->saveXml();
    ?>

Може бути корисним прокоментувати зміни, щоб зробити код більш зрозумілим; ще, приємне доповнення
StormeHawke

Це працювало для мене з WP All Export. У мене було трохи змінити is_numeric частина: if (is_numeric($k)) { $i = $k + 1; $child = $xml->addChild("_$i"); array_to_xml($v, $child); }
Успішність

4

Я використовую пару функцій, про які я писав деякий час назад, щоб генерувати XML для передачі назад і назад з PHP та jQuery тощо. Ніякі додаткові рамки просто не створюють лише рядок, який потім може бути використаний з SimpleXML (або іншим фреймворком) ) ...

Якщо це комусь корисно, будь ласка, використовуйте його :)

function generateXML($tag_in,$value_in="",$attribute_in=""){
    $return = "";
    $attributes_out = "";
    if (is_array($attribute_in)){
        if (count($attribute_in) != 0){
            foreach($attribute_in as $k=>$v):
                $attributes_out .= " ".$k."=\"".$v."\"";
            endforeach;
        }
    }
    return "<".$tag_in."".$attributes_out.((trim($value_in) == "") ? "/>" : ">".$value_in."</".$tag_in.">" );
}

function arrayToXML($array_in){
    $return = "";
    $attributes = array();
    foreach($array_in as $k=>$v):
        if ($k[0] == "@"){
            // attribute...
            $attributes[str_replace("@","",$k)] = $v;
        } else {
            if (is_array($v)){
                $return .= generateXML($k,arrayToXML($v),$attributes);
                $attributes = array();
            } else if (is_bool($v)) {
                $return .= generateXML($k,(($v==true)? "true" : "false"),$attributes);
                $attributes = array();
            } else {
                $return .= generateXML($k,$v,$attributes);
                $attributes = array();
            }
        }
    endforeach;
    return $return;
}   

Любов усім :)


4

Я хотів код, який буде приймати всі елементи всередині масиву і трактувати їх як атрибути, а всі масиви - як елементи.

Тож на щось подібне

array (
'row1' => array ('head_element' =>array("prop1"=>"some value","prop2"=>array("empty"))),
"row2"=> array ("stack"=>"overflow","overflow"=>"overflow")
);

Я отримав би щось подібне

<?xml version="1.0" encoding="utf-8"?>
<someRoot>
  <row1>
    <head_element prop1="some value">
      <prop2 0="empty"/>
    </head_element>
  </row1>
  <row2 stack="overflow" overflow="stack"/>
 </someRoot>

Щоб досягти цього коду, наведено нижче, але будьте дуже обережні, він є рекурсивним і може насправді спричинити потоковий процес :)

function addElements(&$xml,$array)
{
$params=array();
foreach($array as $k=>$v)
{
    if(is_array($v))
        addElements($xml->addChild($k), $v);
    else $xml->addAttribute($k,$v);
}

}
function xml_encode($array)
{
if(!is_array($array))
    trigger_error("Type missmatch xml_encode",E_USER_ERROR);
$xml=new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
addElements($xml,$array[key($array)]);
return $xml->asXML();
} 

Ви можете додати перевірки на довжину масиву, щоб якийсь елемент встановився всередині частини даних, а не як атрибут.


4

На основі всього іншого тут, обробляє числові індекси + атрибути за допомогою префіксації @та може вводити xml до існуючих вузлів:

Код

function simple_xmlify($arr, SimpleXMLElement $root = null, $el = 'x') {
    // based on, among others http://stackoverflow.com/a/1397164/1037948

    if(!isset($root) || null == $root) $root = new SimpleXMLElement('<' . $el . '/>');

    if(is_array($arr)) {
        foreach($arr as $k => $v) {
            // special: attributes
            if(is_string($k) && $k[0] == '@') $root->addAttribute(substr($k, 1),$v);
            // normal: append
            else simple_xmlify($v, $root->addChild(
                    // fix 'invalid xml name' by prefixing numeric keys
                    is_numeric($k) ? 'n' . $k : $k)
                );
        }
    } else {
        $root[0] = $arr;
    }

    return $root;
}//--   fn  simple_xmlify

Використання

// lazy declaration via "queryparam"
$args = 'hello=4&var[]=first&var[]=second&foo=1234&var[5]=fifth&var[sub][]=sub1&var[sub][]=sub2&var[sub][]=sub3&var[@name]=the-name&var[@attr2]=something-else&var[sub][@x]=4.356&var[sub][@y]=-9.2252';
$q = array();
parse_str($val, $q);

$xml = simple_xmlify($q); // dump $xml, or...
$result = get_formatted_xml($xml); // see below

Результат

<?xml version="1.0"?>
<x>
  <hello>4</hello>
  <var name="the-name" attr2="something-else">
    <n0>first</n0>
    <n1>second</n1>
    <n5>fifth</n5>
    <sub x="4.356" y="-9.2252">
      <n0>sub1</n0>
      <n1>sub2</n1>
      <n2>sub3</n2>
    </sub>
  </var>
  <foo>1234</foo>
</x>

Бонус: Форматування XML

function get_formatted_xml(SimpleXMLElement $xml, $domver = null, $preserveWhitespace = true, $formatOutput = true) {
    // http://stackoverflow.com/questions/1191167/format-output-of-simplexml-asxml

    // create new wrapper, so we can get formatting options
    $dom = new DOMDocument($domver);
    $dom->preserveWhiteSpace = $preserveWhitespace;
    $dom->formatOutput = $formatOutput;
    // now import the xml (converted to dom format)
    /*
    $ix = dom_import_simplexml($xml);
    $ix = $dom->importNode($ix, true);
    $dom->appendChild($ix);
    */
    $dom->loadXML($xml->asXML());

    // print
    return $dom->saveXML();
}//--   fn  get_formatted_xml

Оновлена ​​версія, що повторюється як дочірні елементи, а не числові теги: github.com/zaus/forms-3rdparty-xpost/blob/…
drzaus

3

Ось функція, яка зробила для мене хитрість:

Просто назвіть це чимось на кшталт

echo arrayToXml("response",$arrayIWantToConvert);
function arrayToXml($thisNodeName,$input){
        if(is_numeric($thisNodeName))
            throw new Exception("cannot parse into xml. remainder :".print_r($input,true));
        if(!(is_array($input) || is_object($input))){
            return "<$thisNodeName>$input</$thisNodeName>";
        }
        else{
            $newNode="<$thisNodeName>";
            foreach($input as $key=>$value){
                if(is_numeric($key))
                    $key=substr($thisNodeName,0,strlen($thisNodeName)-1);
                $newNode.=arrayToXml3($key,$value);
            }
            $newNode.="</$thisNodeName>";
            return $newNode;
        }
    }

3

Ви можете використовувати XMLParser, над яким я працював.

$xml = XMLParser::encode(array(
    'bla' => 'blub',
    'foo' => 'bar',
    'another_array' => array (
        'stack' => 'overflow',
    )
));
// @$xml instanceof SimpleXMLElement
echo $xml->asXML();

Це призведе до:

<?xml version="1.0"?>
<root>
    <bla>blub</bla>
    <foo>bar</foo>
    <another_array>
        <stack>overflow</stack>
    </another_array>
</root>

3

Я знайшов це рішення подібним до початкової проблеми

<?php

$test_array = array (
  'bla' => 'blub',
  'foo' => 'bar',
  'another_array' => array (
    'stack' => 'overflow',
  ),
);

class NoSimpleXMLElement extends SimpleXMLElement {
 public function addChild($name,$value) {
  parent::addChild($value,$name);
 }
}
$xml = new NoSimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

3

Більшість наведених відповідей є правильними. Однак я придумав цю відповідь, яка вирішує проблему сумісності array_walk_recursive, а також проблему числових ключів. Він також пройшов усі тести, які я зробив:

function arrayToXML(Array $array, SimpleXMLElement &$xml) {

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

        // None array
        if (!is_array($value)) {
            (is_numeric($key)) ? $xml->addChild("item$key", $value) : $xml->addChild($key, $value);
            continue;
        }   

        // Array
        $xmlChild = (is_numeric($key)) ? $xml->addChild("item$key") : $xml->addChild($key);
        arrayToXML($value, $xmlChild);
    }
}   

Я також додав тестовий клас для цього, який вам може бути корисним:

class ArrayToXmlTest extends PHPUnit_Framework_TestCase {

    public function setUp(){ }
    public function tearDown(){ }

    public function testFuncExists() {
        $this->assertTrue(function_exists('arrayToXML'));
    }

    public function testFuncReturnsXml() {
        $array = array(
            'name' => 'ardi',
            'last_name' => 'eshghi',
            'age' => 31,
            'tel' => '0785323435'
        );

        $xmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $xmlEl);

        $this->assertTrue($xmlEl instanceOf SimpleXMLElement);
    }

    public function testAssocArrayToXml() {

        $array = array(
            'name' => 'ardi',
            'last_name' => 'eshghi',
            'age' => 31,
            'tel' => '0785323435'
        );

        $expectedXmlEl = new SimpleXMLElement('<root/>'); 
        $expectedXmlEl->addChild('name', $array['name']);
        $expectedXmlEl->addChild('last_name', $array['last_name']);
        $expectedXmlEl->addChild('age', $array['age']);
        $expectedXmlEl->addChild('tel', $array['tel']);

        $actualXmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }

    public function testNoneAssocArrayToXml() {

        $array = array(
            'ardi',
            'eshghi',
            31,
            '0785323435'
        );

        // Expected xml value
        $expectedXmlEl = new SimpleXMLElement('<root/>'); 
        foreach($array as $key => $value)
            $expectedXmlEl->addChild("item$key", $value);

        // What the function produces       
        $actualXmlEl =  new SimpleXMLElement('<root/>');
        arrayToXml($array, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }

    public function testNestedMixArrayToXml() {

        $testArray = array(
            "goal",
            "nice",
            "funny" => array(
                'name' => 'ardi',
                'tel'   =>'07415517499',
                "vary",
                "fields" => array(
                    'small',
                    'email' => 'ardi.eshghi@gmail.com'
                ),

                'good old days'

            ),

            "notes" => "come on lads lets enjoy this",
            "cast" => array(
                'Tom Cruise',
                'Thomas Muller' => array('age' => 24)
            )
        );

        // Expected xml value
        $expectedXmlEl = new SimpleXMLElement('<root/>'); 
        $expectedXmlEl->addChild('item0', $testArray[0]);
        $expectedXmlEl->addChild('item1', $testArray[1]);
        $childEl = $expectedXmlEl->addChild('funny');
        $childEl->addChild("name", $testArray['funny']['name']);
        $childEl->addChild("tel", $testArray['funny']['tel']);
        $childEl->addChild("item0", "vary");
        $childChildEl = $childEl->addChild("fields");
        $childChildEl->addChild('item0', 'small');
        $childChildEl->addChild('email', $testArray['funny']['fields']['email']);
        $childEl->addChild("item1", 'good old days');
        $expectedXmlEl->addChild('notes', $testArray['notes']);
        $childEl2 = $expectedXmlEl->addChild('cast');
        $childEl2->addChild('item0', 'Tom Cruise');
        $childChildEl2 = $childEl2->addChild('Thomas Muller');
        $childChildEl2->addChild('age', $testArray['cast']['Thomas Muller']['age']);

        // What the function produces       
        $actualXmlEl = new SimpleXMLElement('<root/>');
        arrayToXml($testArray, $actualXmlEl);

        $this->assertEquals($expectedXmlEl->asXML(), $actualXmlEl->asXML());
    }
}      

3

інше рішення:

$marray=array(....);
$options = array(
                "encoding" => "UTF-8",
                "output_type" => "xml", 
                "version" => "simple",
                "escaping" => array("non-ascii, on-print, markup")
                );
$xmlres = xmlrpc_encode_request('root', $marray, $options);
print($xmlres);

Це має несподіваний ефект від створення XML у стилі RPC з такими речами, як methodCall, methodName, скаляри та вектори тощо. Це насправді не перетворює масив у XML у прямому сенсі.
Воломіке

3

Якби масив є асоціативним і введений правильно, певно, було б простіше перетворити його в xml. Щось на зразок:

  function array2xml ($array_item) {
    $xml = '';
    foreach($array_item as $element => $value)
    {
        if (is_array($value))
        {
            $xml .= "<$element>".array2xml($value)."</$element>";
        }
        elseif($value == '')
        {
            $xml .= "<$element />";
        }
        else
        {
            $xml .= "<$element>".htmlentities($value)."</$element>";
        }
    }
    return $xml;
}

$simple_xml = simplexml_load_string(array2xml($assoc_array));

Іншим маршрутом було б спочатку створити базовий xml

$simple_xml = simplexml_load_string("<array></array>");

а потім для кожної частини масиву використовуйте щось подібне до мого циклу створення тексту та замість цього використовуйте функції simplexml "addChild" для кожного вузла масиву.

Я спробую це пізніше та оновити цю публікацію обома версіями.


Цей біт, де я згадав "<array> </array>", дав мені зрозуміти, що версія рядка потребує чогось подібного. В основному масив повинен мати один вузол на самій зовнішній стороні. Дозвольте мені спати на всьому, у мене буде щось, що вловить цю початкову помилку відразу.
Ентоні

2

Просто редагування функції вище, коли ключ є числовим, додайте префікс "key_"

// initializing or creating array
$student_info = array(your array data);

// creating object of SimpleXMLElement
$xml_student_info = new SimpleXMLElement("<?xml version=\"1.0\"?><student_info></student_info>");

// function call to convert array to xml
array_to_xml($student,$xml_student_info);

//saving generated xml file
$xml_student_info->asXML('file path and name');


function array_to_xml($student_info, &$xml_student_info) {
     foreach($student_info as $key => $value) {
          if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml_student_info->addChild("$key");
                array_to_xml($value, $subnode);
            }
            else{
                $subnode = $xml_student_info->addChild("key_$key");
                array_to_xml($value, $subnode);
            }
          }
          else {
               if(!is_numeric($key)){
                    $xml_student_info->addChild("$key","$value");
               }else{
                    $xml_student_info->addChild("key_$key","$value");
               }
          }
     }
}

1

Ви можете безпосередньо використовувати наступну функцію у своєму коді,

    function artoxml($arr, $i=1,$flag=false){
    $sp = "";
    for($j=0;$j<=$i;$j++){
        $sp.=" ";
     }
    foreach($arr as $key=>$val){
        echo "$sp&lt;".$key."&gt;";
        if($i==1) echo "\n";
        if(is_array($val)){
            if(!$flag){echo"\n";}
            artoxml($val,$i+5);
            echo "$sp&lt;/".$key."&gt;\n";
        }else{
              echo "$val"."&lt;/".$key."&gt;\n";
         }
    }

}

Викликайте функцію з першого аргументу як масив, а другий аргумент повинен бути 1, це буде збільшено для ідеального відступу, а третій повинен бути істинним.

наприклад, якщо змінна масиву, яку потрібно перетворити, є $ array1, тоді, виклик буде, функція виклику повинна бути інкапсульована <pre>тегом.

  artoxml ($ array1,1, true);   

Перевірте джерело сторінки після виконання файлу, оскільки символи <і> не відображатимуться на сторінці html.


1
function toXML($data, $obj = false, $dom) {
    $is_first_level = false;
    if($obj === false) {
        $dom = new DomDocument('1.0');
        $obj = $dom;
        $is_first_level = true;
    }

    if(is_array($data)) {
        foreach($data as $key => $item) {
            $this->toXML($item, $obj->appendChild($dom->createElement($key)), $dom);
        }
    }else {
        $obj->appendChild($dom->createTextNode($data));
    }

    if($is_first_level) {
        $obj->formatOutput = true;
        return $obj->saveXML();
    }
    return $obj;
}

Це відмінний варіант для створення DOMDocument xml. Дякуємо @Andrey
altsyset

1
function array2xml(array $data, SimpleXMLElement $object = null, $oldNodeName = 'item')
{
    if (is_null($object)) $object = new SimpleXMLElement('<root/>');
    $isNumbered = true;
    $idx = 0;
    foreach ($data as $key => $x)
        if (is_string($key) || ($idx++ != $key + 0))
            $isNumbered = false;
    foreach ($data as $key => $value)
    {   
        $attribute = preg_match('/^[0-9]/', $key . '') ? $key : null;
        $key = (is_string($key) && !preg_match('/^[0-9]/', $key . '')) ? $key : preg_replace('/s$/', '', $oldNodeName);
        if (is_array($value))
        {
            $new_object = $object->addChild($key);
            if (!$isNumbered && !is_null($attribute)) $new_object->addAttribute('id', $attribute);
            array2xml($value, $new_object, $key);
        }
        else
        {
            if (is_bool($value)) $value = $value ? 'true' : 'false';
            $node = $object->addChild($key, htmlspecialchars($value));
            if (!$isNumbered && !is_null($attribute) && !isset($node->attributes()->id))
                $node->addAttribute('id', $attribute);
        }
    }
    return $object;
}

Ця функція повертає, наприклад, список тегів <obj>...</obj> <obj> ... </obj> XML для числових індексів.

Вхід:

    array(
    'people' => array(
        'dog',
        'cat',
        'life' => array(
            'gum',
            'shoe',
        ),
        'fish',
    ),
    array('yeah'),
)

Вихід:

<root>
    <people>
        <people>dog</people>
        <people>cat</people>
        <life>
            <life>gum</life>
            <life>shoe</life>
        </life>
        <people>fish</people>
        <people>
            <people>yeah</people>
        </people>
    </people>
</root>

Це повинно задовольняти всі загальні потреби. Можливо, ви можете змінити 3-й рядок на:

$key = is_string($key) ? $key : $oldNodeName . '_' . $key;

або якщо ви працюєте з множиною, що закінчується s:

$key = is_string($key) ? $key : preg_replace('/s$/', '', $oldNodeName);

1

За допомогою FluidXML ви можете генерувати, починаючи з масиву PHP , XML для SimpleXML з ... всього двома рядками коду.

$fluidxml  = fluidxml($array);
$simplexml = simplexml_import_dom($fluidxml->dom());

Приклад масиву може бути

$array = [ 'doc' => [
              'fruit' => 'orange',
              'cake'  => [
                   '@id' => '123', 
                   '@'   => 'tiramisu' ],
              [ 'pasta' => 'matriciana' ],
              [ 'pasta' => 'boscaiola'  ]
] ];

https://github.com/servo-php/fluidxml


0

Ви можете використовувати xmlrpc_encode для створення xml з масиву, якщо багатослівний xml не є проблемою. www.php.net/xmlrpc_encode

будьте обережні, що створений xml відрізняється, якщо ви використовуєте асоціативні та / або цифрові ключі

<?php
// /params/param/value/struct/member
// there is a tag "member" for each element
// "member" contains a tag "name". its value is the associative key
$xml1 = xmlrpc_encode(array('a'=>'b','c'=>'d'));
$simplexml1 = simplexml_load_string($xml1);
print_r($xml1);
print_r($simplexml1);

// /params/param/value/array/data
// there is a tag "data" for each element
// "data" doesn't contain the tag "name"
$xml2 = xmlrpc_encode(array('a','b'));
$simplexml2 = simplexml_load_string($xml2);
print_r($xml2);
print_r($simplexml2);
?>

Ця функція не підтримується, і насправді вона не передбачена в моїх збірках PHP 5.2.16 або PHP 5.3.5. (повертає «PHP Fatal error: Call to undefined function xmlrpc_encode ()»)
danorton

Ви повинні прокоментувати наступний рядок у php.ini: extension = php_xmlrpc.dll
w35l3y

@ w35l3y Я перевірив свій іні. Він навіть не містить цього розширення, і я використовую v 5.3.6.
Майк С.

0
function array2xml($array, $xml = false){

    if($xml === false){

        $xml = new SimpleXMLElement('<?xml version=\'1.0\' encoding=\'utf-8\'?><'.key($array).'/>');
        $array = $array[key($array)];

    }
    foreach($array as $key => $value){
        if(is_array($value)){
            $this->array2xml($value, $xml->addChild($key));
        }else{
            $xml->addChild($key, $value);
        }
    }
    return $xml->asXML();
}

0

Моя відповідь, зближуючи відповіді інших. Це повинно виправлятись у разі неможливості компенсації числових клавіш:

function array_to_xml($array, $root, $element) {
    $xml = new SimpleXMLElement("<{$root}/>");
    foreach ($array as $value) {
        $elem = $xml->addChild($element);
        xml_recurse_child($elem, $value);
    }
    return $xml;
}

function xml_recurse_child(&$node, $child) {
    foreach ($child as $key=>$value) {
        if(is_array($value)) {
            foreach ($value as $k => $v) {
                if(is_numeric($k)){
                    xml_recurse_child($node, array($key => $v));
                }
                else {
                    $subnode = $node->addChild($key);
                    xml_recurse_child($subnode, $value);
                }
            }
        }
        else {
            $node->addChild($key, $value);
        }
    }   
}

array_to_xml()Функція передбачає , що масив складається з цифрових клавіш перший. Якби у вашому масиві був початковий елемент, ви випалите з цього пункту foreach()та $elemоператори array_to_xml()та просто переходите $xmlзамість цього.


0

Я б прокоментував другий найбільш проголосований відповідь, тому що він не зберігає структуру і генерує неправильний xml, якщо є внутрішні масиви, що індексуються числом.

Я розробив власну версію на її основі, тому що мені потрібен був простий конвертер між json та xml незалежно від структури даних. Моя версія зберігає цифрову ключову інформацію та структуру вихідного масиву. Він створює елементи для числових індексованих значень, обертаючи значення на елементи з ім'ям значення з атрибутом key, який містить числовий ключ.

Наприклад

array('test' => array(0 => 'some value', 1 => 'other'))

перетворюється в

<test><value key="0">some value</value><value key="1">other</value></test>

Моя версія array_to_xml -функція (сподіваюся, що це комусь допоможе :)

function array_to_xml($arr, &$xml) {
    foreach($arr as $key => $value) {
        if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml->addChild("$key");
            } else {
                $subnode = $xml->addChild("value");
                $subnode->addAttribute('key', $key);                    
            }
            array_to_xml($value, $subnode);
        }
        else {
            if (is_numeric($key)) {
                $xml->addChild("value", $value)->addAttribute('key', $key);
            } else {
                $xml->addChild("$key",$value);
            }
        }
    }
}   

0

Вся структура XML визначається у масиві $ data:

function array2Xml($data, $xml = null)
{
    if (is_null($xml)) {
        $xml = simplexml_load_string('<' . key($data) . '/>');
        $data = current($data);
        $return = true;
    }
    if (is_array($data)) {
        foreach ($data as $name => $value) {
            array2Xml($value, is_numeric($name) ? $xml : $xml->addChild($name));
        }
    } else {
        $xml->{0} = $data;
    }
    if (!empty($return)) {
        return $xml->asXML();
    }
}

0

Якщо ви працюєте в магенто і у вас є такий тип асоціативного масиву

$test_array = array (
    '0' => array (
            'category_id' => '582',
            'name' => 'Surat',
            'parent_id' => '565',
            'child_id' => '567',
            'active' => '1',
            'level' => '6',
            'position' => '17'
    ),

    '1' => array (
            'category_id' => '567', 
            'name' => 'test',
            'parent_id' => '0',
            'child_id' => '576',
            'active' => '0',
            'level' => '0',
            'position' => '18'
    ),
);

тоді це найкраще конвертувати асоціативний масив у формат XML. Використовуйте цей код у файлі контролера.

$this->loadLayout(false);
//header ("content-type: text/xml");
$this->getResponse()->setHeader('Content-Type','text/xml');
$this->renderLayout();

$clArr2xml = new arr2xml($test_array, 'utf-8', 'listdata');
$output = $clArr2xml->get_xml();
print $output; 

class arr2xml
{
var $array = array();
var $xml = '';
var $root_name = '';
var $charset = '';

public function __construct($array, $charset = 'utf-8', $root_name = 'root')
{
    header ("content-type: text/xml");
    $this->array = $array;
    $this->root_name = $root_name;
    $this->charset = $charset;

    if (is_array($array) && count($array) > 0) {
        $this->struct_xml($array);

    } else {
        $this->xml .= "no data";
    }
}

public function struct_xml($array)
{
    foreach ($array as $k => $v) {
        if (is_array($v)) {
            $tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data'
            $this->xml .= "<$tag>";
            $this->struct_xml($v);
            $this->xml .= "</$tag>";
        } else {
            $tag = ereg_replace('^[0-9]{1,}', 'item', $k); // replace numeric key in array to 'data'
            $this->xml .= "<$tag><![CDATA[$v]]></$tag>";
        }
    }
}

public function get_xml()
{

    $header = "<?xml version=\"1.0\" encoding=\"" . $this->charset . "\"?><" . $this->root_name . ">";
    $footer = "</" . $this->root_name . ">";

    return $header . $this->xml . $footer;
}
}

Я сподіваюся, що це допомагає всім.


0

// Structered array for XML convertion.
$data_array = array(
  array(
    '#xml_tag' => 'a',
    '#xml_value' => '',
    '#tag_attributes' => array(
      array(
        'name' => 'a_attr_name',
        'value' => 'a_attr_value',
      ),
    ),
    '#subnode' => array(
      array(
        '#xml_tag' => 'aa',
        '#xml_value' => 'aa_value',
        '#tag_attributes' => array(
          array(
            'name' => 'aa_attr_name',
            'value' => 'aa_attr_value',
          ),
        ),
        '#subnode' => FALSE,
      ),
    ),
  ),
  array(
    '#xml_tag' => 'b',
    '#xml_value' => 'b_value',
    '#tag_attributes' => FALSE,
    '#subnode' => FALSE,
  ),
  array(
    '#xml_tag' => 'c',
    '#xml_value' => 'c_value',
    '#tag_attributes' => array(
      array(
        'name' => 'c_attr_name',
        'value' => 'c_attr_value',
      ),
      array(
        'name' => 'c_attr_name_1',
        'value' => 'c_attr_value_1',
      ),
    ),
    '#subnode' => array(
      array(
        '#xml_tag' => 'ca',  
        '#xml_value' => 'ca_value',
        '#tag_attributes' => FALSE,
        '#subnode' => array(
          array(
            '#xml_tag' => 'caa',
            '#xml_value' => 'caa_value',
            '#tag_attributes' => array(
              array(
                'name' => 'caa_attr_name',
                'value' => 'caa_attr_value',
              ),
            ),
            '#subnode' => FALSE,
          ),
        ),
      ),
    ),
  ),
);


// creating object of SimpleXMLElement
$xml_object = new SimpleXMLElement('<?xml version=\"1.0\"?><student_info></student_info>');


// function call to convert array to xml
array_to_xml($data_array, $xml_object);

// saving generated xml file
$xml_object->asXML('/tmp/test.xml');

/**
 * Converts an structured PHP array to XML.
 *
 * @param Array $data_array
 *   The array data for converting into XML.
 * @param Object $xml_object
 *   The SimpleXMLElement Object
 *
 * @see https://gist.github.com/drupalista-br/9230016
 * 
 */
function array_to_xml($data_array, &$xml_object) {
  foreach($data_array as $node) {
    $subnode = $xml_object->addChild($node['#xml_tag'], $node['#xml_value']);

    if ($node['#tag_attributes']) {
      foreach ($node['#tag_attributes'] as $tag_attributes) {
        $subnode->addAttribute($tag_attributes['name'], $tag_attributes['value']); 
      }
    }

    if ($node['#subnode']) {
      array_to_xml($node['#subnode'], $subnode);
    }
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.