# 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)