<commit_before><?php
namespace wcf\util;
use wcf\system\exception\SystemException;

/**
 * Writes XML documents.
 * 
 * @author	<NAME>
 * @copyright	2001-2017 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package	WoltLabSuite\Core\Util
 */
class XMLWriter {
	/**
	 * true, if a document is still processed
	 * @var	boolean
	 */
	protected $activeDocument = false;
	
	/**
	 * number of open elements
	 * @var	integer
	 */
	protected $openElements = 0;
	
	/**
	 * XMLWriter object
	 * @var	\XMLWriter
	 */
	protected $xml = null;
	
	/**
	 * Creates a new XML document.
	 * 
	 * @param	string		$rootElement
	 * @param	string		$namespace
	 * @param	string		$schemaLocation
	 * @param	string[]	$attributes
	 * @throws	SystemException
	 */
	public function beginDocument($rootElement, $namespace, $schemaLocation, array $attributes = []) {
		if ($this->activeDocument) {
			throw new SystemException("Could not begin a new document unless the previous is finished");
		}
		
		if ($this->xml === null) {
			$this->xml = new \XMLWriter();
			$this->xml->openMemory();
			$this->xml->setIndent(true);
			$this->xml->setIndentString("\t");
		}
		
		$this->xml->startDocument('1.0', 'UTF-8');
		$this->startElement($rootElement);
		$attributes = array_merge($attributes, [
			'xmlns' => $namespace,
			'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
			'xsi:schemaLocation' => $namespace . ' ' . $schemaLocation
		]);
		$this->writeAttributes($attributes);
		
		$this->activeDocument = true;
	}
	
	/**
	 * Returns the generated XML document or writes it to given filename. All open
	 * elements will be automatically closed before flushing.
	 * 
	 * @param	string		$filename
	 * @return	mixed
	 */
	public function endDocument($filename = '') {
		// mark document as done
		$this->activeDocument = false;
		
		// close all open tags
		while ($this->openElements) {
			$this->endElement();
		}
		
		if (empty($filename)) {
			// return XML as string
			return $this->xml->flush(true);
		}
		else {
			// write to file
			file_put_contents($filename, $this->xml->flush(true));
		}
	}
	
	/**
	 * Begins a new element.
	 * 
	 * @param	string		$element
	 * @param	string[]	$attributes
	 */
	public function startElement($element, array $attributes = []) {
		$this->xml->startElement($element);
		$this->openElements++;
		
		if (!empty($attributes)) {
			$this->writeAttributes($attributes);
		}
	}
	
	/**
	 * Ends the last opened element.
	 */
	public function endElement() {
		if ($this->openElements) {
			$this->xml->endElement();
			$this->openElements--;
		}
	}
	
	/**
	 * Writes an element directly.
	 * 
	 * @param	string		$element
	 * @param	string		$cdata
	 * @param	string[]	$attributes
	 */
	public function writeElement($element, $cdata, array $attributes = []) {
		$this->startElement($element);
		
		// write attributes
		if (!empty($attributes)) {
			$this->writeAttributes($attributes);
		}
		
		// content
		$this->xml->writeCdata(StringUtil::escapeCDATA($cdata));
		
		$this->endElement();
	}
	<commit_msg>Support empty/self-closing XML elements<commit_after><?php
namespace wcf\util;
use wcf\system\exception\SystemException;

/**
 * Writes XML documents.
 * 
 * @author	<NAME>
 * @copyright	2001-2017 WoltLab GmbH
 * @license	GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package	WoltLabSuite\Core\Util
 */
class XMLWriter {
	/**
	 * true, if a document is still processed
	 * @var	boolean
	 */
	protected $activeDocument = false;
	
	/**
	 * number of open elements
	 * @var	integer
	 */
	protected $openElements = 0;
	
	/**
	 * XMLWriter object
	 * @var	\XMLWriter
	 */
	protected $xml = null;
	
	/**
	 * Creates a new XML document.
	 * 
	 * @param	string		$rootElement
	 * @param	string		$namespace
	 * @param	string		$schemaLocation
	 * @param	string[]	$attributes
	 * @throws	SystemException
	 */
	public function beginDocument($rootElement, $namespace, $schemaLocation, array $attributes = []) {
		if ($this->activeDocument) {
			throw new SystemException("Could not begin a new document unless the previous is finished");
		}
		
		if ($this->xml === null) {
			$this->xml = new \XMLWriter();
			$this->xml->openMemory();
			$this->xml->setIndent(true);
			$this->xml->setIndentString("\t");
		}
		
		$this->xml->startDocument('1.0', 'UTF-8');
		$this->startElement($rootElement);
		$attributes = array_merge($attributes, [
			'xmlns' => $namespace,
			'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
			'xsi:schemaLocation' => $namespace . ' ' . $schemaLocation
		]);
		$this->writeAttributes($attributes);
		
		$this->activeDocument = true;
	}
	
	/**
	 * Returns the generated XML document or writes it to given filename. All open
	 * elements will be automatically closed before flushing.
	 * 
	 * @param	string		$filename
	 * @return	mixed
	 */
	public function endDocument($filename = '') {
		// mark document as done
		$this->activeDocument = false;
		
		// close all open tags
		while ($this->openElements) {
			$this->endElement();
		}
		
		if (empty($filename)) {
			// return XML as string
			return $this->xml->flush(true);
		}
		else {
			// write to file
			file_put_contents($filename, $this->xml->flush(true));
		}
	}
	
	/**
	 * Begins a new element.
	 * 
	 * @param	string		$element
	 * @param	string[]	$attributes
	 */
	public function startElement($element, array $attributes = []) {
		$this->xml->startElement($element);
		$this->openElements++;
		
		if (!empty($attributes)) {
			$this->writeAttributes($attributes);
		}
	}
	
	/**
	 * Ends the last opened element.
	 */
	public function endElement() {
		if ($this->openElements) {
			$this->xml->endElement();
			$this->openElements--;
		}
	}
	
	/**
	 * Writes an element directly.
	 * 
	 * @param	string		$element
	 * @param	string		$cdata
	 * @param	string[]	$attributes
	 */
	public function writeElement($element, $cdata, array $attributes = []) {
		$this->startElement($element);
		
		// write attributes
		if (!empty($attributes)) {
			$this->writeAttributes($attributes);
		}
		
		// content
		if ($cdata !== '') $this->xml->writeCdata(StringUtil::escapeCDATA($cdata));
		
		$this->endElement();
	}
	
{'fraction_non_alphanumeric': 0.15951117543013346, 'fraction_numerical': 0.005467116899823122, 'mean_word_length': 3.325452016689847, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 28}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3744101', 'n_tokens_mistral': 2265, 'n_tokens_neox': 1934, 'n_words': 471}