Articles Archive
Articles Search
Director Wiki
 

Reading XML Into Director MX 2004 With a Simple Flash Object

May 9, 2005
by Darrel Plant

Personally, I love lists. Linear lists or property lists, I've used both of them for over a decade to store data in a variety of forms inside Director. They're easy to create, they're easy to manipulate, and they play well with Lingo.

Unfortunately, the rest of the world is not so enamored of lists as I. They are not the lingua franca of data transfer. No, everyone else seems to be smitten with this creature called XML (Extensible Markup Language). It's all over the Internet. It's become so pervasive that many of the Director projects I've done in the past few years have required me to work with it, to save preferences that can be edited by the end-users or some other purpose.

Now, I think XML's a little wordy, myself. An awful lot of what's out there uses long, descriptive text strings for node names that are repeated dozens or hundreds of times in an XML data file. It's like using strings as the names in a property list instead of symbols. Just gives me the heebie-jeebies.

But what are you gonna do? Sometimes you just need to go with the flow.

Unfortunately, as many of you know, when XML capabilities were added to Director, there were a few rocks in the channel of that flow. The XML Parser Xtra (introduced, if I remember correctly, in Director 7) was plagued by a memory leak that wasn't fixed for some time. Andy White wrote a Lingo XML parser that's been popular for years. And sites like Shocknet pushed the concept of structured document manipulation with their DOM-Lingo.

But what if — like me — your brain starts to hurt reading about the myriad possibilities of nodes and branches? What if you just want something that will load the dang XML into Director?

What I've been doing with a fair amount of success over the past year is using Flash objects to read XML data from URLs over the Internet and also from local files. It's fairly fast, it's a small amount of code, and I've modified it for complex situations as needed. For the purposes of this article, however, I've stripped it down to its bare necessities.

First, let's establish what we're trying to do. This is the beginning of the XML data we want to read; the Most Recent Articles XML feed from right here at Director Online (as viewed in Internet Explorer):

As a control, this is a portion of the property list that the makeList method of the XML Parser Xtra creates from the same section of data:

["ROOT OF XML DOCUMENT": ["!ATTRIBUTES": [:], "rdf:RDF": ["!ATTRIBUTES": ["xmlns:rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "xmlns:dc": "http://purl.org/dc/elements/1.1/", "xmlns": "http://purl.org/rss/1.0/", "xmlns:admin": "http://webns.net/mvcb/", "xmlns:l": "http://purl.org/rss/1.0/modules/link/", "xmlns:content": "http://purl.org/rss/1.0/modules/content/"], "channel": ["!ATTRIBUTES": ["rdf:about": "http://director-online.com"], "title": ["!ATTRIBUTES": [:], "!CHARDATA": "Director Online Articles"], "link": ["!ATTRIBUTES": [:], "!CHARDATA": "http://director-online.com"], "description": ["!ATTRIBUTES": [:], "!CHARDATA": "Articles for Macromedia Director developers."], "dc:date": ["!ATTRIBUTES": [:], "!CHARDATA": "2005-04-28T06:54:43Z"], "dc:language": ["!ATTRIBUTES": [:], "!CHARDATA": "en-US"]], "item": ["!ATTRIBUTES": ["rdf:about": "http://director-online.com/buildArticle.php?id=1152"], "title": ["!ATTRIBUTES": [:], "!CHARDATA": "Scrolling Text Horizontally"], "link": ["!ATTRIBUTES": [:], "!CHARDATA": "http://director-online.com/buildArticle.php?id=1152"], "description": ["!ATTRIBUTES": [:], "!CHARDATA": "Use a single line text sprite to make horizontally scrolling text that automatically scrolls to the left."], "dc:creator": ["!ATTRIBUTES": [:], "!CHARDATA": "Director Online"], "dc:date": ["!ATTRIBUTES": [:], "!CHARDATA": "2005-04-11T08:52:03Z"]], "item": ["!ATTRIBUTES": ["rdf:about": "http://director-online.com/buildArticle.php?id=1151"], "title": ["!ATTRIBUTES": [:], "!CHARDATA": "Highlighting Multiple Text Selections"], "link": ["!ATTRIBUTES": [:], "!CHARDATA": "http://director-online.com/buildArticle.php?id=1151"], "description": ["!ATTRIBUTES": [:], "!CHARDATA": "Highlighting text in uneditable Text members is not a simple matter. It requires a separate sprite. So why not exploit this fact to create a multiple selection highlight?"], "dc:creator": ["!ATTRIBUTES": [:], "!CHARDATA": "Director Online"], "dc:date": ["!ATTRIBUTES": [:], "!CHARDATA": "2005-04-07T09:49:29Z"]]...
Not very pretty, is it? Remember what I was saying about using strings instead of symbols for property names?

If things aren't going to be pretty, why not just stay with XML?

My XML-reading routine creates a Lingo script parent object. The parent object is fed two parameter values, a string with the path to the XML data (which can be a local file for a projector or a network file for projectors and Shockwave) and an object reference where a message is sent when the data's been received (because retrieving the data doesn't happen instantaneously, it needs to send a message on completion).

Here's the entirety of the parent script I named "XMLObject":

property objXML, boolValid, objTarget

on new me, strXMLFilePath, objTarg
  boolValid = false
  objTarget = objTarg
  objXML = newObject ("XML")
  objXML.ignoreWhite = true
  setCallback (objXML, "onLoad", #XMLLoadComplete, me)
  objXML.load (strXMLFilePath)
  return me
end

on XMLLoadComplete me
  boolValid = not voidP (objXML.xmlDecl)
  objTarget.mXMLCompleted (boolValid, me)
end

The object has three properties. boolValid is a flag that can be checked at any time to see if there is valid XML data to be accessed. objXML is a Flash XML object created to read and parse the XML text data. objTarget determines which object the mXMLCompleted callback message is sent to.

When the object is instantiated, the properties are initialized, the Flash XML object is created (why wouldn't you set the ignoreWhite option?) and a Flash callback is set up that notifies the parent script object when the Flash XML object has received an onLoad message. Then a load command is issued with the file path and it's in Flash's hands.

When the load operation completes (either through a finished load or an error), the parent script's XMLLoadComplete handler is invoked (because of the callback set in the new handler). My own crude methodology for determining that a proper XML document has been successfully retrieved is to check for the xmlDecl property that's supposed to be a part of every XML document. If the value in the Flash XML object is not void, then you should have good XML. Perhaps not the XML document you were expecting, but an XML document; there's always room for more error-checking.

With the changes to the object model access in Director MX 2004, _movie can be passed as the second parameter to the parent script's new handler. If so, the movie script handler here would be called:

on mXMLCompleted boolValid, scriptXML
  put "XML Load Completed"
  if boolValid then
    put scriptXML.objXML.toString ()
  end if
end
When a valid XML document has been parsed, the Flash XML object's toString method is used to display the data in the Message window (but of course, you could do anything you want). Here's a sample series of lines from the Message window:

doug = new (script "XMLObject", "http://director-online.com/rss/director-online-articles.xml", _movie)
-- "XML Load Completed"
-- "<?xml version="1.0" encoding="UTF-8"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://purl.org/rss/1.0/" xmlns:admin="http://webns.net/mvcb/" xmlns:l="http://purl.org/rss/1.0/modules/link/" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel rdf:about="http://director-online.com"><title>Director Online Articles</title><link>http://director-online.com</link><description>Articles for Macromedia Director developers.</description><dc:date>2005-04-28T06:54:43Z</dc:date><dc:language>en-US</dc:language></channel><item rdf:about="http://director-online.com/buildArticle.php?id=1152"><title>Scrolling Text Horizontally</title><link>http://director-online.com/buildArticle.php?id=1152</link><description>Use a single line text sprite to make horizontally scrolling text that automatically scrolls to the left.</description><dc:creator>Director Online</dc:creator><dc:date>2005-04-11T08:52:03Z</dc:date></item><item rdf:about="http://director-online.com/buildArticle.php?id=1151"><title>Highlighting Multiple Text Selections</title><link>http://director-online.com/buildArticle.php?id=1151</link><description>Highlighting text in uneditable Text members is not a simple matter. It requires a separate sprite. So why not exploit this fact to create a multiple selection highlight?</description><dc:creator>Director Online</dc:creator><dc:date>2005-04-07T09:49:29Z</dc:date></item>
...
</rdf:RDF>"

put doug.objXML.firstChild.firstChild.nodeName
-- "channel"
put doug.objXML.firstChild.childNodes.length
-- 6.0000
put doug.objXML.firstChild.childNodes[0].firstChild.nodeName
-- "title"
put doug.objXML.firstChild.childNodes[0].firstChild.firstChild.nodeValue
-- "Director Online Articles"
put doug.objXML.firstChild.childNodes[2].firstChild.nodeName
-- "title"
put doug.objXML.firstChild.childNodes[2].firstChild.firstChild.nodeValue
-- "Highlighting Multiple Text Selections"

Note that because the XML object is a Flash entity that its indexing system begins with 0 rather than our beloved 1. And don't forget that text nodes in XML (like the actual text data of the item title node) are additional, unnamed child nodes, which is why the value of the title is accessed with firstChild.nodeValue.

That's it, really. Because you can directly manipulate the XML object through MX 2004's access to Flash object methods, you can do most everything you need natively in Flash, including looping through the XML tree as if it was an array (using the childNodes sub-object). Or, if you're like me, you'll write a series of scripts to convert the XML data to property list structures that are a bit more to your personal taste than those produced by the XML Parser Xtra. Of course, if you're saving out XML data, you've got to go the other way, as well. It's not incredibly difficult, but it's beyond the scope of this article.

My extensions to this for my own use have mostly been to add options for tracking the file path (it's not saved in this version in either the parent script or the Flash XML object) and add options for the message sent when the XML loading is complete. On a more meta level, it's always good to set up a way to delete these objects when you're done with them (and after you've done everything you might need to with the XML data), a sequencer so that you're not trying to pull in too many simultaneous streams of XML data (or anything else) at the same time, some way to cancel operations, etc. But if you've been gritting your teeth over XML operations and you're using Director MX 2004, this method may provide you with a good alternative to what you're using now.

Happy loading!

(Source movie, for both Mac and PC, .zip fomat: simplexml.zip)

Darrel Plant is Technical Editor of Director Online. He is the Publisher at Moshofsky/Plant Creative Services in Portland, Oregon, and the author of or contributor to a number of books on Macromedia Director and Flash, including Special Edition Using Flash 5,, Flash 5 Bible, and Director 8.5 Studio..

Copyright 1997-2017, Director Online. Article content copyright by respective authors.