XML documents

A document stored with an XML-family content type is composed with the same namespaced directives as HTML, and served back as well-formed XML. This makes RSS and Atom feeds, sitemaps, SVG images, and XHTML dynamic without leaving the XML serialization.

XML-family content types

A document is treated as XML when its stored content type is application/xml, text/xml, or any …+xml structured-syntax-suffix type:

Content type Typical use
application/xml, text/xml Generic XML
application/rss+xml RSS feeds
application/atom+xml Atom feeds
image/svg+xml SVG images
application/xhtml+xml XHTML
any other …+xml type sitemaps, and so on

The content type is set when the document is written — send it as the Content-Type header on PUT, or let it be inferred from the file extension. The response keeps the stored XML content type.

The XML dialect

XML documents are parsed with an XML dialect rather than the lenient HTML parser:

The composed result is serialised as well-formed XML: empty elements self-close (<entry/>), element and attribute case is preserved, and processing instructions are retained.

Composition

XML documents run through the same composition pipeline as HTML. Every namespaced directive works:

Microdata @read resolvers also run on XML: an element carrying itemscope/itemprop whose schema declares a @read resolver has its values transformed on the read path, exactly as in HTML. An XML document with no Pagelove namespaces and no microdata is served unchanged.

Differences from HTML composition

Two HTML-representation behaviours do not apply to XML documents:

Behaviour HTML XML
JSON-LD content negotiation Accept: application/ld+json returns JSON-LD Not applied — an XML document is always served as XML, regardless of Accept
xmlns: declaration stripping Pagelove xmlns: declarations are removed from the response Preserved — an XML document legitimately declares namespaces, so all xmlns: declarations (including xmlns:e / xmlns:p) remain in the served output

Example

An Atom feed whose <title> is filled by an Expression Binding and emitted with <p:stamp>. It is stored with an XML content type and composed on read:

If /feed.xml contains
PUT /feed.xml HTTP/2
Host: 127.0.0.1
Content-Type: application/atom+xml

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:e="https://pagelove.org/Binding/Sessel" xmlns:p="https://pagelove.org/1.0" e:site="'Pagelove Blog'">
  <title><p:stamp site></p:stamp></title>
  <entry><id>urn:1</id></entry>
  <div hidden="hidden" itemscope="itemscope" itemtype="https://pagelove.org/AuthorizationRule">
    <meta itemprop="actor" content="*"></meta>
    <meta itemprop="resource" content="/*"></meta>
    <meta itemprop="method" content="GET"></meta>
    <meta itemprop="action" content="allow"></meta>
  </div>
</feed>

Fetching the feed runs composition and returns well-formed XML with its stored content type:

GET /feed.xml HTTP/2
Host: 127.0.0.1
HTTP/2 200
content-type: application/atom+xml

<title>Pagelove Blog</title>

The e:site binding resolves and <p:stamp site> is replaced by its value; the xmlns: declarations remain because stripping is HTML-only.

See also