xmloutputter.php 7.32 KB
Newer Older
1 2
<?php
/**
3
 * StatusNet, the distributed open-source microblogging tool
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * Low-level generator for XML
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Output
23
 * @package   StatusNet
24 25
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@status.net>
26
 * @copyright 2008 StatusNet, Inc.
27
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
28
 * @link      http://status.net/
29 30
 */

31
if (!defined('STATUSNET') && !defined('LACONICA')) {
32 33 34 35 36 37 38 39 40 41 42
    exit(1);
}

/**
 * Low-level generator for XML
 *
 * This is a thin wrapper around PHP's XMLWriter. The main
 * advantage is the element() method, which simplifies outputting
 * an element.
 *
 * @category Output
43
 * @package  StatusNet
44 45
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@status.net>
46
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
47
 * @link     http://status.net/
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
 * @see      Action
 * @see      HTMLOutputter
 */

class XMLOutputter
{
    /**
     * Wrapped XMLWriter object, which does most of the heavy lifting
     * for output.
     */

    var $xw = null;

    /**
     * Constructor
     *
     * Initializes the wrapped XMLWriter.
     *
66
     * @param string  $output URL for outputting, if null it defaults to stdout ('php://output')
67
     * @param boolean $indent Whether to indent output, default true
68 69
     */

70
    function __construct($output=null, $indent=null)
71
    {
72 73 74
        if (is_null($output)) {
            $output = 'php://output';
        }
75 76
        $this->xw = new XMLWriter();
        $this->xw->openURI($output);
77 78 79
        if(is_null($indent)) {
            $indent = common_config('site', 'indent');
        }
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
        $this->xw->setIndent($indent);
    }

    /**
     * Start a new XML document
     *
     * @param string $doc    document element
     * @param string $public public identifier
     * @param string $system system identifier
     *
     * @return void
     */

    function startXML($doc=null, $public=null, $system=null)
    {
95
        $this->xw->startDocument('1.0', 'UTF-8');
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
        if ($doc) {
            $this->xw->writeDTD($doc, $public, $system);
        }
    }

    /**
     * finish an XML document
     *
     * It's probably a bad idea to continue to use this object
     * after calling endXML().
     *
     * @return void
     */

    function endXML()
    {
        $this->xw->endDocument();
        $this->xw->flush();
    }

    /**
     * output an XML element
     *
     * Utility for outputting an XML element. A convenient wrapper
     * for a bunch of longer XMLWriter calls. This is best for
121
     * when an element doesn't have any sub-elements; if that's the
122 123 124 125 126 127
     * case, use elementStart() and elementEnd() instead.
     *
     * The $content element will be escaped for XML. If you need
     * raw output, use elementStart() and elementEnd() with a call
     * to raw() in the middle.
     *
128 129 130
     * If $attrs is a string instead of an array, it will be treated
     * as the class attribute of the element.
     *
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
     * @param string $tag     Element type or tagname
     * @param array  $attrs   Array of element attributes, as
     *                        key-value pairs
     * @param string $content string content of the element
     *
     * @return void
     */

    function element($tag, $attrs=null, $content=null)
    {
        $this->elementStart($tag, $attrs);
        if (!is_null($content)) {
            $this->xw->text($content);
        }
        $this->elementEnd($tag);
    }

148 149 150 151 152 153 154 155 156
    function elementNS(array $ns, $tag, $attrs=null, $content=null)
    {
        $this->elementStartNS($ns, $tag, $attrs);
        if (!is_null($content)) {
            $this->xw->text($content);
        }
        $this->elementEnd($tag);
    }

157 158 159 160 161 162
    /**
     * output a start tag for an element
     *
     * Mostly used for when an element has content that's
     * not a simple string.
     *
163 164 165
     * If $attrs is a string instead of an array, it will be treated
     * as the class attribute of the element.
     *
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
     * @param string $tag   Element type or tagname
     * @param array  $attrs Array of element attributes
     *
     * @return void
     */

    function elementStart($tag, $attrs=null)
    {
        $this->xw->startElement($tag);
        if (is_array($attrs)) {
            foreach ($attrs as $name => $value) {
                $this->xw->writeAttribute($name, $value);
            }
        } else if (is_string($attrs)) {
            $this->xw->writeAttribute('class', $attrs);
        }
    }

184 185 186 187 188 189 190 191 192 193 194 195 196 197
    function elementStartNS(array $ns, $tag, $attrs=null)
    {
        reset($ns); // array pointer to 0
        $uri = key($ns);
        $this->xw->startElementNS($ns[$uri], $tag, $uri);
        if (is_array($attrs)) {
            foreach ($attrs as $name => $value) {
                $this->xw->writeAttribute($name, $value);
            }
        } else if (is_string($attrs)) {
            $this->xw->writeAttribute('class', $attrs);
        }
    }

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
    /**
     * output an end tag for an element
     *
     * Used in conjunction with elementStart(). $tag param
     * should match the elementStart() param.
     *
     * For HTML 4 compatibility, this method will force
     * a full end element (</tag>) even if the element is
     * empty, except for a handful of exception tagnames.
     * This is a hack.
     *
     * @param string $tag Element type or tagname.
     *
     * @return void
     */

    function elementEnd($tag)
    {
        static $empty_tag = array('base', 'meta', 'link', 'hr',
                                  'br', 'param', 'img', 'area',
218
                                  'input', 'col', 'source');
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
        // XXX: check namespace
        if (in_array($tag, $empty_tag)) {
            $this->xw->endElement();
        } else {
            $this->xw->fullEndElement();
        }
    }

    /**
     * output plain text
     *
     * Text will be escaped. If you need it not to be,
     * use raw() instead.
     *
     * @param string $txt Text to output.
     *
     * @return void
     */

    function text($txt)
    {
        $this->xw->text($txt);
    }

    /**
     * output raw xml
     *
     * This will spit out its argument verbatim -- no escaping is
     * done.
     *
     * @param string $xml XML to output.
     *
     * @return void
     */

    function raw($xml)
    {
        $this->xw->writeRaw($xml);
    }
258 259 260 261 262 263 264 265 266 267 268 269 270

    /**
     * output a comment
     *
     * @param string $txt text of the comment
     *
     * @return void
     */

    function comment($txt)
    {
        $this->xw->writeComment($txt);
    }
Evan Prodromou's avatar
Evan Prodromou committed
271 272 273 274 275 276 277 278 279 280 281

    /**
     * Flush output buffers
     *
     * @return void
     */

    function flush()
    {
        $this->xw->flush();
    }
282
}