Skip to content

Instantly share code, notes, and snippets.

@meoyawn
Last active February 29, 2024 16:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save meoyawn/5b4c9888704071f0f58c65a492a54a6f to your computer and use it in GitHub Desktop.
Save meoyawn/5b4c9888704071f0f58c65a492a54a6f to your computer and use it in GitHub Desktop.
fast XML DSL in 70 lines
package lib.xml
import org.apache.commons.text.StringEscapeUtils
fun StringBuilder.put(attrs: Array<out Pair<String, Any?>>) {
for ((k, v) in attrs) {
if (v == null) continue
append(' ')
append(k)
append('=')
append('"')
append(StringEscapeUtils.escapeXml10(v.toString()))
append('"')
}
}
context(StringBuilder)
operator fun String.invoke(vararg attrs: Pair<String, Any?>) {
val name = this
append('<')
append(name)
put(attrs)
append("/>")
appendLine()
}
context(StringBuilder)
inline operator fun String.invoke(vararg attrs: Pair<String, Any?>, f: StringBuilder.() -> Unit) {
val name = this
append('<')
append(name)
put(attrs)
append('>')
f(this@StringBuilder)
append("</")
append(name)
append('>')
appendLine()
}
context(StringBuilder)
operator fun String?.unaryPlus() {
if (isNullOrBlank()) return
append(StringEscapeUtils.escapeXml10(this))
}
/** when you don't need to escape */
context(StringBuilder)
operator fun String?.unaryMinus() {
if (isNullOrBlank()) return
append(this)
}
inline fun rss2(chan: StringBuilder.() -> Unit): String =
buildString {
appendLine("""<?xml version="1.0" encoding="UTF-8"?>""")
"rss"("xmlns:itunes" to "http://www.itunes.com/dtds/podcast-1.0.dtd", "version" to "2.0") {
"channel" {
chan()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment