[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * 5 * Created on Sep 19, 2006 6 * 7 * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com" 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 * http://www.gnu.org/copyleft/gpl.html 23 * 24 * @file 25 */ 26 27 /** 28 * API XML output formatter 29 * @ingroup API 30 */ 31 class ApiFormatXml extends ApiFormatBase { 32 33 private $mRootElemName = 'api'; 34 public static $namespace = 'http://www.mediawiki.org/xml/api/'; 35 private $mIncludeNamespace = false; 36 private $mXslt = null; 37 38 public function getMimeType() { 39 return 'text/xml'; 40 } 41 42 public function getNeedsRawData() { 43 return true; 44 } 45 46 public function setRootElement( $rootElemName ) { 47 $this->mRootElemName = $rootElemName; 48 } 49 50 public function execute() { 51 $params = $this->extractRequestParams(); 52 $this->mIncludeNamespace = $params['includexmlnamespace']; 53 $this->mXslt = $params['xslt']; 54 55 $this->printText( '<?xml version="1.0"?>' ); 56 if ( !is_null( $this->mXslt ) ) { 57 $this->addXslt(); 58 } 59 if ( $this->mIncludeNamespace ) { 60 // If the result data already contains an 'xmlns' namespace added 61 // for custom XML output types, it will override the one for the 62 // generic API results. 63 // This allows API output of other XML types like Atom, RSS, RSD. 64 $data = $this->getResultData() + array( 'xmlns' => self::$namespace ); 65 } else { 66 $data = $this->getResultData(); 67 } 68 69 $this->printText( 70 self::recXmlPrint( $this->mRootElemName, 71 $data, 72 $this->getIsHtml() ? -2 : null 73 ) 74 ); 75 } 76 77 /** 78 * This method takes an array and converts it to XML. 79 * 80 * There are several noteworthy cases: 81 * 82 * If array contains a key '_element', then the code assumes that ALL 83 * other keys are not important and replaces them with the 84 * value['_element']. 85 * 86 * @par Example: 87 * @verbatim 88 * name='root', value = array( '_element'=>'page', 'x', 'y', 'z') 89 * @endverbatim 90 * creates: 91 * @verbatim 92 * <root> <page>x</page> <page>y</page> <page>z</page> </root> 93 * @endverbatim 94 * 95 * If any of the array's element key is '*', then the code treats all 96 * other key->value pairs as attributes, and the value['*'] as the 97 * element's content. 98 * 99 * @par Example: 100 * @verbatim 101 * name='root', value = array( '*'=>'text', 'lang'=>'en', 'id'=>10) 102 * @endverbatim 103 * creates: 104 * @verbatim 105 * <root lang='en' id='10'>text</root> 106 * @endverbatim 107 * 108 * Finally neither key is found, all keys become element names, and values 109 * become element content. 110 * 111 * @note The method is recursive, so the same rules apply to any 112 * sub-arrays. 113 * 114 * @param string $elemName 115 * @param mixed $elemValue 116 * @param int $indent 117 * 118 * @return string 119 */ 120 public static function recXmlPrint( $elemName, $elemValue, $indent ) { 121 $retval = ''; 122 if ( !is_null( $indent ) ) { 123 $indent += 2; 124 $indstr = "\n" . str_repeat( ' ', $indent ); 125 } else { 126 $indstr = ''; 127 } 128 $elemName = str_replace( ' ', '_', $elemName ); 129 130 if ( is_array( $elemValue ) ) { 131 if ( isset( $elemValue['*'] ) ) { 132 $subElemContent = $elemValue['*']; 133 unset( $elemValue['*'] ); 134 135 // Add xml:space="preserve" to the 136 // element so XML parsers will leave 137 // whitespace in the content alone 138 $elemValue['xml:space'] = 'preserve'; 139 } else { 140 $subElemContent = null; 141 } 142 143 if ( isset( $elemValue['_element'] ) ) { 144 $subElemIndName = $elemValue['_element']; 145 unset( $elemValue['_element'] ); 146 } else { 147 $subElemIndName = null; 148 } 149 150 if ( isset( $elemValue['_subelements'] ) ) { 151 foreach ( $elemValue['_subelements'] as $subElemId ) { 152 if ( isset( $elemValue[$subElemId] ) && !is_array( $elemValue[$subElemId] ) ) { 153 $elemValue[$subElemId] = array( '*' => $elemValue[$subElemId] ); 154 } 155 } 156 unset( $elemValue['_subelements'] ); 157 } 158 159 $indElements = array(); 160 $subElements = array(); 161 foreach ( $elemValue as $subElemId => & $subElemValue ) { 162 if ( is_int( $subElemId ) ) { 163 $indElements[] = $subElemValue; 164 unset( $elemValue[$subElemId] ); 165 } elseif ( is_array( $subElemValue ) ) { 166 $subElements[$subElemId] = $subElemValue; 167 unset( $elemValue[$subElemId] ); 168 } elseif ( is_bool( $subElemValue ) ) { 169 // treat true as empty string, skip false in xml format 170 if ( $subElemValue === true ) { 171 $subElemValue = ''; 172 } else { 173 unset( $elemValue[$subElemId] ); 174 } 175 } 176 } 177 178 if ( is_null( $subElemIndName ) && count( $indElements ) ) { 179 ApiBase::dieDebug( __METHOD__, "($elemName, ...) has integer keys " . 180 "without _element value. Use ApiResult::setIndexedTagName()." ); 181 } 182 183 if ( count( $subElements ) && count( $indElements ) && !is_null( $subElemContent ) ) { 184 ApiBase::dieDebug( __METHOD__, "($elemName, ...) has content and subelements" ); 185 } 186 187 if ( !is_null( $subElemContent ) ) { 188 $retval .= $indstr . Xml::element( $elemName, $elemValue, $subElemContent ); 189 } elseif ( !count( $indElements ) && !count( $subElements ) ) { 190 $retval .= $indstr . Xml::element( $elemName, $elemValue ); 191 } else { 192 $retval .= $indstr . Xml::element( $elemName, $elemValue, null ); 193 194 foreach ( $subElements as $subElemId => & $subElemValue ) { 195 $retval .= self::recXmlPrint( $subElemId, $subElemValue, $indent ); 196 } 197 198 foreach ( $indElements as &$subElemValue ) { 199 $retval .= self::recXmlPrint( $subElemIndName, $subElemValue, $indent ); 200 } 201 202 $retval .= $indstr . Xml::closeElement( $elemName ); 203 } 204 } elseif ( !is_object( $elemValue ) ) { 205 // to make sure null value doesn't produce unclosed element, 206 // which is what Xml::element( $elemName, null, null ) returns 207 if ( $elemValue === null ) { 208 $retval .= $indstr . Xml::element( $elemName ); 209 } else { 210 $retval .= $indstr . Xml::element( $elemName, null, $elemValue ); 211 } 212 } 213 214 return $retval; 215 } 216 217 function addXslt() { 218 $nt = Title::newFromText( $this->mXslt ); 219 if ( is_null( $nt ) || !$nt->exists() ) { 220 $this->setWarning( 'Invalid or non-existent stylesheet specified' ); 221 222 return; 223 } 224 if ( $nt->getNamespace() != NS_MEDIAWIKI ) { 225 $this->setWarning( 'Stylesheet should be in the MediaWiki namespace.' ); 226 227 return; 228 } 229 if ( substr( $nt->getText(), -4 ) !== '.xsl' ) { 230 $this->setWarning( 'Stylesheet should have .xsl extension.' ); 231 232 return; 233 } 234 $this->printText( '<?xml-stylesheet href="' . 235 htmlspecialchars( $nt->getLocalURL( 'action=raw' ) ) . '" type="text/xsl" ?>' ); 236 } 237 238 public function getAllowedParams() { 239 return array( 240 'xslt' => null, 241 'includexmlnamespace' => false, 242 ); 243 } 244 245 public function getParamDescription() { 246 return array( 247 'xslt' => 'If specified, adds <xslt> as stylesheet. This should be a wiki page ' 248 . 'in the MediaWiki namespace whose page name ends with ".xsl"', 249 'includexmlnamespace' => 'If specified, adds an XML namespace' 250 ); 251 } 252 253 public function getDescription() { 254 return 'Output data in XML format' . parent::getDescription(); 255 } 256 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |