PHP: Как перевести массив в xml

В одном из свои проектов столкнулся с необходимостью предоставления данных в виде JSON и xml, если с джейсоном ничего сложного нет, то с xml готового решения нет, вместо банального решения, которое приходит на ум первым делом, хотелось универсального и изящного решения. Полез в гугл и вот что нашел:

$xml = new SimpleXMLElement('<root/>');
array_walk_recursive($test_array, array ($xml, 'addChild'));
print $xml->asXML();

Но проблема в том, что полученный xml не повторяет вложенность массива из которого тот был получен. Для кого сей нюанс не критичен, то могут вполне себе пользоваться этим кодом, он хорош своей компактностью. Но мне хотелось что бы структура  получаемого xml копировала структуру массива. По этой причине я наотрез отказался от функции array_walk_recursive. После нескольких проб и ошибок я получил вот такой код:

function array_as_xml( $array, $root ) {
  $xml = new SimpleXMLElement( '<' . $root . '/>' );
  foreach( $array as $element=>$value ) {
    $element = is_numeric( $element ) ? $root : $element;
    if ( is_array( $value ) ) {
      if ( is_numeric_keys( $value ) ) {
        array2xml( $value, $xml, $element );
      } else {
        $$element = $xml->addChild( $element );
        array2xml( $value, $$element, $element );
      }
    } else {
      $xml->addChild( $element, $value );
    }
   }
  return $xml->asXML();
}

function array2xml( $array, &$xml, $root ) {
  foreach( $array as $element=>$value ) {
    $element = is_numeric( $element ) ? $root : $element;
    if ( is_array( $value ) ) {
      if ( is_numeric_keys( $value ) ) {
        array2xml( $value, $xml, $element );
      } else {
        $$element = $xml->addChild( $element );
        array2xml( $value, $$element, $element );
      }
    } else {
      if ( preg_match( '/^@/', $element) ) {
        $xml->addAttribute( str_replace( '@', '', $element ), $value );
      } else {
        $xml->addChild( $element, $value );
      }
    }
  }
}

function is_numeric_keys( $array ) {
  foreach( $array as $key=>$value ) {
    if ( ! is_numeric( $key ) ) {
      return false;
    }
  }
  return true;
}

Единственный недостаток этого подхода лишь в том, что в случае отправки обычного списка, вместо ассоциативного массива, xml получается не совсем правильный.

Пример использования

$array = array(
 'key'=>'value',
 'key2'=>'value2',
 'key3'=>'value3',
 'key4'=> array(
 'key'=>'value',
 'key2'=>'value2',
 ),
 'key5'=>array(
 'value',
 'value2',
 'value3',
 'value4',
 'value5',
 ),
);
echo array_as_xml( $array, 'root' );

Результат

<root>
 <key>value</key>
 <key2>value2</key2>
 <key3>value3</key3>
 <key4>
 <key>value</key>
 <key2>value2</key2>
 </key4>
 <key5>value</key5>
 <key5>value2</key5>
 <key5>value3</key5>
 <key5>value4</key5>
 <key5>value5</key5>
</root>

Оценка статьи

Полная фигняУзнал немного новогоНормальная статьяХорошая статьяСупер! (1 оценок, среднее: 5,00 из 5)
Загрузка...

2 thoughts on “PHP: Как перевести массив в xml

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Подпишитесь на рассылку и получайте новые статьи на почту