Belajar Parsing File XML, CSV, dan TSV di Ionic Bagian 3

Ditulis oleh Takagi Fujimaru, dipublikasi pada 04 Apr 2018 dalam kategori Tutorial
Belajar Parsing File XML, CSV, dan TSV di Ionic Bagian 3 - CodePolitan.com

Baca dulu bagian pertama dan kedua

Memuat dan Membaca File TSV

Sejujurnya, TSV bukan format data yang asyik untuk dipakai bekerja, penulis bahkan tidak tahu untuk apa ia diciptakan, tapi tidak ada yang tahu kapan pembaca suatu saat nanti akan bekerja dengan file jenis ini.

Untungnya, membaca file serperti ini dengan Angulat/Ionic tidak sulit untuk dilakukan.

Sekarang, kita perlu membuat dulu sumber datanya!

Membuat file TSV di Mac OS X bisa dengan membuka file comics.numbers yang sebelumnya sudah di buat, salin data di kolom dan baris-barisnya kemudian tempel dan simpan ke aplikasi secamam TextEdit dan simpan dengan nama comics.tsv.

Jika menggunakan Windows pembaca bisa cukup mengekspornya dari Microsoft Excel menggunakan file comics csv yang sudah ada.

Seperti sebelumnya, kita perlu menyimpan file TSV ini di comics/src/assets/data/.

Sekarang modifikasi file comics/src/pages/home/home.ts untuk menambahkan kode berikut di dalam kelas HomePage:

public tsvItems : any;

constructor(public navCtrl: NavController,
            public http   : HttpClient)
{

}

ionViewWillEnter()
{
   this.loadTSV();
}

loadTSV()
{
   this.http.get('/assets/data/comics.tsv')
   .map(res => res.text())
   .subscribe((data)=>
   {
      var tsv         = this.parseTSVFile(data);
      this.tsvItems  = tsv;
   });
}

parseTSVFile(str)
{
   var arr  = [],
       obj  = [],
       row,
       col,
       c;

   // iterate over each character, keep track of current row and column (of the returned array)
   for (row = col = c = 0; c < str.length; c++)
   {
      var cc            = str[c];

      arr[row]           = arr[row] || [];
      arr[row][col]  = arr[row][col] || '';

      // If it's a tab move on to the next column
      if (cc == '\t')
      {
         ++col;
         continue;
      }

      /* If it's a newline move on to the next
         row and move to column 0 of that new row */
      if (cc == '\n')
      {
         ++row;
         col = 0;
         continue;
      }

      // Otherwise, append the current character to the current column
      arr[row][col] += cc;
   }

   return this.formatParsedObject(arr, false);
}

Seperti yang bisa pembaca lihat, kodenya hampir sama dengan loadCSV dan parseCSV dibagian memuat dan membaca file CSV.

Selain perbedaan nama method (dan tentu saja pemuatan file comics.tsv), method parseTSVFile lebih sederhana karena hanya melakukan 2 pemeriksaan kondisi untuk melihat apakah karakter saat ini adalah sebuah Tab (yang artinya kita akan membaca kolom berikutnya) atau baris New Line (baris baru yang artinya kita akan mereset ulang pencatat nomor kolom dan masuk ke baris baru).

Sekali lagi, datanya dimasukkan ke array multidimensi yang kemudian dikirim ke method formatParseObject kali ini dengan hasTitles diatur menjadi false.

Kita tentu saja akan menambahkan kode berikut di file comics/src/pages/home/home.html agar data TSV yang sudah dibaca bisa ditampilkan ke layar:

<ion-item-group>
   <ion-item-divider color="light">TSV</ion-item-divider>
   <ion-item *ngFor="let item of tsvItems">
      {{ item.title }}
   </ion-item>
</ion-item-group>

Kemudian kita bisa menjalankan perintah ionic serve untuk melihat hasilnya. Berikut ini tampilan list yang membaca data dari file TSV.

//

Hasil ini mengakhiri tutorial memuat dan membaca file TSV untuk Ionic.

Seperti yang bisa pembaca lihat, logika untuk TSV sedikit lebih sederhana (karena tinggal mengubah sedikit kode dari pembacaan CSV sebelumnya) dan memanfaatkan method formatParsedObject untuk membaca data dan mengubahnya menjadi array objek JSON dan dikirim kembali ke template HTML untuk di render.

Kode Keseluruhan

