Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsGeneralPHPASPPerlColdFusionFlashHTML, CSS, ScriptsBrowsers

Webmaster Forum / Flash / Data Integration / March 2008



Tip: Looking for answers? Try searching our database.

parsing XML

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
miquael - 18 Mar 2008 23:06 GMT
Why won't this work?  I just want to create one Node for each <placemark> tag
in the xml.

the xmlData trace gets:

<kml xmlns="http://earth.google.com/kml/2.2">
  <Placemark id="0" type="1">
    <name>Zero - zero</name>
    <description>This is at zero latitude and zero longitude</description>
    <Point>
      <coordinates>0,0,0</coordinates>
    </Point>
  </Placemark>
  <Placemark id="1" type="2">
    <name>Simple placemark</name>
    <description>Attached to the ground. Intelligently places itself
       at the height of the underlying terrain.</description>
    <Point>
      <coordinates>-122.0822035425683,37.42228990140251,0</coordinates>
    </Point>
  </Placemark>
  <Placemark id="2" type="3">
    <name>New York City</name>
    <description>This is a rockin' town</description>
    <Point>
      <coordinates>42.3583,-75.85,0</coordinates>
    </Point>
  </Placemark>
</kml>

Yet, I cannot even get the second "success!" trace.  

public function processMarkerData (xmlData:XML):void {

    // loop through all markers in the XML
    // and generate a node for each one
    trace ("xmlData: " + xmlData);

    for each (var xmlPlacemark:XML in xmlData.placemark) {
               
        trace ("success!");
               
        // create node
        var node:Node = new Node(
                    xmlPlacemark,
                    {
                    nodeID:    nodeID,
                    app:    this
                       });
               
        // add node to nodeArray and display container
        nodes.push(node);
        container.addChild(node);
               
               // increment id
        nodeID++;
        }
    }
}
miquael - 19 Mar 2008 02:35 GMT
please help ...
Raymond Basque - 19 Mar 2008 11:16 GMT
xmlData.placemark should be xmlData.Placemark
Raymond Basque - 19 Mar 2008 11:39 GMT
Just noticed you're using a namespace. This will work whether or not there
is a default namespace declared in the xml.

public function processMarkerData (xmlData:XML):void
{
// retrieve the default namespace
var ns:Namespace = xmlData.namespace();

// loop through all markers in the XML
// and generate a node for each one
trace ("xmlData: " + xmlData);

for each (var xmlPlacemark:XML in xmlData.ns::Placemark) {

 trace ("success!");

 // create node
 var node:Node = new Node(
   xmlPlacemark,
   {
   nodeID: nodeID,
   app: this
      });

 // add node to nodeArray and display container
 nodes.push(node);
 container.addChild(node);

 // increment id
 nodeID++;
}
}
miquael - 20 Mar 2008 02:36 GMT
Great, thanks.  Yes, that works: i am now getting the XML passed into the loop.

So, next issue is this: I'm passing xmlPlacemark to another function that then
extracts the data from the XML structure.  I am partially successfull with
extrafcting a few attributes, but am not able to extract element values.  I've
tried everything I could find in the CS3 help files.  Seem like it should be
pretty straight forward, but this does not work:

private function initContent(xmlPlacemark:XML):void {
           
            trace ("xmlPlacemark: " + xmlPlacemark); // returns just the portion of xml
needed here

            // extract data from XML
            id             = xmlPlacemark.attribute("id"); // works
            type         = xmlPlacemark.attribute("type"); // works
           
            title                = xmlPlacemark.name; // returns nothing!
            contentPath    = xmlPlacemark.description;// returns nothing!
            geoPosition     = xmlPlacemark.Point.coordinates; // returns nothing!
           
            trace ("*** id: " + id);
            trace ("*** type: " + type);
            trace ("*** title: " + title);
            trace ("*** contentPath: " + contentPath);
            trace ("*** geoPosition: " + geoPosition);
           
            // more calculations ...
        }
