XML2Array is a class to convert XML to an array in PHP. It returns an array which can be converted back to XML using the Array2XML class.
It can take a string XML as input or an object of type DOMDocument
.
['tag_name']['@attributes']
['tag_name']['@cdata']
['tag_name']['@value']
The usage is pretty simple. You have to include the class file in your code and call the following function.
$array = XML2Array::createArray($xml); print_r($array);
Important thing to note is that the $array
returned can be converted back to XML using the Array2XML class.
The Following XML:
<?xml version="1.0" encoding="UTF-8"?> <movies type="documentary"> <movie> <title>PHP: Behind the Parser</title> <characters> <character> <name>Ms. Coder</name> <actor>Onlivia Actora</actor> </character> <character> <name>Mr. Coder</name> <actor>El ActÓr</actor> </character> </characters> <plot><![CDATA[So, this language. It's like, a programming language. Or is it a scripting language? All is revealed in this thrilling horror spoof of a documentary.]]></plot> <great-lines> <line>PHP solves all my web problems</line> </great-lines> <rating type="thumbs">7</rating> <rating type="stars">5</rating> </movie> </movies>
will generate the following output:
array ( 'movies' => array ( 'movie' => array ( 'title' => 'PHP: Behind the Parser', 'characters' => array ( 'character' => array ( 0 => array ( 'name' => 'Ms. Coder', 'actor' => 'Onlivia Actora', ), 1 => array ( 'name' => 'Mr. Coder', 'actor' => 'El ActÓr', ), ), ), 'plot' => array ( '@cdata' => 'So, this language. It\'s like, a programming language. Or is it a scripting language? All is revealed in this thrilling horror spoof of a documentary.', ), 'great-lines' => array ( 'line' => 'PHP solves all my web problems', ), 'rating' => array ( 0 => array ( '@value' => '7', '@attributes' => array ( 'type' => 'thumbs', ), ), 1 => array ( '@value' => '5', '@attributes' => array ( 'type' => 'stars', ), ), ), ), '@attributes' => array ( 'type' => 'documentary', ), ), )
The code is released under Apache License 2.0
Plain text PHP source | Formatted PHP source
来源: http://www.lalit.org/lab/convert-xml-to-array-in-php-xml2array/
源码:
<?php /** * XML2Array: A class to convert XML to array in PHP * It returns the array which can be converted back to XML using the Array2XML script * It takes an XML string or a DOMDocument object as an input. * * See Array2XML: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes * * Author : Lalit Patel * Website: http://www.lalit.org/lab/convert-xml-to-array-in-php-xml2array * License: Apache License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * Version: 0.1 (07 Dec 2011) * Version: 0.2 (04 Mar 2012) * Fixed typo 'DomDocument' to 'DOMDocument' * * Usage: * $array = XML2Array::createArray($xml); */ class XML2Array { private static $xml = null; private static $encoding = 'UTF-8'; /** * Initialize the root XML node [optional] * @param $version * @param $encoding * @param $format_output */ public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { self::$xml = new DOMDocument($version, $encoding); self::$xml->formatOutput = $format_output; self::$encoding = $encoding; } /** * Convert an XML to Array * @param string $node_name - name of the root node to be converted * @param array $arr - aray to be converterd * @return DOMDocument */ public static function &createArray($input_xml) { $xml = self::getXMLRoot(); if(is_string($input_xml)) { $parsed = $xml->loadXML($input_xml); if(!$parsed) { throw new Exception('[XML2Array] Error parsing the XML string.'); } } else { if(get_class($input_xml) != 'DOMDocument') { throw new Exception('[XML2Array] The input XML object should be of type: DOMDocument.'); } $xml = self::$xml = $input_xml; } $array[$xml->documentElement->tagName] = self::convert($xml->documentElement); self::$xml = null; // clear the xml node in the class for 2nd time use. return $array; } /** * Convert an Array to XML * @param mixed $node - XML as a string or as an object of DOMDocument * @return mixed */ private static function &convert($node) { $output = array(); switch ($node->nodeType) { case XML_CDATA_SECTION_NODE: $output['@cdata'] = trim($node->textContent); break; case XML_TEXT_NODE: $output = trim($node->textContent); break; case XML_ELEMENT_NODE: // for each child node, call the covert function recursively for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) { $child = $node->childNodes->item($i); $v = self::convert($child); if(isset($child->tagName)) { $t = $child->tagName; // assume more nodes of same kind are coming if(!isset($output[$t])) { $output[$t] = array(); } $output[$t][] = $v; } else { //check if it is not an empty text node if($v !== '') { $output = $v; } } } if(is_array($output)) { // if only one node of its kind, assign it directly instead if array($value); foreach ($output as $t => $v) { if(is_array($v) && count($v)==1) { $output[$t] = $v[0]; } } if(empty($output)) { //for empty nodes $output = ''; } } // loop through the attributes and collect them if($node->attributes->length) { $a = array(); foreach($node->attributes as $attrName => $attrNode) { $a[$attrName] = (string) $attrNode->value; } // if its an leaf node, store the value in @value instead of directly storing it. if(!is_array($output)) { $output = array('@value' => $output); } $output['@attributes'] = $a; } break; } return $output; } /* * Get the root XML node, if there isn't one, create it. */ private static function getXMLRoot(){ if(empty(self::$xml)) { self::init(); } return self::$xml; } } ?>
Array2XML is a class to convert an array in PHP to XML. It allows you to parse a multidimensional array into XML including attributes unlike other scripts available on the internet. It returns the XML in form of DOMDocument object for further manipulation.
This library is very helpful when you know the scheme before hand and you have to generate an XML for it using dynamic values from the database.
The resulting XML can be converted back to an Array using the XML2Array class.
The usage is pretty simple. You have to include the class file in your code and call the following function.
$xml = Array2XML::createXML('root_node_name', $php_array); echo $xml->saveXML();
Important thing to note is that the $xml
object returned is of type DOMDocument
and hence you can perform further operations on it.
Optionally you can also set the version of XML and encoding by calling the Array2XML::init()
function before calling the Array2XML::createXML()
function.
Array2XML::init($version /* ='1.0' */, $encoding /* ='UTF-8' */);
It throws exception if the tag name or attribute name has illegal chars as per W3C spec .
The array passed to the Array2XML::createXML()
function follows few conventions, which are quite literal and easy to learn/use. The examples below demonstrate their usage
1. Empty Nodes: Following will create an empty node.
$books = array(); // or $books = null; // or $books = ''; $xml = Array2XML::createXML('books', $books); // all three cases above create <books/>
2. Attributes: Attributes can be added to any node by having a @attributes
key in the array
$books = array( '@attributes' => array( 'type' => 'fiction', 'year' => 2011, 'bestsellers' => true ) ); $xml = Array2XML::createXML('books', $books); // creates <books type="fiction" year="2011" bestsellers="true"/>
3. Node Value: For nodes without attributes, value can be assigned directly, else we need to have a @value
key in the array. Following examples will make it clear
$books = 1984; // or $books = array( '@value' = 1984 ); // creates <books>1984</books> $books = array( '@attributes' => array( 'type' => 'fiction' ), '@value' = 1984 ); // creates <books type="fiction">1984</books> $books = array( '@attributes' => array( 'type' => 'fiction' ), 'book' => 1984 ); /* creates <books type="fiction"> <book>1984</book> </books> */ $books = array( '@attributes' => array( 'type' => 'fiction' ), 'book'=> array('1984','Foundation','Stranger in a Strange Land') ); /* creates <books type="fiction"> <book>1984</book> <book>Foundation</book> <book>Stranger in a Strange Land</book> </books> */
4. Complex XML: Following example clarifies most of the usage of the library
$books = array( '@attributes' => array( 'type' => 'fiction' ), 'book' => array( array( '@attributes' => array( 'author' => 'George Orwell' ), 'title' => '1984' ), array( '@attributes' => array( 'author' => 'Isaac Asimov' ), 'title' => array('@cdata'=>'Foundation'), 'price' => '$15.61' ), array( '@attributes' => array( 'author' => 'Robert A Heinlein' ), 'title' => array('@cdata'=>'Stranger in a Strange Land'), 'price' => array( '@attributes' => array( 'discount' => '10%' ), '@value' => '$18.00' ) ) ) ); /* creates <books type="fiction"> <book author="George Orwell"> <title>1984</title> </book> <book author="Isaac Asimov"> <title><![CDATA[Foundation]]></title> <price>$15.61</price> </book> <book author="Robert A Heinlein"> <title><![CDATA[Stranger in a Strange Land]]</title> <price discount="10%">$18.00</price> </book> </books> */
You can see a much more detailed example here .
The code is released under Apache License 2.0
Plaint text PHP source | Formatted PHP source
来源: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes/
源码:
<?php /** * Array2XML: A class to convert array in PHP to XML * It also takes into account attributes names unlike SimpleXML in PHP * It returns the XML in form of DOMDocument class for further manipulation. * It throws exception if the tag name or attribute name has illegal chars. * * Author : Lalit Patel * Website: http://www.lalit.org/lab/convert-php-array-to-xml-with-attributes * License: Apache License 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * Version: 0.1 (10 July 2011) * Version: 0.2 (16 August 2011) * - replaced htmlentities() with htmlspecialchars() (Thanks to Liel Dulev) * - fixed a edge case where root node has a false/null/0 value. (Thanks to Liel Dulev) * Version: 0.3 (22 August 2011) * - fixed tag sanitize regex which didn't allow tagnames with single character. * Version: 0.4 (18 September 2011) * - Added support for CDATA section using @cdata instead of @value. * Version: 0.5 (07 December 2011) * - Changed logic to check numeric array indices not starting from 0. * Version: 0.6 (04 March 2012) * - Code now doesn't @cdata to be placed in an empty array * Version: 0.7 (24 March 2012) * - Reverted to version 0.5 * Version: 0.8 (02 May 2012) * - Removed htmlspecialchars() before adding to text node or attributes. * * Usage: * $xml = Array2XML::createXML('root_node_name', $php_array); * echo $xml->saveXML(); */ class Array2XML { private static $xml = null; private static $encoding = 'UTF-8'; /** * Initialize the root XML node [optional] * @param $version * @param $encoding * @param $format_output */ public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) { self::$xml = new DomDocument($version, $encoding); self::$xml->formatOutput = $format_output; self::$encoding = $encoding; } /** * Convert an Array to XML * @param string $node_name - name of the root node to be converted * @param array $arr - aray to be converterd * @return DomDocument */ public static function &createXML($node_name, $arr=array()) { $xml = self::getXMLRoot(); $xml->appendChild(self::convert($node_name, $arr)); self::$xml = null; // clear the xml node in the class for 2nd time use. return $xml; } /** * Convert an Array to XML * @param string $node_name - name of the root node to be converted * @param array $arr - aray to be converterd * @return DOMNode */ private static function &convert($node_name, $arr=array()) { //print_arr($node_name); $xml = self::getXMLRoot(); $node = $xml->createElement($node_name); if(is_array($arr)){ // get the attributes first.; if(isset($arr['@attributes'])) { foreach($arr['@attributes'] as $key => $value) { if(!self::isValidTagName($key)) { throw new Exception('[Array2XML] Illegal character in attribute name. attribute: '.$key.' in node: '.$node_name); } $node->setAttribute($key, self::bool2str($value)); } unset($arr['@attributes']); //remove the key from the array once done. } // check if it has a value stored in @value, if yes store the value and return // else check if its directly stored as string if(isset($arr['@value'])) { $node->appendChild($xml->createTextNode(self::bool2str($arr['@value']))); unset($arr['@value']); //remove the key from the array once done. //return from recursion, as a note with value cannot have child nodes. return $node; } else if(isset($arr['@cdata'])) { $node->appendChild($xml->createCDATASection(self::bool2str($arr['@cdata']))); unset($arr['@cdata']); //remove the key from the array once done. //return from recursion, as a note with cdata cannot have child nodes. return $node; } } //create subnodes using recursion if(is_array($arr)){ // recurse to get the node for that key foreach($arr as $key=>$value){ if(!self::isValidTagName($key)) { throw new Exception('[Array2XML] Illegal character in tag name. tag: '.$key.' in node: '.$node_name); } if(is_array($value) && is_numeric(key($value))) { // MORE THAN ONE NODE OF ITS KIND; // if the new array is numeric index, means it is array of nodes of the same kind // it should follow the parent key name foreach($value as $k=>$v){ $node->appendChild(self::convert($key, $v)); } } else { // ONLY ONE NODE OF ITS KIND $node->appendChild(self::convert($key, $value)); } unset($arr[$key]); //remove the key from the array once done. } } // after we are done with all the keys in the array (if it is one) // we check if it has any text value, if yes, append it. if(!is_array($arr)) { $node->appendChild($xml->createTextNode(self::bool2str($arr))); } return $node; } /* * Get the root XML node, if there isn't one, create it. */ private static function getXMLRoot(){ if(empty(self::$xml)) { self::init(); } return self::$xml; } /* * Get string representation of boolean value */ private static function bool2str($v){ //convert boolean to text value. $v = $v === true ? 'true' : $v; $v = $v === false ? 'false' : $v; return $v; } /* * Check if the tag name or attribute name contains illegal characters * Ref: http://www.w3.org/TR/xml/#sec-common-syn */ private static function isValidTagName($tag){ $pattern = '/^[a-z_]+[a-z0-9\:\-\.\_]*[^:]*$/i'; return preg_match($pattern, $tag, $matches) && $matches[0] == $tag; } } ?>