XmlResponseFormatter.php 2.61 KB
Newer Older
Qiang Xue committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\web;

use DOMDocument;
use DOMElement;
use DOMText;
use yii\base\Arrayable;
use yii\base\Component;
use yii\helpers\StringHelper;

/**
 * XmlResponseFormatter formats the given data into an XML response content.
 *
20 21
 * It is used by [[Response]] to format response data.
 *
Qiang Xue committed
22 23 24
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
25
class XmlResponseFormatter extends Component implements ResponseFormatterInterface
Qiang Xue committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
{
	/**
	 * @var string the Content-Type header for the response
	 */
	public $contentType = 'application/xml';
	/**
	 * @var string the XML version
	 */
	public $version = '1.0';
	/**
	 * @var string the XML encoding. If not set, it will use the value of [[Response::charset]].
	 */
	public $encoding;
	/**
	 * @var string the name of the root element.
	 */
	public $rootTag = 'response';
	/**
	 * @var string the name of the elements that represent the array elements with numeric keys.
	 */
	public $itemTag = 'item';

	/**
49 50
	 * Formats the specified response.
	 * @param Response $response the response to be formatted.
Qiang Xue committed
51
	 */
52
	public function format($response)
Qiang Xue committed
53 54 55 56 57
	{
		$response->getHeaders()->set('Content-Type', $this->contentType);
		$dom = new DOMDocument($this->version, $this->encoding === null ? $response->charset : $this->encoding);
		$root = new DOMElement($this->rootTag);
		$dom->appendChild($root);
58 59
		$this->buildXml($root, $response->data);
		$response->content = $dom->saveXML();
Qiang Xue committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73
	}

	/**
	 * @param DOMElement $element
	 * @param mixed $data
	 */
	protected function buildXml($element, $data)
	{
		if (is_object($data)) {
			$child = new DOMElement(StringHelper::basename(get_class($data)));
			$element->appendChild($child);
			if ($data instanceof Arrayable) {
				$this->buildXml($child, $data->toArray());
			} else {
Alexander Makarov committed
74
				$array = [];
Qiang Xue committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
				foreach ($data as $name => $value) {
					$array[$name] = $value;
				}
				$this->buildXml($child, $array);
			}
		} elseif (is_array($data)) {
			foreach ($data as $name => $value) {
				if (is_int($name) && is_object($value)) {
					$this->buildXml($element, $value);
				} elseif (is_array($value) || is_object($value)) {
					$child = new DOMElement(is_int($name) ? $this->itemTag : $name);
					$element->appendChild($child);
					$this->buildXml($child, $value);
				} else {
					$child = new DOMElement(is_int($name) ? $this->itemTag : $name);
					$element->appendChild($child);
					$child->appendChild(new DOMText((string)$value));
				}
			}
		} else {
			$element->appendChild(new DOMText((string)$data));
		}
	}
}