Idrees Khan
Idrees Khan

Reputation: 7752

Map hierarchical data from XML File to Kendo UI DataSource

i have an xml file with different child nodes (here its fake but the real one is the same structure), and i want to fetch it and bind it to listview. I tried it but i can't access the data and neight i found a suitable example.

<cars type="metadata">
  <categories>
    <category name="BMW" />
    <category name="Honda" />
    .....
  </categories>
  <manufacturers>
    <names>
      <name alias="BMW" />
    </names>
  </manufacturers>
</cars>
........
//another different noeds

here is my code for datasource

    var dataSource = new kendo.data.DataSource({
        transport: {
            // specify the XML file to read. The same as read: { url: "books.xml" }
            //read: "http://demos.telerik.com/kendo-ui/content/web/datasource/books.xml"
            read: "content/quran-data.xml",
            dataType: "xml"
        },
        schema: {
            type: "xml",
            data: "/cars",
            model: {
                fields: {
                    children: "categories"
                    //children: {
                    //    schema: {
                    //        data : "category",
                    //        model: {
                    //            fields : {
                    //                name: "@name",
                    //            },
                    //            hasChildren: "category"
                    //        }
                    //    }
                    //}
                },
                hasChildren: "true"
            }
        },
        change: onChage
    });

I tried differen ways but couldn't succeed. And i also know about HierarchicalDataSource in Kendo, but i'm not sure what example is suitable for it. i only want to access the child nodes i.e Categories, manufacturers and their nested nodes

Upvotes: 0

Views: 1551

Answers (1)

Juli&#235;n
Juli&#235;n

Reputation: 9522

I understand your dilemma. As discussed in the comments, my advise would be to seperate the concerns of each entity type, e.g. 'cars', 'manufacturers', 'categories' into seperate datasources. I'll explain how and why further on.

As for the Kendo's HierarchicalDataSource; this requires the data to be homogenuous in nature. Meaning, it always expects objects of the same type. This means for your purpose, it's probably not going to work considering you're combining different objects (or with a hell of a strange hierarchy in your schema/model).

However, if you consider the in the comments mentioned alternative to use a datasource per object/domain type, this can actually work out just fine.

With this in mind, I'm thinking something like the following:

// Define the 'Categories' datasource
var categories = new kendo.data.DataSource({
    transport: {
        read: "content/quran-data.xml",
        dataType: "xml"
    },
    schema: {
        // specify the the schema is XML
        type: "xml",
        // the XML element which represents a single data record
        data: "/cars/categories/category",
        // define the model - the object which will represent a single data record
        model: {
            // configure the fields of the object
            fields: {
                // the "name" field is mapped to the text of the "name" XML element
                name: "name/text()"
            }
        }
    }
});

// Define the 'Manufacturers' datasource
var manufacturers = new kendo.data.DataSource({
    transport: {
        read: "content/quran-data.xml",
        dataType: "xml"
    },
    schema: {
        // specify the the schema is XML
        type: "xml",
        // the XML element which represents a single data record
        data: "/cars/manufacturers/names/name",
        // define the model - the object which will represent a single data record
        model: {
            // configure the fields of the object
            fields: {
                // the "alias" field is mapped to the text of the "alias" XML element
                alias: "alias/text()"
            }
        }
    }
});

These definitions can be setup somewhere global (I like the convention of placing them seperately in something like datasources.js, or something), whilst you can initialize them quite easily anywhere in your app, like so:

// Fetch both, by default always async
categories.read();
manufacturers.read();

Note: Of course, this could be done with a HierarchicalDataSource as well. This would make your schema more clearer if you can map and re-use the properties of the children one-on-one.

Besides the fact seperating your datasources is both cleaner as well as easier to maintain, it will not hurt performance more than loading one, big datafile. Especially not if you take the following big advantages (in terms of performance and reusability) in consideration:

  • Individual datasources can load asynchronously, thus reducing the load
  • Individual datasources can be load 'on demand'; if you only need a small node, no need to load in the entire document
  • Individual datasources can use paging and caching seperately; ideal if you have large lists or only want to load something once (for example, read the xml only once after deviceReady, and derive your datasources from this)
  • It's easy to combine multiple datasources (e.g. CarTypes and Manufacturers) into a new, specific datasource. And this'll cost you little in terms of performance, considering it's already in-memory

Just my thoughts, but hope it helps ;)

Upvotes: 1

Related Questions