I have a xml file like this: (this is dynamically create xml file the categories are not static)
<data>
<step id="1">
<category id="js"></category>
<category id="css"></category>
<category id="xml"></category>
</step>
<step id="2">
<category id="js"></category>
<category id="css"></category>
<category id="xml"></category>
<category id="php"></category>
<category id="html"></category>
</step>
<step id="3">
<category id="xml"></category>
<category id="php"></category>
<category id="html"></category>
</step>
</data>
I want convert the xml file in a javascript object i do it with jquery
$.get('data.xml', function(xml){
var oXML = $(xml).find('data'),
data = {};
oXML.each(function(){
var stepID = jQuery(this).attr('id');
data[stepID] = {};
jQuery(this).each(function(){
var categoryID = jQuery(this).attr('id')
data[stepID][categoryID] = 'is available';
});
});
});
the result looks like this
obj = {
1: {
js: 'is available',
css: 'is available',
xml: 'is available'
},
2: {
js: 'is available',
css: 'is available',
xml: 'is available',
php: 'is available',
html: 'is available'
},
3: {
xml: 'is available',
php: 'is available',
html: 'is available'
}
}
but i want have all categories in all steps. do you have a idea how i can do it? I want a result object like this
obj = {
1: {
js: 'is available',
css: 'is available',
xml: 'is available',
php: 'is not available',
html: 'is not available'
},
2: {
js: 'is available',
css: 'is available',
xml: 'is available',
php: 'is available',
html: 'is available'
},
3: {
js: 'is not available',
css: 'is not available',
xml: 'is available',
php: 'is available',
html: 'is available'
}
}
I have a xml file like this: (this is dynamically create xml file the categories are not static)
<data>
<step id="1">
<category id="js"></category>
<category id="css"></category>
<category id="xml"></category>
</step>
<step id="2">
<category id="js"></category>
<category id="css"></category>
<category id="xml"></category>
<category id="php"></category>
<category id="html"></category>
</step>
<step id="3">
<category id="xml"></category>
<category id="php"></category>
<category id="html"></category>
</step>
</data>
I want convert the xml file in a javascript object i do it with jquery
$.get('data.xml', function(xml){
var oXML = $(xml).find('data'),
data = {};
oXML.each(function(){
var stepID = jQuery(this).attr('id');
data[stepID] = {};
jQuery(this).each(function(){
var categoryID = jQuery(this).attr('id')
data[stepID][categoryID] = 'is available';
});
});
});
the result looks like this
obj = {
1: {
js: 'is available',
css: 'is available',
xml: 'is available'
},
2: {
js: 'is available',
css: 'is available',
xml: 'is available',
php: 'is available',
html: 'is available'
},
3: {
xml: 'is available',
php: 'is available',
html: 'is available'
}
}
but i want have all categories in all steps. do you have a idea how i can do it? I want a result object like this
obj = {
1: {
js: 'is available',
css: 'is available',
xml: 'is available',
php: 'is not available',
html: 'is not available'
},
2: {
js: 'is available',
css: 'is available',
xml: 'is available',
php: 'is available',
html: 'is available'
},
3: {
js: 'is not available',
css: 'is not available',
xml: 'is available',
php: 'is available',
html: 'is available'
}
}
Share
Improve this question
edited Jan 13, 2013 at 18:58
mal200
asked Jan 13, 2013 at 18:41
mal200mal200
3897 silver badges19 bronze badges
4 Answers
Reset to default 2collect all categories and then enumerate through data and set missing categories:
$.get('data.xml', function(xml){
var oXML = $(xml).find('data'),
data = {},
categories = {};
oXML.each(function(){
var stepID = jQuery(this).attr('id');
data[stepID] = {};
jQuery(this).each(function(){
var categoryID = jQuery(this).attr('id');
if (!categories[categoryID]) {
categories[categoryID] = true;
}
data[stepID][categoryID] = 'is available';
});
});
$.each(data, function (key, value) {
$.each(categories, function (key) {
if (value[key] === undefined) {
value[key] = 'is not available';
}
});
});
});
You can iterate over the object after it is constructed to fill in the missing members:
$.each(data, function (i, ival) {
var member = ival;
$.each(data, function (j, jval) {
if (jval === member) return;
$.each(jval, function (k, kval) {
if (typeof (member[k]) === 'undefined') {
member[k] = 'is not available';
}
});
});
});
Your final code will look like this:
$.get('data.xml', function(xml){
var oXML = $(xml).find('data'),
data = {};
oXML.each(function(){
var stepID = jQuery(this).attr('id');
data[stepID] = {};
jQuery(this).each(function(){
var categoryID = jQuery(this).attr('id')
data[stepID][categoryID] = 'is available';
});
});
$.each(data, function (i, ival) {
var member = ival;
$.each(data, function (j, jval) {
if (jval === member) return;
$.each(jval, function (k, kval) {
if (typeof (member[k]) === 'undefined') {
member[k] = 'is not available';
}
});
});
});
});
Initiate your object with all properties set to "is not available".
After adding that you don't know which categories you have I'd suggest something like this
$.get('data.xml', function(xml){
var oXML = $(xml).find('data'),
data = {};
// create a constructor for our object. We'll add the "not available" to the prototype later
// I create it inside your request because I assume that the process of "remembering"
// which properties exists should not be global but just for this request
function DataObject () {};
oXML.each(function(){
var stepID = jQuery(this).attr('id');
data[stepID] = new DataObject; // use an instance of our DataObject
jQuery(this).each(function(){
var categoryID = jQuery(this).attr('id')
data[stepID][categoryID] = 'is available';
// now add this propertiy to our prototype
// this will "add" them to all instances of DataObject
DataObject.prototype[categoryID] = 'is not available';
});
});
});
To understand this fully you have to understand the concept of prototype. Every object has a __proto__
property. If you access data[0].html
and it is not available in the object Javascript checks what is in __proto__
which is a reference to the constructors prototype
. Because you added your 'is not available
in the prototype the result of data[0].html
is 'is not available
.
Store an array of all the categories available in the xml as you parse the data:
Then once all xml parsed you will have plete array of all categories that are available, loop over main object and see if each element contains each category property:
var oXML = $(xml).find('step'),
data = {},
cats_array=[];
oXML.each(function(){
var stepID = jQuery(this).attr('id');
data[stepID] = {};
jQuery(this).find('category').each(function(){
var categoryID = jQuery(this).attr('id');
/* add category to array if doesn't already exist*/
if( $.inArray( categoryID, cats_array) ==-1){
cats_array.push( categoryID);
}
data[stepID][categoryID] = 'is available';
});
});
/* all categories now in array, loop over main object and if category doesn't exist add it*/
$.each(data, function(){
for( i=0;i< cats_array.length; i++){
if( ! this[cats_array[i]] ){
this[cats_array[i]] ="not available";
}
}
})
Working demo: http://jsfiddle/MYXNh/2/