Преобразование ассоциативного массива в XML в PHP
Мне было интересно, существует ли функция, способная преобразовывать ассоциативный массив в XML-документ в PHP (или в некоторую широкодоступную библиотеку PHP).
Я много искал и мог найти только функции, которые не выводят корректный XML. Я считаю, что массив, в котором я их тестирую, правильно построен, так как он может быть правильно использован для создания документа JSON с использованием json_encode. Однако он довольно большой и вложен в четыре уровня, что может объяснить, почему функции, которые я пробовал до сих пор, не работают.
В конечном счете, я напишу код для генерации самого XML, но, безусловно, должен быть более быстрый способ сделать это.
Ответы
Ответ 1
Нет. По крайней мере, такая встроенная функция отсутствует. Это не проблема, чтобы написать это вообще.
Конечно, должен быть более быстрый способ сделать это
Как вы представляете атрибут в массиве? Я могу предположить, что тегами и значениями являются теги.
Базовый PHP-массив → JSON работает просто отлично, потому что эта структура... ну... почти то же самое.
Ответ 2
Я понимаю, что здесь я здесь, Джонни-Леди, но я работал с ОЧЕНЬ той же проблемой, и в учебниках, которые я узнал, будет почти (но не совсем на модульном тестировании) покройте его.
После долгих разочарований и исследований, вот что я расправляюсь с
XML To Assoc. Массив:
От http://www.php.net/manual/en/simplexml.examples-basic.php
json_decode( json_encode( simplexml_load_string( $string ) ), TRUE );
доц. Массив в XML
заметки:
- XML-атрибуты не обрабатываются
- Будет ли также обрабатывать вложенные массивы с числовыми индексами (которые недопустимы для XML!)
От http://www.devexp.eu/2009/04/11/php-domdocument-convert-array-to-xml/
/// Converts an array to XML
/// - http://www.devexp.eu/2009/04/11/php-domdocument-convert-array-to-xml/
/// @param <array> $array The associative array you want to convert; nested numeric indices are OK!
function getXml( array $array ) {
$array2XmlConverter = new XmlDomConstructor('1.0', 'utf-8');
$array2XmlConverter->xmlStandalone = TRUE;
$array2XmlConverter->formatOutput = TRUE;
try {
$array2XmlConverter->fromMixed( $array );
$array2XmlConverter->normalizeDocument ();
$xml = $array2XmlConverter->saveXML();
// echo "\n\n-----vvv start returned xml vvv-----\n";
// print_r( $xml );
// echo "\n------^^^ end returned xml ^^^----\n"
return $xml;
}
catch( Exception $ex ) {
// echo "\n\n-----vvv Rut-roh Raggy! vvv-----\n";
// print_r( $ex->getCode() ); echo "\n";
// print_r( $->getMessage() );
// var_dump( $ex );
// echo "\n------^^^ end Rut-roh Raggy! ^^^----\n"
return $ex;
}
}
... и вот класс, который следует использовать для объекта $array2XmlConverter
:
/**
* Extends the DOMDocument to implement personal (utility) methods.
* - From: http://www.devexp.eu/2009/04/11/php-domdocument-convert-array-to-xml/
* - `parent::` See http://www.php.net/manual/en/class.domdocument.php
*
* @throws DOMException http://www.php.net/manual/en/class.domexception.php
*
* @author Toni Van de Voorde
*/
class XmlDomConstructor extends DOMDocument {
/**
* Constructs elements and texts from an array or string.
* The array can contain an element name in the index part
* and an element text in the value part.
*
* It can also creates an xml with the same element tagName on the same
* level.
*
* ex:
\verbatim
<nodes>
<node>text</node>
<node>
<field>hello</field>
<field>world</field>
</node>
</nodes>
\verbatim
*
*
* Array should then look like:
\verbatim
array(
"nodes" => array(
"node" => array(
0 => "text",
1 => array(
"field" => array (
0 => "hello",
1 => "world",
),
),
),
),
);
\endverbatim
*
* @param mixed $mixed An array or string.
*
* @param DOMElement[optional] $domElement Then element
* from where the array will be construct to.
*
*/
public function fromMixed($mixed, DOMElement $domElement = null) {
$domElement = is_null($domElement) ? $this : $domElement;
if (is_array($mixed)) {
foreach( $mixed as $index => $mixedElement ) {
if ( is_int($index) ) {
if ( $index == 0 ) {
$node = $domElement;
}
else {
$node = $this->createElement($domElement->tagName);
$domElement->parentNode->appendChild($node);
}
}
else {
$node = $this->createElement($index);
$domElement->appendChild($node);
}
$this->fromMixed($mixedElement, $node);
}
}
else {
$domElement->appendChild($this->createTextNode($mixed));
}
}
} // end of class
Ответ 3
PHP DOMDocument
объекты, вероятно, то, что вы ищете. Вот ссылка на пример использования этого класса для преобразования многомерного массива в XML файл - http://www.php.net/manual/en/book.dom.php#78941
Ответ 4
Вызов
// $data = array(...);
$dataTransformator = new DataTransformator();
$domDocument = $dataTransformator->data2domDocument($data);
$xml = $domDocument->saveXML();
DataTransformator
class DataTransformator {
/**
* Converts the $data to a \DOMDocument.
* @param array $data
* @param string $rootElementName
* @param string $defaultElementName
* @see MyNamespace\Dom\DataTransformator#data2domNode(...)
* @return Ambigous <DOMDocument>
*/
public function data2domDocument(array $data, $rootElementName = 'data', $defaultElementName = 'item') {
return $this->data2domNode($data, $rootElementName, null, $defaultElementName);
}
/**
* Converts the $data to a \DOMNode.
* If the $elementContent is a string,
* a DOMNode with a nested shallow DOMElement
* will be (created if the argument $node is null and) returned.
* If the $elementContent is an array,
* the function will applied on every its element recursively and
* a DOMNode with a nested DOMElements
* will be (created if the argument $node is null and) returned.
* The end result is always a DOMDocument object.
* The casue is, that a \DOMElement object
* "is read only. It may be appended to a document,
* but additional nodes may not be appended to this node
* until the node is associated with a document."
* See {@link http://php.net/manual/en/domelement.construct.php here}).
*
* @param Ambigous <string, mixed> $elementName Used as element tagname. If it not a string $defaultElementName is used instead.
* @param Ambigous <string, array> $elementContent
* @param Ambigous <\DOMDocument, NULL, \DOMElement> $parentNode The parent node is
* either a \DOMDocument (by the method calls from outside of the method)
* or a \DOMElement or NULL (by the calls from inside).
* Once again: For the calls from outside of the method the argument MUST be either a \DOMDocument object or NULL.
* @param string $defaultElementName If the key of the array element is a string, it determines the DOM element name / tagname.
* For numeric indexes the $defaultElementName is used.
* @return \DOMDocument
*/
protected function data2domNode($elementContent, $elementName, \DOMNode $parentNode = null, $defaultElementName = 'item') {
$parentNode = is_null($parentNode) ? new \DOMDocument('1.0', 'utf-8') : $parentNode;
$name = is_string($elementName) ? $elementName : $defaultElementName;
if (!is_array($elementContent)) {
$content = htmlspecialchars($elementContent);
$element = new \DOMElement($name, $content);
$parentNode->appendChild($element);
} else {
$element = new \DOMElement($name);
$parentNode->appendChild($element);
foreach ($elementContent as $key => $value) {
$elementChild = $this->data2domNode($value, $key, $element);
$parentNode->appendChild($elementChild);
}
}
return $parentNode;
}
}
Ответ 5
Конечно, должен быть более быстрый способ сделать это
Если у вас установлен PEAR, есть. Посмотрите на XML_Seralizer. Это бета-версия, поэтому вам придется использовать
pear install XML_Serializer-beta
для установки
Ответ 6
Мне понадобилось решение, которое способно преобразовывать массивы с неассоциативными подмассивами и контентом, которые должны быть экранированы с помощью CDATA (< > &). Поскольку я не мог найти подходящего решения, я реализовал свой собственный на основе SimpleXML, который должен быть довольно быстрым.
https://github.com/traeger/SimplestXML (это решение поддерживает (Ассоциативное) Array = > XML и XML = > (ассоциативное) преобразование массива без поддержки атрибутов), Надеюсь, это поможет кому-то.
Ответ 7
function combArrToXML($arrC=array(), $root="root", $element="element"){
$doc = new DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement( $root );
$doc->appendChild( $r );
$b = $doc->createElement( $element );
foreach( $arrC as $key => $val)
{
$$key = $doc->createElement( $key );
$$key->appendChild(
$doc->createTextNode( $val )
);
$b->appendChild( $$key );
$r->appendChild( $b );
}
return $doc->saveXML();
}
Пример:
$b=array("testa"=>"testb", "testc"=>"testd");
combArrToXML($b, "root", "element");
Вывод:
<?xml version="1.0"?>
<root>
<element>
<testa>testb</testa>
<testc>testd</testc>
</element>
</root>