Created
November 4, 2012 16:40
-
-
Save hakre/4012538 to your computer and use it in GitHub Desktop.
Convert/Import an Array into a SimpleXMLElement
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Convert/Import an Array into a SimpleXMLElement | |
* | |
* @author hakre <http://hakre.wordpress.com/> | |
* @see http://stackoverflow.com/a/13219372/367456 for usage examples | |
*/ | |
class SimpleXMLArrayImport | |
{ | |
const TYPE_INVALID = 0; | |
const TYPE_EMPTY = 1; | |
const TYPE_VALUE = 2; | |
const TYPE_NAMED = 3; | |
const TYPE_LIST = 4; | |
private $doc; | |
public function __construct(array $data = array()) { | |
$data && $this->importArray($data); | |
} | |
public function getDocument() { | |
if (!$this->hasDocument()) { | |
throw new BadMethodCallException('No SimpleXML document has been created or assigned so far.'); | |
} | |
return $this->doc; | |
} | |
public function setDocument(SimpleXMLElement $doc) { | |
list($root) = $doc->xpath('/*'); | |
$this->doc = $root; | |
} | |
public function hasDocument() { | |
return $this->doc instanceof SimpleXMLElement; | |
} | |
/** | |
* Create a new SimpleXML document out of an array | |
* | |
* @param array $array | |
* @return SimpleXMLElement root element | |
* @throws InvalidArgumentException | |
*/ | |
public function importArray(array $array) { | |
$count = count($array); | |
if ($count !== 1) { | |
throw new InvalidArgumentException(sprintf('Array must have exactly one root element, %d given.', $count)); | |
} | |
list($name, $children) = each($array); | |
$xml = new SimpleXMLElement(sprintf('<%s/>', $name)); | |
$this->addNode($xml, $children); | |
$this->doc = $xml; | |
return $xml; | |
} | |
public function addArray(SimpleXMLElement $parent, array $array) { | |
list($this->doc) = $parent->xpath('/*'); | |
return $this->addNode($parent, $array); | |
} | |
/** | |
* @param SimpleXMLElement $parent | |
* @param $node | |
* @return SimpleXMLElement The last element added. If a value content or an empty element was added | |
* returns the parent. | |
* @throws InvalidArgumentException | |
*/ | |
private function addNode(SimpleXMLElement $parent, $node) { | |
$type = $this->getType($node); | |
$added = NULL; | |
switch ($type) { | |
case self::TYPE_VALUE: | |
$parent->{0} = (string)$node; # fall-through intended | |
case self::TYPE_EMPTY: | |
$added = $parent; | |
break; | |
case self::TYPE_NAMED: | |
foreach ($node as $name => $child) { | |
$added = $this->addChild($parent, $name, $child); | |
} | |
break; | |
case self::TYPE_LIST: | |
foreach ($node as $name => $children) { | |
$added = $this->addChildren($parent, $name, $children); | |
} | |
break; | |
default: | |
throw new InvalidArgumentException('Invalid Node Type'); | |
} | |
return $added; | |
} | |
/** | |
* add child element | |
*/ | |
private function addChild(SimpleXMLElement $parent, $name, $node) { | |
$element = $parent->addChild($name); | |
$this->addNode($element, $node); | |
return $element; | |
} | |
/** | |
* add multiple children with the same name | |
*/ | |
private function addChildren(SimpleXMLElement $parent, $name, array $children) { | |
foreach ($children as $child) { | |
$element = $this->addChild($parent, $name, $child); | |
} | |
return $element; | |
} | |
private function getType($node) { | |
if (!is_array($node)) { | |
return self::TYPE_VALUE; | |
} | |
$keys = array_keys($node); | |
if (!$keys) { | |
return self::TYPE_EMPTY; | |
} | |
if ($keys[0] === 0) { | |
return self::TYPE_INVALID; | |
} | |
if (isset($node[$keys[0]][0])) { | |
return self::TYPE_LIST; | |
} | |
return self::TYPE_NAMED; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment