ansible/dhall/Prelude/XML/render.dhall

141 lines
3.7 KiB
Text
Raw Normal View History

2024-11-26 05:55:44 +00:00
{-|
Render an `XML` value as `Text`
For indentation and schema validation, see the `xmllint` utility
bundled with libxml2.
```
let XML = ./package.dhall
in XML.render
( XML.element
{ name = "foo"
, attributes = [ XML.attribute "a" "x", XML.attribute "b" (Natural/show 2) ]
, content = [ XML.leaf { name = "bar", attributes = XML.emptyAttributes } ]
}
)
= "<foo a=\"x\" b=\"2\"><bar/></foo>"
```
-}
let XML =
missing
sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9
? ./Type.dhall
let Text/concatMap =
missing
sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f
? ../Text/concatMap.dhall
let Text/concat =
missing
sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0
? ../Text/concat.dhall
let element =
missing
sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9
? ./element.dhall
let text =
missing
sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab
? ./text.dhall
let emptyAttributes =
missing
sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5
? ./emptyAttributes.dhall
let Attr = { mapKey : Text, mapValue : Text }
let esc = λ(x : Text) → λ(y : Text) → Text/replace x "&${y};"
let `escape&` = esc "&" "amp"
let `escape<` = esc "<" "lt"
let `escape>` = esc ">" "gt"
let `escape'` = esc "'" "apos"
let `escape"` = esc "\"" "quot"
let escapeCommon = λ(text : Text) → `escape<` (`escape&` text)
let escapeAttr = λ(text : Text) → `escape"` (`escape'` (escapeCommon text))
let escapeText = λ(text : Text) → `escape>` (escapeCommon text)
let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${escapeAttr x.mapValue}\""
let render
: XML → Text
= λ(x : XML) →
x
Text
{ text = escapeText
, rawText = λ(t : Text) → t
, element =
λ ( elem
: { attributes : List { mapKey : Text, mapValue : Text }
, content : List Text
, name : Text
}
) →
let attribs = Text/concatMap Attr renderAttr elem.attributes
in "<${elem.name}${attribs}"
++ ( if Natural/isZero (List/length Text elem.content)
then "/>"
else ">${Text/concat elem.content}</${elem.name}>"
)
}
let simple =
λ(name : Text) →
λ(content : List XML) →
element { name, attributes = emptyAttributes, content }
let example0 =
assert
: render
( simple
"note"
[ simple "to" [ text "Tove" ]
, simple "from" [ text "Jani" ]
, simple "heading" [ text "Reminder" ]
, simple "body" [ text "Don't forget me this weekend!" ]
]
)
≡ Text/replace
"\n"
""
''
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
''
let example1 =
assert
: render
( element
{ name = "escape"
, attributes = toMap { attribute = "<>'\"&" }
, content = [ text "<>'\"&" ]
}
)
≡ Text/replace
"\n"
""
''
<escape attribute="&lt;>&apos;&quot;&amp;">&lt;&gt;'"&amp;</escape>
''
in render