How To Customize Xmlresponseformatter?

I’m just getting started in Yii and implementing the RESTful web services. I have it working well so far, but I to figure out how to customize the XML tags to meet a certain specification. Specifically, I need to change the XML tags, add namespaces, and add additional tags that are not in the original data.

I have the following MyXmlResponseFormatter coded as a subclass of XmlResponseFormatter, but I’m not what to do with it.

Where should I put it? And how do I register it as a custom response formatter? Do I do so in my config or in my controller files? I think I’m close, but I just can’t get it to work.




<?php


namespace app\subsplash;


use yii\web\XmlResponseFormatter;


class MyXmlResponseFormatter extends XmlResponseFormatter

{

    /**

     * @var string the name of the root element.

     */

    public $rootTag = 'data';

    /**

     * @var string the name of the elements that represent the array elements with numeric keys.

     */

    public $itemTag = 'row';


    /**

     * @var array of XML namespaces

     */

    public $nameSpaces = [

        'xmlns:foo' => 'h t t p : //example.com/foo',  // (First post spaces added to avoid forbidden links)

        'xmlns:bar' => 'h t t p : //example.com/bar',

    ];


    /**

     * @var string the title

     */

    public $title = 'Untitled';

    


    /**

     * Formats the specified response.

     * @param Response $response the response to be formatted.

     */

    public function format($response)

    {

        $charset = $this->encoding === null ? $response->charset : $this->encoding;

        if (stripos($this->contentType, 'charset') === false) {

            $this->contentType .= '; charset=' . $charset;

        }

        $response->getHeaders()->set('Content-Type', $this->contentType);

        $dom = new DOMDocument($this->version, $charset);


        

        // Add root tag with namespaces

        $root = new DOMElement($this->rootTag);

        foreach ($this->nameSpaces as $ns => $url) {

            $root->setAttributeNS($url, $ns);

        }

        $dom->appendChild($root);


        // Add header with title

        $header = new DOMElement('header');

        $title = new DOMElement('title', $this->title);

        $header->appendChild($title);

        $dom->appendChild($header);


        $this->buildXml($root, $response->data);

        $response->content = $dom->saveXML();

    }

}




I’m also having trouble understanding how to add and/or customize my XML tags just for a particular format.

I have overridden the fields() in my model, but that affects all response formats:




    public function fields()

    {

        return [

            'name'              => 'FullName',

            'date'              => 'PubDate',

            'foo:flagA'         => function() { return 'true'; },  // New field not present in db

            'foo:flagB'         => function() { return ''; },      // New field not present in db

            'link'              => function() {

                return Yii::getAlias('@web/authors/') . $this->AuthorId;

            },

        ];

    }



Do I need to create a custom model? Seems like I’m completely violating the MVC paradigm by putting formatting information into the model. Can I customize the fields in my controller instead?

Additionally, I get a namespace error with ‘foo:flagA’ and ‘foo:flagB’ so it seems like doing this in the model is not the proper place.

It seems that perhaps the best way to handle this is to get the response object and customize it before it goes to the serializer and then XmlResponseFormatter. I’m just not sure how to do this.

Any help would be greatly appreciated!

you can add a configuration in ‘components’ section to override formatter settings.

'response' =&gt; [


        'formatters' =&gt; [


            'xml' =&gt; 'app&#092;subsplash&#092; MyXmlResponseFormatter',


        ]


    ],