| [ Index ] |
|
Code source de GeekLog 1.4.1 |
1 <?php 2 /** 3 * package.xml generation class, package.xml version 2.0 4 * 5 * PHP versions 4 and 5 6 * 7 * LICENSE: This source file is subject to version 3.0 of the PHP license 8 * that is available through the world-wide-web at the following URI: 9 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 10 * the PHP License and are unable to obtain it through the web, please 11 * send a note to license@php.net so we can mail you a copy immediately. 12 * 13 * @category pear 14 * @package PEAR 15 * @author Greg Beaver <cellog@php.net> 16 * @author Stephan Schmidt (original XML_Serializer code) 17 * @copyright 1997-2006 The PHP Group 18 * @license http://www.php.net/license/3_0.txt PHP License 3.0 19 * @version CVS: $Id: v2.php,v 1.34 2006/03/02 20:50:59 cellog Exp $ 20 * @link http://pear.php.net/package/PEAR 21 * @since File available since Release 1.4.0a1 22 */ 23 /** 24 * file/dir manipulation routines 25 */ 26 require_once 'System.php'; 27 /** 28 * This class converts a PEAR_PackageFile_v2 object into any output format. 29 * 30 * Supported output formats include array, XML string (using S. Schmidt's 31 * XML_Serializer, slightly customized) 32 * @category pear 33 * @package PEAR 34 * @author Greg Beaver <cellog@php.net> 35 * @author Stephan Schmidt (original XML_Serializer code) 36 * @copyright 1997-2006 The PHP Group 37 * @license http://www.php.net/license/3_0.txt PHP License 3.0 38 * @version Release: 1.4.11 39 * @link http://pear.php.net/package/PEAR 40 * @since Class available since Release 1.4.0a1 41 */ 42 class PEAR_PackageFile_Generator_v2 43 { 44 /** 45 * default options for the serialization 46 * @access private 47 * @var array $_defaultOptions 48 */ 49 var $_defaultOptions = array( 50 'indent' => ' ', // string used for indentation 51 'linebreak' => "\n", // string used for newlines 52 'typeHints' => false, // automatically add type hin attributes 53 'addDecl' => true, // add an XML declaration 54 'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names 55 'classAsTagName' => false, // use classname for objects in indexed arrays 56 'keyAttribute' => '_originalKey', // attribute where original key is stored 57 'typeAttribute' => '_type', // attribute for type (only if typeHints => true) 58 'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true) 59 'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute 60 'prependAttributes' => '', // prepend string for attributes 61 'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column 62 'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array 63 'addDoctype' => false, // add a doctype declaration 64 'doctype' => null, // supply a string or an array with id and uri ({@see PEAR_PackageFile_Generator_v2_PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration()} 65 'rootName' => 'package', // name of the root tag 66 'rootAttributes' => array( 67 'version' => '2.0', 68 'xmlns' => 'http://pear.php.net/dtd/package-2.0', 69 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0', 70 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 71 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0 72 http://pear.php.net/dtd/tasks-1.0.xsd 73 http://pear.php.net/dtd/package-2.0 74 http://pear.php.net/dtd/package-2.0.xsd', 75 ), // attributes of the root tag 76 'attributesArray' => 'attribs', // all values in this key will be treated as attributes 77 'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray 78 'beautifyFilelist' => false, 79 'encoding' => 'UTF-8', 80 ); 81 82 /** 83 * options for the serialization 84 * @access private 85 * @var array $options 86 */ 87 var $options = array(); 88 89 /** 90 * current tag depth 91 * @var integer $_tagDepth 92 */ 93 var $_tagDepth = 0; 94 95 /** 96 * serilialized representation of the data 97 * @var string $_serializedData 98 */ 99 var $_serializedData = null; 100 /** 101 * @var PEAR_PackageFile_v2 102 */ 103 var $_packagefile; 104 /** 105 * @param PEAR_PackageFile_v2 106 */ 107 function PEAR_PackageFile_Generator_v2(&$packagefile) 108 { 109 $this->_packagefile = &$packagefile; 110 } 111 112 /** 113 * @return string 114 */ 115 function getPackagerVersion() 116 { 117 return '1.4.11'; 118 } 119 120 /** 121 * @param PEAR_Packager 122 * @param bool generate a .tgz or a .tar 123 * @param string|null temporary directory to package in 124 */ 125 function toTgz(&$packager, $compress = true, $where = null) 126 { 127 $a = null; 128 return $this->toTgz2($packager, $a, $compress, $where); 129 } 130 131 /** 132 * Package up both a package.xml and package2.xml for the same release 133 * @param PEAR_Packager 134 * @param PEAR_PackageFile_v1 135 * @param bool generate a .tgz or a .tar 136 * @param string|null temporary directory to package in 137 */ 138 function toTgz2(&$packager, &$pf1, $compress = true, $where = null) 139 { 140 require_once 'Archive/Tar.php'; 141 if (!$this->_packagefile->isEquivalent($pf1)) { 142 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . 143 basename($pf1->getPackageFile()) . 144 '" is not equivalent to "' . basename($this->_packagefile->getPackageFile()) 145 . '"'); 146 } 147 if ($where === null) { 148 if (!($where = System::mktemp(array('-d')))) { 149 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed'); 150 } 151 } elseif (!@System::mkDir(array('-p', $where))) { 152 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' . 153 ' not be created'); 154 } 155 if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') && 156 !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) { 157 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' . 158 ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"'); 159 } 160 if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) { 161 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml'); 162 } 163 $ext = $compress ? '.tgz' : '.tar'; 164 $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion(); 165 $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; 166 if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) && 167 !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) { 168 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' . 169 getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"'); 170 } 171 if ($pkgfile = $this->_packagefile->getPackageFile()) { 172 $pkgdir = dirname(realpath($pkgfile)); 173 $pkgfile = basename($pkgfile); 174 } else { 175 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' . 176 'be created from a real file'); 177 } 178 // {{{ Create the package file list 179 $filelist = array(); 180 $i = 0; 181 $this->_packagefile->flattenFilelist(); 182 $contents = $this->_packagefile->getContents(); 183 if (isset($contents['bundledpackage'])) { // bundles of packages 184 $contents = $contents['bundledpackage']; 185 if (!isset($contents[0])) { 186 $contents = array($contents); 187 } 188 $packageDir = $where; 189 foreach ($contents as $i => $package) { 190 $fname = $package; 191 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; 192 if (!file_exists($file)) { 193 return $packager->raiseError("File does not exist: $fname"); 194 } 195 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; 196 System::mkdir(array('-p', dirname($tfile))); 197 copy($file, $tfile); 198 $filelist[$i++] = $tfile; 199 $packager->log(2, "Adding package $fname"); 200 } 201 } else { // normal packages 202 $contents = $contents['dir']['file']; 203 if (!isset($contents[0])) { 204 $contents = array($contents); 205 } 206 207 $packageDir = $where; 208 foreach ($contents as $i => $file) { 209 $fname = $file['attribs']['name']; 210 $atts = $file['attribs']; 211 $orig = $file; 212 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; 213 if (!file_exists($file)) { 214 return $packager->raiseError("File does not exist: $fname"); 215 } else { 216 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; 217 unset($orig['attribs']); 218 if (count($orig)) { // file with tasks 219 // run any package-time tasks 220 if (function_exists('file_get_contents')) { 221 $contents = file_get_contents($file); 222 } else { 223 $fp = fopen($file, "r"); 224 $contents = @fread($fp, filesize($file)); 225 fclose($fp); 226 } 227 foreach ($orig as $tag => $raw) { 228 $tag = str_replace($this->_packagefile->getTasksNs() . ':', '', $tag); 229 $task = "PEAR_Task_$tag"; 230 $task = &new $task($this->_packagefile->_config, 231 $this->_packagefile->_logger, 232 PEAR_TASK_PACKAGE); 233 $task->init($raw, $atts, null); 234 $res = $task->startSession($this->_packagefile, $contents, $tfile); 235 if (!$res) { 236 continue; // skip this task 237 } 238 if (PEAR::isError($res)) { 239 return $res; 240 } 241 $contents = $res; // save changes 242 System::mkdir(array('-p', dirname($tfile))); 243 $wp = fopen($tfile, "wb"); 244 fwrite($wp, $contents); 245 fclose($wp); 246 } 247 } 248 if (!file_exists($tfile)) { 249 System::mkdir(array('-p', dirname($tfile))); 250 copy($file, $tfile); 251 } 252 $filelist[$i++] = $tfile; 253 $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1); 254 $packager->log(2, "Adding file $fname"); 255 } 256 } 257 } 258 // }}} 259 if ($pf1 !== null) { 260 $name = 'package2.xml'; 261 } else { 262 $name = 'package.xml'; 263 } 264 $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name); 265 if ($packagexml) { 266 $tar =& new Archive_Tar($dest_package, $compress); 267 $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors 268 // ----- Creates with the package.xml file 269 $ok = $tar->createModify(array($packagexml), '', $where); 270 if (PEAR::isError($ok)) { 271 return $packager->raiseError($ok); 272 } elseif (!$ok) { 273 return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name . 274 ' failed'); 275 } 276 // ----- Add the content of the package 277 if (!$tar->addModify($filelist, $pkgver, $where)) { 278 return $packager->raiseError( 279 'PEAR_Packagefile_v2::toTgz(): tarball creation failed'); 280 } 281 // add the package.xml version 1.0 282 if ($pf1 !== null) { 283 $pfgen = &$pf1->getDefaultGenerator(); 284 $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 285 'package.xml', true); 286 if (!$tar->addModify(array($packagexml1), '', $where)) { 287 return $packager->raiseError( 288 'PEAR_Packagefile_v2::toTgz(): adding package.xml failed'); 289 } 290 } 291 return $dest_package; 292 } 293 } 294 295 function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml') 296 { 297 if (!$this->_packagefile->validate($state)) { 298 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml', 299 null, null, null, $this->_packagefile->getValidationWarnings()); 300 } 301 if ($where === null) { 302 if (!($where = System::mktemp(array('-d')))) { 303 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed'); 304 } 305 } elseif (!@System::mkDir(array('-p', $where))) { 306 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' . 307 ' not be created'); 308 } 309 $newpkgfile = $where . DIRECTORY_SEPARATOR . $name; 310 $np = @fopen($newpkgfile, 'wb'); 311 if (!$np) { 312 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' . 313 "$name as $newpkgfile"); 314 } 315 fwrite($np, $this->toXml($state)); 316 fclose($np); 317 return $newpkgfile; 318 } 319 320 function &toV2() 321 { 322 return $this->_packagefile; 323 } 324 325 /** 326 * Return an XML document based on the package info (as returned 327 * by the PEAR_Common::infoFrom* methods). 328 * 329 * @return string XML data 330 */ 331 function toXml($state = PEAR_VALIDATE_NORMAL, $options = array()) 332 { 333 $this->_packagefile->setDate(date('Y-m-d')); 334 $this->_packagefile->setTime(date('H:i:s')); 335 if (!$this->_packagefile->validate($state)) { 336 return false; 337 } 338 if (is_array($options)) { 339 $this->options = array_merge($this->_defaultOptions, $options); 340 } else { 341 $this->options = $this->_defaultOptions; 342 } 343 $arr = $this->_packagefile->getArray(); 344 if (isset($arr['filelist'])) { 345 unset($arr['filelist']); 346 } 347 if (isset($arr['_lastversion'])) { 348 unset($arr['_lastversion']); 349 } 350 if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) { 351 $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']); 352 unset($arr['contents']['dir']['file']); 353 if (isset($use['dir'])) { 354 $arr['contents']['dir']['dir'] = $use['dir']; 355 } 356 if (isset($use['file'])) { 357 $arr['contents']['dir']['file'] = $use['file']; 358 } 359 $this->options['beautifyFilelist'] = true; 360 } 361 $arr['attribs']['packagerversion'] = '1.4.11'; 362 if ($this->serialize($arr, $options)) { 363 return $this->_serializedData . "\n"; 364 } 365 return false; 366 } 367 368 369 function _recursiveXmlFilelist($list) 370 { 371 $dirs = array(); 372 if (isset($list['attribs'])) { 373 $file = $list['attribs']['name']; 374 unset($list['attribs']['name']); 375 $attributes = $list['attribs']; 376 $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes); 377 } else { 378 foreach ($list as $a) { 379 $file = $a['attribs']['name']; 380 $attributes = $a['attribs']; 381 unset($a['attribs']); 382 $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a); 383 } 384 } 385 $this->_formatDir($dirs); 386 $this->_deFormat($dirs); 387 return $dirs; 388 } 389 390 function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null) 391 { 392 if (!$tasks) { 393 $tasks = array(); 394 } 395 if ($dir == array() || $dir == array('.')) { 396 $dirs['file'][basename($file)] = $tasks; 397 $attributes['name'] = basename($file); 398 $dirs['file'][basename($file)]['attribs'] = $attributes; 399 return; 400 } 401 $curdir = array_shift($dir); 402 if (!isset($dirs['dir'][$curdir])) { 403 $dirs['dir'][$curdir] = array(); 404 } 405 $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks); 406 } 407 408 function _formatDir(&$dirs) 409 { 410 if (!count($dirs)) { 411 return array(); 412 } 413 $newdirs = array(); 414 if (isset($dirs['dir'])) { 415 $newdirs['dir'] = $dirs['dir']; 416 } 417 if (isset($dirs['file'])) { 418 $newdirs['file'] = $dirs['file']; 419 } 420 $dirs = $newdirs; 421 if (isset($dirs['dir'])) { 422 uksort($dirs['dir'], 'strnatcasecmp'); 423 foreach ($dirs['dir'] as $dir => $contents) { 424 $this->_formatDir($dirs['dir'][$dir]); 425 } 426 } 427 if (isset($dirs['file'])) { 428 uksort($dirs['file'], 'strnatcasecmp'); 429 }; 430 } 431 432 function _deFormat(&$dirs) 433 { 434 if (!count($dirs)) { 435 return array(); 436 } 437 $newdirs = array(); 438 if (isset($dirs['dir'])) { 439 foreach ($dirs['dir'] as $dir => $contents) { 440 $newdir = array(); 441 $newdir['attribs']['name'] = $dir; 442 $this->_deFormat($contents); 443 foreach ($contents as $tag => $val) { 444 $newdir[$tag] = $val; 445 } 446 $newdirs['dir'][] = $newdir; 447 } 448 if (count($newdirs['dir']) == 1) { 449 $newdirs['dir'] = $newdirs['dir'][0]; 450 } 451 } 452 if (isset($dirs['file'])) { 453 foreach ($dirs['file'] as $name => $file) { 454 $newdirs['file'][] = $file; 455 } 456 if (count($newdirs['file']) == 1) { 457 $newdirs['file'] = $newdirs['file'][0]; 458 } 459 } 460 $dirs = $newdirs; 461 } 462 463 /** 464 * reset all options to default options 465 * 466 * @access public 467 * @see setOption(), XML_Unserializer() 468 */ 469 function resetOptions() 470 { 471 $this->options = $this->_defaultOptions; 472 } 473 474 /** 475 * set an option 476 * 477 * You can use this method if you do not want to set all options in the constructor 478 * 479 * @access public 480 * @see resetOption(), XML_Serializer() 481 */ 482 function setOption($name, $value) 483 { 484 $this->options[$name] = $value; 485 } 486 487 /** 488 * sets several options at once 489 * 490 * You can use this method if you do not want to set all options in the constructor 491 * 492 * @access public 493 * @see resetOption(), XML_Unserializer(), setOption() 494 */ 495 function setOptions($options) 496 { 497 $this->options = array_merge($this->options, $options); 498 } 499 500 /** 501 * serialize data 502 * 503 * @access public 504 * @param mixed $data data to serialize 505 * @return boolean true on success, pear error on failure 506 */ 507 function serialize($data, $options = null) 508 { 509 // if options have been specified, use them instead 510 // of the previously defined ones 511 if (is_array($options)) { 512 $optionsBak = $this->options; 513 if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) { 514 $this->options = array_merge($this->_defaultOptions, $options); 515 } else { 516 $this->options = array_merge($this->options, $options); 517 } 518 } 519 else { 520 $optionsBak = null; 521 } 522 523 // start depth is zero 524 $this->_tagDepth = 0; 525 526 $this->_serializedData = ''; 527 // serialize an array 528 if (is_array($data)) { 529 if (isset($this->options['rootName'])) { 530 $tagName = $this->options['rootName']; 531 } else { 532 $tagName = 'array'; 533 } 534 535 $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']); 536 } 537 538 // add doctype declaration 539 if ($this->options['addDoctype'] === true) { 540 $this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype']) 541 . $this->options['linebreak'] 542 . $this->_serializedData; 543 } 544 545 // build xml declaration 546 if ($this->options['addDecl']) { 547 $atts = array(); 548 if (isset($this->options['encoding']) ) { 549 $encoding = $this->options['encoding']; 550 } else { 551 $encoding = null; 552 } 553 $this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration('1.0', $encoding) 554 . $this->options['linebreak'] 555 . $this->_serializedData; 556 } 557 558 559 if ($optionsBak !== null) { 560 $this->options = $optionsBak; 561 } 562 563 return true; 564 } 565 566 /** 567 * get the result of the serialization 568 * 569 * @access public 570 * @return string serialized XML 571 */ 572 function getSerializedData() 573 { 574 if ($this->_serializedData == null ) { 575 return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION); 576 } 577 return $this->_serializedData; 578 } 579 580 /** 581 * serialize any value 582 * 583 * This method checks for the type of the value and calls the appropriate method 584 * 585 * @access private 586 * @param mixed $value 587 * @param string $tagName 588 * @param array $attributes 589 * @return string 590 */ 591 function _serializeValue($value, $tagName = null, $attributes = array()) 592 { 593 if (is_array($value)) { 594 $xml = $this->_serializeArray($value, $tagName, $attributes); 595 } elseif (is_object($value)) { 596 $xml = $this->_serializeObject($value, $tagName); 597 } else { 598 $tag = array( 599 'qname' => $tagName, 600 'attributes' => $attributes, 601 'content' => $value 602 ); 603 $xml = $this->_createXMLTag($tag); 604 } 605 return $xml; 606 } 607 608 /** 609 * serialize an array 610 * 611 * @access private 612 * @param array $array array to serialize 613 * @param string $tagName name of the root tag 614 * @param array $attributes attributes for the root tag 615 * @return string $string serialized data 616 * @uses PEAR_PackageFile_Generator_v2_XML_Util::isValidName() to check, whether key has to be substituted 617 */ 618 function _serializeArray(&$array, $tagName = null, $attributes = array()) 619 { 620 $_content = null; 621 622 /** 623 * check for special attributes 624 */ 625 if ($this->options['attributesArray'] !== null) { 626 if (isset($array[$this->options['attributesArray']])) { 627 $attributes = $array[$this->options['attributesArray']]; 628 unset($array[$this->options['attributesArray']]); 629 } 630 /** 631 * check for special content 632 */ 633 if ($this->options['contentName'] !== null) { 634 if (isset($array[$this->options['contentName']])) { 635 $_content = $array[$this->options['contentName']]; 636 unset($array[$this->options['contentName']]); 637 } 638 } 639 } 640 641 /* 642 * if mode is set to simpleXML, check whether 643 * the array is associative or indexed 644 */ 645 if (is_array($array) && $this->options['mode'] == 'simplexml') { 646 $indexed = true; 647 if (!count($array)) { 648 $indexed = false; 649 } 650 foreach ($array as $key => $val) { 651 if (!is_int($key)) { 652 $indexed = false; 653 break; 654 } 655 } 656 657 if ($indexed && $this->options['mode'] == 'simplexml') { 658 $string = ''; 659 foreach ($array as $key => $val) { 660 if ($this->options['beautifyFilelist'] && $tagName == 'dir') { 661 if (!isset($this->_curdir)) { 662 $this->_curdir = ''; 663 } 664 $savedir = $this->_curdir; 665 if (isset($val['attribs'])) { 666 if ($val['attribs']['name'] == '/') { 667 $this->_curdir = '/'; 668 } else { 669 if ($this->_curdir == '/') { 670 $this->_curdir = ''; 671 } 672 $this->_curdir .= '/' . $val['attribs']['name']; 673 } 674 } 675 } 676 $string .= $this->_serializeValue( $val, $tagName, $attributes); 677 if ($this->options['beautifyFilelist'] && $tagName == 'dir') { 678 $string .= ' <!-- ' . $this->_curdir . ' -->'; 679 if (empty($savedir)) { 680 unset($this->_curdir); 681 } else { 682 $this->_curdir = $savedir; 683 } 684 } 685 686 $string .= $this->options['linebreak']; 687 // do indentation 688 if ($this->options['indent']!==null && $this->_tagDepth>0) { 689 $string .= str_repeat($this->options['indent'], $this->_tagDepth); 690 } 691 } 692 return rtrim($string); 693 } 694 } 695 696 if ($this->options['scalarAsAttributes'] === true) { 697 foreach ($array as $key => $value) { 698 if (is_scalar($value) && (PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key) === true)) { 699 unset($array[$key]); 700 $attributes[$this->options['prependAttributes'].$key] = $value; 701 } 702 } 703 } 704 705 // check for empty array => create empty tag 706 if (empty($array)) { 707 $tag = array( 708 'qname' => $tagName, 709 'content' => $_content, 710 'attributes' => $attributes 711 ); 712 713 } else { 714 $this->_tagDepth++; 715 $tmp = $this->options['linebreak']; 716 foreach ($array as $key => $value) { 717 // do indentation 718 if ($this->options['indent']!==null && $this->_tagDepth>0) { 719 $tmp .= str_repeat($this->options['indent'], $this->_tagDepth); 720 } 721 722 // copy key 723 $origKey = $key; 724 // key cannot be used as tagname => use default tag 725 $valid = PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key); 726 if (PEAR::isError($valid)) { 727 if ($this->options['classAsTagName'] && is_object($value)) { 728 $key = get_class($value); 729 } else { 730 $key = $this->options['defaultTagName']; 731 } 732 } 733 $atts = array(); 734 if ($this->options['typeHints'] === true) { 735 $atts[$this->options['typeAttribute']] = gettype($value); 736 if ($key !== $origKey) { 737 $atts[$this->options['keyAttribute']] = (string)$origKey; 738 } 739 740 } 741 if ($this->options['beautifyFilelist'] && $key == 'dir') { 742 if (!isset($this->_curdir)) { 743 $this->_curdir = ''; 744 } 745 $savedir = $this->_curdir; 746 if (isset($value['attribs'])) { 747 if ($value['attribs']['name'] == '/') { 748 $this->_curdir = '/'; 749 } else { 750 $this->_curdir .= '/' . $value['attribs']['name']; 751 } 752 } 753 } 754 755 if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) { 756 $value .= str_repeat($this->options['indent'], $this->_tagDepth); 757 } 758 $tmp .= $this->_createXMLTag(array( 759 'qname' => $key, 760 'attributes' => $atts, 761 'content' => $value ) 762 ); 763 if ($this->options['beautifyFilelist'] && $key == 'dir') { 764 if (isset($value['attribs'])) { 765 $tmp .= ' <!-- ' . $this->_curdir . ' -->'; 766 if (empty($savedir)) { 767 unset($this->_curdir); 768 } else { 769 $this->_curdir = $savedir; 770 } 771 } 772 } 773 $tmp .= $this->options['linebreak']; 774 } 775 776 $this->_tagDepth--; 777 if ($this->options['indent']!==null && $this->_tagDepth>0) { 778 $tmp .= str_repeat($this->options['indent'], $this->_tagDepth); 779 } 780 781 if (trim($tmp) === '') { 782 $tmp = null; 783 } 784 785 $tag = array( 786 'qname' => $tagName, 787 'content' => $tmp, 788 'attributes' => $attributes 789 ); 790 } 791 if ($this->options['typeHints'] === true) { 792 if (!isset($tag['attributes'][$this->options['typeAttribute']])) { 793 $tag['attributes'][$this->options['typeAttribute']] = 'array'; 794 } 795 } 796 797 $string = $this->_createXMLTag($tag, false); 798 return $string; 799 } 800 801 /** 802 * create a tag from an array 803 * this method awaits an array in the following format 804 * array( 805 * 'qname' => $tagName, 806 * 'attributes' => array(), 807 * 'content' => $content, // optional 808 * 'namespace' => $namespace // optional 809 * 'namespaceUri' => $namespaceUri // optional 810 * ) 811 * 812 * @access private 813 * @param array $tag tag definition 814 * @param boolean $replaceEntities whether to replace XML entities in content or not 815 * @return string $string XML tag 816 */ 817 function _createXMLTag( $tag, $replaceEntities = true ) 818 { 819 if ($this->options['indentAttributes'] !== false) { 820 $multiline = true; 821 $indent = str_repeat($this->options['indent'], $this->_tagDepth); 822 823 if ($this->options['indentAttributes'] == '_auto') { 824 $indent .= str_repeat(' ', (strlen($tag['qname'])+2)); 825 826 } else { 827 $indent .= $this->options['indentAttributes']; 828 } 829 } else { 830 $multiline = false; 831 $indent = false; 832 } 833 834 if (is_array($tag['content'])) { 835 if (empty($tag['content'])) { 836 $tag['content'] = ''; 837 } 838 } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') { 839 $tag['content'] = ''; 840 } 841 842 if (is_scalar($tag['content']) || is_null($tag['content'])) { 843 if ($this->options['encoding'] == 'UTF-8' && 844 version_compare(phpversion(), '5.0.0', 'lt')) { 845 $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML; 846 } else { 847 $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML; 848 } 849 $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak'], $encoding); 850 } elseif (is_array($tag['content'])) { 851 $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']); 852 } elseif (is_object($tag['content'])) { 853 $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']); 854 } elseif (is_resource($tag['content'])) { 855 settype($tag['content'], 'string'); 856 $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities); 857 } 858 return $tag; 859 } 860 } 861 862 // well, it's one way to do things without extra deps ... 863 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 864 // +----------------------------------------------------------------------+ 865 // | PHP Version 4 | 866 // +----------------------------------------------------------------------+ 867 // | Copyright (c) 1997-2002 The PHP Group | 868 // +----------------------------------------------------------------------+ 869 // | This source file is subject to version 2.0 of the PHP license, | 870 // | that is bundled with this package in the file LICENSE, and is | 871 // | available at through the world-wide-web at | 872 // | http://www.php.net/license/2_02.txt. | 873 // | If you did not receive a copy of the PHP license and are unable to | 874 // | obtain it through the world-wide-web, please send a note to | 875 // | license@php.net so we can mail you a copy immediately. | 876 // +----------------------------------------------------------------------+ 877 // | Authors: Stephan Schmidt <schst@php-tools.net> | 878 // +----------------------------------------------------------------------+ 879 // 880 // $Id: v2.php,v 1.34 2006/03/02 20:50:59 cellog Exp $ 881 882 /** 883 * error code for invalid chars in XML name 884 */ 885 define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS", 51); 886 887 /** 888 * error code for invalid chars in XML name 889 */ 890 define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START", 52); 891 892 /** 893 * error code for non-scalar tag content 894 */ 895 define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT", 60); 896 897 /** 898 * error code for missing tag name 899 */ 900 define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME", 61); 901 902 /** 903 * replace XML entities 904 */ 905 define("PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES", 1); 906 907 /** 908 * embedd content in a CData Section 909 */ 910 define("PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION", 2); 911 912 /** 913 * do not replace entitites 914 */ 915 define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE", 0); 916 917 /** 918 * replace all XML entitites 919 * This setting will replace <, >, ", ' and & 920 */ 921 define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML", 1); 922 923 /** 924 * replace only required XML entitites 925 * This setting will replace <, " and & 926 */ 927 define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED", 2); 928 929 /** 930 * replace HTML entitites 931 * @link http://www.php.net/htmlentities 932 */ 933 define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML", 3); 934 935 /** 936 * replace all XML entitites, and encode from ISO-8859-1 to UTF-8 937 * This setting will replace <, >, ", ' and & 938 */ 939 define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML", 4); 940 941 /** 942 * utility class for working with XML documents 943 * 944 * customized version of XML_Util 0.6.0 945 * 946 * @category XML 947 * @package PEAR 948 * @version 0.6.0 949 * @author Stephan Schmidt <schst@php.net> 950 * @author Gregory Beaver <cellog@php.net> 951 */ 952 class PEAR_PackageFile_Generator_v2_XML_Util { 953 954 /** 955 * return API version 956 * 957 * @access public 958 * @static 959 * @return string $version API version 960 */ 961 function apiVersion() 962 { 963 return "0.6"; 964 } 965 966 /** 967 * replace XML entities 968 * 969 * With the optional second parameter, you may select, which 970 * entities should be replaced. 971 * 972 * <code> 973 * require_once 'XML/Util.php'; 974 * 975 * // replace XML entites: 976 * $string = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities("This string contains < & >."); 977 * </code> 978 * 979 * @access public 980 * @static 981 * @param string string where XML special chars should be replaced 982 * @param integer setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML) 983 * @return string string with replaced chars 984 */ 985 function replaceEntities($string, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) 986 { 987 switch ($replaceEntities) { 988 case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML: 989 return strtr(utf8_encode($string),array( 990 '&' => '&', 991 '>' => '>', 992 '<' => '<', 993 '"' => '"', 994 '\'' => ''' )); 995 break; 996 case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML: 997 return strtr($string,array( 998 '&' => '&', 999 '>' => '>', 1000 '<' => '<', 1001 '"' => '"', 1002 '\'' => ''' )); 1003 break; 1004 case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED: 1005 return strtr($string,array( 1006 '&' => '&', 1007 '<' => '<', 1008 '"' => '"' )); 1009 break; 1010 case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML: 1011 return htmlspecialchars($string); 1012 break; 1013 } 1014 return $string; 1015 } 1016 1017 /** 1018 * build an xml declaration 1019 * 1020 * <code> 1021 * require_once 'XML/Util.php'; 1022 * 1023 * // get an XML declaration: 1024 * $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration("1.0", "UTF-8", true); 1025 * </code> 1026 * 1027 * @access public 1028 * @static 1029 * @param string $version xml version 1030 * @param string $encoding character encoding 1031 * @param boolean $standAlone document is standalone (or not) 1032 * @return string $decl xml declaration 1033 * @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the XML declaration 1034 */ 1035 function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null) 1036 { 1037 $attributes = array( 1038 "version" => $version, 1039 ); 1040 // add encoding 1041 if ($encoding !== null) { 1042 $attributes["encoding"] = $encoding; 1043 } 1044 // add standalone, if specified 1045 if ($standalone !== null) { 1046 $attributes["standalone"] = $standalone ? "yes" : "no"; 1047 } 1048 1049 return sprintf("<?xml%s?>", PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, false)); 1050 } 1051 1052 /** 1053 * build a document type declaration 1054 * 1055 * <code> 1056 * require_once 'XML/Util.php'; 1057 * 1058 * // get a doctype declaration: 1059 * $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd"); 1060 * </code> 1061 * 1062 * @access public 1063 * @static 1064 * @param string $root name of the root tag 1065 * @param string $uri uri of the doctype definition (or array with uri and public id) 1066 * @param string $internalDtd internal dtd entries 1067 * @return string $decl doctype declaration 1068 * @since 0.2 1069 */ 1070 function getDocTypeDeclaration($root, $uri = null, $internalDtd = null) 1071 { 1072 if (is_array($uri)) { 1073 $ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] ); 1074 } elseif (!empty($uri)) { 1075 $ref = sprintf( ' SYSTEM "%s"', $uri ); 1076 } else { 1077 $ref = ""; 1078 } 1079 1080 if (empty($internalDtd)) { 1081 return sprintf("<!DOCTYPE %s%s>", $root, $ref); 1082 } else { 1083 return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd); 1084 } 1085 } 1086 1087 /** 1088 * create string representation of an attribute list 1089 * 1090 * <code> 1091 * require_once 'XML/Util.php'; 1092 * 1093 * // build an attribute string 1094 * $att = array( 1095 * "foo" => "bar", 1096 * "argh" => "tomato" 1097 * ); 1098 * 1099 * $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($att); 1100 * </code> 1101 * 1102 * @access public 1103 * @static 1104 * @param array $attributes attribute array 1105 * @param boolean|array $sort sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities' 1106 * @param boolean $multiline use linebreaks, if more than one attribute is given 1107 * @param string $indent string used for indentation of multiline attributes 1108 * @param string $linebreak string used for linebreaks of multiline attributes 1109 * @param integer $entities setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML) 1110 * @return string string representation of the attributes 1111 * @uses PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities() to replace XML entities in attribute values 1112 * @todo allow sort also to be an options array 1113 */ 1114 function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) 1115 { 1116 /** 1117 * second parameter may be an array 1118 */ 1119 if (is_array($sort)) { 1120 if (isset($sort['multiline'])) { 1121 $multiline = $sort['multiline']; 1122 } 1123 if (isset($sort['indent'])) { 1124 $indent = $sort['indent']; 1125 } 1126 if (isset($sort['linebreak'])) { 1127 $multiline = $sort['linebreak']; 1128 } 1129 if (isset($sort['entities'])) { 1130 $entities = $sort['entities']; 1131 } 1132 if (isset($sort['sort'])) { 1133 $sort = $sort['sort']; 1134 } else { 1135 $sort = true; 1136 } 1137 } 1138 $string = ''; 1139 if (is_array($attributes) && !empty($attributes)) { 1140 if ($sort) { 1141 ksort($attributes); 1142 } 1143 if( !$multiline || count($attributes) == 1) { 1144 foreach ($attributes as $key => $value) { 1145 if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) { 1146 $value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities); 1147 } 1148 $string .= ' '.$key.'="'.$value.'"'; 1149 } 1150 } else { 1151 $first = true; 1152 foreach ($attributes as $key => $value) { 1153 if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) { 1154 $value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities); 1155 } 1156 if ($first) { 1157 $string .= " ".$key.'="'.$value.'"'; 1158 $first = false; 1159 } else { 1160 $string .= $linebreak.$indent.$key.'="'.$value.'"'; 1161 } 1162 } 1163 } 1164 } 1165 return $string; 1166 } 1167 1168 /** 1169 * create a tag 1170 * 1171 * This method will call PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray(), which 1172 * is more flexible. 1173 * 1174 * <code> 1175 * require_once 'XML/Util.php'; 1176 * 1177 * // create an XML tag: 1178 * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#"); 1179 * </code> 1180 * 1181 * @access public 1182 * @static 1183 * @param string $qname qualified tagname (including namespace) 1184 * @param array $attributes array containg attributes 1185 * @param mixed $content 1186 * @param string $namespaceUri URI of the namespace 1187 * @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both 1188 * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line 1189 * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) 1190 * @param string $linebreak string used for linebreaks 1191 * @param string $encoding encoding that should be used to translate content 1192 * @return string $string XML tag 1193 * @see PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() 1194 * @uses PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() to create the tag 1195 */ 1196 function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) 1197 { 1198 $tag = array( 1199 "qname" => $qname, 1200 "attributes" => $attributes 1201 ); 1202 1203 // add tag content 1204 if ($content !== null) { 1205 $tag["content"] = $content; 1206 } 1207 1208 // add namespace Uri 1209 if ($namespaceUri !== null) { 1210 $tag["namespaceUri"] = $namespaceUri; 1211 } 1212 1213 return PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $encoding); 1214 } 1215 1216 /** 1217 * create a tag from an array 1218 * this method awaits an array in the following format 1219 * <pre> 1220 * array( 1221 * "qname" => $qname // qualified name of the tag 1222 * "namespace" => $namespace // namespace prefix (optional, if qname is specified or no namespace) 1223 * "localpart" => $localpart, // local part of the tagname (optional, if qname is specified) 1224 * "attributes" => array(), // array containing all attributes (optional) 1225 * "content" => $content, // tag content (optional) 1226 * "namespaceUri" => $namespaceUri // namespaceUri for the given namespace (optional) 1227 * ) 1228 * </pre> 1229 * 1230 * <code> 1231 * require_once 'XML/Util.php'; 1232 * 1233 * $tag = array( 1234 * "qname" => "foo:bar", 1235 * "namespaceUri" => "http://foo.com", 1236 * "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ), 1237 * "content" => "I'm inside the tag", 1238 * ); 1239 * // creating a tag with qualified name and namespaceUri 1240 * $string = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag); 1241 * </code> 1242 * 1243 * @access public 1244 * @static 1245 * @param array $tag tag definition 1246 * @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both 1247 * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line 1248 * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) 1249 * @param string $linebreak string used for linebreaks 1250 * @return string $string XML tag 1251 * @see PEAR_PackageFile_Generator_v2_XML_Util::createTag() 1252 * @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the tag 1253 * @uses PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName() to get local part and namespace of a qualified name 1254 */ 1255 function createTagFromArray($tag, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) 1256 { 1257 if (isset($tag["content"]) && !is_scalar($tag["content"])) { 1258 return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "Supplied non-scalar value as tag content", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT ); 1259 } 1260 1261 if (!isset($tag['qname']) && !isset($tag['localPart'])) { 1262 return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME ); 1263 } 1264 1265 // if no attributes hav been set, use empty attributes 1266 if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) { 1267 $tag["attributes"] = array(); 1268 } 1269 1270 // qualified name is not given 1271 if (!isset($tag["qname"])) { 1272 // check for namespace 1273 if (isset($tag["namespace"]) && !empty($tag["namespace"])) { 1274 $tag["qname"] = $tag["namespace"].":".$tag["localPart"]; 1275 } else { 1276 $tag["qname"] = $tag["localPart"]; 1277 } 1278 // namespace URI is set, but no namespace 1279 } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) { 1280 $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($tag["qname"]); 1281 $tag["localPart"] = $parts["localPart"]; 1282 if (isset($parts["namespace"])) { 1283 $tag["namespace"] = $parts["namespace"]; 1284 } 1285 } 1286 1287 if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) { 1288 // is a namespace given 1289 if (isset($tag["namespace"]) && !empty($tag["namespace"])) { 1290 $tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"]; 1291 } else { 1292 // define this Uri as the default namespace 1293 $tag["attributes"]["xmlns"] = $tag["namespaceUri"]; 1294 } 1295 } 1296 1297 // check for multiline attributes 1298 if ($multiline === true) { 1299 if ($indent === "_auto") { 1300 $indent = str_repeat(" ", (strlen($tag["qname"])+2)); 1301 } 1302 } 1303 1304 // create attribute list 1305 $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($tag["attributes"], true, $multiline, $indent, $linebreak ); 1306 if (!isset($tag["content"]) || (string)$tag["content"] == '') { 1307 $tag = sprintf("<%s%s />", $tag["qname"], $attList); 1308 } else { 1309 if ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES) { 1310 $tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($tag["content"], $encoding); 1311 } elseif ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION) { 1312 $tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection($tag["content"]); 1313 } 1314 $tag = sprintf("<%s%s>%s</%s>", $tag["qname"], $attList, $tag["content"], $tag["qname"] ); 1315 } 1316 return $tag; 1317 } 1318 1319 /** 1320 * create a start element 1321 * 1322 * <code> 1323 * require_once 'XML/Util.php'; 1324 * 1325 * // create an XML start element: 1326 * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#"); 1327 * </code> 1328 * 1329 * @access public 1330 * @static 1331 * @param string $qname qualified tagname (including namespace) 1332 * @param array $attributes array containg attributes 1333 * @param string $namespaceUri URI of the namespace 1334 * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line 1335 * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) 1336 * @param string $linebreak string used for linebreaks 1337 * @return string $string XML start element 1338 * @see PEAR_PackageFile_Generator_v2_XML_Util::createEndElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag() 1339 */ 1340 function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n") 1341 { 1342 // if no attributes hav been set, use empty attributes 1343 if (!isset($attributes) || !is_array($attributes)) { 1344 $attributes = array(); 1345 } 1346 1347 if ($namespaceUri != null) { 1348 $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($qname); 1349 } 1350 1351 // check for multiline attributes 1352 if ($multiline === true) { 1353 if ($indent === "_auto") { 1354 $indent = str_repeat(" ", (strlen($qname)+2)); 1355 } 1356 } 1357 1358 if ($namespaceUri != null) { 1359 // is a namespace given 1360 if (isset($parts["namespace"]) && !empty($parts["namespace"])) { 1361 $attributes["xmlns:".$parts["namespace"]] = $namespaceUri; 1362 } else { 1363 // define this Uri as the default namespace 1364 $attributes["xmlns"] = $namespaceUri; 1365 } 1366 } 1367 1368 // create attribute list 1369 $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak); 1370 $element = sprintf("<%s%s>", $qname, $attList); 1371 return $element; 1372 } 1373 1374 /** 1375 * create an end element 1376 * 1377 * <code> 1378 * require_once 'XML/Util.php'; 1379 * 1380 * // create an XML start element: 1381 * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createEndElement("myNs:myTag"); 1382 * </code> 1383 * 1384 * @access public 1385 * @static 1386 * @param string $qname qualified tagname (including namespace) 1387 * @return string $string XML end element 1388 * @see PEAR_PackageFile_Generator_v2_XML_Util::createStartElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag() 1389 */ 1390 function createEndElement($qname) 1391 { 1392 $element = sprintf("</%s>", $qname); 1393 return $element; 1394 } 1395 1396 /** 1397 * create an XML comment 1398 * 1399 * <code> 1400 * require_once 'XML/Util.php'; 1401 * 1402 * // create an XML start element: 1403 * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createComment("I am a comment"); 1404 * </code> 1405 * 1406 * @access public 1407 * @static 1408 * @param string $content content of the comment 1409 * @return string $comment XML comment 1410 */ 1411 function createComment($content) 1412 { 1413 $comment = sprintf("<!-- %s -->", $content); 1414 return $comment; 1415 } 1416 1417 /** 1418 * create a CData section 1419 * 1420 * <code> 1421 * require_once 'XML/Util.php'; 1422 * 1423 * // create a CData section 1424 * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection("I am content."); 1425 * </code> 1426 * 1427 * @access public 1428 * @static 1429 * @param string $data data of the CData section 1430 * @return string $string CData section with content 1431 */ 1432 function createCDataSection($data) 1433 { 1434 return sprintf("<![CDATA[%s]]>", $data); 1435 } 1436 1437 /** 1438 * split qualified name and return namespace and local part 1439 * 1440 * <code> 1441 * require_once 'XML/Util.php'; 1442 * 1443 * // split qualified tag 1444 * $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName("xslt:stylesheet"); 1445 * </code> 1446 * the returned array will contain two elements: 1447 * <pre> 1448 * array( 1449 * "namespace" => "xslt", 1450 * "localPart" => "stylesheet" 1451 * ); 1452 * </pre> 1453 * 1454 * @access public 1455 * @static 1456 * @param string $qname qualified tag name 1457 * @param string $defaultNs default namespace (optional) 1458 * @return array $parts array containing namespace and local part 1459 */ 1460 function splitQualifiedName($qname, $defaultNs = null) 1461 { 1462 if (strstr($qname, ':')) { 1463 $tmp = explode(":", $qname); 1464 return array( 1465 "namespace" => $tmp[0], 1466 "localPart" => $tmp[1] 1467 ); 1468 } 1469 return array( 1470 "namespace" => $defaultNs, 1471 "localPart" => $qname 1472 ); 1473 } 1474 1475 /** 1476 * check, whether string is valid XML name 1477 * 1478 * <p>XML names are used for tagname, attribute names and various 1479 * other, lesser known entities.</p> 1480 * <p>An XML name may only consist of alphanumeric characters, 1481 * dashes, undescores and periods, and has to start with a letter 1482 * or an underscore. 1483 * </p> 1484 * 1485 * <code> 1486 * require_once 'XML/Util.php'; 1487 * 1488 * // verify tag name 1489 * $result = PEAR_PackageFile_Generator_v2_XML_Util::isValidName("invalidTag?"); 1490 * if (PEAR_PackageFile_Generator_v2_XML_Util::isError($result)) { 1491 * print "Invalid XML name: " . $result->getMessage(); 1492 * } 1493 * </code> 1494 * 1495 * @access public 1496 * @static 1497 * @param string $string string that should be checked 1498 * @return mixed $valid true, if string is a valid XML name, PEAR error otherwise 1499 * @todo support for other charsets 1500 */ 1501 function isValidName($string) 1502 { 1503 // check for invalid chars 1504 if (!preg_match("/^[[:alnum:]_\-.]$/", $string{0})) { 1505 return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only start with letter or underscore", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START ); 1506 } 1507 1508 // check for invalid chars 1509 if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $string)) { 1510 return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS ); 1511 } 1512 // XML name is valid 1513 return true; 1514 } 1515 1516 /** 1517 * replacement for PEAR_PackageFile_Generator_v2_XML_Util::raiseError 1518 * 1519 * Avoids the necessity to always require 1520 * PEAR.php 1521 * 1522 * @access public 1523 * @param string error message 1524 * @param integer error code 1525 * @return object PEAR_Error 1526 */ 1527 function raiseError($msg, $code) 1528 { 1529 require_once 'PEAR.php'; 1530 return PEAR::raiseError($msg, $code); 1531 } 1532 } 1533 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 12:27:40 2007 | par Balluche grâce à PHPXref 0.7 |
|