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:
- Element and attribute names are case-sensitive —
<Entry>and<entry>are different elements. - There are no void or raw-text elements — every element nests normally.
- Processing instructions (
<?target data?>, including the<?xml …?>declaration) are recognised.
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:
- Expression Binding —
e:attributes - Resource Binding
- Templating —
pagelove:template - Stamp (
<p:stamp>) and Method Elements - Includes —
<p:include> - Transient Elements
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
- Uploading files — how content types are assigned, and how non-HTML/XML files are stored
- Expression Binding — compute the value a feed field displays
- Stamp — emit a bound value into the document
- Content Negotiation — the JSON-LD negotiation that XML documents opt out of