3

I have a total of 4 XML files in same format representing 4 different categories of project contents. However some projects does have more than 1 category.

I want to merge all 4 XML files using jQuery and display all projects contents in a single page within a , but due to the fact that some projects have more than 1 category, the displayed results show duplicates of project contents.

How do I remove duplicates within the combined extracted XML files?

Here is my jQuery Code:

XMLLIST = {

//general settings
xml1: 'xml/structural_steel.xml?' + Math.random(0,1), //solve ie weird caching issue
xml2: 'xml/building_work_id.xml?' + Math.random(0,1), //solve ie weird caching issue
xml3: 'xml/shear_stud_welding.xml?' + Math.random(0,1), //solve ie weird caching issue
xml4: 'xml/custom_solution.xml?' + Math.random(0,1), //solve ie weird caching issue
appendTo: '#list', //set the id/class to insert XML data

init: function () {

    //jQuery ajax call to retrieve the XML file
    $.ajax({
        type: "GET",
        url: XMLLIST.xml1,
        dataType: "xml",            
        success: XMLLIST.parseXML
    }); 

    $.ajax({
        type: "GET",
        url: XMLLIST.xml2,
        dataType: "xml",            
        success: XMLLIST.parseXML
    }); 

    $.ajax({
        type: "GET",
        url: XMLLIST.xml3,
        dataType: "xml",            
        success: XMLLIST.parseXML
    }); 

    $.ajax({
        type: "GET",
        url: XMLLIST.xml4,
        dataType: "xml",            
        success: XMLLIST.parseXML
    }); 

}, // end: init()

parseXML: function (xml) {

    //Grab every single ITEM tags in the XML file
    var data;
    data = $('item', xml).get();        

    var i = 1;

    //Loop through all the ITEMs
    $(data).each(function () {

        //Parse data and embed it with HTML
        XMLLIST.insertHTML($(this));

        i++;
    });

}, // end: parseXML()

insertHTML: function (item) {

    //retrieve each of the data field from ITEM
    var url = item.find('url').text();
    var image = item.find('image').text();
    var title = item.find('title').text();
    var html;

    //Embed them into HTML code
    html = '<div class="item">';
    html += '<a href="' + url + '"><img src="' + image + '"></a><br>';
    html += '<span class="contentsubtitle">' + title + '</span><br><br>';
    html += '</div>';

    //Append it to user predefined element
    $(html).appendTo(XMLLIST.appendTo);

}, // end: insertHTML()        


}

//Run this script
XMLLIST.init();

2 Answers 2

1

I hope my code is correct. Had no data to test with, but I think the idea of it should be a bit more clear.

edited: Now working, version after receiving xml test-data

<html>
    <head>
        <title>asdasd</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
    </head>
    <body>
        <div id="list">

        </div>
        <script>
            XMLLIST = {
                dataToLoad: [
                    'test.xml'
                ],
                loadedData: [],
                appendTo: '#list',
                rand: function() {
                    return new Date().getTime();
                },
                loadData: function(file) {
                    $.ajax({
                        type: "GET",
                        url: file + "?" + XMLLIST.rand(),
                        dataType: "xml",            
                        success: XMLLIST.parseXML,
                        error: function(r) {
                            console.error(r);
                        }
                    }); 
                },
                init: function () {
                    XMLLIST.dataToLoad.forEach(function(file) {
                        XMLLIST.loadData(file);
                    });
                },
                parseXML: function (xml) {
                    var data = $('item', xml).get();
                    $(data).each(function (i, value) {
                        var $value = $(value),
                            item = {
                                url: $value.find('url').text(),
                                image: $value.find('image').text(),
                                title: $value.find('title').text()
                            };

                        if (!XMLLIST.itemIsInList(item)) {
                            XMLLIST.loadedData.push(item);
                            XMLLIST.insertHTML(item);
                        }
                    });
                },
                itemIsInList: function(item) {
                    var hits = XMLLIST.loadedData.filter(function(value){
                        return XMLLIST.compareItem(item, value);
                    });
                    return hits.length > 0
                },
                compareItem: function(item1, item2) {
                    return item1.url === item2.url && item1.image === item2.image && item1.title === item2.title;
                },
                insertHTML: function (item) {
                    var html = '<div class="item">';
                    html += '<a href="' + item.url + '"><img src="' + item.image + '"></a><br>';
                    html += '<span class="contentsubtitle">' + item.title + '</span><br><br>';
                    html += '</div>';
                    $(html).appendTo(XMLLIST.appendTo);
                }
            };
            XMLLIST.init();
        </script>
    </body>
</html>

You have a list, where you push your objects to. This list has a checkFunction "itemIsInList". Additionally you need a seperate check-function "compareItem", because indexOf won't work with objects

Sign up to request clarification or add additional context in comments.

4 Comments

Tested, but nothing displayed. Can explain your purpose of the rand: function() { return new Date().getTime(); },
Sample XML Data:<?xml version="1.0" encoding="utf-8" ?> <items> <item> <url>project1.html</url> <image>images/project1.jpg</image> <title>Project 1</title> </item> <item> <url>project2.html</url> <image>images/project2.jpg</image> <title>Project 2</title> </item> <item> <url>project3.html</url> <image>images/project3.jpg</image> <title>Project 3</title> </item> <item> <url>project4.html</url> <image>images/project4.jpg</image> <title>Project 4</title> </item> </items>
Tried various method. But cannot get the answer to work. Am I missing something?
The purpose of the rand-function is to ALWAYS receive a unique number. Math.random() CAN (VERY VERY VERY RARE :D) output two identical numbers, timestamp not ;)
0

Managed to modify my original script by adding a masterArr for comparison of duplicated data received accross the 4 XMLs.

Here's the codes:

XMLLIST = {

    //general settings
    xml1: 'xml/structural_steel.xml?' + Math.random(0,1), //solve ie weird caching issue
    xml2: 'xml/building_work_id.xml?' + Math.random(0,1), //solve ie weird caching issue
    xml3: 'xml/shear_stud_welding.xml?' + Math.random(0,1), //solve ie weird caching issue
    xml4: 'xml/custom_solution.xml?' + Math.random(0,1), //solve ie weird caching issue
    appendTo: '#list', //set the id/class to insert XML data
    //end general settings

    masterArr: [],
    init: function () {

        //jQuery ajax call to retrieve the XML file
        $.ajax({
            type: "GET",
            url: XMLLIST.xml1,
            dataType: "xml",            
            success: XMLLIST.parseXML
        }); 

        $.ajax({
            type: "GET",
            url: XMLLIST.xml2,
            dataType: "xml",            
            success: XMLLIST.parseXML
        }); 

        $.ajax({
            type: "GET",
            url: XMLLIST.xml3,
            dataType: "xml",            
            success: XMLLIST.parseXML
        }); 

        $.ajax({
            type: "GET",
            url: XMLLIST.xml4,
            dataType: "xml",            
            success: XMLLIST.parseXML
        }); 

    }, // end: init()

    parseXML: function (xml) {

        //Grab every single ITEM tags in the XML file
        var data;
        data = $('item', xml).get();

        var i = 1;

        //Loop through all the ITEMs
        $(data).each(function () {

            //Check if masterArr[] already contains a duplicate of the item by checking using the XML label <image> or any other value/label that is unique. 
            //Insert into masterArr[] if not duplicate and publish HTML if not duplicate.
            var string1 = $(this).find('image').text();
            if( jQuery.inArray(string1, XMLLIST.masterArr) == -1){
                XMLLIST.masterArr.push(string1);
                //Parse data and embed it with HTML
                XMLLIST.insertHTML($(this));            
            };

            //If it reached user predefined total of display item, stop the loop, job done.
            //if (i == XMLLIST.display) return false;
            i++;
        });


    }, // end: parseXML()


    insertHTML: function (item) {

        //retrieve each of the data field from ITEM
        var url = item.find('url').text();
        var image = item.find('image').text();
        var title = item.find('title').text();
        var html;

        //Embed them into HTML code
        html = '<div class="item">';
        html += '<a href="' + url + '"><img src="' + image + '"></a><br>';
        html += '<span class="contentsubtitle">' + title + '</span><br><br>';
        html += '</div>';

        //Append it to user predefined element
        $(html).appendTo(XMLLIST.appendTo);

    }, // end: insertHTML()

}

//Run this script
XMLLIST.init();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.