XmlResponseFormatter.php 2.55 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 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
<?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.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class XmlResponseFormatter extends Component implements ResponseFormatter
{
	/**
	 * @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';

	/**
47 48
	 * Formats the specified response.
	 * @param Response $response the response to be formatted.
Qiang Xue committed
49
	 */
50
	public function format($response)
Qiang Xue committed
51 52 53 54 55
	{
		$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);
56 57
		$this->buildXml($root, $response->data);
		$response->content = $dom->saveXML();
Qiang Xue committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
	}

	/**
	 * @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 {
				$array = array();
				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));
		}
	}
}