1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Port\Xml; |
4
|
|
|
|
5
|
|
|
use Port\Writer; |
6
|
|
|
use Port\Writer\FlushableWriter; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* This writer allows you to write more complex XML from arrays than the default XmlWriter. |
10
|
|
|
* |
11
|
|
|
* The main differences are that nested arrays can be proceed and XML attributes are supported. |
12
|
|
|
* If the key of an array value starts with '@' the value will be used as a XML attribute. |
13
|
|
|
*/ |
14
|
|
|
class AdvancedXmlWriter implements Writer, FlushableWriter |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var \XmlWriter |
18
|
|
|
*/ |
19
|
|
|
protected $xmlWriter; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var string |
23
|
|
|
*/ |
24
|
|
|
protected $file; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $rootElement; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var array<string, string> |
33
|
|
|
*/ |
34
|
|
|
protected $rootElementAttributes; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var string |
38
|
|
|
*/ |
39
|
|
|
protected $itemElement; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var string |
43
|
|
|
*/ |
44
|
|
|
protected $version; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var string|null |
48
|
|
|
*/ |
49
|
|
|
protected $encoding; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @param string $file |
53
|
|
|
*/ |
54
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
55
|
|
|
\XmlWriter $xmlWriter, |
56
|
|
|
$file, |
57
|
|
|
$rootElement = 'items', |
58
|
|
|
$rootElementAttributes = [], |
59
|
|
|
$itemElement = 'item', |
60
|
|
|
$version = '1.0', |
61
|
|
|
$encoding = null |
62
|
|
|
) { |
63
|
|
|
$this->xmlWriter = $xmlWriter; |
64
|
|
|
$this->file = $file; |
65
|
|
|
$this->rootElement = $rootElement; |
66
|
|
|
$this->rootElementAttributes = $rootElementAttributes; |
67
|
|
|
$this->itemElement = $itemElement; |
68
|
|
|
$this->version = $version; |
69
|
|
|
$this->encoding = $encoding; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* {@inheritdoc} |
74
|
|
|
*/ |
75
|
|
|
public function prepare() |
76
|
|
|
{ |
77
|
|
|
$this->xmlWriter->openUri($this->file); |
78
|
|
|
$this->xmlWriter->startDocument($this->version, $this->encoding); |
79
|
|
|
$this->xmlWriter->startElement($this->rootElement); |
80
|
|
|
|
81
|
|
|
foreach($this->rootElementAttributes as $key => $value) { |
82
|
|
|
$this->xmlWriter->writeAttribute($key, $value); |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* {@inheritdoc} |
88
|
|
|
*/ |
89
|
|
|
public function writeItem(array $item) |
90
|
|
|
{ |
91
|
|
|
$this->writeXmlItem($item, $this->itemElement); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Handle XML write with attributes support. |
96
|
|
|
* |
97
|
|
|
* @param array $item |
98
|
|
|
* @param $elementName |
99
|
|
|
*/ |
100
|
|
|
protected function writeXmlItem(array $item, $elementName) |
101
|
|
|
{ |
102
|
|
|
$this->xmlWriter->startElement($elementName); |
103
|
|
|
|
104
|
|
|
$this->writeAttributes($item); |
105
|
|
|
|
106
|
|
|
foreach ($item as $key => $value) { |
107
|
|
|
if (substr($key, 0, 1) === '@') { |
108
|
|
|
continue; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
if (is_array($value)) { |
112
|
|
|
$this->writeXmlItem($value, $key); |
113
|
|
|
} else { |
114
|
|
|
$this->xmlWriter->writeElement($key, $value); |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$this->xmlWriter->endElement(); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Write attributes of item. |
123
|
|
|
* |
124
|
|
|
* @param array $item |
125
|
|
|
*/ |
126
|
|
|
protected function writeAttributes(array $item) |
127
|
|
|
{ |
128
|
|
|
foreach ($item as $key => $value) { |
129
|
|
|
if (substr($key, 0, 1) !== '@') { |
130
|
|
|
continue; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$this->xmlWriter->writeAttribute( |
134
|
|
|
substr($key, 1), |
135
|
|
|
$value |
136
|
|
|
); |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* {@inheritdoc} |
142
|
|
|
*/ |
143
|
|
|
public function finish() |
144
|
|
|
{ |
145
|
|
|
$this->xmlWriter->endElement(); |
146
|
|
|
$this->xmlWriter->endDocument(); |
147
|
|
|
$this->flush(); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* {@inheritdoc} |
152
|
|
|
*/ |
153
|
|
|
public function flush() |
154
|
|
|
{ |
155
|
|
|
$this->xmlWriter->flush(); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
} |
159
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.