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