XML classes
XML-Klassen
Really not much to say about these two classes. class XmlConverter
converts XML
to a structured assiciative array. This makes debugging easier as the whole
structure can be dumped with print_r
. The class Xml
is similar, but with
object nodes.
Es gibt nicht viel über diese beiden Klassen zu sagen. Mit class XmlConverter
kann ein XML-Dokument in ein assoziatives Array eingelesen werden, oder aus einem
solchen erstellt werden. Das erleichtert Debugging, da der die ganze Datenstruktur
mit print_r()
in einem ausgegeben werden kann. Die Klassse class Xml
ist
ähnich, arbeitet jedoch mit Objectknoten.
Class source code
Klassen-Quelltext
<?php
/**
* XML handling. Generates XML output from an associative netsted array.
* @gpackage de.atwillys.sw.php.swLib
* @author Stefan Wilhelm
* @copyright Stefan Wilhelm, 2006-2010
* @license GPL
* @version 1.0
*/
namespace sw;
class XmlConverter {
/**
* Transforms an associative array to an XML string. If a root node
* tag is specified, it is wrapped around the contents.
* @param array $assocArray
* @param string $rootNodeTag
* @return string
*/
public static function fromAssocArray($assocArray, $rootNodeTag='') {
if (trim($rootNodeTag) != '') {
if (!ctype_alnum(str_replace('_', '', $rootNodeTag))) {
throw new LException('root node tag must be alphanumeric.');
}
$xml = new \SimpleXMLElement("<$rootNodeTag></$rootNodeTag>");
} else if (count($assocArray) == 1 && is_array(reset($assocArray))) {
$rootNodeTag = key($assocArray);
$assocArray = reset($assocArray);
} else {
throw new LException('Array to convert has no root node and no root node tag defined');
}
foreach ($assocArray as $key => $value) {
if (is_numeric($key)) {
$key = 'element';
}
if (!is_array($value)) {
$element = $xml->addChild($key, $value);
} else {
$element = $xml->addChild($key);
self::fromAssocArrayR($element, $value);
}
}
return $xml->asXML();
}
/**
* Recursive helper function
* @param string $xml
* @param array $assocArray
*/
private static function fromAssocArrayR($xml, $assocArray) {
foreach ($assocArray as $key => $value) {
if (is_numeric($key)) {
$key = 'element';
}
if (!is_array($value)) {
$element = $xml->addChild($key, $value);
} else {
$element = $xml->addChild($key);
self::fromAssocArrayR($element, $value);
}
}
}
}
?>
<?php
/**
* XML handling. Generates an XML object tree from an XML string
* @gpackage de.atwillys.sw.php.swLib
* @author Stefan Wilhelm
* @copyright Stefan Wilhelm, 2006-2010
* @license GPL
* @version 1.0
*/
namespace sw;
class Xml {
/**
* The XML tag name
* @var string
*/
public $tag;
/**
* The value of the XML element (if not a sub node)
* @var string
*/
public $value;
/**
* Attributes
* @var array
*/
public $attr;
/**
* Node children, if sub nodes exist
* @var array
*/
public $children;
/**
* Creates an Xml object structure
* @param string $xml_string
* @return sw\Xml
*/
public static function fromXmlString($xml_string) {
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
if(!@xml_parse_into_struct($parser, $xml_string, $xml_values)) {
$err = xml_error_string(xml_get_error_code($parser));
@xml_parser_free($parser);
throw new LException('XML parse error: ', array('err' => $err));
}
@xml_parser_free($parser);
$return = array();
$last_obj = array();
$node = &$return;
foreach ($xml_values as $k => $v) {
$i = count($node);
if ($v["type"] == "complete") {
$node[$i] = new Xml;
$node[$i]->tag = $v["tag"];
if (isset($v["value"]) && strlen($v["value"]) > 0)
$node[$i]->value = $v["value"]; else
unset($node[$i]->value);
if (!empty($v["attributes"]))
$node[$i]->attr = $v["attributes"]; else
unset($node[$i]->attr);
unset($node[$i]->children);
} else if ($v["type"] == "open") {
$node[$i] = new Xml;
$node[$i]->tag = $v["tag"];
if (isset($v["value"]) && strlen($v["value"]) > 0)
$node[$i]->value = $v["value"]; else
unset($node[$i]->value);
if (!empty($v["attributes"]))
$node[$i]->attr = $v["attributes"]; else
unset($node[$i]->attr);
$node[$i]->children = array();
$last_obj[count($last_obj)] = &$node;
$node = &$node[$i]->children;
} elseif ($v["type"] == "close") {
$node = &$last_obj[count($last_obj) - 1];
unset($last_obj[count($last_obj) - 1]);
}
}
if (!empty($return)) {
$return = $return[0];
}
return $return;
}
/**
* Converts the object into a structured hash array. Attributes and sub nodes
* are merged in sub arrays. If the node has a scalar value, attributes are
* ignored and the cell content is the string value of the node. If more sub
* nodes with the same tag name exist, the an numerically indexed array ("list")
* will be created. All tag names (array keys) are converted to lower case.
* Note: The function is good for easy data access but cannot completly represent
* the XML document.
* @return array
*/
public function toAssocArray() {
if(!isset($this->tag)) {
return array();
} else if(isset($this->children) && is_array($this->children)) {
$children = (isset($this->attr) && is_array($this->attr)) ? array_change_key_case($this->attr, CASE_LOWER) : array();
foreach($this->children as $child) {
$node = $child->toAssocArray();
if(!isset($children[key($node)])) {
$children[key($node)] = array();
}
$children[key($node)][] = current($node);
}
foreach($children as $k => $v) {
if(count($v) == 1) {
$children[$k] = is_array($v) ? reset($v) : strval($v);
}
}
return array(strtolower($this->tag) => $children);
} else if(isset($this->value)) {
return array(strtolower($this->tag) => strval($this->value));
} else if(isset($this->attr) && is_array($this->attr) && !empty($this->attr)) {
return array(strtolower($this->tag) => array_change_key_case($this->attr, CASE_LOWER));
} else {
return array(strtolower($this->tag) => '');
}
}
}