views:

951

answers:

2

I'm using an XMLparser class to convert XML into an object.

The problem is that the XML I have contains a dot in the nodeName (estate_size.primary_room_area). This of course doesn't work since it uses the dot notation for the object path already.

Some ideas, but have no idea how to do them:
-Replace the dot in the name somehow
-Change the name.
-Any better?

I can't use the native childNodes and stuff, since the XML isn't always in the right order. I don't have access to edit the XML.

Anyone have a solution to this?


XML:

<iad>
  <DataTag>
 <element id="0">
   <changed_string>2009-08-20T10:56:00Z</changed_string>
   <estate_price.price_suggestion>2500000</estate_price.price_suggestion>
   <estate_size.primary_room_area>117</estate_size.primary_room_area>
 </element>
  </DataTag>
</iad>

AS2:

    var xml:XMLParser = new XMLParser();
xml.loadXML("file.xml");
xml.onXMLLoad = function () {
  _root.estate_size.text = xml.data.iad.DataTag.element[0].estate_size.primary_room_area;
}

XMLparser:

//import net.za.mediumrare.xmlPackage.XMLParser;
//var myObject:XMLParser = new XMLParser ();
//myObject.loadXML ("content.xml");
//myObject.onXMLLoad = function () {
// listAll (myObject.data);
//};



// IMPORTED DEPENDENCIES
//
import mx.utils.Delegate;
import mx.events.EventDispatcher;
//
class XMLParser {
    //
    // PRIVATE PROPERTIES
    //
    private var xml:XML;
    public var data:Object;
    //
    //
    //
    public function get _xml():XML {
      return xml;
    }
    public function set _xml(x:XML) {
      xml = x;
    }
    public function get _data():Object {
      return data;
    }
    public function set _data(o:Object):Void {
      trace("ERROR - \"XMLParser\" _data property is read-only and connot be set.");
    }
    //
    // CONSTRUCTOR
    //
    public function XMLParser(s:String) {
      initXML(s);
      //data = new Object();
      EventDispatcher.initialize(this);
    }
    //
    // PRIVATE METHODS
    //
    public function buildObject (n){
   var o = new String (n.firstChild.nodeValue), s, i, t;
  for (s = (o == "null") ? n.firstChild : n.childNodes[1]; s != null; s = s.nextSibling) {
   t = s.childNodes.length > 0 ? arguments.callee (s) : new String (s.nodeValue);
   for (i in s.attributes) {
    t[i] = s.attributes[i];
   }
   if (o[s.nodeName] != undefined) {
    if (!(o[s.nodeName] instanceof Array)) {
     o[s.nodeName] = [o[s.nodeName]];
    }
    o[s.nodeName].push (t);
   }
   else {
    o[s.nodeName] = t;
   }
  }
  data=o;
  xml = new XML();
  return data;
 };

    private function initXML(s:String):Void {
      if (s == undefined) {
        xml = new XML();
      xml.ignoreWhite = true;
      } else {
        xml = new XML(s);
      xml.ignoreWhite = true;
      }
      xml.onLoad = Delegate.create(this, xmlOnLoad);
    }
    private function xmlOnLoad(success:Boolean):Void {
      if (success) {
        trace("SUCCESS - xml loaded successfully.");
        //xml.ignoreWhite = true;
        this.dispatchEvent({type:"onXMLLoad", target:this});
      buildObject(xml);
        this.onXMLLoad();
      } else {
        trace("ERROR - xml could not load");
        return;
      }
    }
    //
    // PUBLIC METHODS
    //
    public function loadXML(url:String):Void {
      xml.load(url);
    }
    public function getBytesTotal():Number {
      return xml.getBytesTotal();
    }
    public function getBytesLoaded():Number {
      return xml.getBytesLoaded();
    }
    public function getPercentLoaded():Number {
      return Math.floor((this.getBytesLoaded() / this.getBytesTotal()) * 100);
    }

    //
    // EVENTS
    //
    public function onXMLLoad():Void {
      // onLoad proxy for internal xml object
    }
    public function onXMLParse():Void {
      // called when xml is finished parsing
    }
    function addEventListener() {
      // Used by EventDispather mixin
    }
    function removeEventListener() {
      // Used by EventDispather mixin
    }
    function dispatchEvent() {
      // Used by EventDispather mixin
    }
    function dispatchQueue() {
      // Used by EventDispather mixin
    }
//



}
+2  A: 

The XMLParser doesn't seem to be working. Putting a trace(xml.data) in your onXMLLoad returns null.

Hmm... I see that you just put an example? First ideea, use this instead

xml.data.iad.DataTag.element[0]['estate_size.primary_room_area']

Second idea, tricky and cumbersome. When you load an XML you can load it using a LoadVars Object. On the LoadVars object you have 2 method: onLoad (which is normally used) and onData which gives you access to the exact string that came from the server. Bypassing the XML loading through a loadVars object will give you access to the XML String that you will be able to manipulate it as a string and eventually replace the dot (harder in AS2 without regexp and given the fact that you might find dots in other places not only in node names).

Virusescu
Actually this worked: xml.data.iad.DataTag.element[0]['estate_size.primary_room_area'], can you explain to me what it does and why it works?
mofle
Because the translation methods in XMLParser were converting all the nodes in the loaded XML into an Object.Any Object in Actionscript can be addressed like an Associative Array. So any property can be accessed like that.. for example _root["movieclipName"].play() or even _root.movieclipName["play"]();
Virusescu
A: 

I'm going for the short answer here. Please don't parse XML use XPath instead.

With XPath your code will be more readable and much more maintainable. Imagine, six months from now you have to make a change to this code because for some reason your XML structure changed. You will be looking at this:

xml.data.iad.DataTag.element[0]['estate_size.primary_room_area']

...and think to yourself. O.M.G...

UPDATE:

To answer your comment, this would be an example of retrieving a value from the XML by using XPath. The code assumes that the example XML you gave in your question is stored in a file called mydata.xml:

import mx.xpath.XPathAPI;

var xmldata : XML;
xmldata = new XML();
xmldata.ignoreWhite = true;
xmldata.onLoad = function(success : Boolean) : Void
{
    var query = "iad/DataTag/element/estate_size.primary_room_area/*";

    var area = XPathAPI.selectSingleNode(this.firstChild, query );

    trace( area );
};
xmldata.load("mydata.xml");

To get a better understanding of XPath have a look through the article I pointed out in my initial answer.

Luke
Can you show me an example get the "estate_size.primary_room_area" with Xpath?
mofle
Updated my answer with an example.
Luke