Register

If this is your first visit, please click the Sign Up now button to begin the process of creating your account so you can begin posting on our forums! The Sign Up process will only take up about a minute of two of your time.

Page 1 of 2 1 2 LastLast
Results 1 to 10 of 15
  1. #1
    Senior Member Tomaszewski's Avatar
    Join Date
    Oct 2006
    Location
    Exton, PA
    Posts
    194
    Member #
    14132
    sooo... i have a question.. i'm tasked with building this app and need to take the below XML and parse it into a multi-dimensional associative array.

    Code:
    trace(_xmlDataArray["AL"][0])
    // 87369
    trace(_xmlDataArray["AL"][1])
    // 12/31/2008
    // etc....

    Code:
    	<state>
    		[INDENT]<name>AL</name>
    		<income>87369</income>
    		<doctorStats>
    			
    <period id="1">
    <date>12/31/2008</date> <participants>485</participants>
    </period> <period id="2"> <date>12/31/2003</date> <participants>294</participants> </period> <period id="3"> <date>12/31/1998</date> <participants>211</participants> </period>
    </doctorStats> <prescription>
    <type>Non-controlled drugs from approved formulary</type>
    </prescription> <programs>
    <prog id="1">
    <name>University of South Alabama in Mobile</name> <link>http://southalbama.edu/alliedhealth/pa/</link>
    </prog> <prog id="2">
    <name>University of Alabama at Birmingham Surgical</name> <link>http://main.uab.edu/shrp/default.aspx?pid=77392</link>
    </prog> <prog id="3">
    <name></name> <link></link>
    </prog>
    </programs> <organizations>
    <org>
    <type>State Organization</type> <name>Alabama Society of Physician Assitants</name> <link>http://www.aapacoms.org/aspa</link>
    </org> <org >
    <type>Federal Organization</type> <name>Federal Society of Physician Assitants</name> <link>http://www.thefeds.gov</link>
    </org> <org >
    <type></type> <name></name> <link></link>[/NDENT] </org>
    </organizations> <fact>Did you know? About 46.3% of Alabama PA's practice in a surgical specialty</fact> <source>Source: American Academy of Physicians Assistants</source>
    </state>
    The question I have is how in the heck do I get is so that each text value of each node gets shoved into the appropriate array index?

    So each state will have a <state>PA</state> XML structure with its own data just like AL above in the XML. So for (i.e., PA), i need to put the relevant data like income into index [0] of the _xmlDataArray["PA"] array.

    Here is what I have so far:

    Code:
    
    
    		private function buildArray(theXML:XML):void
    		{
    			_xmlDataArray = new Array();
    
    			for (var i:uint; i < theXML.state.length(); i++)
    			{
    				//trace(theXML.state.name[i]);
    				_xmlDataArray[theXML.state[i].name.children()] = [theXML.state[i].income.toString()];
    				recurssion(theXML.state[i].name,theXML);
    			}
    		}
    		
    		private function recurssion(usaState:String, theXML:XML):void
    		{
    			if(theXML.children())
    			{
    				//for each
    			}
    			trace(_xmlDataArray[usaState]);
    		}
    I've attached the XML file beacuse the rendering on this post isn't the best!

  2.  

  3. #2
    WDF Staff smoseley's Avatar
    Join Date
    Mar 2003
    Location
    Boston, MA
    Posts
    9,729
    Member #
    819
    Liked
    205 times
    Try something like this.. Not fully tested, but you see where it's going:

    Code:
    var arr:Array = convertXmlToArray(xml);
    
    function convertXmlToArray(xml:XML):Array {
    	var xmlArray:Array = new Array();
    	
    	// Populate children
    	for (var i:uint = 0; i < xml.length(); i++) {
    		var xmlNode:XML = xml.children()[i];
    		if (xmlNode.hasComplexContent()) {
    			// Recursion
    			xmlArray[xmlNode.name().localName] = convertXmlToArray(xmlNode);
    		}  else {
    			// Text node
    			xmlArray[xmlNode.name().localName] = xmlNode.toString();
    		}
    	}
    	
    	// Return appropriate element
    	if (xml.parent() == null) {
    		// Top level element
    		var mainArray:Array = new Array();
    		mainArray[xml.name().localName] = xmlArray;
    		return mainArray;
    	} else {
    		// Other element
    		return xmlArray;
    	}
    }

  4. #3
    Senior Member Tomaszewski's Avatar
    Join Date
    Oct 2006
    Location
    Exton, PA
    Posts
    194
    Member #
    14132
    Quote Originally Posted by smoseley
    Code:
    			xmlArray[xmlNode.name().localName] = convertXmlToArray(xmlNode);

    Ok, but this traces state where it needs to be the name of the state (i.e., "AL"). So i converted it to

    Code:
    _xmlDataArray[xmlNode.child("name")] = "blah blah";
    ... this works...

    Code:
    trace(_xmlDataArray["AL"]);
    //blah blah

    still, i can't figure out a way how to populate the array with the rest of the data

  5. #4
    WDF Staff smoseley's Avatar
    Join Date
    Mar 2003
    Location
    Boston, MA
    Posts
    9,729
    Member #
    819
    Liked
    205 times
    Ok, I see how you want it now.

    On a side note, I forgot that ActionScript Arrays don't allow associative keys. You'll have to use the Object Class.

    This should do what you want (you can still reference the object values as though they are part of an array):

    Code:
    var xml:XML = 
    	<medicalInfo>
    		<state>
    			<name>AL</name>
    			<source>Source: American Academy of Physicians Assistants</source>
    		</state>
    		<state>
    			<name>GA</name>
    			<source>Source: Other Stuff</source>
    			<complex>
    				<val1>test</val1>
    				<val2>another test</val2>
    			</complex>
    		</state>
    	</medicalInfo>;
    	
    
    var medInfo:Object = getStateArray(xml);
    
    trace(medInfo);
    trace(medInfo["AL"]["source"]);
    trace(medInfo.AL.source);
    trace(medInfo.GA.complex.val1);
    trace(medInfo.GA.complex.val2);
    
    function getStateArray(xml:XML):Object {
    	var xmlAssoc:Object = new Object();
    	for (var i:uint = 0; i < xml.children().length(); i++) {
    		var xmlNode:XML = xml.children()[i];
    		xmlAssoc[xmlNode.child("name")] = convertXmlToAssoc(xmlNode);
    	}
    	return xmlAssoc;
    }
    
    
    function convertXmlToAssoc(xml:XML):Object {
    	var xmlAssoc:Object = new Object();
    	
    	// Populate children
    	for (var i:uint = 0; i < xml.children().length(); i++) {
    		var xmlNode:XML = xml.children()[i];
    		if (xmlNode.hasComplexContent()) {
    			// Recursion
    			xmlAssoc[xmlNode.name().localName] = convertXmlToAssoc(xmlNode);
    		}  else {
    			// Text node
    			xmlAssoc[xmlNode.name().localName] = xmlNode.toString();
    		}
    	}
    	return xmlAssoc;
    }

  6. #5
    Senior Member
    Join Date
    Jun 2005
    Location
    Atlanta, GA
    Posts
    4,146
    Member #
    10263
    Liked
    1 times
    To be clear, Array does support associative keys, but if you're going to use them there's no reason to use Array. That is to say, since an Array is an Object, it will also take associative keys, but then you've needlessly added the functionality of an Array to something that need only be an Object.

  7. #6
    Senior Member Tomaszewski's Avatar
    Join Date
    Oct 2006
    Location
    Exton, PA
    Posts
    194
    Member #
    14132
    I feel stupid!

    ME:


    Your a genious. Coulple of question though (surprised?? LOL):

    I rewrote your code to learn what its doing. I also integrated as part of my class.

    1. After reading Adobe's description of xml.hasComplexContent() property, I must say that I'm lost as to why you have used it. The only thing I can think of is that if its complex content, than it gets treated like an XMLList and not XML. But then again... if so... than I didn't see you calling anything from the XMLlist.
    2. The same goes for localName. From what I can tell, this is outputting the name contained by the XML (i.e, <name>AL</name> // AL)...
    3. In my XML tree, there are 3 <period> children under <doctorStats> as an example. Currently, the recursive code is pulling in only 1 of those. So if I wanted to pull into the array, as many as there are, would that mean I would have to do a for loop if the recursion sees children()?

  8. #7
    Senior Member
    Join Date
    Jun 2005
    Location
    Atlanta, GA
    Posts
    4,146
    Member #
    10263
    Liked
    1 times
    hasComplexContent basically returns true if the element has children.

    localName is used to retrieve the name of the XML element without a namespace (in your case, there are no XML namespaces anyway, so it would be the same as the name).

    Your problem with the three period children is that you would have to check for multiple children of the *same name*, and, instead of assigning them to the same spot in the object, you would need an array to store them. So the way it's currently doing it now, it tries to put the first period object into arr["period"], and then when it sees the next one, it puts it in the same place, replacing the other one. One good way to do it would be this:

    Code:
                    var content:Object;
    
                    if (xmlNode.hasComplexContent())
                    {
    			// Recursion
    			content = convertXmlToAssoc(xmlNode);
    		}
                    else
                    {
    			// Text node
    			content = xmlNode.toString();
    		}
    
                   var name:String = xmlNode.name().localName;
                   var currentElement:Object = xmlAssoc[name];
                   if (! currentElement) // if there is nothing there yet
                       xmlAssoc[name] = content;
                   else if (currentElement is Array)
                       currentElement.push(content);
                   else
                       xmlAssoc[name] = new Array(currentElement, content);
    This basically builds the data for the current child, then checks if there is an existing entry in the list for it. If there is, then it makes sure that entry is an array and adds the content of this child to that array.

  9. #8
    Senior Member Tomaszewski's Avatar
    Join Date
    Oct 2006
    Location
    Exton, PA
    Posts
    194
    Member #
    14132
    Quote Originally Posted by Shadowfiend
    localName is used to retrieve the name of the XML element without a namespace (in your case, there are no XML namespaces anyway, so it would be the same as the name).
    can you elaborate on this a little more?

    Quote Originally Posted by Shadowfiend
    Code:
                    var content:Object;
    
                    if (xmlNode.hasComplexContent())
                    {
    			// Recursion
    			content = convertXmlToAssoc(xmlNode);
    		}
                    else
                    {
    			// Text node
    			content = xmlNode.toString();
    		}
    
                   var name:String = xmlNode.name().localName;
                   var currentElement:Object = xmlAssoc[name];
                   if (! currentElement) // if there is nothing there yet
                       xmlAssoc[name] = content;
                   else if (currentElement is Array)
                       currentElement.push(content);
                   else
                       xmlAssoc[name] = new Array(currentElement, content);
    so, would I put this after the first recursion?

    example:

    Code:
    		private function buildArray(xml:XML):Object
    		{
    			var xmlAssoc:Object = new Object();
    			for (var i:uint = 0; i < xml.children().length(); i++)
    			{
    				var xmlNode:XML = xml.children()[i];
    				xmlAssoc[xmlNode.child("name")] = recursion(xmlNode);
    			}
    			
    			return xmlAssoc;
    		}
    		
    		private function recursion(xml:XML):Object
    		{
    			var xmlAssoc:Object = new Object();
    			for (var i:uint = 0; i < xml.children().length(); i++)
    			{
    				var xmlNode:XML = xml.children()[i];
    				if (xmlNode.hasComplexContent())
    				{
    					//Recurssion
    					xmlAssoc[xmlNode.name().localName] = recursion(xmlNode);\
    
    /* ******************* HERE ******************************** /
    } else { xmlAssoc[xmlNode.name().localName] = xmlNode.toString(); } }

  10. #9
    Senior Member
    Join Date
    Jun 2005
    Location
    Atlanta, GA
    Posts
    4,146
    Member #
    10263
    Liked
    1 times
    You would replace the body of the for loop, except for the xmlNode declaration, with it.

    As for namespaces. Basically, an XML namespace is a way to include tags from multiple `categories' in a single document. For example, if I wanted to use regular XHTML with FBML (the Facebook Markup Language) in a browser that understood both, I would have an xmlns for the HTML part and one for the fbml part. This means that I could use tags from both categories in my document.

    Namespaces are usually of the syntax [minicode]namespace:tagname[/minicode]. In your case, as mentioned, you don't actually have a namespace, so name and localName would likely be the same. Namespaces are used a lot in things like the XMPP protocol and Flex MXML.

  11. #10
    WDF Staff smoseley's Avatar
    Join Date
    Mar 2003
    Location
    Boston, MA
    Posts
    9,729
    Member #
    819
    Liked
    205 times
    Expanding on Shadowfiend's above explanation, here's an example of XML namespaces in use:

    Code:
    <?xml version="1.0"?>
    <myXmlDoc xmlns="http://mynamespace.mydomain.com/subnamespace" 
            xmlns:steve="http://stevesnamespace.stevesdomain.com/subnamespace">
    
        <myElement>
            <name>This is an element in my namespace</name>
            <description>Notice the generic 'name' and 'description' children have no namespace
                defined.  This is because they are part of the default namespace.</description>
        </myElement>
    
        <myOtherElement>This is another element in my namespace</myOtherElement>
    
        <steve:stevesElement>
            <steve:name>This is one of Steve's elements</steve:name>
            <steve:description>Notice all of the defining parts of the 'steve' XML element are tagged
                with the 'steve' namespace.  This allows us to selectively parse overlapping elements
                of different schemas using the namespace prefix to separate them.</steve:description>
        </steve:stevesElement>
    
    </myXmlDoc>
    Neat, no? :-)


Page 1 of 2 1 2 LastLast

Remove Ads

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
All times are GMT -6. The time now is 10:51 AM.
Powered by vBulletin® Version 4.2.3
Copyright © 2019 vBulletin Solutions, Inc. All rights reserved.
vBulletin Skin By: PurevB.com