XML Parser for JavaScript - xml2array()

xml2array() parses the given XML document and return the data in an associative array.

See Demo.

Useage

XmlHttp.onreadystatechange = function() {
	if(XmlHttp.readyState == 4 && XmlHttp.status == 200) {
		var arr = xml2array(XmlHttp.responseXml);
		// Do what you want with 'arr'
	}
});

Just load the XML file using the method you are most comfortable with and then call the xml2array function with the XML object as the argument.

Code

The code is given in the xml2array.js file. It is a bit ugly - but it gets the job done. This file also includes the code for the xjx library and the dump function(Javascript equivalent of PHP's print_r function).

The code is somewhat big(100 lines of code) so I am not putting it in this page - just have a look at the js file for the code. You need just the xml2array() function and the two global variables at top - there are two other functions there - just ignore them.

Problems

There are some problems with the script - but this just the first release so it is to be expected.

I have only tested the script in the following browsers. Please let me know how the script worked in other browser's.

Another problem is that the scripts runs into trouble when such details like XML version(<?xml version="1.0"?>) or stylesheet information(<?xml-stylesheet type="text/xsl" href="softwares.xsl" ?>) or some other extra infomation like <!DOCTYPE programs SYSTEM "softwares.dtd"> is there in the XML file. I am hopping this will not be much of a problem as this script is aimed for use with Ajax responses in XML format - so we can safely assume that there will not be any 'stylesheet' information in it ;-). If you find any solution for this problem, please let me know - my email is

Actionscript

I was hoping that I could get this script to work in Actionscript. I don't 'know' actionscript per se - I know javascript and assume that I could code in Actionscript as they have very similar syntax. Unfortunately, the script fails in Actionscript - some problem with the whitespace Regular Expression. If any of you know actionscript, please take a look at the script and if you could get it working in Flash, drop me a line at .

License

This script is released in the BSD license.

Related Scripts

Comments

Extory at 21 Mar, 2007 09:24
when I was count the length of array after transported.
javascript response "undefinded".

//xml2array code
arr = new Object;

and I try to modified to arr = new Array();
is OK.
I want to ask why not define to Object not is array in the codes?

Reply to this.
Binny V A at 22 Mar, 2007 05:53
Because Object represents associative arrays and Array is for Lists. Take a look at these links...
JavaScript "Associative Arrays" Considered Harmful
Javascript Associative Arrays considered harmful
Reply to this.
Luklatlug at 10 May, 2007 04:19
I haven't looked at the code yet, but as far as I know, ActionScript2 (and lesser) does not support regular expressions. AS3 has a native Regular Expressions support, though, but since I don't use AS3 compilers yet, I cannot be of any help to you.
Cheers
Reply to this.
Amjad at 20 Jun, 2007 02:30
hey Binny ...u r jus 2 gud.. was lukin for such code...
well i can run d code without any errors...
how ever if i try to alert(arr)...it says object...
and in some places it says undefined...
plz tell me how do i get the parsed content thts there in the arr!!!
plz reply asap!!!![:)]
Reply to this.
Senning at 17 Mar, 2008 07:19
Thanks Binny V A! This works like a charm... except when responseXML returns a root with only one child. For example, it'll work as expected with


<root>

<child>bullying jerk</child>

<child>all-round awesome</child>

</root>



but not as much with


<root>

<child>slightly spoiled, but pretty rad</child>

</root>


Has anyone else had this problem?
Reply to this.
Alexian at 09 Apr, 2008 05:40
Yes, I have.
I added additional condition for parent compare.

if(xmlDoc.nodeName && xmlDoc.nodeName.charAt(0) != "#") {
if ( (xmlDoc.childNodes.length > 1)
|| ( (xmlDoc.childNodes.length == 1) && (xmlDoc.childNodes[0].childNodes.length > 0) ) ) { //If its a parent
arr = new Object;
parent = xmlDoc.nodeName;
}
}
Reply to this.
Jimmy at 26 Feb, 2009 08:13
This worked awesome, thanks!
Reply to this.
Anonymous at 13 Jul, 2007 03:01
Why is it GPL-licensend, and not LGPL... very fine........ ;(
Reply to this.
Binny V A at 13 Jul, 2007 06:16
You got me there - I usually use BSD license for all my code. I have no idea why I used GPL for this. Just give me some time - I will change it to BSD.
Reply to this.
Anonymous at 19 Oct, 2007 12:54
it's responseXML not responseXml
Reply to this.
Jaakko at 12 Nov, 2007 04:00
Thanks for nice script, but "attribute_inside = 1;" config does not work if there is more than one attribute in element. It totally screws up the element.
Reply to this.
Jaycode at 04 Dec, 2007 08:28
I just want to say heaps thanks for the code you developed. It was one of the best! ;)

All the best for you, BinnyVa
Reply to this.
Anonymous at 20 Feb, 2008 01:28
XmlHttp.onreadystatechange = function() {
if(XmlHttp.readyState == 4 && XmlHttp.status == 200) {
var arr = xml2array(XmlHttp.responseXml);
// Do what you want with 'arr'
}
});
Reply to this.
trosen at 22 Apr, 2008 11:14
attribute_inside = 0 ?

Default behaviour is to place attributes outside, ie. in parents tag and implies that attributes can not be used in the root-tag

In what kind of situations is there an advantage to have attributes placed outside?
Reply to this.
Binny V A at 30 Apr, 2008 11:08
This really comes in useful if the XML in question dont have any attributes - or you don't care about the attributes.
Reply to this.
Anonymous at 13 May, 2008 10:19
<?xml version="1.0"?>
2 <contacts>
3 <contact name="Able Baker">able@example.com</contact>
4 <contact name="Careful Dodger">dodger@example.com</contact>
5 <contact name="Eager Framer" personal="true">framer@example.com</contact>
6 </contacts>
Reply to this.
Anonymous at 17 Jun, 2008 04:12
The xml2array.js file is missing (
Reply to this.
Binny V A at 18 Jun, 2008 09:46
My bad - fixed now.
Reply to this.
Farao at 30 Jun, 2008 02:56
Thanks for this little script, its very handy and does a very good job!

But like the previous Anonymous poster I have a problem with accessing attributes (with attribute_inside 0 and/or 1) when I have multiple nodes like this:

<contacts>
<contact name="Able Baker">able@example.com</contact>
<contact name="Careful Dodger">dodger@example.com</contact>
<contact name="Eager Framer" personal="true">framer@example.com</contact>
</contacts>

I can get the first name (Able Baker) with "arr['contacts']['attribute_contact_name']" (attribute_inside = 1) or with "arr['contacts']['contact'][0]['attribute_name']" (attribute_inside = 0), but any other name (ie.: arr['contacts']['contact'][1]['attribute_name']) return "undefined" or an error.

Any idea how to get "Careful Dodger" or "Eager Framer"?
Reply to this.
Raneesh at 02 Jul, 2008 10:58
hi binny
Unfortunately the code is not working with this xml
<Address>
<AddressLine1 title="Address Line 1" type="string" tooltip=""/>
<AddressLine2 title="Address Line 2" type="string" tooltip=""/>
<TownCity title="Town or City" type="string" tooltip=""/>
<County title="County" type="string" tooltip=""/>
<Postcode title="Postcode" type="string" tooltip=""/>
</Address>

The parsing get stop after the parent node 'Address'. can u plz look at this
. the code is not working in the ie
Reply to this.
Anonymous at 22 Jul, 2008 12:09
Works #1 for me but not on IE 7, same thing with your demo.
Reply to this.
Tom at 18 Sep, 2008 12:17
Great script, but running into errors. in firebug is says "xmlDoc.childNodes[i].attributes is null" when I use this xml file:
<job>
<name>Example 1</name>
<hours>5</hours>
<programmingCost>120</programmingCost>
<programmingPer>hour</programmingPer>
<processingCost>15</processingCost>
<processingPer>thousand records</processingPer/>
<printingCost>28</printingCost>
<printingPer>thousand impressions</printingPer/>
<insertingCost>30</insertingCost>
<insertingPer>thousand mailpacks</insertingPer/>
<lodgement>50</lodgement>
</job>

<job>
<name>Example 2</name>
<hours>8</hours>
<programmingCost>110</programmingCost>
<programmingPer>hour</programmingPer>
<processingCost>20</processingCost>
<processingPer>ten thousand records</processingPer/>
<printingCost>24</printingCost>
<printingPer>thousand impressions</printingPer/>
<insertingCost>28</insertingCost>
<insertingPer>thousand mailpacks</insertingPer/>
<lodgement>60</lodgement>
</job>

any clue how to fix it? thanks in advance
Reply to this.
Binny V A at 18 Sep, 2008 04:30
I have edited the script a little bit - it should avoid the error. But you have to make 2 changes to your xml file.
1) enclose the whole xml in a tag. Something like <xmldata><job>...</job><job>...</job></xmldata>
2) some elements have a /> at the end - remove that.
Reply to this.
Tom at 18 Sep, 2008 03:48
thanks for the quick reply! i'll do that, but where do I download the updated script?
Reply to this.
Binny V A at 20 Sep, 2008 12:18
Just download the script once again. I have uploaded the changes.
Reply to this.
Anonymous at 25 Sep, 2008 02:17
Is there a way to load XML from a string and parse?

Say something like this:

var str = "<xml><x1>jhfh</x1><x2>ghdskjgh</x2></xml>";

Please help.
Reply to this.
Siddhant at 13 Oct, 2008 12:19

var parser = new DOMParser();
var xmldoc = parser.parseFromString(str,'text/xml');

