/**
  * Executes a data source. Invalid XML is escaped (CDATA) but still
  * cached. Prevents persistent cached XML from breaking pages.
  *
  * @param Datasource $datasource
  *  The current data source object
  * @param int $file_age
  *  Cache file age (in seconds), passed by reference
  */
 private function __executeDatasource($datasource, &$param_pool = array())
 {
     $result = $datasource->grab($param_pool);
     $xml = is_object($result) ? $result->generate(true, 1) : $result;
     // Parse DS XML to check for errors. If contains malformed XML such as
     // an unescaped database error, the error is escaped in CDATA
     $doc = new DOMDocument('1.0', 'utf-8');
     libxml_use_internal_errors(true);
     $doc->loadXML($xml);
     $errors = libxml_get_errors();
     libxml_clear_errors();
     libxml_use_internal_errors(false);
     // No error, just return the result
     if (empty($errors)) {
         return $result;
     }
     // There's an error, so $doc will be empty
     // Use regex to get the root node
     // If something's wrong, just push back the broken XML
     if (!preg_match('/<([^ \\/>]+)/', $xml, $matches)) {
         return $result;
     }
     $ret = new XMLElement($matches[1]);
     // Set the invalid flag
     $ret->setAttribute("xml-invalid", "true");
     $errornode = new XMLElement("errors");
     // Store the errors
     foreach ($errors as $error) {
         $item = new XMLElement("error", trim($error->message));
         $item->setAttribute('line', $error->line);
         $item->setAttribute('column', $error->column);
         $errornode->appendChild($item);
     }
     $ret->appendChild($errornode);
     // Return the XML
     $ret->appendChild(new XMLElement('broken-xml', "<![CDATA[" . $xml . "]]>"));
     return $ret;
 }