Array & XML Conversion in PHP

It often requires converting between XML and PHP arrays when working with APIs, feeds and third-party integrations. Learn how to convert XML to array and array to XML in PHP application.

Array & XML Conversion in PHP

When retrieving data from third-party APIs sometimes it is needed to convert received XML data to array. In PHP arrays are native and easy to work with and manipulate, on other hand XML is used to describe data which makes it best option for data exchange and storage. In this post we will understand how to convert XML to array and array to XML in simple way with code snippets.


Convert XML to Array in PHP

Converting XML to array in PHP is possible using different approaches. We will demonstrate two different approaches to convert XML to array in PHP. The first approach involves using simpleXML with JSON encoding and decoding, while the second approach involves using DOMDocument with recursion which gives more control when it comes to attributes.

 

Method 1: Convert XML to Array Using simpleXML

This is the most common and effective approach with simple steps using simplexml_load_string() with with json_encode() and json_decode(). However if the XML elements contain attributes they will be lost on second level and after in tree. 

  • Prepare an XML string, usually from a file content.
  • Load XML string using simplexml_load_string() method.
  • JSON encode and decode the loaded XML string using json_encode() and json_decode() methods. 
// Prepare static XML content
$xml_string = <<<XML
<books>
<book id="1">
<title>Basic PHP</title>
<author>John Doe</author>
<price>29.99</price>
</book>
<book id="2">
<title>Advanced PHP</title>
<author>John Doe</author>
<price>29.99</price>
</book>
</books>
XML;

// Load XML string and json encode and decode
$xml = simplexml_load_string($xml_string);
$xml_to_array = json_decode(json_encode($xml), true);

// Output of $xml_to_array
Array
(
[book] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 1
)

[title] => Basic PHP
[author] => John Doe
[price] => 29.99
)

[1] => Array
(
[@attributes] => Array
(
[id] => 2
)

[title] => Advanced PHP
[author] => John Doe
[price] => 29.99
)

)

)

The above code snippet will convert the XML to array in PHP, however if the elements <title>, <author> and <price> had their attributes they will be lost. This approach should work for not complex XML conversion. 

 

Method 2:  Convert XML to Array Using DOMDocument and Recursion

This approach requires a bit of manual handling but provides more control over conversion for complex XML structure. This approach involves using DOMDocument API with custom recursive function to loop through all elements of XML providing more control and access to elements, attributes, namespaces and text nodes. We will use the same XML as in example above with extra attribute "currency" for <price> element.

  • Prepare an XML document string and assign it to $xml_string variable.
  • Open a new DOMDocument and load XML string into document.
  • Use a recursive function parse_dom_node() and convert XML to array. 
// Prepare static XML content
$xml_string = <<<XML
<books>
<book id="1">
<title>Basic PHP</title>
<author>John Doe</author>
<price currency="usd">29.99</price>
</book>
<book id="2">
<title>Advanced PHP</title>
<author>John Doe</author>
<price currency="usd">29.99</price>
</book>
</books>
XML;

/**
* @param $node
* @return array|string
*/
function parse_dom_node($node): array|string
{
$output = [];

// Get attributes
if ($node->hasAttributes()) {
foreach ($node->attributes as $attribute) {
$output['@attributes'][$attribute->nodeName] = $attribute->nodeValue;
}
}

// Get child nodes
if ($node->hasChildNodes()) {
$children = [];

foreach ($node->childNodes as $child) {
if ($child->nodeType === XML_TEXT_NODE) {
$text = trim($child->nodeValue);

if (!empty($text)) {
$output['@value'] = $text;
}
} elseif ($child->nodeType === XML_ELEMENT_NODE) {
$child_name = $child->nodeName;
$child_data = parse_dom_node($child);

if (!isset($children[$child_name])) {
$children[$child_name] = $child_data;
} else {
// Multiple elements with same name to array
if (!is_array($children[$child_name]) || !isset($children[$child_name][0])) {
$children[$child_name] = [$children[$child_name]];
}

$children[$child_name][] = $child_data;
}
}
}

$output = array_merge($output, $children);
}

return $output;
}

