00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 App::import('Core', 'Set');
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 class XmlNode extends Object {
00042
00043
00044
00045
00046
00047
00048 var $name = null;
00049
00050
00051
00052
00053
00054
00055 var $namespace = null;
00056
00057
00058
00059
00060
00061
00062 var $namespaces = array();
00063
00064
00065
00066
00067
00068
00069 var $value;
00070
00071
00072
00073
00074
00075
00076 var $attributes = array();
00077
00078
00079
00080
00081
00082
00083 var $children = array();
00084
00085
00086
00087
00088
00089
00090 var $__parent = null;
00091
00092
00093
00094
00095
00096
00097
00098
00099 function __construct($name = null, $value = null, $namespace = null) {
00100 if (strpos($name, ':') !== false) {
00101 list($prefix, $name) = explode(':', $name);
00102 if (!$namespace) {
00103 $namespace = $prefix;
00104 }
00105 }
00106 $this->name = $name;
00107 if ($namespace) {
00108 $this->namespace = $namespace;
00109 }
00110
00111 if (is_array($value) || is_object($value)) {
00112 $this->normalize($value);
00113 } elseif(!empty($value) || $value === 0 || $value === '0') {
00114 $this->createTextNode($value);
00115 }
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125 function addNamespace($prefix, $url) {
00126 if ($ns = Xml::addGlobalNs($prefix, $url)) {
00127 $this->namespaces = array_merge($this->namespaces, $ns);
00128 return true;
00129 }
00130 return false;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 function &createNode($name = null, $value = null, $namespace = false) {
00142 $node =& new XmlNode($name, $value, $namespace);
00143 $node->setParent($this);
00144 return $node;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 function &createElement($name = null, $value = null, $attributes = array(), $namespace = false) {
00156 $element =& new XmlElement($name, $value, $attributes, $namespace);
00157 $element->setParent($this);
00158 return $element;
00159 }
00160
00161
00162
00163
00164
00165
00166 function &createTextNode($value = null) {
00167 $node = new XmlTextNode($value);
00168 $node->setParent($this);
00169 return $node;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 function normalize($object, $keyName = null, $options = array()) {
00179 if (is_a($object, 'XmlNode')) {
00180 return $object;
00181 }
00182 $name = null;
00183 $options = array_merge(array('format' => 'attributes'), $options);
00184
00185 if ($keyName !== null && !is_numeric($keyName)) {
00186 $name = $keyName;
00187 } elseif (isset($object->_name_) && !empty($object->_name_)) {
00188 $name = $object->_name_;
00189 } elseif (isset($object->name) && $object->name != null) {
00190 $name = $object->name;
00191 } elseif ($options['format'] == 'attributes') {
00192 $name = get_class($object);
00193 }
00194
00195 $tagOpts = $this->__tagOptions($name);
00196 if ($tagOpts === false) {
00197 return;
00198 }
00199
00200 if (isset($tagOpts['name'])) {
00201 $name = $tagOpts['name'];
00202 } elseif ($name != strtolower($name)) {
00203 $name = Inflector::slug(Inflector::underscore($name));
00204 }
00205
00206 if (!empty($name)) {
00207 $node =& $this->createElement($name);
00208 } else {
00209 $node =& $this;
00210 }
00211
00212 $namespace = array();
00213 $attributes = array();
00214 $children = array();
00215 $chldObjs = array();
00216 $document =& $this->document();
00217
00218 if (is_object($object)) {
00219 $chldObjs = get_object_vars($object);
00220 } elseif (is_array($object)) {
00221 $chldObjs = $object;
00222 } elseif (!empty($object) || $object === 0) {
00223 $node->createTextNode($object);
00224 }
00225 $attr = array();
00226
00227 if (isset($tagOpts['attributes'])) {
00228 $attr = $tagOpts['attributes'];
00229 }
00230 if (isset($tagOpts['value']) && isset($chldObjs[$tagOpts['value']])) {
00231 $node->createTextNode($chldObjs[$tagOpts['value']]);
00232 unset($chldObjs[$tagOpts['value']]);
00233 }
00234 unset($chldObjs['_name_']);
00235 $c = 0;
00236
00237 foreach ($chldObjs as $key => $val) {
00238 if (in_array($key, $attr) && !is_object($val) && !is_array($val)) {
00239 $attributes[$key] = $val;
00240 } else {
00241 if (!isset($tagOpts['children']) || $tagOpts['children'] === array() || (is_array($tagOpts['children']) && in_array($key, $tagOpts['children']))) {
00242 $n = $key;
00243
00244 if (is_numeric($n)) {
00245 $n = $name;
00246 }
00247 if (is_array($val)) {
00248 foreach ($val as $i => $obj2) {
00249 $n2 = $i;
00250 if (is_numeric($n2)) {
00251 $n2 = $n;
00252 }
00253 $node->normalize($obj2, $n2, $options);
00254 }
00255 } else {
00256 if (is_object($val)) {
00257 $node->normalize($val, $n, $options);
00258 } elseif ($options['format'] == 'tags' && $this->__tagOptions($key) !== false) {
00259 $tmp =& $node->createElement($key);
00260 if (!empty($val) || $val === 0) {
00261 $tmp->createTextNode($val);
00262 }
00263 } elseif ($options['format'] == 'attributes') {
00264 $node->addAttribute($key, $val);
00265 }
00266 }
00267 }
00268 }
00269 $c++;
00270 }
00271 if (!empty($name)) {
00272 return $node;
00273 }
00274 return $children;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284 function __tagOptions($name, $option = null) {
00285 if (isset($this->__tags[$name])) {
00286 $tagOpts = $this->__tags[$name];
00287 } elseif (isset($this->__tags[strtolower($name)])) {
00288 $tagOpts = $this->__tags[strtolower($name)];
00289 } else {
00290 return null;
00291 }
00292 if ($tagOpts === false) {
00293 return false;
00294 }
00295 if (empty($option)) {
00296 return $tagOpts;
00297 }
00298 if (isset($tagOpts[$option])) {
00299 return $tagOpts[$option];
00300 }
00301 return null;
00302 }
00303
00304
00305
00306
00307
00308 function name() {
00309 if (!empty($this->namespace)) {
00310 $_this =& XmlManager::getInstance();
00311 if (!isset($_this->options['verifyNs']) || !$_this->options['verifyNs'] || in_array($this->namespace, array_keys($_this->namespaces))) {
00312 return $this->namespace . ':' . $this->name;
00313 }
00314 }
00315 return $this->name;
00316 }
00317
00318
00319
00320
00321
00322 function setParent(&$parent) {
00323 if (strtolower(get_class($this)) == 'xml') {
00324 return;
00325 }
00326 if (isset($this->__parent) && is_object($this->__parent)) {
00327 if ($this->__parent->compare($parent)) {
00328 return;
00329 }
00330 foreach ($this->__parent->children as $i => $child) {
00331 if ($this->compare($child)) {
00332 array_splice($this->__parent->children, $i, 1);
00333 break;
00334 }
00335 }
00336 }
00337 if ($parent == null) {
00338 unset($this->__parent);
00339 } else {
00340 $parent->children[] =& $this;
00341 $this->__parent =& $parent;
00342 }
00343 }
00344
00345
00346
00347
00348
00349
00350 function cloneNode() {
00351 return clone($this);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 function compare($node) {
00361 $keys = array(get_object_vars($this), get_object_vars($node));
00362 return ($keys[0] === $keys[1]);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 function &append(&$child, $options = array()) {
00373 if (empty($child)) {
00374 $return = false;
00375 return $return;
00376 }
00377
00378 if (is_array($child) || is_object($child)) {
00379 if (is_object($child) && is_a($child, 'XmlNode') && $this->compare($child)) {
00380 trigger_error('Cannot append a node to itself.');
00381 $return = false;
00382 return $return;
00383 }
00384 if (is_array($child)) {
00385 $child = Set::map($child);
00386 }
00387 if (is_array($child)) {
00388 if (!is_a(current($child), 'XmlNode')) {
00389 foreach ($child as $i => $childNode) {
00390 $child[$i] = $this->normalize($childNode, null, $options);
00391 }
00392 } else {
00393 foreach ($child as $childNode) {
00394 $this->append($childNode, $options);
00395 }
00396 }
00397 return $child;
00398 }
00399 if (!is_a($child, 'XmlNode')) {
00400 $child = $this->normalize($child, null, $options);
00401 }
00402
00403 if (empty($child->namespace) && !empty($this->namespace)) {
00404 $child->namespace = $this->namespace;
00405 }
00406 } elseif (is_string($child)) {
00407 $attr = array();
00408 if (func_num_args() >= 2 && is_array(func_get_arg(1))) {
00409 $attributes = func_get_arg(1);
00410 }
00411 $document = $this->document();
00412 $child =& $document->createElement($child, null, $attributes);
00413 }
00414 return $child;
00415 }
00416
00417
00418
00419
00420
00421
00422 function &first() {
00423 if (isset($this->children[0])) {
00424 return $this->children[0];
00425 } else {
00426 return null;
00427 }
00428 }
00429
00430
00431
00432
00433
00434
00435 function &last() {
00436 if (count($this->children) > 0) {
00437 return $this->children[count($this->children) - 1];
00438 } else {
00439 return null;
00440 }
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 function &child($id) {
00450 $null = null;
00451
00452 if (is_int($id)) {
00453 if (isset($this->children[$id])) {
00454 return $this->children[$id];
00455 } else {
00456 return null;
00457 }
00458 } elseif (is_string($id)) {
00459 for ($i = 0; $i < count($this->children); $i++) {
00460 if ($this->children[$i]->name == $id) {
00461 return $this->children[$i];
00462 }
00463 }
00464 }
00465 return $null;
00466 }
00467
00468
00469
00470
00471
00472
00473
00474 function children($name) {
00475 $nodes = array();
00476 $count = count($this->children);
00477 for ($i = 0; $i < $count; $i++) {
00478 if ($this->children[$i]->name == $name) {
00479 $nodes[] =& $this->children[$i];
00480 }
00481 }
00482 return $nodes;
00483 }
00484
00485
00486
00487
00488
00489
00490 function &nextSibling() {
00491 $count = count($this->__parent->children);
00492 for ($i = 0; $i < $count; $i++) {
00493 if ($this->__parent->children == $this) {
00494 if ($i >= $count - 1 || !isset($this->__parent->children[$i + 1])) {
00495 return null;
00496 }
00497 return $this->__parent->children[$i + 1];
00498 }
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507 function &previousSibling() {
00508 $count = count($this->__parent->children);
00509 for ($i = 0; $i < $count; $i++) {
00510 if ($this->__parent->children == $this) {
00511 if ($i == 0 || !isset($this->__parent->children[$i - 1])) {
00512 return null;
00513 }
00514 return $this->__parent->children[$i - 1];
00515 }
00516 }
00517 }
00518
00519
00520
00521
00522
00523
00524 function &parent() {
00525 return $this->__parent;
00526 }
00527
00528
00529
00530
00531
00532
00533 function &document() {
00534 $document =& $this;
00535 while (true) {
00536 if (get_class($document) == 'Xml' || $document == null) {
00537 break;
00538 }
00539 $document =& $document->parent();
00540 }
00541 return $document;
00542 }
00543
00544
00545
00546
00547
00548
00549 function hasChildren() {
00550 if (is_array($this->children) && count($this->children) > 0) {
00551 return true;
00552 }
00553 return false;
00554 }
00555
00556
00557
00558
00559
00560
00561 function toString($options = array(), $depth = 0) {
00562 if (is_int($options)) {
00563 $depth = $options;
00564 $options = array();
00565 }
00566 $defaults = array('cdata' => true, 'whitespace' => false, 'convertEntities' => false, 'showEmpty' => true, 'leaveOpen' => false);
00567 $options = array_merge($defaults, Xml::options(), $options);
00568 $tag = !(strpos($this->name, '#') === 0);
00569 $d = '';
00570
00571 if ($tag) {
00572 if ($options['whitespace']) {
00573 $d .= str_repeat("\t", $depth);
00574 }
00575
00576 $d .= '<' . $this->name();
00577 if (count($this->namespaces) > 0) {
00578 foreach ($this->namespaces as $key => $val) {
00579 $val = str_replace('"', '\"', $val);
00580 $d .= ' xmlns:' . $key . '="' . $val . '"';
00581 }
00582 }
00583
00584 $parent =& $this->parent();
00585 if ($parent->name === '#document' && count($parent->namespaces) > 0) {
00586 foreach ($parent->namespaces as $key => $val) {
00587 $val = str_replace('"', '\"', $val);
00588 $d .= ' xmlns:' . $key . '="' . $val . '"';
00589 }
00590 }
00591
00592 if (is_array($this->attributes) && count($this->attributes) > 0) {
00593 foreach ($this->attributes as $key => $val) {
00594 $val = str_replace('"', '\"', $val);
00595 $d .= ' ' . $key . '="' . h($val) . '"';
00596 }
00597 }
00598 }
00599
00600 if (!$this->hasChildren() && empty($this->value) && $this->value !== 0 && $tag) {
00601 if (!$options['leaveOpen']) {
00602 $d .= ' />';
00603 }
00604 if ($options['whitespace']) {
00605 $d .= "\n";
00606 }
00607 } elseif ($tag || $this->hasChildren()) {
00608 if ($tag) {
00609 $d .= '>';
00610 }
00611 if ($this->hasChildren()) {
00612 if ($options['whitespace']) {
00613 $d .= "\n";
00614 }
00615
00616 $count = count($this->children);
00617 $cDepth = $depth + 1;
00618 for ($i = 0; $i < $count; $i++) {
00619 $d .= $this->children[$i]->toString($options, $cDepth);
00620 }
00621 if ($tag) {
00622 if ($options['whitespace'] && $tag) {
00623 $d .= str_repeat("\t", $depth);
00624 }
00625 if (!$options['leaveOpen']) {
00626 $d .= '</' . $this->name() . '>';
00627 }
00628 if ($options['whitespace']) {
00629 $d .= "\n";
00630 }
00631 }
00632 }
00633 }
00634
00635 return $d;
00636 }
00637
00638
00639
00640
00641
00642
00643 function __toString() {
00644 return $this->toString();
00645 }
00646
00647
00648
00649
00650
00651
00652
00653 function __killParent($recursive = true) {
00654 unset($this->__parent, $this->_log);
00655 if ($recursive && $this->hasChildren()) {
00656 for ($i = 0; $i < count($this->children); $i++) {
00657 $this->children[$i]->__killParent(true);
00658 }
00659 }
00660 }
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 class Xml extends XmlNode {
00673
00674
00675
00676
00677
00678
00679
00680 var $__parser;
00681
00682
00683
00684
00685
00686
00687 var $__file;
00688
00689
00690
00691
00692
00693
00694 var $__rawData = null;
00695
00696
00697
00698
00699
00700
00701
00702 var $__header = null;
00703
00704
00705
00706
00707
00708
00709
00710
00711 var $__tags = array();
00712
00713
00714
00715
00716
00717
00718
00719 var $version = '1.0';
00720
00721
00722
00723
00724
00725
00726
00727 var $encoding = 'UTF-8';
00728
00729
00730
00731
00732
00733
00734
00735
00736 function __construct($input = null, $options = array()) {
00737 $defaults = array('root' => '#document', 'tags' => array(), 'namespaces' => array(), 'version' => '1.0', 'encoding' => 'UTF-8', 'format' => 'attributes');
00738 $options = array_merge($defaults, Xml::options(), $options);
00739
00740 foreach (array('version', 'encoding', 'namespaces') as $key) {
00741 $this->{$key} = $options[$key];
00742 }
00743 $this->__tags = $options['tags'];
00744 parent::__construct($options['root']);
00745
00746 if (!empty($input)) {
00747 if (is_string($input)) {
00748 $this->load($input);
00749 } elseif (is_array($input) || is_object($input)) {
00750 $this->append($input, $options);
00751 }
00752 }
00753
00754
00755
00756
00757 }
00758
00759
00760
00761
00762
00763
00764
00765 function load($input) {
00766 if (!is_string($input)) {
00767 return false;
00768 }
00769 $this->__rawData = null;
00770 $this->__header = null;
00771
00772 if (strstr($input, "<")) {
00773 $this->__rawData = $input;
00774 } elseif (strpos($input, 'http:
00775 App::import('Core', 'HttpSocket');
00776 $socket = new HttpSocket();
00777 $this->__rawData = $socket->get($input);
00778 } elseif (file_exists($input)) {
00779 $this->__rawData = file_get_contents($input);
00780 } else {
00781 trigger_error('XML cannot be read');
00782 return false;
00783 }
00784 return $this->parse();
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794 function parse() {
00795 $this->__initParser();
00796 $this->__header = trim(str_replace(a('<' . '?', '?' . '>'), a('', ''), substr(trim($this->__rawData), 0, strpos($this->__rawData, "\n"))));
00797
00798 xml_parse_into_struct($this->__parser, $this->__rawData, $vals);
00799 $xml =& $this;
00800 $count = count($vals);
00801
00802 for ($i = 0; $i < $count; $i++) {
00803 $data = $vals[$i];
00804 $data = array_merge(array('tag' => null, 'value' => null, 'attributes' => array()), $data);
00805 switch($data['type']) {
00806 case "open" :
00807 $xml =& $xml->createElement($data['tag'], $data['value'], $data['attributes']);
00808 break;
00809 case "close" :
00810 $xml =& $xml->parent();
00811 break;
00812 case "complete" :
00813 $xml->createElement($data['tag'], $data['value'], $data['attributes']);
00814 break;
00815 case 'cdata':
00816 $xml->createTextNode($data['value']);
00817 break;
00818 }
00819 }
00820 return true;
00821 }
00822
00823
00824
00825
00826
00827
00828 function __initParser() {
00829 if (empty($this->__parser)) {
00830 $this->__parser = xml_parser_create();
00831 xml_set_object($this->__parser, $this);
00832 xml_parser_set_option($this->__parser, XML_OPTION_CASE_FOLDING, 0);
00833 xml_parser_set_option($this->__parser, XML_OPTION_SKIP_WHITE, 1);
00834 }
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 function compose($options = array()) {
00847 return $this->toString($options);
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857 function error($msg, $code = 0, $line = 0) {
00858 if (Configure::read('debug')) {
00859 echo $msg . " " . $code . " " . $line;
00860 }
00861 }
00862
00863
00864
00865
00866
00867
00868
00869 function getError($code) {
00870 $r = @xml_error_string($code);
00871 return $r;
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 function &next() {
00883 $return = null;
00884 return $return;
00885 }
00886
00887
00888
00889
00890
00891
00892 function &previous() {
00893 $return = null;
00894 return $return;
00895 }
00896
00897
00898
00899
00900
00901
00902 function &parent() {
00903 $return = null;
00904 return $return;
00905 }
00906
00907
00908
00909
00910
00911
00912
00913 function addNamespace($prefix, $url) {
00914 if ($count = count($this->children)) {
00915 for ($i = 0; $i < $count; $i++) {
00916 $this->children[$i]->addNamespace($prefix, $url);
00917 }
00918 return true;
00919 }
00920 return parent::addNamespace($prefix, $url);
00921 }
00922
00923
00924
00925
00926
00927
00928 function toString($options = array()) {
00929 if (is_bool($options)) {
00930 $options = array('header' => $options);
00931 }
00932
00933 $defaults = array('header' => false, 'encoding' => $this->encoding);
00934 $options = array_merge($defaults, Xml::options(), $options);
00935 $data = parent::toString($options, 0);
00936
00937 if ($options['header']) {
00938 if (!empty($this->__header)) {
00939 return $this->header($this->__header) . "\n" . $data;
00940 }
00941 return $this->header() . "\n" . $data;
00942 }
00943
00944 return $data;
00945 }
00946
00947
00948
00949
00950
00951
00952 function header($attrib = array()) {
00953 $header = 'xml';
00954 if (is_string($attrib)) {
00955 $header = $attrib;
00956 } else {
00957
00958 $attrib = array_merge(array('version' => $this->version, 'encoding' => $this->encoding), $attrib);
00959 foreach ($attrib as $key=>$val) {
00960 $header .= ' ' . $key . '="' . $val . '"';
00961 }
00962 }
00963 return '<' . '?' . $header . ' ?' . '>';
00964 }
00965
00966
00967
00968
00969
00970
00971 function __destruct() {
00972 if (is_resource($this->__parser)) {
00973 xml_parser_free($this->__parser);
00974 }
00975 }
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 function addGlobalNs($name, $url = null) {
00987 $_this =& XmlManager::getInstance();
00988 if ($ns = Xml::resolveNamespace($name, $url)) {
00989 $_this->namespaces = array_merge($_this->namespaces, $ns);
00990 return $ns;
00991 }
00992 return false;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001 function resolveNamespace($name, $url) {
01002 $_this =& XmlManager::getInstance();
01003 if ($url == null && in_array($name, array_keys($_this->defaultNamespaceMap))) {
01004 $url = $_this->defaultNamespaceMap[$name];
01005 } elseif ($url == null) {
01006 return false;
01007 }
01008
01009 if (!strpos($url, ':
01010 $_url = $_this->defaultNamespaceMap[$name];
01011 $name = $url;
01012 $url = $_url;
01013 }
01014 return array($name => $url);
01015 }
01016
01017
01018
01019
01020
01021
01022 function addGlobalNamespace($name, $url = null) {
01023 return Xml::addGlobalNs($name, $url);
01024 }
01025
01026
01027
01028
01029
01030
01031
01032 function removeGlobalNs($name) {
01033 $_this =& XmlManager::getInstance();
01034 if (in_array($name, array_keys($_this->namespaces))) {
01035 unset($_this->namespaces[$name]);
01036 unset($this->namespaces[$name]);
01037 } elseif (in_array($name, $_this->namespaces)) {
01038 $keys = array_keys($_this->namespaces);
01039 $count = count($keys);
01040 for ($i = 0; $i < $count; $i++) {
01041 if ($_this->namespaces[$keys[$i]] == $name) {
01042 unset($_this->namespaces[$keys[$i]]);
01043 unset($this->namespaces[$keys[$i]]);
01044 return;
01045 }
01046 }
01047 }
01048 }
01049
01050
01051
01052
01053
01054
01055 function removeGlobalNamespace($name, $url = null) {
01056 Xml::removeGlobalNs($name, $url);
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066 function options($options = array()) {
01067 $_this =& XmlManager::getInstance();
01068 $_this->options = array_merge($_this->options, $options);
01069 return $_this->options;
01070 }
01071 }
01072
01073
01074
01075
01076 class XmlElement extends XmlNode {
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 function __construct($name = null, $value = null, $attributes = array(), $namespace = false) {
01087 parent::__construct($name, $value, $namespace);
01088 $this->addAttribute($attributes);
01089 }
01090
01091
01092
01093
01094
01095 function attributes() {
01096 return $this->attributes;
01097 }
01098
01099
01100
01101
01102
01103
01104
01105 function addAttribute($name, $val = null) {
01106 if (is_object($name)) {
01107 $name = get_object_vars($name);
01108 }
01109 if (is_array($name)) {
01110 foreach ($name as $key => $val) {
01111 $this->addAttribute($key, $val);
01112 }
01113 return true;
01114 }
01115 if (is_numeric($name)) {
01116 $name = $val;
01117 $val = null;
01118 }
01119 if (!empty($name)) {
01120 if (strpos($name, 'xmlns') === 0) {
01121 if ($name == 'xmlns') {
01122 $this->namespace = $val;
01123 } else {
01124 list($pre, $prefix) = explode(':', $name);
01125 $this->addNamespace($prefix, $val);
01126 return true;
01127 }
01128 }
01129 $this->attributes[$name] = $val;
01130 return true;
01131 }
01132 return false;
01133 }
01134
01135
01136
01137
01138
01139
01140 function removeAttribute($attr) {
01141 if ($this->attributes[$attr]) {
01142 unset($this->attributes[$attr]);
01143 return true;
01144 }
01145 return false;
01146 }
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 class XmlTextNode extends XmlNode {
01159
01160
01161
01162
01163
01164 var $name = '#text';
01165
01166
01167
01168
01169
01170 var $value = null;
01171
01172
01173
01174
01175
01176
01177 function __construct($value = null) {
01178 if (is_numeric($value)) {
01179 $value = floatval($value);
01180 }
01181 $this->value = $value;
01182 }
01183
01184
01185
01186
01187
01188 function hasChildren() {
01189 return false;
01190 }
01191
01192
01193
01194
01195
01196
01197 function append() {
01198 return false;
01199 }
01200
01201
01202
01203
01204
01205
01206 function toString($options = array(), $depth = 0) {
01207 if (is_int($options)) {
01208 $depth = $options;
01209 $options = array();
01210 }
01211
01212 $defaults = array('cdata' => true, 'whitespace' => false, 'convertEntities' => false);
01213 $options = array_merge($defaults, Xml::options(), $options);
01214 $val = $this->value;
01215
01216 if ($options['convertEntities'] && function_exists('mb_convert_encoding')) {
01217 $val = mb_convert_encoding($val,'UTF-8', 'HTML-ENTITIES');
01218 }
01219
01220 if ($options['cdata'] === true && is_string($val)) {
01221 $val = '<![CDATA[' . $val . ']]>';
01222 }
01223
01224 if ($options['whitespace']) {
01225 return str_repeat("\t", $depth) . $val . "\n";
01226 }
01227 return $val;
01228 }
01229 }
01230
01231
01232
01233
01234
01235
01236 class XmlManager {
01237
01238
01239
01240
01241
01242
01243
01244 var $namespaces = array();
01245
01246
01247
01248
01249
01250
01251 var $options = array();
01252
01253
01254
01255
01256
01257
01258 var $defaultNamespaceMap = array(
01259 'dc' => 'http:
01260 'dct' => 'http:
01261 'g' => 'http:
01262 'rc' => 'http:
01263 'wf' => 'http:
01264 'fb' => 'http:
01265 'lj' => 'http:
01266 'itunes' => 'http:
01267 'xhtml' => 'http:
01268 'atom' => 'http:
01269 );
01270
01271
01272
01273
01274
01275
01276 function &getInstance() {
01277 static $instance = array();
01278
01279 if (!isset($instance[0]) || !$instance[0]) {
01280 $instance[0] =& new XmlManager();
01281 }
01282 return $instance[0];
01283 }
01284 }
01285 ?>