admin管理员组

文章数量:1429066

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
Add a ment  | 

4 Answers 4

Reset to default 2

collect 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/

本文标签: javascriptconvert xml to object with jqueryStack Overflow