Authored on
Changed
When developing a site, it is sometimes necessary to set up an XML feed. Even though JSON is now the dominant format, there are still applications already developed that require data in XML format.
With Drupal 8's webservices modules, whether with the core or with community modules as add-ons, it is possible to obtain content in XML format.
But sometimes the structure of the XML feed is so specific that it's better to do some development.
Here are some sample codes for generating such a feed.
xml_feed_example.info.yml file
To declare the module.
name: XML feed example description: "Provides example to make a XML feed." type: module core: 8.x
xml_feed_example.module file
To enable a Twig template and thus structure the XML as desired.
<?php
/**
* @file
* Contains hook implementations for xml_feed_example module.
*/
/**
* Implements hook_theme().
*/
function xml_feed_example_theme($existing, $type, $theme, $path) {
return [
xml_feed_example' => [
variables' => [
items' => [],
],
],
];
}
xml_feed_example.routing.yml file
To declare the URL of our feed.
xml_feed_example.feed:
path: '/feed.xml'
defaults:
_controller: '\Drupal\xml_feed_example\Controller\FeedController::feed'
requirements:
_permission: 'access content'
File templates/xml-feed-example.html.twig
Simplified for the example.
<?xml version="1.0" encoding="UTF-8" ?>
<datas>
{% for item in items %}
<data>
<Title>{{ item.title }}</Title>
</data>
{% endfor %}
</datas>
File src/Controller/FeedController.php
<?php
namespace Drupal\xml_feed_example\Controller;
use Drupal\Core\CacheableMetadata;
use Drupal\Core\CacheableResponse;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\RendererInterface;
use SymfonyComponentDependencyInjectionContainerInterface;
/**
* Class FeedController.
*/
class FeedController extends ControllerBase {
/**
* Renderer service.
*
* @var \Drupal\Core\RendererInterface
*/
protected $renderer;
/**
* Constructor.
*
* @param \Drupal\Core\RendererInterface $renderer
* The renderer service.
*/
public function __construct(
RendererInterface $renderer
) {
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('renderer')
);
}
/**
* XML feed.
*
* @return \Drupal\Core\Cache\CacheableResponseInterface
* Return the XML feed.
*/
public function feed() {
$items = [];
$cache = new CacheableMetadata();
// Adapt data retrieval to your needs.
$nodes = $this->entityTypeManager()->getStorage('node')->loadMultiple();
foreach ($nodes as $node) {
$cache->addCacheableDependency($node);
$data = [];
$data['title'] = $node->label();
$items[] = $data;
}
$datas = [
'#theme' => 'xml_feed_example',
'#items' => $items,
];
$cache->applyTo($datas);
$content = $this->renderer->renderRoot($datas);
$response = new CacheableResponse();
$response->setContent($content);
$response->addCacheableDependency($cache);
$response->headers->set('Content-Type', 'xml');
// If you want to obtain the feed in the form of a downloaded file.
//$response->headers->set('Content-Disposition', 'attachment; filename="feed.xml"');
return $response;
}
}