When considering a conversion between PHP native data types and XML, we would normally consider an array as the primary target. With this in mind, the process of converting from a PHP array to XML differs radically from the approach needed to do the reverse.
Application\Parse\ConvertXml class. This class will holdthe methods that will convert from XML to a PHP array, and vice versa. We will need both the SimpleXMLElement and SimpleXMLIterator classes from the SPL:namespace Application\Parse;
use SimpleXMLIterator;
use SimpleXMLElement;
class ConvertXml
{
}xmlToArray() method that will accept a SimpleXMLIterator instance as an argument. It will be called recursively and will produce a PHP array from an XML document. We take advantage of the SimpleXMLIterator ability to advance through the XML document, using the key(), current(), next(), and rewind() methods to navigate:public function xmlToArray(SimpleXMLIterator $xml) : array
{
$a = array();
for( $xml->rewind(); $xml->valid(); $xml->next() ) {
if(!array_key_exists($xml->key(), $a)) {
$a[$xml->key()] = array();
}
if($xml->hasChildren()){
$a[$xml->key()][] = $this->xmlToArray($xml->current());
}
else{
$a[$xml->key()] = (array) $xml->current()->attributes();
$a[$xml->key()]['value'] = strval($xml->current());
}
}
return $a;
}arrayToXml(), sets up an initial SimpleXMLElement instance, and then calls the second method, phpToXml():public function arrayToXml(array $a)
{
$xml = new SimpleXMLElement(
'<?xml version="1.0" standalone="yes"?><root></root>');
$this->phpToXml($a, $xml);
return $xml->asXML();
}get_object_vars() in case one of the array elements is an object. You'll also note that numbers alone are not allowed as XML tags, which means adding some text in front of the number:protected function phpToXml($value, &$xml)
{
$node = $value;
if (is_object($node)) {
$node = get_object_vars($node);
}
if (is_array($node)) {
foreach ($node as $k => $v) {
if (is_numeric($k)) {
$k = 'number' . $k;
}
if (is_array($v)) {
$newNode = $xml->addChild($k);
$this->phpToXml($v, $newNode);
} elseif (is_object($v)) {
$newNode = $xml->addChild($k);
$this->phpToXml($v, $newNode);
} else {
$xml->addChild($k, $v);
}
}
} else {
$xml->addChild(self::UNKNOWN_KEY, $node);
}
}As a sample XML document, you can use the Web Services Definition Language (WSDL) for the United States National Weather Service. This is an XML document that describes a SOAP service, and can be found at http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl.
We will use the SimpleXMLIterator class to provide an iteration mechanism. You can then configure autoloading, and get an instance of Application\Parse\ConvertXml, using xmlToArray() to convert the WSDL to a PHP array:
require __DIR__ . '/../Application/Autoload/Loader.php'; Application\Autoload\Loader::init(__DIR__ . '/..'); use Application\Parse\ConvertXml; $wsdl = 'http://graphical.weather.gov/xml/' . 'SOAP_server/ndfdXMLserver.php?wsdl'; $xml = new SimpleXMLIterator($wsdl, 0, TRUE); $convert = new ConvertXml(); var_dump($convert->xmlToArray($xml));
The resulting array is shown here:

To do the reverse, use the arrayToXml() method described in this recipe. As a source document, you can use a source/data/mongo.db.global.php file that contains an outline for a training video on MongoDB available through O'Reilly Media (disclaimer: by this author!). Using the same autoloader configuration and instance of Application\Parse\ConvertXml, here is the sample code you could use:
$convert = new ConvertXml();
header('Content-Type: text/xml');
echo $convert->arrayToXml(include CONFIG_FILE);Here is the output in a browser:
