Note: This has only been tested with Drupal 6.x.
For some boneheaded reason, the latest version of Views for Drupal doesn’t let you customize the fields output in an RSS feed. If you create a new feed view, under the Fields block, you’ll get a message saying “The style selected does not utilize fields.” Well la de da. This means you’re stuck displaying the default content, despite which fields CCK says it is displaying or hiding.
Of course. Why would you want to customize your fields, anyway?
So here’s how I was able to customize the RSS fields output by including the entire node in the RSS feed results. If you want a tutorial on how to first setup an RSS feed, there’s a tutorial on creating a custom rss feed in Drupal.
Now that you have your feed setup, you’ll see there’s nothing you can do with it. But there is a Views function you can overwrite in template.php to add more data to the output rows.
/**
* Default theme function for all RSS rows.
*/
function phptemplate_preprocess_views_view_row_rss(&$vars) {
$view = &$vars['view'];
$options = &$vars['options'];
$item = &$vars['row'];
// Use the [id] of the returned results to determine the nid in [results]
$result = &$vars['view']->result;
$id = &$vars['id'];
$node = node_load( $result[$id-1]->nid );
$vars['title'] = check_plain($item->title);
$vars['link'] = check_url($item->link);
$vars['description'] = check_plain($item->description);
//$vars['description'] = check_plain($node->teaser);
$vars['node'] = $node;
$vars['item_elements'] = empty($item->elements) ? '' : format_xml_elements($item->elements);
} |
/**
* Default theme function for all RSS rows.
*/
function phptemplate_preprocess_views_view_row_rss(&$vars) {
$view = &$vars['view'];
$options = &$vars['options'];
$item = &$vars['row'];
// Use the [id] of the returned results to determine the nid in [results]
$result = &$vars['view']->result;
$id = &$vars['id'];
$node = node_load( $result[$id-1]->nid );
$vars['title'] = check_plain($item->title);
$vars['link'] = check_url($item->link);
$vars['description'] = check_plain($item->description);
//$vars['description'] = check_plain($node->teaser);
$vars['node'] = $node;
$vars['item_elements'] = empty($item->elements) ? '' : format_xml_elements($item->elements);
}
I need to get a real code parser. This is just embarrassing.
What I’ve done above is use the 'result'
array and 'id'
value returned in the &$vars
variable to determine the node ID of the returned results. The ID is just the position the node appears in the list of results (1,2,3,etc.). It’s one higher than the keys to the objects in the ‘results’ array (0,1,2,etc.) so just tell the function to get the nid
in the object at position ID minus 1, and now you have the nid
of the result. I load the nid
into the &$vars
array to be sent to the Views template, which I’ll get to now.
Views already has support for templates, but my complaint with its templates — like my complaint with much of Drupal — is that it gives you a half-finished template. It doesn’t give you the perfectly-rendered, nicely polished HTML to want, and it doesn’t give you an array to customize how you see fit: it gives you something in the middle, usually consisting of an array of preformatted elements. So thanks for that. I hope you like all your content wrapped in <p>
tags! Well, most of the time, anyway!
Ahem, where was I? Ah, the template. Views recommends using a template called views-view-row-rss.tpl.php (you’ll notice it corresponds to the function name above). This is the most generic RSS template, but you can use a more specific one if you don’t want to use the same formatting on all your RSS feeds. Now that you have the $node variable at your fingertips, you can put any of the node content in the feed. Here’s what I did with it.
< ?php
// $Id: views-view-row-rss.tpl.php 3296 2009-05-27 23:08:21Z timtoon $
/**
* @file views-view-row-rss.tpl.php
* Default view template to display a item in an RSS feed.
*
* @ingroup views_templates
*/
?>
<item>
<title>< ?php print $title; ?></title>
<link />< ?php print $link; ?>
<description>![CDATA[< ?php
$desc = $node->field_teaser[0]['value'] ? $node->field_teaser[0]['value'] : $node->body;
print nl2br(check_plain(trim($desc)));
?>]]</description>
< ?php print $item_elements; ?>
</item> |
< ?php
// $Id: views-view-row-rss.tpl.php 3296 2009-05-27 23:08:21Z timtoon $
/**
* @file views-view-row-rss.tpl.php
* Default view template to display a item in an RSS feed.
*
* @ingroup views_templates
*/
?>
<item>
<title>< ?php print $title; ?></title>
<link />< ?php print $link; ?>
<description>![CDATA[< ?php
$desc = $node->field_teaser[0]['value'] ? $node->field_teaser[0]['value'] : $node->body;
print nl2br(check_plain(trim($desc)));
?>]]</description>
< ?php print $item_elements; ?>
</item>
Christ how can anyone read that. Fixed! Anyway, nothing too fancy here. I don’t like Drupal’s auto-truncating teaser field, so I’m using my own in a custom field called field_teaser. But if there is no field_teaser value, use the whole node body. I hope this isn’t too many unrelated things to make a clear example.
Now that I have my node’s teaser/body, I trim the content, use Drupal’s check_plain function to do the same thing as PHP’s strip_tags method, and convert the new lines to line breaks using nl2br.
So your RSS reader won’t try to parse those <br />
tags as XML, I enclosed the content in <![CDATA[ ... ]]>
, so now you won’t lose any formatting that wasn’t just stripped out by check_plain.
At last, I have a custom-formatted RSS feed showing only the field I want. I can use this to put whatever node content I want into my RSS feed, and if you have been able to follow my rambling example, so can you!
There is another method here: Control Title link and “read more” in RSS Feed of views