Merge branch '3.0'
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / util / XMLWriter.class.php
CommitLineData
6f5d6b49
AE
1<?php
2namespace wcf\util;
3use 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 */
13class 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}