// Open new DOMDocument & load XMl string to document
$doc = new DOMDocument();
$doc->loadXML($xml_string);

// Get root element of document
$root = $doc->documentElement;

// Prepare array of XML elements recursively
$xml_to_array = parse_dom_node($root);

// Output
Array
(
[book] => Array
(
[0] => Array
(
[@attributes] => Array
(
[id] => 1
)

[title] => Array
(
[@value] => Basic PHP
)

[author] => Array
(
[@value] => John Doe
)

[price] => Array
(
[@attributes] => Array
(
[currency] => usd
)

[@value] => 29.99
)

)

[1] => Array
(
[@attributes] => Array
(
[id] => 2
)

[title] => Array
(
[@value] => Advanced PHP
)

[author] => Array
(
[@value] => John Doe
)

[price] => Array
(
[@attributes] => Array
(
[currency] => usd
)

[@value] => 29.99
)

)

)

)
 

Convert Array to XML in PHP

Converting PHP array to XML is used more as PHP does not offer a built-in function for that. So this step involves use of DOMDocument and recursive function to go through all elements of array and prepare an XML document.

  • Prepare an array of books and assign it to a variable $books.
  • Write a recursive function convert_array_to_xml() which accepts three parameters, $data, $doc, and $parent.
  • Open a new DomDocument and set formatOutput to true.
  • Create a root element books and assign attribute collection-name for indexed array as XML does not support numeric element names.
  • Append the root element to document.
  • Call the convert_array_to_xml() function providing it the required parameters.
  • Finally print or save the prepared XML. 
// Array of Books
$books = [
[
'@attributes' => [
'id' => 1
],
'title' => [
'@value' => 'Basic PHP'
],
'author' => [
'@value' => 'John Doe'
],
'price' => [
'@attributes' => [
'currency' => 'usd'
],
'@value' => 29.99
]
],
[
'@attributes' => [
'id' => 2
],
'title' => [
'@value' => 'Advanced PHP'
],
'author' => [
'@value' => 'John Doe'
],
'price' => [
'@attributes' => [
'currency' => 'usd'
],
'@value' => 29.99
]
],
];

/**
* @param $data
* @param $doc
* @param $parent
* @return mixed
*/
function convert_array_to_xml($data, &$doc, $parent = null): mixed
{
foreach ($data as $key => $value) {
if (is_numeric($key)) {
// Assume numeric keys mean repeating elements
$key = $parent->getAttribute('collection-name') ?? 'item';
}

$element = $doc->createElement($key);

if ($parent) {
$parent->appendChild($element);
} else {
$doc->appendChild($element);
}

if (is_array($value)) {
if (isset($value['@attributes'])) {
foreach ($value['@attributes'] as $attribute_name => $attribute_value) {
$element->setAttribute($attribute_name, $attribute_value);
}
}

if (isset($value['@value'])) {
$element->appendChild($doc->createTextNode($value['@value']));
}

// Recurse into other child elements
$children = array_diff_key($value, ['@attributes' => '', '@value' => '']);

if (!empty($children)) {
convert_array_to_xml($children, $doc, $element);
}
} else {
// Scalar value
$element->appendChild($doc->createTextNode($value));
}
}

return $doc;
}

// Open a new DOMDocument and set formatOutput to true
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true;

// Add a root element i.e. books and set collection name for indexed array of books
$root = $doc->createElement('books');
$root->setAttribute('collection-name', 'book');

$doc->appendChild($root);

// Convert array to XML recursively
$xml = convert_array_to_xml($books, $doc, $root);

echo $xml->saveXML();

PHP makes it simple to work with XML and arrays with a bit of manual work for converting array to XML or when converting more complicated XML structure to array. We demonstrated how to convert XML to array and array to XML in PHP.