1: <?php
2: namespace NGS\Converter;
3:
4: require_once(__DIR__.'/../Utils.php');
5:
6: use InvalidArgumentException;
7: use NGS\Utils;
8:
9: 10: 11:
12: abstract class XmlConverter
13: {
14: public static function toXml($value)
15: {
16: if($value instanceof \SimpleXMLElement)
17: return $value;
18: if(is_string($value))
19: return new \SimpleXMLElement($value);
20: if(is_array($value))
21: return self::build_xml($value);
22: throw new InvalidArgumentException('Could not convert value '.$value.' of type "'.Utils::getType($value).'" to xml!');
23: }
24:
25: public static function toXmlArray(array $items, $allowNullValues=false)
26: {
27: $results = array();
28: try {
29: foreach ($items as $key => $val) {
30: if ($allowNullValues && $val===null) {
31: $results[] = null;
32: } elseif ($val === null) {
33: throw new InvalidArgumentException('Null value found in provided array');
34: } else {
35: $results[] = self::toXml($val);
36: }
37: }
38: }
39: catch (\Exception $e) {
40: throw new \InvalidArgumentException('Element at index '.$key.' could not be converted to xml!', 42, $e);
41: }
42: return $items;
43: }
44:
45: public static function toArray($value)
46: {
47: if($value instanceof \SimpleXMLElement)
48: return self::toArrayObject($value);
49: $result = array();
50: foreach($value as $key => $item) {
51: try {
52: if($item === null)
53: throw new InvalidArgumentException('Null value found in provided array');
54: $item = self::toArrayObject($item);
55: }
56: catch(\Exception $e) {
57: throw new \InvalidArgumentException('Element at index '.$key.' could not be converted to xml array!', 42, $e);
58: }
59: $result[$key] = $item;
60: }
61: return $result;
62: }
63:
64: private static function build_xml(array $arr) {
65: $keys = array_keys($arr);
66: $name = $keys[0];
67: $root = $arr[$name];
68:
69: $text = is_array($root) && array_key_exists('#text', $root)
70: ? $root['#text']
71: : '';
72: $str = '<'.$name.'>'.$text.'</'.$name.'>';
73: $xml = new \SimpleXmlElement($str);
74:
75: if(is_array($root))
76: self::array_to_xml($root, $xml);
77:
78: return $xml;
79: }
80:
81: private static function array_to_xml(array $arr, &$xml) {
82: foreach($arr as $key => $value) {
83: if(strpos($key, '@', 0) === 0) {
84: $xml->addAttribute(substr($key, 1), $value);
85: }
86: else if(is_array($value)) {
87: $child_has_only_numeric_keys = true;
88: $i = 0;
89: foreach($value as $k=>$v)
90: if($k!==$i++)
91: $child_has_only_numeric_keys = false;
92:
93: if($child_has_only_numeric_keys) {
94: foreach($value as $k=>$v) {
95: $subnode = array_key_exists('#text', $v)
96: ? $xml->addChild("$key", $v['#text'])
97: : $xml->addChild("$key");
98: self::array_to_xml($v, $subnode);
99: }
100: }
101: else if(!is_numeric($key)) {
102: $subnode = array_key_exists('#text', $value)
103: ? $xml->addChild("$key", $value['#text'])
104: : $xml->addChild("$key");
105: self::array_to_xml($value, $subnode);
106: }
107: else {
108: self::array_to_xml($value, $xml);
109: }
110: }
111: else if($key !== '#text')
112: $xml->$key = "$value";
113: }
114: }
115:
116: private static function xml_to_array(\SimpleXMLElement $xml, array &$arr)
117: {
118: if(count($xml->attributes()) === 0
119: && count($xml->children()) === 0
120: && !(string)$xml) {
121: $arr = null;
122: return;
123: }
124: foreach($xml->attributes() as $key => $value) {
125: $arr['@'.$key] = (string)$value;
126: }
127: $text = (string)$xml;
128: if($text && count($xml->children()) === 0) {
129: $arr['#text'] = $text;
130: }
131: foreach($xml->children() as $key => $value) {
132: $arr[$key] = isset($arr[$key]) ? array() : false;
133: }
134: foreach($arr as $key=>$value)
135: if($arr[$key]===false)
136: unset($arr[$key]);
137:
138: foreach($xml->children() as $key => $value) {
139: if(isset($arr[$key])) {
140: $index = count($arr[$key]);
141: $arr[$key][$index] = array();
142: self::xml_to_array($value, $arr[$key][$index]);
143: }
144: else {
145: $arr[$key] = array();
146: self::xml_to_array($xml->{$key}, $arr[$key]);
147: }
148: }
149: }
150:
151: private static function toArrayObject(\SimpleXMLElement $value)
152: {
153: $root = array();
154:
155: self::xml_to_array($value, $root);
156: $arr = array($value->getName() => $root);
157: return $arr;
158: }
159: }
160: