73 lines
2.1 KiB
Nim
73 lines
2.1 KiB
Nim
|
# 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)
|