...do whatever you want to do with xmldoc...
Reply to this.
Binny V A at 13 Oct, 2008 03:52
Nice - I did not know that. Thanks for pointing it out.
Reply to this.
Robert at 23 Oct, 2008 05:39
So, I suppose we cannot use a XML file like this, isn't it?:

<GeoMediaElementManager>
<numElements value="2" />
<GeoMediaElement>
<mID value="0" />
<mType value="Text" />
<mURL value="Audio0.wav" />
<mDate value="21.9.2008" />
<mUserName value="User 1" />
<mScenario value="Teatro Cervantes" />
<GPSPosition>
<latitude value="0" />
<longitude value="0" />
<altitude value="0" />
</GPSPosition>
</GeoMediaElement>
<GeoMediaElement>
<mID value="1" />
<mType value="Image" />
<mURL value="d:\code\cpp\Projects\GeoMedia\project\vc8\GeoMedia\image1.bmp" />
<mDate value="21.9.2008" />
<mUserName value="User 1" />
<mScenario value="Teatro Cervantes" />
<GPSPosition>
<latitude value="0" />
<longitude value="0" />
<altitude value="0" />
</GPSPosition>
</GeoMediaElement>
</GeoMediaElementManager>


Thanks!
Reply to this.
Binny V A at 23 Oct, 2008 07:41
It should be working - but apparently there is some problem. I'll looking into this.
Reply to this.
spor at 04 Jan, 2009 02:12
1) enclose the whole xml in a tag. Something like <xmldata><job>...</job><job>...</job></xmldata>
2) some elements have a /> at the end - remove that.
Reply to this.
Asaf at 28 Jan, 2009 11:20
hello

could u add a code example at HTML how to read the xml2array function

Thanks!
Reply to this.
Jimmy at 24 Feb, 2009 09:37
Seems to not work when an element (i.e. response['key']) has a subarray of only one value in IE7+. Works fine in other browsers, in IE7+ response['key']['value']['value2'] is instead found at response['value']['value2']. Any advice?
Reply to this.
tutunmayan at 03 Apr, 2009 01:36
For Actionscript
I used xml.ignoreWhite = true;
and commentted out

//var not_whitespace = new RegExp(/[^\s]/);

and

//if(not_whitespace.test(value)) {//If its a child
arr = new Object;
arr[xmlDoc.parentNode.nodeName] = value;
//}


I looks like working
Reply to this.
Binny V A at 06 Apr, 2009 01:21
Thanks! I was looking for an ActionScript working version of my code.
Reply to this.
Anonymous at 08 Apr, 2009 01:37
I found a small bug that was halting me from using the numeric array portion of the code. I couldn't get arr['something'].length
I added/modified the line to
var temp_arr = arr[key];
arr[key] = [];
arr[key][0] = new Object;
arr[key][0] = temp_arr;

the output is exactly as before but now I can get lengths of the numeric arrays. (as opposed to it being an associative array)
Reply to this.
Anonymous at 17 Apr, 2009 02:33
The script does not correctly parse this xml:
<xml><contacts><contact email="joe@email.com">Joe</contact><contact email="bob@email.com">Bob</contact></contacts></xml>

with attribute_inside = 1

Reply to this.
Brian at 12 May, 2009 09:36
Found bug in this function.

The following codes:
if(xmlDoc.nodeName && xmlDoc.nodeName.charAt(0) != "#") {
if(xmlDoc.childNodes.length > 1) { //If its a parent
arr = new Object;
parent = xmlDoc.nodeName;

}

shall be changed to:

if(xmlDoc.nodeName && xmlDoc.nodeName.charAt(0) != "#") {
if(xmlDoc.childNodes.length > 1) { //If its a parent
arr = new Object;
parent = xmlDoc.nodeName;

}
else if (xmlDoc.childNodes.length == 1 && xmlDoc.childNodes[0].nodeType != 3){ //TEXT_NODE: 3
arr = new Object;
parent = xmlDoc.nodeName;
}


Consider below example:



<c>
kkk
</c>



The original function cannot parse node "b" correctly. a.b is null....
Reply to this.
Brian at 12 May, 2009 09:40
Sorry, the example I listed is confused. Look at this one:

e.g.,
<aa>
<bb>
<cc>
kkkk
</cc>
</bb>
</aa>

The original function cannot parse node "bb" correctly. aa.bb is null....since bb only has one child node and it is parent node.


Reply to this.
Anonymous at 26 Jun, 2009 03:32
yaar xml to js

XML Parser for JavaScript - xml2array() ki complete file to do
Reply to this.
Comment

Please dont enter you comments in this form - this is a fake form to confuse spamming bots. The next form is the real one.




Comment




Comment Formating : HTML tags a, strong, em, b, i, code, pre, p and br allowed. Other tags will be shown as code(< will become &lt;). Urls, Line breaks will be auto-formated.