У меня есть массив, который мне нужно преобразовать в XML с помощью SimpleXML. Метод, приведенный ниже, почти выполняет работу, но есть одна проблема с ним. Он не может генерировать такую структуру:
$xmlFields = array( 'rootElt' => array( 'field1' => '', 'field2' => '', 'field3' => array( 'field4' => array( 'income' => array( 'owner' => '', 'description' => '', ), 'income' => array( 'owner' => '', 'description' => '', ), ), ) ) );
Он пишет только последний «доход» раздела «field4», но мне нужен вывод:
<field4> <income> <owner>....</owner> <description>....</description> </income> <income> <owner>....</owner> <description>....</description> </income> </field4>
Может ли кто-нибудь помочь мне исправить эту функцию:
/** * @param array $dataArr * @param SimpleXMLElement $xmlObj */ private function array2xml( $dataArr, $xmlObj ) { foreach ( $dataArr as $key => $value ) { if ( is_array($value) ) { if ( !is_numeric($key) ) { $subnode = $xmlObj->addChild( $key ); self::array2xml( $value, $subnode ); } else { self::array2xml( $value, $xmlObj ); } } else { $xmlObj->addChild( $key, $value ); } } }
Код выглядит отлично с точки зрения SimpleXML, однако у вас есть непонимание того, как массивы работают в PHP:
'field4' => array( 'income' => array( 'owner' => '', 'description' => '', ), 'income' => array( 'owner' => '', 'description' => '', ),
Это не добавляет два значения в массив field4
, но один. См. http://php.net/array , например, пример # 2 . Второе определение ключа income
заменяет первое.
В этом случае вы можете использовать другую структуру с массивом:
'field4' => array( array('income' => array( 'owner' => '', 'description' => '', )), array('income' => array( 'owner' => '', 'description' => '', )),
Если вы оберните каждый элемент внутри элемента массива, он будет собственный, ваш код даже не будет иметь особых случаев, потому что каждый элемент будет таким же. Однако это означало бы, что вы – если вы создадите массив вручную – напишите больше кода, чтобы определить его.
Еще одна альтернатива, которая приходит на ум, такова:
'field4' => array( 'income' => array( array( 'owner' => '', 'description' => '', ), array( 'owner' => '', 'description' => '', ), ),
Это все равно не позволит вам иметь несколько групп с одним и тем же именем элемента, но писать было бы, вероятно, проще.
Для более поздней структуры массива (я думаю, это то, что вы хотели использовать), я создал импортер / конвертер массива simplexml ( Gist ). Использование довольно прямолинейно в базовой форме, но вы можете сделать с ним еще более дифференцированные вещи:
/* Example 1: Create a new SimpleXMLElement based on an array */ $import = new SimpleXMLArrayImport(); $xml = $import->importArray(['root' => '']); /* <?xml version="1.0"?> * <root/> */ /* Example 2: Add an empty child element to the root */ $new = $import->addArray($xml, ['numbers' => '']); /* <?xml version="1.0"?> * <root> * <numbers/> * </root> */ /* Example 3: Add a list of same-named elements to the root */ $last = $import->addArray($new, ['number' => [0, 1, 42]]); /* <?xml version="1.0"?> * <root> * <numbers> * <number>0</number> * <number>1</number> * <number>42</number> * </numbers> * </root> */ /* Example 4: Set attribute of last added element */ $last['note'] = 'The Answer to the Ultimate Question of Life, the Universe, and Everything'; /* <?xml version="1.0"?> * <root> * <numbers> * <number>0</number> * <number>1</number> * <number note="The Answer to the ...">42</number> * </numbers> * </root> */ /* Example 5: Create a full document */ $xmlFields = array( 'rootElt' => array( 'field1' => '', 'field2' => '', 'field3' => array( 'field4' => array( 'income' => array( array( 'owner' => '', 'description' => '', ), array( 'owner' => '', 'description' => '', ), ), ), ) ) ); $import = new SimpleXMLArrayImport($xmlFields); $xml = $import->getDocument(); # The SimpleXML Root Element /* <?xml version="1.0"?> * <rootElt> * <field1/> * <field2/> * <field3> * <field4> * <income> * <owner/> * <description/> * </income> * <income> * <owner/> * <description/> * </income> * </field4> * </field3> * </rootElt> */