5 use wcf\system\exception\SystemException
;
8 * Writes XML documents.
10 * @author Alexander Ebert
11 * @copyright 2001-2019 WoltLab GmbH
12 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
17 * true, if a document is still processed
20 protected $activeDocument = false;
23 * number of open elements
26 protected $openElements = 0;
35 * Creates a new XML document.
37 * @param string $rootElement
38 * @param string $namespace
39 * @param string $schemaLocation
40 * @param string[] $attributes
41 * @throws SystemException
43 public function beginDocument($rootElement, $namespace, $schemaLocation, array $attributes = [])
45 if ($this->activeDocument
) {
46 throw new SystemException("Could not begin a new document unless the previous is finished");
49 if ($this->xml
=== null) {
50 $this->xml
= new \
XMLWriter();
51 $this->xml
->openMemory();
52 $this->xml
->setIndent(true);
53 $this->xml
->setIndentString("\t");
56 $this->xml
->startDocument('1.0', 'UTF-8');
57 $this->startElement($rootElement);
58 $attributes = \array_merge
(
60 'xmlns' => $namespace,
61 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
62 'xsi:schemaLocation' => $namespace . ' ' . $schemaLocation,
64 // `xmlns`, `xmlns:xsi`, and `xsi:schemaLocation` are explicitly set
65 // as first attributes in that order
66 \array_filter
($attributes, static function ($attributeName) {
67 return !\
in_array($attributeName, ['xmlns', 'xmlns:xsi', 'xsi:schemaLocation']);
68 }, \ARRAY_FILTER_USE_KEY
)
70 $this->writeAttributes($attributes);
72 $this->activeDocument
= true;
76 * Returns the generated XML document or writes it to given filename. All open
77 * elements will be automatically closed before flushing.
79 * @param string $filename
82 public function endDocument($filename = '')
84 // mark document as done
85 $this->activeDocument
= false;
87 // close all open tags
88 while ($this->openElements
) {
92 if (empty($filename)) {
93 // return XML as string
94 return $this->xml
->flush(true);
97 \file_put_contents
($filename, $this->xml
->flush(true));
102 * Begins a new element.
104 * @param string $element
105 * @param string[] $attributes
107 public function startElement($element, array $attributes = [])
109 $this->xml
->startElement($element);
110 $this->openElements++
;
112 if (!empty($attributes)) {
113 $this->writeAttributes($attributes);
118 * Ends the last opened element.
120 public function endElement()
122 if ($this->openElements
) {
123 $this->xml
->endElement();
124 $this->openElements
--;
129 * Writes an element directly.
131 * @param string $element
132 * @param string $cdata
133 * @param string[] $attributes
134 * @param bool $writeAsCdata
136 public function writeElement($element, $cdata, array $attributes = [], $writeAsCdata = true)
138 $this->startElement($element);
141 if (!empty($attributes)) {
142 $this->writeAttributes($attributes);
148 $this->xml
->writeCdata(StringUtil
::escapeCDATA($cdata));
150 $this->xml
->text($cdata);
160 * @param string $comment
163 public function writeComment($comment)
165 $this->xml
->writeComment($comment);
169 * Writes an attribute to last opened element.
171 * @param string $attribute
172 * @param string $value
174 public function writeAttribute($attribute, $value)
176 $this->writeAttributes([$attribute => $value]);
180 * Writes a list of attributes to last opened element.
182 * @param string[] $attributes
184 public function writeAttributes(array $attributes)
186 foreach ($attributes as $attribute => $value) {
187 $this->xml
->writeAttribute($attribute, $value);