home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';
import xml2js from 'xml2js';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

   public xmlItems : any;
   public csvItems : any;
   public tsvItems : any;

   constructor(public navCtrl: NavController,
               public http   : HttpClient)
   {

   }

   ionViewWillEnter()
   {
      this.loadXML();
      this.loadCSV();
      this.loadTSV();
   }

   loadXML()
   {
      this.http.get('/assets/data/comics.xml')
      .map(res => res.text())
      .subscribe((data)=>
      {
         this.parseXML(data)
         .then((data)=>
         {
            this.xmlItems = data;
         });
      });
   }

   loadCSV()
   {
      this.http.get('/assets/data/comics.csv')
      .map(res => res.text())
      .subscribe((data)=>
      {
         var csv         = this.parseCSVFile(data);
             this.csvItems    = csv;
      });
   }

   loadTSV()
   {
      this.http.get('/assets/data/comics.tsv')
      .map(res => res.text())
      .subscribe((data)=>
      {
         var tsv     = this.parseTSVFile(data);
         this.tsvItems  = tsv;
      });
   }

   parseCSVFile(str)
   {
      var arr  = [],
          obj  = [],
          row,
          col,
          c,
          quote = false;  // true means we're inside a quoted field

      // iterate over each character, keep track of current row and column (of the returned array)
      for (row = col = c = 0; c < str.length; c++)
      {
         var cc = str[c],
             nc = str[c+1];        // current character, next character

         arr[row]        = arr[row] || [];             // create a new row if necessary
         arr[row][col]  = arr[row][col] || '';   // create a new column (start with empty string) if necessary

         /* If the current character is a quotation mark, and we're inside a
            quoted field, and the next character is also a quotation mark,
            add a quotation mark to the current column and skip the next character */
         if (cc == '"' && quote && nc == '"')
         {
            arr[row][col] += cc;
            ++c;
            continue;
         }

         // If it's just one quotation mark, begin/end quoted field
         if (cc == '"')
         {
            quote = !quote;
            continue;
         }

         // If it's a comma and we're not in a quoted field, move on to the next column
         if (cc == ',' && !quote)
         {
            ++col;
            continue;
         }

         /* If it's a newline and we're not in a quoted field, move on to the next
            row and move to column 0 of that new row */
         if (cc == '\n' && !quote)
         {
            ++row;
            col = 0;
            continue;
         }

         // Otherwise, append the current character to the current column
         arr[row][col] += cc;
      }

      return this.formatParsedObject(arr, true);
   }

   parseTSVFile(str)
   {
      var arr  = [],
          obj  = [],
          row,
          col,
          c;

      // iterate over each character, keep track of current row and column (of the returned array)
      for (row = col = c = 0; c < str.length; c++)
      {
         var cc         = str[c];

         arr[row]        = arr[row] || [];             // create a new row if necessary
         arr[row][col]  = arr[row][col] || '';   // create a new column (start with empty string) if necessary

         // If it's a tab move on to the next column
         if (cc == '\t')
         {
            ++col;
            continue;
         }

         /* If it's a newline move on to the next
            row and move to column 0 of that new row */
         if (cc == '\n')
         {
            ++row;
            col = 0;
            continue;
         }

         // Otherwise, append the current character to the current column
         arr[row][col] += cc;
      }

      return this.formatParsedObject(arr, false);
   }

   parseXML(data)
   {
      return new Promise(resolve =>
      {
         var k,
             arr    = [],
             parser = new xml2js.Parser({
                         trim: true,
                         explicitArray: true
                      });

         parser.parseString(data, function (err, result)
         {
            var obj = result.comics;
            for(k in obj.publication)
            {
               var item = obj.publication[k];
               arr.push({
                  id       : item.id[0],
                  title    : item.title[0],
                  publisher : item.publisher[0],
                  genre    : item.genre[0]
               });
            }

            resolve(arr);
         });
      });
   }

   formatParsedObject(arr, hasTitles)
   {
      let id,
          title,
          publisher,
          genre,
          obj = [];

      for(var j = 0; j < arr.length; j++)
      {
         var items   = arr[j];

         if(items.indexOf("") === -1)
         {
            if(hasTitles === true && j === 0)
            {
               id           = items[0];
               title       = items[1];
               publisher   = items[2];
               genre       = items[3];
            }
            else
            {
               obj.push({
                  id       : items[0],
                  title    : items[1],
                  publisher : items[2],
                  genre    : items[3]
               });
            }
         }
      }

      return obj;
   }

}

home.html

<ion-header>
   <ion-navbar>
      <ion-title>
         British Comics of the 60's - 80's
      </ion-title>
   </ion-navbar>
</ion-header>

<ion-content padding>

   <ion-item-group>
      <ion-item-divider color="light">XML</ion-item-divider>
      <ion-item *ngFor="let item of xmlItems">
         {{ item.title }}
      </ion-item>
   </ion-item-group>

   <ion-item-group>
      <ion-item-divider color="light">CSV</ion-item-divider>
      <ion-item *ngFor="let item of csvItems">
         {{ item.title }}
      </ion-item>
   </ion-item-group>

   <ion-item-group>
      <ion-item-divider color="light">TSV</ion-item-divider>
      <ion-item *ngFor="let item of tsvItems">
         {{ item.title }}
      </ion-item>
   </ion-item-group>

</ion-content>

Penutup

Membaca data XML, CSV, dan TSV tidak terlalu sulit untuk dilakukan di Ionic berkat method yang disediakan oleh framework Angular (dan library xml2js untuk membaca XML).

Sebisa mungkin untuk selalu menggunakan data bertipe JSON agar proses pemuatan dan pembacaannya lebih cepat dan mudah. Tapi kita sama-sama tapi, terkadang sistem yang akan dipakai tidak selalu memiliki opsi mengeluarkan file JSON. Jika itu terjadi, sekarang pembaca sudah memiliki dasar-dasar bagaimana untuk memakai pengetahuan yang sudah didapat agar aplikasi Ionic bisa terintegrasi dengan data dari sistem tersebut.



Berlangganan Informasi CodePolitan Melalui Email

Jangan sampai kamu melewatkan informasi penting tentang pemrograman dan teknologi! Kamu bisa berlangganan Newsletter CodePolitan dengan cara mengisi formulir di samping.