# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[parseutils, strtabs, xmltree] import ../preserves proc toPreservesFromString*(s: string): Value = # This is a bad and slow thing to do, but that is XML. case s of "false", "no", "off": result = toPreserves(false) of "true", "yes", "on": result = toPreserves(true) else: var n: BiggestInt f: float if parseBiggestInt(s, n) == s.len: result = toPreserves(n) elif parseHex(s, n) == s.len: result = toPreserves(n) elif parseFloat(s, f) == s.len: result = toPreserves(f) else: result = toPreserves(s) proc toPreservesHook*(xn: XmlNode): Value = if xn.kind == xnElement: result = Value(kind: pkRecord) if not xn.attrs.isNil: var attrs = initDictionary() for xk, xv in xn.attrs.pairs: attrs[toSymbol(xk)] = toPreservesFromString(xv) result.record.add(attrs) var isText = xn.len > 0 # escaped text is broken up and must be concatenated for child in xn.items: if child.kind == xnElement: isText = false break if isText: result.record.add(toPreserves(xn.innerText)) else: for child in xn.items: case child.kind of xnElement: result.record.add(toPreservesHook(child)) of xnText, xnVerbatimText, xnCData, xnEntity: result.record.add(toPreserves(text(child))) of xnComment: discard result.record.add(toSymbol(xn.tag)) # record labels are stored after the fields proc toUnquotedString(pr: Value): string {.inline.} = case pr.kind of pkString: pr.string of pkBoolean: if pr.bool: "true" else: "false" else: $pr proc fromPreservesHook*(xn: var XmlNode; pr: Value): bool = if pr.kind == pkRecord and pr.label.kind == pkSymbol: xn = newElement($pr.label) var i: int for e in pr.fields: if i == 0 and e.kind == pkDictionary: var pairs = newSeqOfCap[tuple[key, val: string]](e.dict.len) for key, val in e.dict.items: pairs.add((key.toUnquotedString, val.toUnquotedString,)) xn.attrs = pairs.toXmlAttributes elif e.kind == pkString: xn.add newText(e.string) else: var child: XmlNode result = fromPreservesHook(child, e) if not result: return xn.add child inc i result = true when isMainModule: var xn = newElement("foobar") var pr = xn.toPreservesHook() assert fromPreservesHook(xn, pr)