[TYPO3] Problem after Typo3 upgrade :-(

Dmitry Martynenko dima at realt.by
Thu Mar 27 12:03:23 CET 2008


Hi Nino,

NK> After upgrade from ver. 3.8.1 to 4.1.6 i get following php warning when
NK> displaying page:

NK> Warning: xml_parser_set_option() [function.xml-parser-set-option]: 
NK> Unsupported target encoding "iso-8859-2" in 
NK> /www/htdocs/typo3_src-4.1.6/t3lib/class.t3lib_div.php on line 2174

NK> I searched for a solution but only one i found was to change encoding to
NK> UTF8. I can't make this because all sites under my Typo3 are made with
NK> iso-8859-2 encoding. Is there a way to solve this? Thx.

We also had this problem when using TYPO3 4.1.xx with Windows-1251 encoding.
It was solved with this patch to class.t3lib_div.php
Replace (or smartly merge) function xml2array() with the following code.
It does conversion of source XML to required UTF-8 encoding before xml parser.

----------------------------------------------------------------------------------
        function xml2array($string,$NSprefix='',$reportDocTag=FALSE) {
                global $TYPO3_CONF_VARS;

                        // Create parser:
                $parser = xml_parser_create();
                $vals = array();
                $index = array();
                $is_encoded = false;

                xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
                xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);

                        //  PHP4 doesn't like Unicode byte order marks (BOM), so we have to check for them
                        // The BOM check comes first, so that the PHP5 preg_match() below doesn't have to check for it
                if(substr($string,0,3)=="\xEF\xBB\xBF") {
                        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'utf-8');
                }
                        // PHP 4.x: output charset is the same as the input charset, charsets are handled transparently if not specified in xml_parser_create()
                        // PHP 5.0.0 & 5.0.1: default output charset is ISO-8859-1, only ASCII, ISO-8859-1 and UTF-8 are supported!!!
                        // PHP 5.0.2+: default output charset is UTF-8  , only ASCII, ISO-8859-1 and UTF-8 are supported!!!
                elseif ((double)phpversion()>=5)        {
                        $match = array();
                        preg_match('/^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/',substr($string,0,200),$match);
                        $theCharset = $match[1] ? $match[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
                        
                        $encoding = strtoupper($theCharset);
                        if($encoding != "UTF-8" && $encoding != "US-ASCII" && $encoding != "ISO-8859-1") {
#                               debug($encoding, 'ENCODING');
                                $string = @mb_convert_encoding($string, "UTF-8", $encoding);
                                $rx = '/<\?xml.*\?>/m';
                                $string = preg_replace($rx, '', $string);
#                               debug($string, 'ENCODED STRING');
                                $theCharset = "utf-8";
                                $is_encoded = true;
                        } 
                        
                        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1

                        
                }

                        // Parse content:
                xml_parse_into_struct($parser, $string, $vals, $index);

                        // If error, return error message:
                if (xml_get_error_code($parser))        {
                        return 'Line '.xml_get_current_line_number($parser).': '.xml_error_string(xml_get_error_code($parser));
                }
                xml_parser_free($parser);

                        // Init vars:
                $stack = array(array());
                $stacktop = 0;
                $current=array();
                $tagName = '';
                $documentTag = '';

                        // Traverse the parsed XML structure:
                foreach($vals as $key => $val) {

                                // First, process the tag-name (which is used in both cases, whether "complete" or "close")
                        $tagName = $val['tag'];
                        if (!$documentTag)      $documentTag = $tagName;

                                // Test for name space:
                        $tagName = ($NSprefix && substr($tagName,0,strlen($NSprefix))==$NSprefix) ? substr($tagName,strlen($NSprefix)) : $tagName;

                                // Test for numeric tag, encoded on the form "nXXX":
                        $testNtag = substr($tagName,1); // Closing tag.
                        $tagName = (substr($tagName,0,1)=='n' && !strcmp(intval($testNtag),$testNtag)) ? intval($testNtag) : $tagName;

                                // Test for alternative index value:
                        if (strlen($val['attributes']['index']))        { $tagName = $val['attributes']['index']; }

                                // Setting tag-values, manage stack:
                        switch($val['type'])    {
                                case 'open':            // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
                                        $current[$tagName] = array();   // Setting blank place holder
                                        $stack[$stacktop++] = $current;
                                        $current = array();
                                break;
                                case 'close':   // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
                                        $oldCurrent = $current;
                                        $current = $stack[--$stacktop];
                                        end($current);  // Going to the end of array to get placeholder key, key($current), and fill in array next:
                                        $current[key($current)] = $oldCurrent;
                                        unset($oldCurrent);
                                break;
                                case 'complete':        // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
                                        if ($val['attributes']['base64'])       {
                                                $current[$tagName] = base64_decode($val['value']);
                                        } else {
                                                $current[$tagName] = $is_encoded ? @mb_convert_encoding((string)$val['value'], $encoding, "UTF-8") : (string)$val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!

                                                        // Cast type:
                                                switch((string)$val['attributes']['type'])      {
                                                        case 'integer':
                                                                $current[$tagName] = (integer)$current[$tagName];
                                                        break;
                                                        case 'double':
                                                                $current[$tagName] = (double)$current[$tagName];
                                                        break;
                                                        case 'boolean':
                                                                $current[$tagName] = (bool)$current[$tagName];
                                                        break;
                                                        case 'array':
                                                                $current[$tagName] = array();   // MUST be an empty array since it is processed as a value; Empty arrays would end up here because they would have no tags inside...
                                                        break;
                                                }
                                        }
                                break;
                        }
                }

                if ($reportDocTag)      {
                        $current[$tagName]['_DOCUMENT_TAG'] = $documentTag;
                }

                        // Finally return the content of the document tag.
                return $current[$tagName];
        }
----------------------------------------------------------------------------------

-- 
Dmitry Martynenko
Developer

Web: http://realt.by



More information about the TYPO3-english mailing list