'rss', 'attributes' => array( 'version' => '2.0', ), 'value' => array(), ); // Prepare namespaces and add them to feed array. // xml:base cannot be defined by hook_views_rss_namespaces() implementation, // as we don't want its value to be cached, it needs to be dynamic. $rss_feed['attributes']['xml:base'] = url('', array('absolute' => TRUE)); // All other namespaces are taken from hook_views_rss_namespaces() implementations. foreach (views_rss_get('namespaces') as $module => $module_namespaces) { foreach ($module_namespaces as $namespace => $definition) { // Check if definition provided through modules hooks // should be overwritten by module configuration. if ( isset($view->style_plugin->options['namespaces'][$module][$namespace]) && !empty($view->style_plugin->options['namespaces'][$module][$namespace]) ) { $definition['uri'] = $view->style_plugin->options['namespaces'][$module][$namespace]; } // Add namespace to feed array. if (isset($definition['uri']) && !empty($definition['uri'])) { // Namespaces with prefix, for example xml:base="" or xmlns:dc="" if (isset($definition['prefix']) && !empty($definition['prefix'])) { $namespace_key = $definition['prefix'] . ':' . $namespace; $rss_feed['attributes'][$namespace_key] = $definition['uri']; } // Namespaces without prefix, for example: content="" or foaf="" else { $rss_feed['attributes'][$namespace] = $definition['uri']; } } } } // Prepare elements and add them to feed array. $rss_channel = array(); foreach (views_rss_get('channel_elements') as $module => $module_channel_elements) { foreach ($module_channel_elements as $element => $definition) { list($namespace, $element_name) = views_rss_extract_element_names($element, 'core'); // Try to fetch namespace value from view configuration. if (isset($view->style_plugin->options['channel'][$namespace][$module][$element_name])) { $value = $view->style_plugin->options['channel'][$namespace][$module][$element_name]; } // Otherwise check if it was provided by element definition. elseif (isset($definition['default_value'])) { $value = $definition['default_value']; } else { $value = NULL; } // Avoid double encoding: the $value might be already encoded here, // depending on the field configuration/processing, and because we know // it will be encoded again when the whole feed array will be passed to // format_xml_elements(), let's make sure we decode it here first. if (is_string($value)) { $value = decode_entities($value); } // Start building XML channel element array compatible with format_xml_elements(). $rss_elements = array( array( 'key' => $element, 'value' => $value, ), ); // Preprocess element value. if (isset($definition['preprocess functions']) && is_array($definition['preprocess functions'])) { foreach ($definition['preprocess functions'] as $preprocess_function) { if (function_exists($preprocess_function)) { $item_variables = array( 'elements' => &$rss_elements, 'item' => $view->style_plugin->options['channel'], 'view' => $view, ); $preprocess_function($item_variables); } } } // If there is no value and no attributes (in case of self-closing elements) // already set for the element at this stage, it is not going to be set // at any point further, so the element should not be added to the feed. foreach ($rss_elements as $key => $rss_element) { if (empty($rss_element['value']) && empty($rss_element['attributes'])) { unset($rss_elements[$key]); } } if (empty($rss_elements)) continue; // Add XML element(s) to the channel array. $rss_channel = array_merge($rss_channel, $rss_elements); } } // Channel array should not be added to the feed array yet, as first // it needs to get populated with all elements. // Prepare elements and add them to the channel array. $item_elements = views_rss_get('item_elements'); $items = $view->style_plugin->map_rows($variables['rows']); foreach ($items as $item_key => $item) { // Start building XML item element array compatible with format_xml_elements(). $rss_item = array( 'key' => 'item', 'value' => array(), ); // Preprocess whole item array before preprocessing separate elements. foreach (module_implements('views_rss_preprocess_item') as $module) { $preprocess_function = $module . '_views_rss_preprocess_item'; $item_variables = array( 'item' => &$item, 'view' => $view, ); // Add raw row if generated based on raw item values provided by field formatter. if (!empty($view->views_rss['raw_items'][$item_key])) { $item_variables['raw'] = $view->views_rss['raw_items'][$item_key]; } $preprocess_function($item_variables); } // Process each element separately. foreach ($item as $module => $module_item_elements) { foreach ($module_item_elements as $element => $value) { // Avoid double encoding: the $value might be already encoded here, // depending on the field configuration/processing, and because we know // it will be encoded again when the whole feed array will be passed to // format_xml_elements(), let's make sure we decode it here first. if (is_string($value)) { $value = decode_entities($value); } // Start building XML element array compatible with format_xml_elements(). $rss_elements = array( array( 'key' => $element, 'value' => $value, ), ); // Preprocess element initial value if required. if (isset($item_elements[$module][$element]['preprocess functions']) && is_array($item_elements[$module][$element]['preprocess functions'])) { foreach ($item_elements[$module][$element]['preprocess functions'] as $preprocess_function) { if (function_exists($preprocess_function)) { $item_variables = array( 'elements' => &$rss_elements, 'item' => $item, 'view' => $view, ); // Add raw item if provided by field formatter. if (!empty($view->views_rss['raw_items'][$item_key][$module][$element])) { $item_variables['raw'] = $view->views_rss['raw_items'][$item_key][$module][$element]; } $preprocess_function($item_variables); } } } // If no preprocess function was defined, and we have received // #rss_element value (XML element array) from the formatter, it should // be added to the feed array without any further modifications. elseif ( !empty($view->views_rss['raw_items'][$item_key][$module][$element]) && is_array($view->views_rss['raw_items'][$item_key][$module][$element]) ) { // At this point we don't know yet if we got #rss_elements in raw // values, so do not overwrite and empty main $rss_elements yet, just // start working with new $formatter_rss_elements - it could be // overwritten once we are sure we have all required values. $formatter_rss_elements = array(); foreach ($view->views_rss['raw_items'][$item_key][$module][$element] as $raw_item) { if (!empty($raw_item['rendered']['#rss_element'])) { $formatter_rss_elements[] = $raw_item['rendered']['#rss_element']; } } // Now we can overwrite main $rss_elements. if (!empty($formatter_rss_elements)) { $rss_elements = $formatter_rss_elements; } } // If there is no value and no attributes (in case of self-closing elements) // already set for the element at this stage, it is not going to be set // at any point further, so the element should not be added to the feed. foreach ($rss_elements as $key => $rss_element) { if (empty($rss_element['value']) && empty($rss_element['attributes'])) { unset($rss_elements[$key]); } } if (empty($rss_elements)) continue; // Add XML element(s) to the item array. $rss_item['value'] = array_merge($rss_item['value'], $rss_elements); } } // Add XML item element to the channe; array. $rss_channel[] = $rss_item; } // Finally, let's put together the whole feed array. $rss_feed['value'][] = array( 'key' => 'channel', 'value' => $rss_channel, ); // Allow for altering it before final render and passing it to the template. drupal_alter('views_rss_feed', $rss_feed); // Assign rendered feed to the template variables. $variables['rss_feed'] = format_xml_elements(array($rss_feed)); // Set XML header. drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8'); }