Node.js: servire XML nelle view di ExpressJS

In questo articolo vedremo come servire XML nelle view di ExpressJS quando la nostra applicazione deve essere interoperabile.

Node.js di Gabriele Romanato

In questo articolo vedremo come servire XML nelle view di ExpressJS quando la nostra applicazione deve essere interoperabile.

Non tutti i linguaggi di programmazione usati sul Web dispongono di un supporto nativo a JSON. Java ad esempio è un linguaggio che storicamente supporta nativamente XML ma non JSON. Se la nostra applicazione mira ad essere interoperabile, dobbiamo fornire un'alternativa al formato JSON.

Nella logica di ExpressJS non cambia molto: il metodo response.render() genera per impostazione predefinita un documento HTML. Se vogliamo cambiare questo comportamento, dobbiamo impostare l'header HTTP Content-Type su text/xml e creare un template XML con il nostro template engine di riferimento (ad esempio EJS).

Supponiamo di voler creare un feed con gli ultimi dieci prodotti di un e-commerce. Creiamo quindi una route specifica:

'use strict';

const express = require('express');
const router = express.Router();
const Product = require('../models/product');


router.get('/products.xml', async (req, res, next) => {
    try {
        const products = await Product.find().sort({ added: -1 }).limit(10);
        res.setHeader( 'Content-Type', 'text/xml');
        res.render('products', { products });
    } catch(err) {
        res.sendStatus(500);
    }
});

module.exports = router;

Il fatto che la route termini con .xml è puramente indicativo e viene qui usato solo per rendere chiaro attraverso l'URL che restituiremo un documento XML.

Dobbiamo creare quindi la view products generando la struttura del documento XML in modo dinamico a partire dall'array di documenti restituito dalla query al database.

Il modo più semplice è quello di assegnare ai nomi degli elementi XML lo stesso nome delle proprietà del modello del database.

<?xml version="1.0" encoding="UTF-8"?>

<products>
    <% products.forEach(product => { %>
    <product>
        <tags>
            <% if(product.tags.length > 0 ) {
                product.tags.forEach(tag => { %>
                <tag><%= tag %></tag>
            <% });
            } %>     
        </tags>
        <price><%= product.price %></price>
        <name><%= product.name %></name>
        <description><![CDATA[<%= product.description %>]]></description>
        <slug><%= product.slug %></slug>
        <added><%= product.added %></added>
        <manufacturer><%= product.manufacturer %></manufacturer>
        <itemType><%= product.itemType %></itemType>
        <productImg><%= product.productImg %></productImg>
    </product>
    <% }); %>
</products>

L'unico problema che si potrebbe incontrare è quello di avere dei contenuti composti da codice HTML. In quel caso possiamo usare una sezione CDATA per istruire il parser XML a trattare il contenuto dell'elemento come testo semplice, ignorando quindi gli eventuali tag HTML presenti al suo interno.

Commenti