Search code examples
phprsssimplexmlcdata

How do I properly add CDATA to <content:encoded> in an RSS feed using PHP SimpleXMLElement?


I'm building an RSS feed for the first time (https://www.uaccb.edu/news/feed), and I'm attempting to emulate how this feed https://feeds.npr.org/1001/rss.xml adds images in content:encoded elements but am having issues with the feed output. Any item that has a content:encoded element seems to only display the item title and the text of the CDATA string. I also noticed that the NPR feed has the CDATA as a child of content:encoded whereas mine is simply between the element tags. I've attempted $cdata->addChild(), but that just causes the content:encoded element to disappear from the feed. What's the trick here?

$rss = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"></rss>');
$channel = $rss->addChild('channel');

$channel->addChild('title', 'UACCB News');
$channel->addChild('link', 'https://uaccb.edu/news/feed/');
$channel->addChild('description', 'News from the University of Arkansas Community College at Batesville');
$channel->addChild('language', 'en-us');
$channel->addChild('pubDate', date(DATE_RSS));

$image = $channel->addChild('image');
$image->addChild('url', 'https://uaccb.edu/images/logo.png');
$image->addChild('title', 'UACCB News');
$image->addChild('link', 'https://uaccb.edu/news/feed/');

foreach ($pages as $row) {
    $item = $channel->addChild('item');
    $item->addChild('title', htmlspecialchars($row['title']));
    $item->addChild('description', htmlspecialchars($row['content']));
    $item->addChild('pubDate', date(DATE_RSS, strtotime($row['date'])));
    $item->addChild('link', 'https://uaccb.edu/news/'.$row['id'].'/');
    $item->addChild('guid', 'https://uaccb.edu/news/'.$row['id'].'/');
    if (!empty($row['images'][0]['url'])){
        $cdata = $item->addChild('encoded', '', 'http://purl.org/rss/1.0/modules/content/');
        $cdata[0] = '<![CDATA[<img src="'.$row['images'][0]['url'].'" alt="'.htmlspecialchars($row['images'][0]['caption']).'">]]>';
    }
}

Solution

  • Thanks to cOle2 in the comments for pointing me in the right direction.

    class SimpleXMLExtended extends SimpleXMLElement {
        public function addCData( $cdata_text ) {
            $node = dom_import_simplexml( $this );
            $no   = $node->ownerDocument;
            $node->appendChild( $no->createCDATASection( $cdata_text ) );
        }
    }
    

    and my relevant changes

    $rss = new SimpleXMLExtended('<?xml version="1.0" encoding="UTF-8"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"></rss>');
    
    $cdata->addCData('<img src="'.$row['images'][0]['url'].'" alt="'.htmlspecialchars($row['images'][0]['caption']).'">');