Angular and XML? No Problem!

This entry is part 7 of 9 in the series: AngularJS Learning Series
Social Share Toolbar

The Finished Product

JSON is a native object to AngularJS so working solely with JSON examples is easy. In the real world, however, you’ll probably need to deal with other types of data sources, like XML. Before I get too wordy, let’s start with what you’re really here for…the example:

The Explanation

While the finished product looks like the result of 15 minutes of coding, I have to admit that it took me significantly longer to figure out. If you search the Angular Developer Guide or API for “XML” you’re going to come up woefully absent of useful results. Googling won’t get you much further. As frustration began to set in, I started thinking about what made loading an XML file more difficult than loading a JSON file. The answer is: not much!

Bridging the Language Gap

Angular likes JSON, and can you blame it? Angular is a JavaScript toolset and JSON is JavaScript Object Notation, a native brethren. XML, on the other hand, is tag-based markup…a foreign language to Angular. What I needed was a way to make Angular understand what XML was trying to communicate.

The key to overcoming any language gap is to have a translator. If there were a way to translate XML to JSON before handing it to the application then I could eliminate the language gap, and the problem.

A quick search for xml converters turned up multiple results. I chose Abdulla Abdurakhmano’s X2JS library because it was the first one I came across, it was lightweight, and it was pretty easy to use.

The code required to perform the translation is short and simple. Provide the library with XML, tell it which method to use, and receive JSON in return:

function(xml) {
 var x2js = new X2JS();
 var json = x2js.xml_str2json( xml );
 return json;
}

Where to Stick It

Your ads will be inserted here by

Easy AdSense Pro.

Please go to the plugin admin page to paste your ad code.

Now that I had a solution to the language gap I needed to decide where to implement it. Angular’s $http service conveniently applies transformation functions for both requests and responses. These functions apply transformations to data when it is sent and received, and they can be overridden.

Using the X2JS conversion code as a transformResponse function it was simple to get the $http service to read in XML and return JSON to the application, effectively creating the translator I needed. The results look something like this:

angular.module('myApp.service',[]).
    factory('DataSource', ['$http',function($http){
       return {
           get: function(callback){
                $http.get(
                    'data.xml',
                    {transformResponse:function(data) {
                    	// convert the data to JSON and provide
                    	// it to the success function below
						var x2js = new X2JS();
						var json = x2js.xml_str2json( data );
						return json;
						}
					}
                ).
                success(function(data, status) {
					// send the converted data back
					// to the callback function
                    callback(data);
                })
           }
       }
    }]);
    
angular.module('myApp',['myApp.service']);

var AppController = function($scope,DataSource) {
    
    //This is the callback function
    setData = function(data) {
        $scope.dataSet = data;
    }
        
    DataSource.get(setData);
    
}

That’s really all there is to it! The example above will retrieve an xml file named “data.xml”, convert it to JSON, and assign the results to $scope.dataSet.

The Caveat

XML comes in all shapes and sizes. Some use attributes, others don’t, and many use a combination of both. Some XML files use a proper header, others are just fragments. Your application will likely require tweaking to get the data into the shape that your application requires. Always read the docs, read the comments, and experiment.

The example at the beginning of this post is a great starting point. Fork it and experiment with different libraries or XML formats.

Keep on Coding!

Series Navigation<< Responsive Form Validation with AngularJS and HTML5

12 thoughts on “Angular and XML? No Problem!

  1. “Googling won’t get you much further.” but now it gets you here !! and there are a couple of others appearing now so you are not Robinson Crusoe. They do seem to be following your lead by going the x2js route.

    Thanks.

    • Hi Tim,

      Unless you’re dealing with a system that stores data in your scripting language (Angular/MongoDB for example), some conversion always has to take place. Performance will depend on your servers, your code, and the volume of data and users you’re dealing with. A few years back I used ColdFusion to generate XML from an MS SQL database to be used by a Flash web application. We had millions of users every month and never ran into performance issues.

      So, for best performance, you would use JSON for an Angular app. But if you had to use XML (and many people do), this is a pretty simple way to do it. If you have concerns about whether it would be performant in a specific landscape, load testing would be the way to go.

  2. Very nice tutorial, great help. is possible instead of putting a local file XML put a url? Thanks.

    • You can definitely use a URL. Just be conscious of possible cross-domain issues. I have a post with an accompanying fiddle that covers a little bit of this here. – Glenn

      • This looks really useful, and I’ve changed the file to an URL, but am getting an error. In the Chrome developer tools it says ‘Load cancelled’ in the Status column.

        Is this due to cross-domain issues? Any idea how I could fix this given I’m not using PHP or JSFiddle?

        • Thanks for letting me know about the problem, Anthony. Somewhere along the line a change occurred that caused the app to hang while trying to load non-existent images before angular was loaded. I fixed the issue by changing “img src” to “img ng-src” in the html, which I should have done in the first place.

          “Using Angular markup like {{hash}} in a src attribute doesn’t work right: The browser will fetch from the URL with the literal text {{hash}} until Angular replaces the expression inside {{hash}}. The ngSrc directive solves this problem.” – Angular Docs

  3. Hi, great tutorial, but actually there’s a problem :
    if there is only one guitar in the xml, is not interpreted as an array so the ng-repeat infinite loop on the true expression {guitar in DataSet} (because it’s not an array).