Contents
Articles
Behaviors
Books
Director News
Director Web Sites
FAQ
Games
Mailing Lists
News Groups
Project Examples
Reviews
Software
Tools
Useful Web Sites
Utilities
Xtras

Don't miss these
Creating Records - Valentina
zlibXtra
Rollover Trigger-Alphamania
Generic behavior to get Key State.
Exit Browser
Generic Countdown Timer
TurnPict
ZGTSB-TextInteractivity
Video Cleanup
blending on casts
 

 

 

Behavior Store and restore Director objects as an XML string

Added on 4/19/2004

 

Compatibilities:
D9

This item has not yet been rated

Author: mildavw

This is a movie script containing two handlers: toXML() and fromXML(). These will convert the the following data types to XML and back. See the comments for more details and requirements. #list (containing any of the convertible types in this list) #propList (see #list) #void #integer #float #string #symbol #rect #point #color ( #rgb or #paletteIndex ) #date #member #castLib #sprite #xtra

-- XML Object Storage v1.0
-- Copyright 2004 Dave Miller, DMiller Studios
-- davmil@tenet.edu

-- Version History:
-- v20040215 - First Release

-- Requires a text member named "decoder" in a cast somewhere.
-- This also requires the Director MX 2004 XML parser Xtra

-- This is a group of scripts that allow one to store various Director objects as a giant string.
-- And as if that weren't handy enough, it also restores the objects from the string!
-- The string is damn near an XML document (all it it lacks is the tag at the beginning.)

-- Why would you want this? Well, if you want to store data anywhere, say, using setPrefs or on a server using postNetText,
-- you can only send the data as a string. What if you want to store a sprite reference? Or a vertexList? or a float with all of
-- its precision? You could use string() to convert your object and value() to restore it, but that has problems.  Try these in the
-- message window and see if you get back what you tried to convert:

-- x = VOID
-- arg = [1,2,x]
-- put value(string(arg))
--
-- the floatPrecision = 4
-- arg = 1.123456789
-- result = value(string(arg))
-- the floatPrecision = 9
-- put result

-- arg = ["I said," & QUOTE & "Oops!" & QUOTE]
-- put value(string(arg))

-- There are probably more, but those were enough reason for me to write the scripts below. Also, it is well formed XML so if you have
-- some other application that you want to send data to, you can use it for that too!

-- The two handlers to use are toXML() and fromXML()
-- The objects you can convert are listed in the case statement in the toXML() handler.
-- Lists and pLists can only contain convertible objects.
-- If you come with with other data that is storable this way, let me know and I'll share it with the world.

