xml.interpolate
, which lets you create an XML chunk or document using interpolating either by locals or using a fry-like syntax. Here's a taste, from the syndication
vocab, to create an Atom file:: feed>xml ( feed -- xml )This could also be written with locals:
[ title>> ]
[ url>> present ]
[ entries>> [ entry>xml ] map ] tri
<XML
<feed xmlns="http://www.w3.org/2005/Atom">
<title><-></title>
<link href=<-> />
<->
</feed>
XML> ;
:: feed>xml ( feed -- xml )Here's an example with more complicated logic:
feed title>> :> title
feed url>> present :> url
feed entries>> [ entry>xml ] map :> entries
<XML
<feed xmlns="http://www.w3.org/2005/Atom">
<title><-title-></title>
<link href=<-url-> />
<-entries->
</feed>
XML> ;
"one two three" " " splitwhose prettyprinted output (using
[ [XML <item><-></item> XML] ] map
<XML <doc><-></doc> XML>
xml.writer:pprint-xml
) is<?xml version="1.0" encoding="UTF-8"?>The word
<doc>
<item>
one
</item>
<item>
two
</item>
<item>
three
</item>
</doc>
<XML
starts a literal XML document, and [XML
starts a literal XML chunk. (A document has a prolog and exactly one tag, whereas a chunk can be any kind of snippet, as long as tags are balanced.) The syntax for splicing things in is using a tag like <-foo->
. This syntax is a strict superset of XML, as a tag name in XML 1.0 is not allowed to start with -
.It took me just an evening to hack this up. It's less than 15 lines of code modifying the XML parser, and all the interpolation is less than 75 lines of code. Best of all, unlike Scala's XML literals, this doesn't affect the core of the language or make anything else more complicated. It's just nicely tucked away in its own little vocabulary. I plan on replacing usages of
html.components
with this, once I make some tweaks.