-
Notifications
You must be signed in to change notification settings - Fork 475
/
class-ArrayToXML.php
134 lines (126 loc) · 3.99 KB
/
class-ArrayToXML.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
/**
* Based on: http://stackoverflow.com/questions/99350/passing-php-associative-arrays-to-and-from-xml
*/
class ArrayToXML
{
private $version;
private $encoding;
/**
* Construct ArrayToXML object with selected version and encoding
*
* for available values check XmlWriter docs http://www.php.net/manual/en/function.xmlwriter-start-document.php
* @param string $xmlVersion XML Version, default 1.0
* @param string $xmlEncoding XML Encoding, default UTF-8
*/
public function __construct($xmlVersion = '1.0', $xmlEncoding = 'UTF-8')
{
$this->version = $xmlVersion;
$this->encoding = $xmlEncoding;
}
/**
* Build an XML Data Set
*
* @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
* @param string $startElement Root Opening Tag, default data
* @return string XML String containing values
* @return mixed Boolean false on failure, string XML result on success
*/
public function buildXML($data, $startElement = 'data')
{
if (!is_array($data)) {
$err = 'Invalid variable type supplied, expected array not found on line ' . __LINE__ . ' in Class: ' . __CLASS__ . ' Method: ' . __METHOD__;
trigger_error($err);
return false; //return false error occurred
}
$xml = new XmlWriter();
$xml->openMemory();
$xml->startDocument($this->version, $this->encoding);
$xml->startElement($startElement);
$data = $this->writeAttr($xml, $data);
$this->writeEl($xml, $data);
$xml->endElement(); //write end element
//returns the XML results
return $xml->outputMemory(true);
}
/**
* Write keys in $data prefixed with @ as XML attributes, if $data is an array.
* When an @ prefixed key is found, a '%' key is expected to indicate the element itself,
* and '#' prefixed key indicates CDATA content
*
* @param XMLWriter $xml object
* @param array $data with attributes filtered out
* @return array $data | $nonAttributes
*/
protected function writeAttr(XMLWriter $xml, $data)
{
if (is_array($data)) {
$nonAttributes = array();
foreach ($data as $key => $val) {
//handle an attribute with elements
if ($key[0] == '@') {
$xml->writeAttribute(substr($key, 1), $val);
} else if ($key[0] == '%') {
if (is_array($val)) $nonAttributes = $val;
else $xml->text($val);
} elseif ($key[0] == '#') {
if (is_array($val)) $nonAttributes = $val;
else {
$xml->startElement(substr($key, 1));
$xml->writeCData($val);
$xml->endElement();
}
}else if($key[0] == "!"){
if (is_array($val)) $nonAttributes = $val;
else $xml->writeCData($val);
}
//ignore normal elements
else $nonAttributes[$key] = $val;
}
return $nonAttributes;
} else return $data;
}
/**
* Write XML as per Associative Array
*
* @param XMLWriter $xml object
* @param array $data Associative Data Array
*/
protected function writeEl(XMLWriter $xml, $data)
{
foreach ($data as $key => $value) {
if (is_array($value) && !$this->isAssoc($value)) { //numeric array
foreach ($value as $itemValue) {
if (is_array($itemValue)) {
$xml->startElement($key);
$itemValue = $this->writeAttr($xml, $itemValue);
$this->writeEl($xml, $itemValue);
$xml->endElement();
} else {
$itemValue = $this->writeAttr($xml, $itemValue);
$xml->writeElement($key, "$itemValue");
}
}
} else if (is_array($value)) { //associative array
$xml->startElement($key);
$value = $this->writeAttr($xml, $value);
$this->writeEl($xml, $value);
$xml->endElement();
} else { //scalar
$value = $this->writeAttr($xml, $value);
$xml->writeElement($key, "$value");
}
}
}
/**
* Check if array is associative with string based keys
* FROM: http://stackoverflow.com/questions/173400/php-arrays-a-good-way-to-check-if-an-array-is-associative-or-sequential/4254008#4254008
*
* @param array $array Array to check
* @return bool
*/
protected function isAssoc($array)
{
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
}