-- To see the scripts in action run these in the message window
--
-- x = toXML( [#p:1 , "test":[1,2,VOID] , #sym:rect(1,2,3,4) , #mem:member("decoder"), #sp:sprite(1) ]  ,1)
-- put x
-- put fromXML(x)
-- x = VOID
-- arg = [1,2,x]
-- put fromXML(toXML(arg))
--
-- the floatPrecision = 4
-- arg = 1.123456789
-- result = fromXML(toXML(arg))
-- the floatPrecision = 9
-- put result
--
-- arg = ["I said," & QUOTE & "Oops!" & QUOTE]
-- put fromXML(toXML(arg))


on toXML arg, aMode
  -- if aMode = 1 then make the XML human readable with returns and spaces.
  -- If aMode = 0 or VOID then save a few bytes and omit the dressing.
  
  vSpace = EMPTY
  if aMode > 0 then
    put RETURN after vSpace
    repeat with i = 1 to aMode-1
      put "  " after vSpace
    end repeat
  else
    aMode = -1
  end if
  
  txt = EMPTY
  case arg.ilk of
    (#void):
      put vSpace & "" after txt
    (#integer):
      put vSpace & "" & arg & "" after txt
    (#float):
      f = the floatPrecision
      the floatPrecision = 15
      put vSpace & "" & arg & "" after txt
      the floatPrecision = f
    (#string):
      if arg = EMPTY then
        put vSpace & "" & QUOTE & QUOTE & "" after txt
      else
        put vSpace & "" & enCode(arg) & "" after txt
      end if
    (#symbol):
      put vSpace & "" & enCode(string(arg)) & "" after txt
    (#rect):
      put vSpace & "" after txt
      repeat with i = 1 to 4
        put toXML(arg[i], aMode+1) after txt
      end repeat
      put vSpace & "
" after txt
    (#point):
      put vSpace & "

" after txt
      repeat with i = 1 to 2
        put toXML(arg[i]) after txt
      end repeat
      put vSpace & "

" after txt
    (#list):
      put vSpace & "" after txt
      lim = arg.count
      repeat with i = 1 to lim
        put toXML(arg[i], aMode+1) after txt
      end repeat
      put vSpace & "
" after txt
    (#propList):
      put vSpace & "" after txt
      lim = arg.count
      repeat with i = 1 to lim
        put toXML( arg.getPropAt(i) ,aMode+1 ) after txt
        put toXML( arg[i] ,aMode+1 ) after txt
      end repeat
      put vSpace & "
" after txt
    (#color):
      put vSpace & "" after txt  
      case arg.colorType of
        (#rgb):
          put toXML( arg.red  ,aMode+1 ) after txt
          put toXML( arg.green  ,aMode+1 )  after txt
          put toXML( arg.blue  ,aMode+1 ) after txt
        (#paletteIndex):
          put arg.paletteIndex after txt
      end case
      put vSpace & "
" after txt
    (#date):
      put vSpace & "" after txt
      put toXML( arg.year  ,aMode+1 ) after txt
      put toXML( arg.month  ,aMode+1 ) after txt
      put toXML( arg.day  ,aMode+1 ) after txt
      put vSpace & "
" after txt
    (#member):
      put vSpace & "" after txt
      put toXML( arg.name ,aMode+1 ) after txt
      --put toXML( arg.number ,aMode+1 ) after txt
      -- put toXML( arg.castLibNum  ,aMode+1 ) after txt
      put vSpace & "
" after txt
    (#castLib):
      put vSpace & "" & arg.number & "" after txt
    (#sprite):
      put vSpace & "" & arg.spriteNum & "" after txt
    (#xtra):
      put vSpace & "" & enCode( arg.name ) & "" after txt
    otherwise
      if voidP(arg.ill) then
        alert("XML parser error: Could not find a data type for" && arg)
      else
        alert("XML parser error: Data type" && arg.ilk &&  "not supported for XML conversion")
      end if
  end case
  return txt
end toXML

on fromXML aXML
  -- aXML is a string of XML created by toXML above.
  -- It returns the object(s) described in the XML
  vX = new(xtra "xmlparser")
  errCode = vX.parseString(aXML)
  errorString = vX.getError()
  if voidP(errorString) then
    vResult = convertXML( vX.makePropList() )
  else
    alert "Error parsing XML string:" && errorString
    exit
  end if
  return vResult
end fromXML

on convertXML aList
  --put aList
  -- XML to object converter.  Expects the makePropList() from an XML object created by toXML  
  case aList.name of
    ("v"): return VOID
    ("i"): return integer( aList.charData )
    ("f"): return float( aList.charData )
    ("s"): return decode( aList.charData )
    ("sy"): return symbol( decode(aList.charData) )
    ("r"): return rect( convertXML(aList.child[1]), convertXML(aList.child[2]), convertXML(aList.child[3]), convertXML(aList.child[4]) )
    ("p"): return point ( convertXML( aList.child[1]) , convertXML(aList.child[2]) )
    ("ll"):
      vList = []
      lim = aList.child.count
      repeat with i = 1 to lim
        vList.add( convertXML( aList.child[i] ) )
      end repeat
      return vList
    ("pl"):
      vList = [:]
      lim = aList.child.count/2
      repeat with i = 1 to lim
        vList.addProp( convertXML( aList.child[i*2-1] ) , convertXML( aList.child[i*2] ) )
      end repeat
      return vList  
    ("c"):
      if aList.child.count = 0 then
        return paletteIndex( integer(aList.charData) )
      else
        return rgb( integer(aList.child[1].charData), integer(aList.child[2].charData), integer(aList.child[3].charData) )        
      end if
    ("d"): return date ( integer(aList.child[1].charData) , integer(aList.child[2].charData), integer(aList.child[3].charData) )
    ("m"): return member(aList.child[1].charData)
      --return member integer(aList.child[1].charData) of castLib integer(aList.child[2].charData)
    ("cl"): return castLib integer(aList.charData)
    ("sp"): return sprite integer(aList.charData)
    ("x"): return xtra( decode ( aList.charData ) )
    otherwise
      alert("Can't convert XML" && aList.name && "to data type.")
      return VOID
  end case
end convertXML

-- The next two handlers convert special characters for XML.  e.g.  & <=> &
-- It requires a text member named "decoder" in a cast somewhere.
on deCode aTxt
  
  -- replace returns with


  newTxt = EMPTY
  the itemDelimiter = RETURN
  lim = aTxt.items.count
  repeat with i = 1 to lim
    put aTxt.item[i] after newTxt
    if i < lim then put "
" after newTxt
  end repeat
  
  -- use the internal HTML handler to decode.
  member("decoder").html = "" & newTxt & ""  
  aTxt = member("decoder").text
  return (aTxt)
end deCode

on enCode aTxt
  if aTxt = "" then return EMPTY
  vCharList = [ ["&","&"] , ["<","<"] , [">",">"] , [QUOTE,"""] , ["'","'"] ] -- "&" must be first in this list!
  lim = vCharList.count
  repeat with i = 1 to lim
    the itemDelimiter = vCharList[i][1]
    lim2 = aTxt.item.count
    if lim2 > 1 then
      tempTxt = EMPTY
      repeat with j = 1 to lim2
        put aTxt.item[j] after tempTxt
        if j < lim2 then put vCharList[i][2] after tempTxt
      end repeat
      aTxt = tempTxt
    end if
  end repeat
  
  return aTxt
end enCode  

 


Contact

MMI
36 South Court Sq
Suite 300
Newnan, GA 30263
USA

Send e-mail