Output XML Sites


I’m just trying to output xml instead of html with Kirby3, for example: article.php

    header('Content-type: text/xml; charset="utf-8"');
    echo '<?xml version="1.0" encoding="utf-8"?>';

I tried this: config.php

return [
    'routes' => [
            'pattern' => 'list/(:any)',
            'action'  => function($pageName) {
                $page = page('list/'.$pageName);
                $string = $kirby->render($page);
                return new response($string, 'application/xml');

With an XML string it works, but not that way. Anyone have any idea?


Maybe it will help you with how it’s used.

But is this a sitemap or something else? There is a sitemap plugin, and of course you can do it manually with the site map cook book guide.

If it’s something else, ive done it with a virtual page and a route…something like this in the routes…

'pattern' => '/list/your.xml',
'action'  => function () {
  return Page::factory([
      'slug' => 'your-page-slug',
      'template' => 'yourxmltemplate',

Then you can put the full XML into the php template and do any dynamic stuff in there. i might have gone about that wrongly, but it worked for me in a recent project.

What about using content representations? I don’t see much sense in the additional route unless I’m missing something, given that the pages exist in the file system.

I had success with XML and route-only with the code below. You can adapt it for your use case.

<?php // site/config/config.php

return [
    'routes' => [
            'pattern' => 'sitemap.xml',
            'action'  => function() {
                $pages = site()->pages()->index();

                $ignore = kirby()->option('sitemap.ignore', ['error']);

                $content = snippet('sitemap', compact('pages', 'ignore'), true);

                return new Kirby\Cms\Response($content, 'application/xml');

And here’s the site/snippets/sitemap.php:

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <?php foreach ($pages as $p) : ?>
        <?php if (in_array($p->uri(), $ignore)) continue ?>
            <loc><?= html($p->url()) ?></loc>
            <lastmod><?= $p->modified('c') ?></lastmod>
            <priority><?= ($p->isHomePage()) ? 1 : number_format(0.5 / $p->depth(), 1) ?></priority>
    <?php endforeach ?>

You don’t need to set the Content-Type header in the snippet because Kirby’s Response class will do that already.

Thank you all for your answers!

With the virtual pages i get it to worked. But the most practical for me will indeed be the usage of »content representations«.

It’s not for a sitemap, but I’ll take a closer look at the solution with the snippet when I have a little more time.