DEV Community

Cover image for Flutter XML Data Parsing
Kunal Jain for CodeDecoders

Posted on • Updated on • Originally published at dev.to

Flutter XML Data Parsing

Hello guys, this blog post is a part of a Flutter Video Series we are started to upload on YouTube.
Flutter News App (Frontend to Backend)

Here is the video:-

In this blog, we are going to implement the backend of our homepage.

We are going to use XML data and convert into formatted JSON objects to make it easier to use in our app.

What is an RSS Feed?

RSS is a web feed that allows users and applications to access updates to websites in a standardized, computer-readable format.

Accessing an RSS Feed directly into our app is not quite possible.
So, we will parse the RSS/XML data into JSON and display it into the UI portion of our application.

For that, we are going to use the package named xml2json: An XML to JSON conversion package.
https://pub.dev/packages/xml2json.

xml2json

This package allows the parsing of XML strings and the transformation of the resulting parse tree into the following XML JSON conventions:-

The package uses the XML parser to perform the parsing of XML data into a parse tree.

  • Parker
  • Badgerfish
  • Google Data(GData).

The Parker convention is a lossy but lean conversion from XML into JSON, ideal for lightweight XML parsing, where attributes and namespace information is not needed.

Badgerfish and GData both preserve XML information such as attributes and namespaces. These are more suited to heavyweight XML parsing of say RSS feeds where this information may be needed.

Now let's see what our single item in the RSS feed looks like:

As we can see here (line:17) the url is an attribute, hence we need to use either BadgerFish or GData.

In this tutorial, we will be using the GData XML Parser

Add this to your package's pubspec.yaml file:

dependencies:
  xml2json: ^4.3.0

Let's create a new file for handling the parsing process:
rss_to_json.dart

Lets first import the necessary libraries.

  • convert: To convert a String into a List/Map
  • xml2json
  • http: For getting the XML data from the web
import 'dart:convert';
import 'package:xml2json/xml2json.dart';
import 'package:http/http.dart' as http;

Now create a function rssToJson.

Future<List> rssToJson (String category,
    {String baseUrl = "https://www.hindustantimes.com/rss/"}) async{
  var client = new http.Client();
  final myTransformer = Xml2Json();
  return await client.get(baseUrl + category + "/rssfeed.xml").then((response) {
    return response.body;
  }).then((bodyString) {
    myTransformer.parse(bodyString);
    var json = myTransformer.toGData();
    return jsonDecode(json)['rss']['channel']['item'];
  });
}

Here the jsonDecode function is used because the XML parser returns a String. So we just converted the String into a List.

Using rssToJson in our homepage

Now there are two ways to fetch Json data:

  1. FutureBuilder()
  2. Future.wait()

We will use Future.wait() in this tutorial.

Future.wait()

Future.wait() waits for multiple futures to complete and collects their results.

Returns a future which will complete once all the provided futures have completed, either with their results or with an error if any of the provided futures fail.

The value of the returned future will be a list of all the values that were produced in the order that the futures are provided by iterating futures.

We will create a Map named as newsData.

Future getData() async {
    return Future.wait([
      rssToJson('topnews'),
      rssToJson('india'),
      rssToJson('world'),
      rssToJson('business'),
      rssToJson('sports'),
      rssToJson('cricket'),
      rssToJson('tech-features'),
      rssToJson('education'),
      rssToJson('entertainment'),
      rssToJson('music'),
      rssToJson('lifestyle'),
      rssToJson('health-fitness'),
      rssToJson('fashion-trends'),
      rssToJson('art-culture'),
      rssToJson('travel'),
      rssToJson('books'),
      rssToJson('realestate'),
      rssToJson('its-viral'),
    ]).then((value){
       newsData['topnews'] = value[0];
    newsData['india'] = value[1];
    newsData['world'] = value[2];
    newsData['business'] = value[3];
    newsData['sports'] = value[4];
    newsData['cricket'] = value[5];
    newsData['tech'] = value[6];
    newsData['education'] = value[7];
    newsData['entertainment'] = value[8];
    newsData['music'] = value[9];
    newsData['lifestyle'] = value[10];
    newsData['health-fitness'] = value[11];
    newsData['fashion-trends'] = value[12];
    newsData['art-culture'] = value[13];
    newsData['travel'] = value[14];
    newsData['books'] = value[15];
    newsData['realestate'] = value[16];
    newsData['its-viral'] = value[17];
       setState(() {
        isLoading = false;
      });
    });
  }

Here value containers all the results as a List.

Now we will call the initState() in the Home() Class and call the getData function.

@override
void initState() {
  super.initState();
  getData();
  }

Now we are getting the XML Data to JSON but we want this data in the homepage.dart. So we will declare the Map<String, List> named newsData in HomePage() and then we will pass it to its constructor

class HomePage extends StatefulWidget {
  final Map<String, List> newsData;

  const HomePage({Key key, this.newsData}) : super(key: key);
  @override
  _HomePageState createState() => _HomePageState();
}

Now we need to set the data into HomePageCard (our reusable Widget).

TabBarView(
  controller: _tabController,
  children: List.generate(
    categories.length,
    (index) {
      var key = categories[index]
        .imageUrl
        .toString()
        .split("/")[3]
        .split(".")[0]
        .replaceAll("_", "-");
      return ListView.builder(
        padding: EdgeInsets.symmetric(horizontal: 25),
        itemBuilder: (context, i) {
          String time = _newsData[key][i]['pubDate']['__cdata'];
          DateTime timeIST = DateTime.parse(time.split(" ")[3] +
            "-" +
            getMonthNumberFromName(month: time.split(" ")[2]) +
            "-" +
            time.split(" ")[1] +
            " " +
            time.split(" ")[4]);
          timeIST = timeIST
            .add(Duration(hours: 5))
            .add(Duration(minutes: 30));
          return HomePageCard(
            title: _newsData[key][i]['title']['__cdata'],
            description: _newsData[key][i]['description']['__cdata'],
            date: timeIST.day.toString() +
                " " +
                getMonthInWordsFromNumber(month: timeIST.month) +
                " " +
                timeIST.toString().split(" ")[1].substring(0, 5),
                imageUrl: _newsData[key][i]['media\$content']['url'],
            );
        },
        itemCount: _newsData[key]?.length ?? 0,
      );
    },
)),

So our backend part is finished So we get the final output.
Alt Text

Github Source Code Link:-



Branch: Part--4--XmlToJson

Top comments (0)