preserves-nim/src/preserves/xmlhooks.nim

73 lines
2.1 KiB
Nim
Raw Normal View History

2021-12-06 23:28:00 +00:00
# SPDX-FileCopyrightText: 2021 ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[xmltree, strtabs, tables]
import ../preserves
proc toPreserveHook*(xn: XmlNode; E: typedesc): Preserve[E] =
case xn.kind
of xnElement:
var children = initSequence[E](xn.len)
var i: int
for child in xn.items:
children[i] = toPreserveHook(child, E)
inc i
var attrMap = initDictionary[E]()
if not xn.attrs.isNil:
for key, val in xn.attrs.pairs:
attrMap[toSymbol(key, E)] = toPreserve(val, E)
result = initRecord[E](xn.tag, attrMap, children)
of xnText:
result = toPreserve(xn.text, E)
of xnVerbatimText:
result = initRecord[E]("verbatim", xn.text.toPreserve(E))
of xnComment:
result = initRecord[E]("comment", xn.text.toPreserve(E))
of xnCData:
result = initRecord[E]("cdata", xn.text.toPreserve(E))
of xnEntity:
result = initRecord[E]("entity", xn.text.toPreserve(E))
proc fromPreserveHook*[E](xn: var XmlNode; pr: Preserve[E]): bool =
case pr.kind:
of pkString:
xn = newText(pr.string)
result = true
of pkRecord:
if pr.len == 2 and pr[0].isDictionary and pr[1].isSequence and pr.label.isSymbol:
xn = newElement(pr[2].symbol)
result = true
if pr[0].len > 0:
var attrs = newStringTable()
for key, val in pr[0].dict.items:
if not (key.isSymbol and val.isString):
result = false
break
attrs[key.symbol] = val.string
xn.attrs = attrs
var child: XmlNode
for e in pr[1]:
result = fromPreserveHook(child, e)
if not result: break
xn.add(move child)
if not result: reset xn
elif pr.len == 1 and pr.label.isSymbol:
result = true
case pr.label.symbol:
of "verbatim":
xn = newVerbatimText(pr[0].string)
of "comment":
xn = newComment(pr[0].string)
of "cdata":
xn = newCData(pr[0].string)
of "entity":
xn = newEntity(pr[0].string)
else:
result = false
else: discard
when isMainModule:
var xn = XmlNode()
var pr = xn.toPreserveHook(void)
assert fromPreserveHook(xn, pr)