miquael - 20 Mar 2008 02:37 GMT
Here is the XML again:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
  <Placemark id="0" type ="1">
    <name>Zero - zero</name>
    <description>This is at zero latitude and zero longitude</description>
    <Point>
      <coordinates>0,0,0</coordinates>
    </Point>
  </Placemark>
 
    <Placemark id="1" type ="2">
    <name>Simple placemark</name>
    <description>Attached to the ground. Intelligently places itself
       at the height of the underlying terrain.</description>
    <Point>
      <coordinates>-122.0822035425683,37.42228990140251,0</coordinates>
    </Point>
  </Placemark>
 
    <Placemark id="2" type ="3">
    <name>New York City</name>
    <description>This is a rockin' town</description>
    <Point>
      <coordinates>42.3583,-75.85,0</coordinates>
    </Point>
  </Placemark>
 
</kml>
miquael - 20 Mar 2008 02:43 GMT
The trace ("xmlPlacemark: " + xmlPlacemark) returns just portions of the total
XML (as it should):

<Placemark id="2" type="3" xmlns="http://earth.google.com/kml/2.2">
  <name>New York City</name>
  <description>This is a rockin' town</description>
  <Point>
    <coordinates>42.3583,-75.85,0</coordinates>
  </Point>
</Placemark>
miquael - 20 Mar 2008 02:44 GMT
Interesting that the namespace is in there again ...
miquael - 20 Mar 2008 02:48 GMT
I've also tried this with no success:

title             = xmlPlacemark.descendants("name");
geoPosition     = xmlPlacemark.Point.(elements("coordinates"));
miquael - 20 Mar 2008 02:53 GMT
And neither of these works:

title             = xmlPlacemark..name;
title             = xmlPlacemark.elements("name");
miquael - 20 Mar 2008 03:02 GMT
These both return "null".  Why?

title             = xmlPlacemark..name[0];
title             = xmlPlacemark.name[0];
Raymond Basque - 20 Mar 2008 13:11 GMT
Dealing with xml namespaces can be a little tricky. But this document uses only
one default namespace ( xmlns="http://earth.google.com/kml/2.2" ), and it's
applied to the root node. In this case, all child nodes and their attributes
belong to that namespace, which makes it fairly easy to work with.

private function initContent(xmlPlacemark:XML):void {
 
  trace ("xmlPlacemark: " + xmlPlacemark);
 
  // declare a default namespace -- inherited from
  // parent node if none declared

  var ns:Namespace = xmlPlacemark.namespace();
  default xml namespace = ns;

  // extract data from XML
  // assumes all target members are string types:
 
  id = xmlPlacemark.@id.toString();
  type = xmlPlacemark.@type.toString();
 
  title = xmlPlacemark.name.toString();
  contentPath = xmlPlacemark.description.toString();
  geoPosition = xmlPlacemark.Point.coordinates.toString();
 
  trace ("*** id: " + id);
  trace ("*** type: " + type);
  trace ("*** title: " + title);
  trace ("*** contentPath: " + contentPath);
  trace ("*** geoPosition: " + geoPosition);
 
  // more calculations ...
  }
miquael - 20 Mar 2008 22:02 GMT
Great, yes, that helps!  I am getting good results now.  Thanks!

However, a new problem now arises: although the values are now being extracted
from the XML, when the next function is called, I get a very strange error.

Here is the new function as I have it now (which gets values for all the trace
vars):

private function initContent1(xmlPlacemark:XML, data:Object):void {
           
            trace ("xmlPlacemark: " + xmlPlacemark);
           
             // declare a default namespace -- inherited from
            // parent node if none declared
            var ns:Namespace = xmlPlacemark.namespace();
             default xml namespace = ns;
           
            // extract data from XML
           // (assumes all target members are string types)
           
            // from attributes
            id = xmlPlacemark.@id.toString();
           type = xmlPlacemark.@type.toString();
           
            // from elements
            title = xmlPlacemark.name.toString();
            contentPath = xmlPlacemark.description.toString();
             geoPosition = xmlPlacemark.Point.coordinates.toString();
           
            // parse latitude and longitude from geoPosition
            var geoPos:Array = new Array();
            geoPos = geoPosition.split(",", 3); // *
            latitude  = geoPos[0];
            longitude = geoPos[1];
            elevation = geoPos[2];
           
            trace ("*** id: " + id);
            trace ("*** type: " + type);
            trace ("*** title: " + title);
            trace ("*** contentPath: " + contentPath);
            trace ("*** geoPosition: " + geoPosition);
            trace ("*** latitude: " + latitude);
            trace ("*** longitude: " + longitude);
            trace ("*** elevation: " + elevation);
           
            // extract data from data object
            nodeID         = data.nodeID;
            app         = data.app;
        }
miquael - 20 Mar 2008 22:09 GMT
Here is the resulting output and error.  Although there are 3 <Placemark> nodes
in the XML, only the first is processed before the error emerges. I've never
seen an error like this before, followed by "VerifyError: Error #1025: An
invalid register 3 was accessed."  What's this about?

xmlPlacemark: <Placemark id="0" type="1"
xmlns="http://earth.google.com/kml/2.2">
  <name>Zero point: 0, 0, 0</name>
  <description>sample.html</description>
  <Point>
    <coordinates>0,0,0</coordinates>
  </Point>
</Placemark>
*** id: 0
*** type: 1
*** title: Zero point: 0, 0, 0
*** contentPath: sample.html
*** geoPosition: 0,0,0
*** latitude: 0
*** longitude: 0
*** elevation: 0
verify UI::Node/UI:Node::setType()
                        stack:
                        scope: [global Object$ flash.events::EventDispatcher$
flash.display::DisplayObject$ flash.display::InteractiveObject$
flash.display::DisplayObjectContainer$ flash.display::Sprite$
flash.display::MovieClip$ UI::Node$]
                         locals: UI::Node *
  0:getlocal0
                        stack: UI::Node
                        scope: [global Object$ flash.events::EventDispatcher$
flash.display::DisplayObject$ flash.display::InteractiveObject$
flash.display::DisplayObjectContainer$ flash.display::Sprite$
flash.display::MovieClip$ UI::Node$]
                         locals: UI::Node *
  1:pushscope
                        stack:
                        scope: [global Object$ flash.events::EventDispatcher$
flash.display::DisplayObject$ flash.display::InteractiveObject$
flash.display::DisplayObjectContainer$ flash.display::Sprite$
flash.display::MovieClip$ UI::Node$] UI::Node
                         locals: UI::Node *
  2:getlocal3
VerifyError: Error #1025: An invalid register 3 was accessed.
    at UI::Node/UI:Node::setType()
    at UI::Node$iinit()
    at MeadanGlobe/processMarkerData()
    at Function/http://adobe.com/AS3/2006/builtin::call()
    at support::DataLoader/support:DataLoader::loadDataComplete()
    at
flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunctio
n()
    at flash.events::EventDispatcher/dispatchEvent()
    at flash.net::URLLoader/flash.net:URLLoader::onComplete()
miquael - 20 Mar 2008 22:15 GMT
Now if I revert to the previous function that uses the previous XML schema,
then this error does not emerge. I mean, I have now "initContent1(xmlPlacemark,
data);" and "initContent2(xmlPlacemark, data);" to easily switch between
functions for testing (I call either one or the other).  If I use the original
function (initContent2), everything works--but only if I comment out the entire
new function (initContent1).  Here is the original function again.  Not much is
different:

private function initContent2(xmlPlacemark:XML, data:Object):void {
           
            trace ("xmlPlacemark: " + xmlPlacemark);
           
            var attributes:XMLList = xmlPlacemark.attributes();
         
            id             = attributes[0];
            title         = attributes[1];
            type         = attributes[2];
            contentPath = attributes[3];
           
            geoPosition   = xmlPlacemark.georss;
           
            // parse latitude and longitude from georss
            var latlong:Array = new Array();
            latlong = geoPosition.split(" ", 2);
            latitude  = latlong[0];
            longitude = latlong[1];
           
            trace ("*** id: " + id);
            trace ("*** type: " + type);
            trace ("*** title: " + title);
            trace ("*** contentPath: " + contentPath);
            trace ("*** geoPosition: " + geoPosition);
            trace ("*** latitude: " + latitude);
            trace ("*** longitude: " + longitude);
           
            // extract data from data object
            nodeID         = data.nodeID;
            app         = data.app;
        }
