Commit | Line | Data |
---|---|---|
6f5d6b49 AE |
1 | <?php |
2 | namespace wcf\util; | |
3 | use wcf\system\exception\SystemException; | |
4 | ||
5 | /** | |
6 | * Writes XML documents. | |
7 | * | |
0c166126 | 8 | * @author Alexander Ebert |
c839bd49 | 9 | * @copyright 2001-2018 WoltLab GmbH |
6f5d6b49 | 10 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
e71525e4 | 11 | * @package WoltLabSuite\Core\Util |
6f5d6b49 AE |
12 | */ |
13 | class XMLWriter { | |
14 | /** | |
15 | * true, if a document is still processed | |
16 | * @var boolean | |
17 | */ | |
18 | protected $activeDocument = false; | |
19 | ||
20 | /** | |
b2aa772d | 21 | * number of open elements |
6f5d6b49 AE |
22 | * @var integer |
23 | */ | |
24 | protected $openElements = 0; | |
25 | ||
26 | /** | |
27 | * XMLWriter object | |
28 | * @var \XMLWriter | |
29 | */ | |
30 | protected $xml = null; | |
31 | ||
32 | /** | |
33 | * Creates a new XML document. | |
34 | * | |
35 | * @param string $rootElement | |
36 | * @param string $namespace | |
37 | * @param string $schemaLocation | |
2b770bdd MS |
38 | * @param string[] $attributes |
39 | * @throws SystemException | |
6f5d6b49 | 40 | */ |
058cbd6a | 41 | public function beginDocument($rootElement, $namespace, $schemaLocation, array $attributes = []) { |
6f5d6b49 AE |
42 | if ($this->activeDocument) { |
43 | throw new SystemException("Could not begin a new document unless the previous is finished"); | |
44 | } | |
45 | ||
46 | if ($this->xml === null) { | |
47 | $this->xml = new \XMLWriter(); | |
48 | $this->xml->openMemory(); | |
49 | $this->xml->setIndent(true); | |
50 | $this->xml->setIndentString("\t"); | |
51 | } | |
52 | ||
53 | $this->xml->startDocument('1.0', 'UTF-8'); | |
54 | $this->startElement($rootElement); | |
058cbd6a | 55 | $attributes = array_merge($attributes, [ |
6f5d6b49 AE |
56 | 'xmlns' => $namespace, |
57 | 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', | |
58 | 'xsi:schemaLocation' => $namespace . ' ' . $schemaLocation | |
058cbd6a | 59 | ]); |
6f5d6b49 AE |
60 | $this->writeAttributes($attributes); |
61 | ||
62 | $this->activeDocument = true; | |
63 | } | |
64 | ||
65 | /** | |
66 | * Returns the generated XML document or writes it to given filename. All open | |
67 | * elements will be automatically closed before flushing. | |
68 | * | |
69 | * @param string $filename | |
70 | * @return mixed | |
71 | */ | |
72 | public function endDocument($filename = '') { | |
73 | // mark document as done | |
74 | $this->activeDocument = false; | |
75 | ||
76 | // close all open tags | |
77 | while ($this->openElements) { | |
78 | $this->endElement(); | |
79 | } | |
80 | ||
81 | if (empty($filename)) { | |
82 | // return XML as string | |
83 | return $this->xml->flush(true); | |
84 | } | |
85 | else { | |
86 | // write to file | |
87 | file_put_contents($filename, $this->xml->flush(true)); | |
88 | } | |
89 | } | |
90 | ||
91 | /** | |
92 | * Begins a new element. | |
93 | * | |
94 | * @param string $element | |
7a23a706 | 95 | * @param string[] $attributes |
6f5d6b49 | 96 | */ |
058cbd6a | 97 | public function startElement($element, array $attributes = []) { |
6f5d6b49 AE |
98 | $this->xml->startElement($element); |
99 | $this->openElements++; | |
100 | ||
101 | if (!empty($attributes)) { | |
102 | $this->writeAttributes($attributes); | |
103 | } | |
104 | } | |
105 | ||
106 | /** | |
107 | * Ends the last opened element. | |
108 | */ | |
109 | public function endElement() { | |
110 | if ($this->openElements) { | |
111 | $this->xml->endElement(); | |
112 | $this->openElements--; | |
113 | } | |
114 | } | |
115 | ||
116 | /** | |
117 | * Writes an element directly. | |
118 | * | |
119 | * @param string $element | |
120 | * @param string $cdata | |
7a23a706 | 121 | * @param string[] $attributes |
6f5d6b49 | 122 | */ |
058cbd6a | 123 | public function writeElement($element, $cdata, array $attributes = []) { |
6f5d6b49 AE |
124 | $this->startElement($element); |
125 | ||
126 | // write attributes | |
127 | if (!empty($attributes)) { | |
128 | $this->writeAttributes($attributes); | |
129 | } | |
130 | ||
131 | // content | |
5fff9dca | 132 | if ($cdata !== '') $this->xml->writeCdata(StringUtil::escapeCDATA($cdata)); |
6f5d6b49 AE |
133 | |
134 | $this->endElement(); | |
135 | } | |
136 | ||
137 | /** | |
138 | * Writes an attribute to last opened element. | |
139 | * | |
140 | * @param string $attribute | |
141 | * @param string $value | |
142 | */ | |
143 | public function writeAttribute($attribute, $value) { | |
058cbd6a | 144 | $this->writeAttributes([$attribute => $value]); |
6f5d6b49 AE |
145 | } |
146 | ||
147 | /** | |
148 | * Writes a list of attributes to last opened element. | |
149 | * | |
7a23a706 | 150 | * @param string[] $attributes |
6f5d6b49 AE |
151 | */ |
152 | public function writeAttributes(array $attributes) { | |
153 | foreach ($attributes as $attribute => $value) { | |
154 | $this->xml->writeAttribute($attribute, $value); | |
155 | } | |
156 | } | |
157 | } |