Version: current

      1 <?php
      2 /**
      3  * Base class for XML parsers
      4  * @package sapphire
      5  * @subpackage misc
      6  */
      7 class XML extends Object {
      8     protected $parser;
      9     protected $context, $attributeStore;
     10     protected $parsed;
     11     protected $collatedText;
     12
     13
     14     function tidyXHTML($content) {
     15         $cleanFile = TEMP_FOLDER . "/cleaner.tmp";
     16         $fh = fopen($cleanFile,"wb");
     17         fwrite($fh, $content);
     18         fclose($fh);
     19
     20         if(file_exists($cleanFile)) {
     21             $result = `tidy -asxhtml $cleanFile`;
     22             unlink($cleanFile);
     23             return $result;
     24         }
     25     }
     26
     27     function parse($content, $recursive = false) {
     28         $this->parser = xml_parser_create('UTF-8');
     29
     30         // Andrew keeps giving me the wrong FSKING encoding! :-P
     31         $content = ereg_replace('encoding="[^"]+"','encoding="utf-8"', $content);
     32
     33         xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
     34         //xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
     35         xml_set_object($this->parser, $this);
     36         xml_set_element_handler($this->parser, "tag_open", "tag_close");
     37         xml_set_character_data_handler($this->parser, "cdata");
     38
     39         $this->parsed = null;
     40         $this->context = array();
     41         $this->attributeStore = array();
     42
     43         xml_parse($this->parser, $content);
     44
     45         // Handle a bad encoding type by forcing ISO-8859-15
     46         if(xml_get_error_code($this->parser) == 32 && !$recursive) {
     47             $content = ereg_replace('encoding="[^"]+"','encoding="utf-8"', $content);
     48             return $this->parse($content, true);
     49         }
     50
     51         if($err = xml_get_error_code($this->parser)) {
     52             user_error("XML parser broke with error $err:" . xml_error_string($err), E_USER_ERROR);
     53         }
     54
     55         return $this->parsed;
     56     }
     57
     58     function inContext() {
     59         $items = func_get_args();
     60         $i=0;
     61         foreach($items as $item) {
     62             while($i < sizeof($this->context)) {
     63                 if($this->context[$i] == $item) break;
     64                 $i++;
     65             }
     66             if($this->context[$i] != $item) return false;
     67         }
     68         return true;
     69     }
     70
     71     function stackActionFor($tag) {
     72         for($i=sizeof($this->contextStack)-1;$i>=0;$i--) {
     73             if($this->context[$i]['tag'] == $tag) return $this->contextStack[$i]['action'];
     74         }
     75     }
     76
     77     function tag_open($parser, $tag, $attributes) {
     78         // Strip namespaces out of tags and attributes
     79         $tag = ereg_replace('[^:]+:','',$tag);
     80         if($attributes) foreach($attributes as $k => $v) $newAttributes[ereg_replace('[^:]+:','',$k)] = $v;
     81         $attributes = isset($newAttributes) ? $newAttributes : $attributes;
     82
     83
     84         if(isset($attributes['class'])) {
     85             $this->context[] = "$tag.{$attributes['class']}";
     86         } else {
     87             $this->context[] = $tag;
     88         }
     89         $this->attributeStore[] = $attributes;
     90
     91         $this->collatedText = "";
     92
     93         $tagProcessorFunc = "process_$tag";
     94         if($this->hasMethod($tagProcessorFunc)) {
     95             $this->$tagProcessorFunc($attributes);
     96         }elseif($this->hasMethod($tagProcessorFunc = "process_tag")){
     97             $this->$tagProcessorFunc($tag, $attributes);
     98         }
     99
    100
    101         if($attributes) foreach($attributes as $k => $v) {
    102             $attProcessorFunc = "processatt_$k";
    103             if($this->hasMethod($attProcessorFunc)) {
    104                 $this->$attProcessorFunc($tag, $attributes);
    105             }
    106         }
    107     }
    108
    109     function tag_close($parser, $tag) {
    110         $tag = ereg_replace('[^:]+:','',$tag);
    111
    112         array_pop($this->context);
    113         $attributes = array_pop($this->attributeStore);
    114
    115         if(method_exists($this, $funcName = "process_{$tag}_end")) {
    116             $this->$funcName($this->collatedText, $attributes);
    117         }elseif(method_exists($this,$funcName = "process_tag_end")){
    118             // else run default method
    119                 $this->$funcName($tag,$this->collatedText, $attributes);
    120         }
    121
    122         $this->collatedText = "";
    123     }
    124
    125     function cdata($parser, $cdata) {
    126         $this->collatedText .= $cdata;
    127     }
    128 }

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -