« Breeze Does it All (including 3-D) | Main | Leaving for Flashforward 2004 »

February 27, 2004

Searching Through XML Objects

It's not exactly XPath, but it's handy. The ActionScript 2.0 SearchableXML object below will help find elements in an XML object quickly. Assume, for instance, that you have an XML file like this:


<software>
    <tools>
        <product name="Flash" version="MX 2004"/>
        <product name="Dreamweaver" version="MX 2004"/>
    </tools>
    <servers>
        <product name="ColdFusion" version="MX 6.1"/>
        <product name="Flex" version="1.0"/>
    </servers>
    <foo>
        <bar>
            <baz>Have a good weekend</baz>
        </bar>
    </foo>
</software>

The SearchableXML object will let you do this:


import com.macromedia.xml.SearchableXML;

var myXml:SearchableXML = new SearchabelXML();
myXml.parseXML(xmlFileAbove);

// Returns the Flash and Dreamweaver XML elements.
var allTools:Array = myXml.findElement("software.tools");

// Returns the ColdFusion and Flex XML elements.
var allServers:Array = myXml.findElement("software.servers");

// Returns "Have a good weekend"
var msg:String = myXml.findElement("software.foo.bar.baz")[0].firstChild.nodeValue;

Here's the code:


/**
 * Adds some search functionality to the XML object.
 *
 * @author Christian Cantrell
 */
class com.macromedia.xml.SearchableXML
    extends XML
{       
    /** 
     * Iterates through the XML object, looking for a specific
     * element or set of elements.
     *  
     * @path A dot delimited path to the element you're looking for.
     */ 
    public function findElement(path:String):Array
    {
        var pathNodes:Array = path.split(".");
        var currentChild:XML = this;
        var elementArray:Array = new Array();
        for (var i = 0; i < pathNodes.length; ++i)
        {
            var children = currentChild.childNodes;
            for (var j = 0; j < children.length; ++j)
            {
                if (children[j].nodeType == 1 && children[j].nodeName == pathNodes[i])
                {
                    if (i == (pathNodes.length - 1))
                    {
                        elementArray.push(children[j]);
                    }
                    else
                    {
                        currentChild = children[j];
                    }
                }
            }
        }
        return elementArray;
    }
}

Disclaimer: Only lightly tested for a project I just started working on. Let me know if you find any bugs.

Posted by cantrell at February 27, 2004 4:54 PM

Comments

Chris,
I haven't used the code or done a lot of xml parsing with AS 2.0 as of yet but you might want to change the token you parse to build your query. Some XML parsers ( I'm not sure about AS 2.0 ) accept a period in element names and that can lead to some unexpeceted results here. =^)

Ex:
<this.breaks><message /></this.breaks>

Regards

Posted by: rob at February 27, 2004 9:21 PM

Good point. Maybe I'll change to slashes, or make the token configurable.

Christian

Posted by: Christian Cantrell at February 27, 2004 11:28 PM

Nice stuff though!

Posted by: Mike Britton at March 1, 2004 3:15 PM




Remember Me?

(you may use HTML tags for style)