miquael - 20 Mar 2008 22:19 GMT
And here is the setType() function, on which it appear the error is happening.  
Again, this error only happens here whenever initContent1 is left in the code
(not commented out), independent of weather it is actually being called or not!
What's going on here?!

Here is setType():

private function setType():void {
           
            switch (type) {
               
                case "1":
                    colorCode = 0xE06117; // red
                    break;
               
                case "2":
                    colorCode = 0x6DC1EF; // blue
                    break;
               
                case "3":
                    colorCode = 0x7FDD34; // green
                    break;
               
                case "4":
                    colorCode = 0xD0C32E; // yellow
                    break;
                   
                default:
                    colorCode = 0xFFFFFF; // white
                    break;
            }
           
            if (!meadanColors) {colorCode = 0xFFFFFF}
            colorTransform(colorCode);
        }
miquael - 20 Mar 2008 22:21 GMT
FYI, the entire code base for this project is an open-source project that is available here:

http://code.google.com/p/meadanglobe
miquael - 20 Mar 2008 22:29 GMT
I was not able to find much info on "Error #1025: An invalid register 3 was accessed".  What's this about?
Raymond Basque - 21 Mar 2008 15:16 GMT
Holy crap! Took a little bit of investigating, but it seems that if you hold
a reference to a namespace within a method and set the default xml namespace
to that namespace, BANG!  Most likely the namespace goes out of scope. There
are 2 ways to fix the problem.

1. In each method, set the default xml namespace to null when no longer
needed:

 private function initContent1(xmlPlacemark:XML, data:Object):void {

  trace ("xmlPlacemark: " + xmlPlacemark);

    // declare a default namespace
   var ns:Namespace = xmlPlacemark.namespace();
    default xml namespace = ns;
// ... other stuff
 default xml namespace = null;
}

2. Store the namespace in a private field:

 // private variable to hold a copy of the namespace belonging
 // to the xmlPlacemark node passed to the ctor
 // We need to do this to get around a nasty problem
 // where if we set the default xml namespace to a local reference
 // and then forget to set it to null, we get
 // "VerifyError: Error #1025: An invalid register 3 was accessed."
 // OUCH!!
 private var ns:Namespace = null;

 // NODE CONSTRUCTOR ////////////////////////////////////
 public function Node(xmlPlacemark:XML, data:Object):void {
  // store the namespace for future reference
  ns = xmlPlacemark.namespace();
  initContent1(xmlPlacemark, data);
  //initContent2(xmlPlacemark, data);

  setType();
  setPosition();
  initTextDisplay();
  //
  addEventListener(Event.ENTER_FRAME, update);
  addEventListener(MouseEvent.CLICK, clickHandler);
  addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
  addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler);
 }

 private function initContent1(xmlPlacemark:XML, data:Object):void {

  trace ("xmlPlacemark: " + xmlPlacemark);

    // declare a default namespace -- was stored in private var
    default xml namespace = ns;
// ... other stuff
}
 private function initContent2(xmlPlacemark:XML, data:Object):void {

  trace ("xmlPlacemark: " + xmlPlacemark);

    // declare a default namespace -- was stored in private var
    default xml namespace = ns;
// ... other stuff
}
Raymond Basque - 21 Mar 2008 16:55 GMT
... Most likely "because" the namespace goes out of scope. ..
miquael - 21 Mar 2008 21:38 GMT
That's it!  Good find.  I went with solution #1

Thanks so much for your help!
Raymond Basque - 21 Mar 2008 23:11 GMT
You're welcome.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.