<?php
/*
* QXML
* @author: Thomas Schäfer
* @mail: hide@address.com
*/
class QXML {
/* attribute constant, used for array conversion, preserves xml attributes */
const attribute = "@attributes";
/* place for textnodes, used for array converion, CDATA enabling
*/
const textNode = "@textNode";
protected $xml;
protected $object;
protected $nodes = array();
protected $array = null;
protected $cdata = true;
/**
* set property cdata
* useful if you want to make rss feeds or something similar
*/
public function noCDATA(){
$this->cdata = false;
}
/**
* facade for getting an object from xml
*
* @return mixed
*/
public function asObject(){
if(strlen($this->asXML())){
return simplexml_load_string($this->asXml(), null, LIBXML_NOCDATA);
} else {
return false;
}
}
/**
* setter method for xml property
*
* @param mixed $xml
*/
public function setXml($xml){
$this->xml = $xml;
}
/**
* getter method for xml property
*
* @return mixed
*/
public function getXml(){
return $this->xml;
}
/**
* loads an xml from file and converts it to an object
*
* @param string $file
*/
public function setXmlFromFile($file){
$xmlObject = simplexml_load_string(file_get_contents($file));
if($xmlObject instanceof SimpleXMLElement){
$array = $this->toArray($xmlObject);
$root = array();
$root[$xmlObject->getName()] = (array) $xmlObject->attributes();
$root[$xmlObject->getName()] = array_merge($root[$xmlObject->getName()], $array);
$xmlArray = $root;
$this->array = $xmlArray;
$this->toNodeList($xmlArray);
$this->toXML($this->array);
$this->object = $this->asObject();
}
}
/**
* serialize objects resp. arrays
*
* @param mixed $toSerialize
* @return string
*/
public function serialize($toSerialize){
if($toSerialize instanceof SimpleXMLElement){
$stdClass = new stdClass();
$stdClass->type = get_class($toSerialize);
$stdClass->data = $toSerialize->asXml();
return serialize($stdClass);
} else {
return serialize($stdClass);
}
}
/**
* unserialize to object
*
* @param string $toUnserialize
* @return object
*/
function unserialize($toUnserialize){
$toUnserialize = unserialize($toUnserialize);
if($toSerialize instanceof stdclass){
if($toUnserialize->type == "SimpleXMLElement"){
$toUnserialize = simplexml_load_string($toUnserialize->data);
}
return $toUnserialize;
} else {
return $toUnserialize;
}
}
/**
* getter and alias for xml property
*
* @return string
*/
public function asXML(){
return $this->xml;
}
/**
* facade to preserve an object's root element and its attributes
*
* @return array
*/
public function asArray() {
$array = $this->toArray($this->xml);
$root[$this->xml->getName()] = (array) $this->xml->attributes();
$root[$this->xml->getName()] = array_merge($root[$this->xml->getName()], $array);
return $root;
}
/**
* gets a node list
*
* @return array
*/
public function getNodesFromArray() {
$array = $this->array;
$root[$this->object->getName()] = (array) $this->object->attributes();
$root[$this->object->getName()] = array_merge($root[$this->object->getName()], $array);
return $root;
}
/**
* node merging method
*
* @param array $array
* @param string $node
* @param integer $level
* @param string $delim
* @return array
*/
protected function buildNodes($array, $node = "", $level=0, $delim = ".") {
$text = array();
foreach($array as $key => $value) {
if (is_array($value)) {
$nodeset = ($node=="")?$key:$node.$delim.$key;
$text = array_merge($text,$this->buildNodes($value,$nodeset,$level++,$delim));
} else {
$nodeset = $node.$delim.$key;
$text[] = $nodeset;
}
}
return $text;
}
/*
* facade for node builder
*/
public function toNodeList($array){
$this->nodes = $this->buildNodes($array);
}
/**
* method for return a node list
*
* @return array
*/
public function getNodeList(){
return $this->nodes;
}
/**
* facade for getting a nodelist form XML
*
* @return array
*/
public function getNodesFromXML(){
$this->toNodeList($this->asArray());
return $this->getNodeList();
}
/**
* facade for array helper class
*
* @param string $path
* @return array
*/
public function getNode($path){
return QSet::get($this->asArray(), $path);
}
/**
* facade for array helper class
*
* @param string $path
* @param array $data
* @param string $root
*/
public function setNode($path, $data, $root = "chart"){
if(empty($this->array)) {
$this->array = $this->asArray();
}
$this->array = QSet::set($this->array, $path, $data);
}
/*
* return helper
*/
public function getArray(){
return $this->array;
}
/**
* getter for object property
*
* @return SimpleXMLElement object
*/
public function getObject(){
return $this->object;
}
/**
* facade for array helper method
*
* @param string $name
* @param SimpleXMLElement $object
* @return bool
*/
public function hasAttribute($name, $object){
$attrs = $object->attributes();
if(isset($attrs[$name])) {
return true;
} else {
return false;
}
}
/*
*
* @param object SimpleXMLElement
* @return array
*/
public function toArray(SimpleXMLElement $xml) {
$results = array();
foreach($xml->children() as $key => $object) {
$recObj = $this->toArray($object);
foreach( $object->attributes() as $ak => $av ) {
$recObj[self::attribute][$ak] = (string)$av;
}
if(!$recObj[self::attribute]){
$recObj[self::attribute] = "";
}
if(!$recObj[self::textNode]){
$recObj[self::textNode] = trim((string)$object);
}
if (!in_array($key,array_keys($results))) {
$results[$key] = $recObj;
} elseif (@in_array(0,@array_keys($results[$key]))) {
if(count($results[$key])==2){
if($results[$key][self::attribute] ||$results[$key][self::textNode] ){
$tmp=Array();
$tmp[self::attribute] = $results[$key][self::attribute];
$tmp[self::textNode] = $results[$key][self::textNode];
unset($results[$key][self::attribute]);
unset($results[$key][self::textNode]);
$results[$key][0]=$tmp;
unset($tmp);
}
}
if(count(array_diff_key($results[$key],$recObj))==0 && count($results[$key])>0){
$tmp=$results[$key];
unset($results[$key]);
$results[$key][]=$tmp;
}
$results[$key][] = $recObj;
} else {
$results[$key] = array($results[$key]);
$results[$key][] = $recObj;
}
}
return $results;
}
/*
* @desc facade method for recursion
* @param mixed $mixed array or SimpleXMLElement
* @param string $elmName Name of root element
* @return void
*/
public function toXML($mixed, $elmName='chart'){
if($mixed instanceof SimpleXMLElement){
$array = $this->toArray($this->xml);
$root = array();
$root[$this->xml->getName()] = (array) $this->xml->attributes();
$root[$this->xml->getName()] = array_merge($root[$this->xml->getName()], $array);
$mixed = $root;
}
$xml = $this->_toXML($mixed, $elmName);
$this->setXml($xml);
}
/*
* recursing method for mining xml to array
* @param array $xmlArray
* @param string $elmName Name of root node
* @param string $elmCloseTag optional:<br/>normally used by function _toXML() itself
* @param integer $level counter
* @return string
*/
protected function _toXML($xmlArray, $elmName='chart', $elmCloseTag="", $level=0) {
$xmlString = "";
if(is_array($xmlArray)){
$strXmlAttributes = "";
$key_xml = "";
$keysXmlArray = array_keys($xmlArray);
$curLevel = $level + 1;
if(in_array(self::attribute,$keysXmlArray)){
if(isset($xmlArray[self::attribute])){
if(is_array($xmlArray[self::attribute])){
foreach($xmlArray[self::attribute] as $xmlArrayKey => $xmlArrayValue){
$strXmlAttributes .= sprintf(' %s="%s"',$xmlArrayKey,addslashes($xmlArrayValue));
}
}
}
unset($xmlArray[self::attribute]);
}
if(in_array(self::textNode,$keysXmlArray)){
if(isset($xmlArray[self::textNode])){
if($xmlArray[self::textNode]){
$key_xml = $xmlArray[self::textNode];
}
if(strlen($key_xml)){
if($this->cdata==true){
$key_xml = sprintf("<![CDATA[%s]]>",$key_xml);
}
} else {
$key_xml = "";
}
}
unset($xmlArray[self::textNode]);
}
$keysXmlArray=array_keys($xmlArray);
if($elmCloseTag){
$indent=str_repeat(" ",$level * 5);
$xmlString.="\n".$indent."<".$elmCloseTag.$strXmlAttributes.">".$key_xml;
}
if(is_array($xmlArray) && count($xmlArray)>0 && count($keysXmlArray)>0){
reset($xmlArray);
foreach($keysXmlArray as $key){
$altKey = $altKeyXml = $xmlArray[$key];
$check = false;
if(is_array($altKeyXml)){
foreach(array_keys($altKeyXml) as $j=>$p){
if(is_numeric($j)){
$check=true;
$xmlString.= $this->_toXML($altKeyXml[$j],"",$key,$curLevel);
unset($altKeyXml[$j]);
}
}
}
if($check){
$altKey = $altKeyXml;
}
if($altKey){
$xmlString .= $this->_toXML($altKey,"",$key,$curLevel);
}
}
}
if($elmCloseTag){
$xmlString.=(count($xmlArray)>0?"\n".$indent:"")."</".$elmCloseTag.">";
}
}
if($elmName) {
$xmlString = "<?xml version='1.0' encoding='UTF-8'?>\n$xmlString\n";
}
return $xmlString;
}
/**
* convert xml string to JSON object
*
* @param string $xml
* @return string JSON
*/
public function toJSONFromXML($xml){
return xml2json::transformXmlStringToJson($xml);
}
/**
* convert SimpleXmlElement to JSON Object
*
* @param SimpleXMLElement $xml
* @return string JSON
*/
public function toJSONFromObject(SimpleXMLElement $xml){
return xml2json::convertSimpleXmlElementObjectIntoArray($xml);
}
}
?>