[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 3 include_once 'XML/WBXML.php'; 4 include_once 'XML/WBXML/ContentHandler.php'; 5 include_once 'XML/WBXML/DTDManager.php'; 6 include_once 'Horde/String.php'; 7 8 /** 9 * $Horde: framework/XML_WBXML/WBXML/Encoder.php,v 1.25.10.13 2006/05/31 17:06:37 selsky Exp $ 10 * 11 * Copyright 2003-2006 Anthony Mills <amills@pyramid6.com> 12 * 13 * See the enclosed file COPYING for license information (LGPL). If you 14 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 15 * 16 * From Binary XML Content Format Specification Version 1.3, 25 July 17 * 2001 found at http://www.wapforum.org 18 * 19 * @package XML_WBXML 20 */ 21 class XML_WBXML_Encoder extends XML_WBXML_ContentHandler { 22 23 var $_strings = array(); 24 25 var $_stringTable; 26 27 var $_hasWrittenHeader = false; 28 29 var $_dtd; 30 31 var $_output = ''; 32 33 var $_uris = array(); 34 35 var $_uriNums = array(); 36 37 var $_currentURI; 38 39 var $_subParser = null; 40 var $_subParserStack = 0; 41 42 /** 43 * The XML parser. 44 * 45 * @var resource 46 */ 47 var $_parser; 48 49 /** 50 * The DTD Manager. 51 * 52 * @var XML_WBXML_DTDManager 53 */ 54 var $_dtdManager; 55 56 /** 57 * Constructor. 58 */ 59 function XML_WBXML_Encoder() 60 { 61 $this->_dtdManager = &new XML_WBXML_DTDManager(); 62 $this->_stringTable = &new XML_WBXML_HashTable(); 63 } 64 65 /** 66 * Take the input $xml and turn it into WBXML. This is _not_ the 67 * intended way of using this class. It is derived from 68 * Contenthandler and one should use it as a ContentHandler and 69 * produce the XML-structure with startElement(), endElement(), 70 * and characters(). 71 */ 72 function encode($xml) 73 { 74 // Create the XML parser and set method references. 75 $this->_parser = xml_parser_create_ns($this->_charset); 76 xml_set_object($this->_parser, $this); 77 xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); 78 xml_set_element_handler($this->_parser, '_startElement', '_endElement'); 79 xml_set_character_data_handler($this->_parser, '_characters'); 80 xml_set_processing_instruction_handler($this->_parser, ''); 81 xml_set_external_entity_ref_handler($this->_parser, ''); 82 83 if (!xml_parse($this->_parser, $xml)) { 84 return $this->raiseError(sprintf('XML error: %s at line %d', 85 xml_error_string(xml_get_error_code($this->_parser)), 86 xml_get_current_line_number($this->_parser))); 87 } 88 89 xml_parser_free($this->_parser); 90 91 return $this->_output; 92 } 93 94 /** 95 * This will write the correct headers. 96 */ 97 function writeHeader($uri) 98 { 99 $this->_dtd = &$this->_dtdManager->getInstanceURI($uri); 100 if (!$this->_dtd) { 101 // TODO: proper error handling 102 die('Unable to find dtd for ' . $uri); 103 } 104 $dpiString = $this->_dtd->getDPI(); 105 106 // Set Version Number from Section 5.4 107 // version = u_int8 108 // currently 1, 2 or 3 109 $this->writeVersionNumber($this->_wbxmlVersion); 110 111 // Set Document Public Idetifier from Section 5.5 112 // publicid = mb_u_int32 | ( zero index ) 113 // zero = u_int8 114 // containing the value zero (0) 115 // The actual DPI is determined after the String Table is read. 116 $this->writeDocumentPublicIdentifier($dpiString, $this->_strings); 117 118 // Set Charset from 5.6 119 // charset = mb_u_int32 120 $this->writeCharset($this->_charset); 121 122 // Set String Table from 5.7 123 // strb1 = length *byte 124 $this->writeStringTable($this->_strings, $this->_charset, $this->_stringTable); 125 126 $this->_currentURI = $uri; 127 128 $this->_hasWrittenHeader = true; 129 } 130 131 function writeVersionNumber($version) 132 { 133 $this->_output .= chr($version); 134 } 135 136 function writeDocumentPublicIdentifier($dpiString, &$strings) 137 { 138 $i = XML_WBXML::getDPIInt($dpiString); 139 140 if ($i == 0) { 141 $strings[0] = $dpiString; 142 $this->_output .= chr(0); 143 $this->_output .= chr(0); 144 } else { 145 XML_WBXML::intToMBUInt32($this->_output, $i); 146 } 147 } 148 149 function writeCharset($charset) 150 { 151 $cs = XML_WBXML::getCharsetInt($charset); 152 153 if ($cs == 0) { 154 return $this->raiseError('Unsupported Charset: ' . $charset); 155 } else { 156 XML_WBXML::intToMBUInt32($this->_output, $cs); 157 } 158 } 159 160 function writeStringTable($strings, $charset, $stringTable) 161 { 162 $stringBytes = array(); 163 $count = 0; 164 foreach ($strings as $str) { 165 $bytes = $this->_getBytes($str, $charset); 166 $stringBytes = array_merge($stringBytes, $bytes); 167 $nullLength = $this->_addNullByte($bytes); 168 $this->_stringTable->set($str, $count); 169 $count += count($bytes) + $nullLength; 170 } 171 172 XML_WBXML::intToMBUInt32($this->_output, count($stringBytes)); 173 $this->_output .= implode('', $stringBytes); 174 } 175 176 function writeString($str, $cs) 177 { 178 $bytes = $this->_getBytes($str, $cs); 179 $this->_output .= implode('', $bytes); 180 $this->writeNull($cs); 181 } 182 183 function writeNull($charset) 184 { 185 $this->_output .= chr(0); 186 return 1; 187 } 188 189 function _addNullByte(&$bytes) 190 { 191 $bytes[] = chr(0); 192 return 1; 193 } 194 195 function _getBytes($string, $cs) 196 { 197 $string = String::convertCharset($string, $cs, 'utf-8'); 198 $nbytes = strlen($string); 199 200 $bytes = array(); 201 for ($i = 0; $i < $nbytes; $i++) { 202 $bytes[] = $string{$i}; 203 } 204 205 return $bytes; 206 } 207 208 function _splitURI($tag) 209 { 210 $parts = explode(':', $tag); 211 $name = array_pop($parts); 212 $uri = implode(':', $parts); 213 return array($uri, $name); 214 } 215 216 function startElement($uri, $name, $attributes) 217 { 218 if ($this->_subParser == null) { 219 if (!$this->_hasWrittenHeader) { 220 $this->writeHeader($uri); 221 } 222 if ($this->_currentURI != $uri) { 223 $this->changecodepage($uri); 224 } 225 if ($this->_subParser == null) { 226 $this->writeTag($name, $attributes, true, $this->_charset); 227 } else { 228 $this->_subParser->startElement($uri,$name, $attributes); 229 } 230 } else { 231 $this->_subParserStack++; 232 $this->_subParser->startElement($uri,$name,$attributes); 233 } 234 } 235 236 function _startElement($parser, $tag, $attributes) 237 { 238 list($uri, $name) = $this->_splitURI($tag); 239 240 $this->startElement($uri, $name, $attributes); 241 } 242 243 function opaque($o) 244 { 245 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE); 246 XML_WBXML::intToMBUInt32($this->_output, strlen($o)); 247 $this->_output .= $o; 248 } 249 250 function characters($chars) 251 { 252 $chars = trim($chars); 253 254 if (strlen($chars)) { 255 /* We definitely don't want any whitespace. */ 256 if ($this->_subParser == null) { 257 $i = $this->_stringTable->get($chars); 258 if ($i != null) { 259 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T); 260 XML_WBXML::intToMBUInt32($this->_output, $i); 261 } else { 262 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I); 263 $this->writeString($chars, $this->_charset); 264 } 265 } else { 266 $this->_subParser->characters($chars); 267 } 268 } 269 } 270 271 function _characters($parser, $chars) 272 { 273 $this->characters($chars); 274 } 275 276 function writeTag($name, $attrs, $hasContent, $cs) 277 { 278 if ($attrs != null && !count($attrs)) { 279 $attrs = null; 280 } 281 282 $t = $this->_dtd->toTagInt($name); 283 if ($t == -1) { 284 $i = $this->_stringTable->get($name); 285 if ($i == null) { 286 return $this->raiseError($name . ' is not found in String Table or DTD'); 287 } else { 288 if ($attrs == null && !$hasContent) { 289 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL); 290 } elseif ($attrs == null && $hasContent) { 291 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_A); 292 } elseif ($attrs != null && $hasContent) { 293 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_C); 294 } elseif ($attrs != null && !$hasContent) { 295 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL_AC); 296 } 297 298 XML_WBXML::intToMBUInt32($this->_output, $i); 299 } 300 } else { 301 if ($attrs == null && !$hasContent) { 302 $this->_output .= chr($t); 303 } elseif ($attrs == null && $hasContent) { 304 $this->_output .= chr($t | 64); 305 } elseif ($attrs != null && $hasContent) { 306 $this->_output .= chr($t | 128); 307 } elseif ($attrs != null && !$hasContent) { 308 $this->_output .= chr($t | 192); 309 } 310 } 311 312 if ($attrs != null && is_array($attrs) && count($attrs) > 0) { 313 $this->writeAttributes($attrs, $cs); 314 } 315 } 316 317 function writeAttributes($attrs, $cs) 318 { 319 foreach ($attrs as $name => $value) { 320 $this->writeAttribute($name, $value, $cs); 321 } 322 323 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END); 324 } 325 326 function writeAttribute($name, $value, $cs) 327 { 328 $a = $this->_dtd->toAttribute($name); 329 if ($a == -1) { 330 $i = $this->_stringTable->get($name); 331 if ($i == null) { 332 return $this->raiseError($name . ' is not found in String Table or DTD'); 333 } else { 334 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_LITERAL); 335 XML_WBXML::intToMBUInt32($this->_output, $i); 336 } 337 } else { 338 $this->_output .= $a; 339 } 340 341 $i = $this->_stringTable->get($name); 342 if ($i != null) { 343 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_T); 344 XML_WBXML::intToMBUInt32($this->_output, $i); 345 } else { 346 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_STR_I); 347 $this->writeString($value, $cs); 348 } 349 } 350 351 function endElement($uri, $name) 352 { 353 if ($this->_subParser == null) { 354 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_END); 355 } else { 356 $this->_subParser->endElement($uri, $name); 357 $this->_subParserStack--; 358 359 if ($this->_subParserStack == 0) { 360 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_OPAQUE); 361 362 XML_WBXML::intToMBUInt32($this->_output, 363 strlen($this->_subParser->getOutput())); 364 $this->_output .= $this->_subParser->getOutput(); 365 366 $this->_subParser = null; 367 } 368 } 369 } 370 371 function _endElement($parser, $tag) 372 { 373 list($uri, $name) = $this->_splitURI($tag); 374 $this->endElement($uri, $name); 375 } 376 377 function changecodepage($uri) 378 { 379 // @todo: this is a hack! 380 if ($this->_dtd->getVersion() == 1 && !preg_match('/1\.1$/', $uri)) { 381 $uri .= '1.1'; 382 } 383 if ($this->_dtd->getVersion() == 0 && !preg_match('/1\.0$/', $uri)) { 384 $uri .= '1.0'; 385 } 386 387 $cp = $this->_dtd->toCodePageURI($uri); 388 if (strlen($cp)) { 389 $this->_dtd = &$this->_dtdManager->getInstanceURI($uri); 390 391 $this->_output .= chr(XML_WBXML_GLOBAL_TOKEN_SWITCH_PAGE); 392 $this->_output .= chr($cp); 393 $this->_currentURI = $uri; 394 395 } else { 396 $this->_subParser = &new XML_WBXML_Encoder(true); 397 $this->_subParserStack = 1; 398 } 399 } 400 401 /** 402 * Getter for property output. 403 */ 404 function getOutput() 405 { 406 return $this->_output; 407 } 408 409 function getOutputSize() 410 { 411 return strlen($this->_output); 412 } 413 414 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |