Here's some code that takes an associative array and prints it asXML() but creates CDATA sections for each string
<?php
class SimpleXMLExtended extends SimpleXMLElement{ 
    public function addCData($string){ 
$dom = dom_import_simplexml($this);
$cdata = $dom->ownerDocument->createCDATASection($string);
$dom->appendChild($cdata);
    } 
}
function assocArrayToXML($root_element_name,$ar){
$xml = new SimpleXMLExtended("<?xml version=\"1.0\"?><{$root_element_name}></{$root_element_name}>");
$f = create_function('$f,$c,$a','
            foreach($a as $k=>$v) {
                if(is_array($v)) {
                    if (!is_numeric($k))$ch=$c->addChild($k);
                    else $ch = $c->addChild(substr($c->getName(),0,-1));
                    $f($f,$ch,$v);
                } else {
                    if (is_numeric($v)){ $c->addChild($k, $v);
                    }else{$n = $c->addChild($k); $n->addCData($v);}
                }
            }');
$f($f,$xml,$ar);
    return $xml->asXML();
} 
$result = array("title"=>"CDATA Sample");
$result['items'] = array();
$result['items'][] = array('title'=>'Some string', 'number' => 1);
$result['items'][] = array('title'=>'Some string', 'number' => 2);
$result['items'][] = array('title'=>'Some string', 'number' => 3);
echo assocArrayToXML('result',$result);
?>
The is_numeric check could be changed by a more elaborate regular expression to check if the string is actually xml unsafe but this worked for me.