--****************************************************************************
-- Software: SIMPLE XML SERIALIZER
-- Version: 1.0
-- Date: 2009/03/11
-- Author: Valentin Schmidt
--
-- Usage:
-- put mSerialize([#1:[1,2,3], #a:23, "b": rect(0,0,1,2), "xxx":point(2,3)], true)
-- put mDeserialize(mSerialize([#a:[1,2,[3,4]], #b:23, "c": rect(0,0,1,2)]))
--
-- Supported data types:
-- #list, #propList, #string, #symbol, #integer, #float, #point, #rect, #vector, #rgb, #color, #date (ignoring seconds), #void
--****************************************************************************
----------------------------------------
--
----------------------------------------
on mSerialize (v, declarationFlag)
xml = ""
if declarationFlag then put "<?xml version='1.0' encoding='ISO-8859-1' ?>" after xml
put "<root>" after xml
put _encode(v) after xml
put "</root>" after xml
return xml
end
----------------------------------------
--
----------------------------------------
on mDeserialize (xmlStr)
xmlParser = xtra("XmlParser").new()
xmlParser.parseString(xmlStr)
rawList = xmlParser.makePropList()
if not listP(rawList) then return 0
data = _makeSimplePropList(rawList)
xmlParser = 0
return data["root"]
end
----------------------------------------
--
----------------------------------------
on _encode (v)
t = ilk(v)
case (t) of
#list:
s = ""
cnt = count(v)
repeat with i = 1 to cnt
put "<__item__>" after s
put _encode(v[i]) after s
put "</__item__>" after s
end repeat
#proplist:
s = ""
cnt = count(v)
repeat with i = 1 to cnt
propName = string(v.getPropAt(i))
-- <23>...</23> not well-formed xml!
if ilk(v.getPropAt(i))=#integer OR ilk(v.getPropAt(i))=#symbol then put "__sym__" before propName
put "<"&propName&">" after s
put _encode(v[i]) after s
put "</"&propName&">" after s
end repeat
#string:
s = v
s = _str_replace(QUOTE, QUOTE&""E&""E, s)
s = "<![CDATA[""E&s"E&"]]>"
#symbol:
s = "#" & string(v)
-- everything that can be evaluated directly using value()!
#integer, #float, #point, #rect, #rgb, #color, #vector,#date:
s = string(v)
otherwise: -- , #void:
s = "Void"
end case
return s
end
----------------------------------------
--
----------------------------------------
on _makeSimplePropList (pl)
data = [:]
_parseNode (data, pl)
return data
end
----------------------------------------
--
----------------------------------------
on _parseNode (data, node)
if not voidP(node["chardata"]) then
val = value(node.chardata)
else
val = [:]
cnt = node.child.count
repeat with i = 1 to cnt
_parseNode(val, node.child[i])
end repeat
if not voidP(val["__item__"]) then
val = val["__item__"]
end if
end if
if voidP(data[node.name]) then
if node.name starts "__sym__" then
p = symbol(node.name.char[8..node.name.length])
else
p = node.name
end if
data.addProp(p, val)
else
if ilk(data[node.name])<>#list then
data[node.name] = [data[node.name]]
end if
data[node.name].add(val)
end if
end
----------------------------------------
-- replace in string
----------------------------------------
on _str_replace (stringToFind, stringToInsert, input)
output = ""
findLen = stringToFind.length - 1
repeat while true
currOffset = offset(stringToFind, input)
if currOffset=0 then exit repeat
put input.char [1..currOffset] after output
delete the last char of output
put stringToInsert after output
delete input.char [1.. (currOffset + findLen)]
end repeat
put input after output
return output
end