Halo, nama saya Agung. Berasal dari Denpasar, Bali. Blog ini adalah blog harian saya, dari tips dan trick code, curahan hati, dan beberapa tulisan tidak penting.

Menu & Search

JAXP – SAX Parser & Validasi XML

February 28, 2011

JAXP (Java API for XML) merupakan API dari Java untuk pemprosessan XML. API ini memiliki fungsi untuk parsing, validasi xml dengan menggunakan DTD atau XSD.
JAXP sendiri dibagi menjadi 3 basic methode parsing, yaitu :

  1. SAX parser interface : Simple API for XML
  2. DOM interface : Document Object Model
  3. StAX : Streaming API for XML

SAX parser merupakan parser yang paling ringan dari pada semua yang saya sebutkan diatas.SAX menggunakan urutan event untuk melakukan parsing.Tidak seperti DOM yang akan otomatis melakukan parsing pada XML dokument, SAX memberikan kebebasan kepada programmer untuk menentukan setiap element / attribute yang perlu untuk di proses untuk dimasukkan kedalam model object custom sesuai dengan isi dari XML tersebut.

Kapan menggunakan SAX atau DOM ? 

Saya pribadi akan lebih condong menggunakan SAX parser apabila tag dari document XML tersebut sudah dapat diterka. Dan tag dari xml tersebut tidak terlalu berubah banyak. Sedangkan DOM untuk memparsing XML document yang lebih complex contoh nya HTML file atau XML file yang susah untuk diparsing oleh SAX parser.

Kali ini saya akan membahas tentang SAX parser baik method parsing maupun validasi xml dengan menggunakan DTD.XML yang saya buat berfungsi untuk memberikan kemudahan untuk mengconfigurasi scheduling task di java yang akan banyak menggunakan API dari Quartz untuk scheduler.

XML file berbentuk seperti ini :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE scheduleList PUBLIC "http://agungbayuiswara.blogspot.com//DTD Scheduler Module 1.0" "scheduler.dtd">
<schedulelist>
    <scheduler concurrent="false" id="scheduler01">
        <handler>com.jegbagus.util.scheduler.ExampleJob</handler>
        <cron>*/5 * * * * ?</cron>
        <group>Group01</group>
    </scheduler> 
</schedulelist>

Schedule list merupakan parent tag yang akan memuat list dari schedule – schedule yang akan dieksekusi. Attribute concurrent untuk menandakan scheduler dapat berjalan beriringan jika scheduler sebelum nya selesai. Name merupakan nama dari scheduler. Kemudian element handler menandakan class handler dari scheduler tersebut. Cron adalah aturan dari eksekusi scheduler. Group adalah group dari eksekusi scheduler.

XML tersebut akan di validasi dengan DTD berikut :

<?xml version="1.0" encoding="UTF-8"?>

<!ELEMENT scheduleList (scheduler*)>
<!ATTLIST ScheduleList
   name   CDATA   #IMPLIED   
>

<!ELEMENT scheduler (handler,cron,group)>
<!ATTLIST scheduler
 id    CDATA   #REQUIRED
 concurrent (true|false) "false" 
>

<!ELEMENT handler (#PCDATA)>

<!ELEMENT cron (#PCDATA)>

<!ELEMENT group (#PCDATA)>

untuk informasi lebih tentang DTD silahkan refer ke website seperti http://www.w3schools.com/DTD/default.asp

XML dan DTD tersebut akan divalidasi dan di parsing melalui SAX implementasi. Berikut Class dari sax parser :

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jegbagus.util.scheduler.parser;

/**
 *
 * @author agung.iswara
 */
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

import com.jegbagus.util.scheduler.domain.ScheduleConf;

public class SaxScheduleParser extends DefaultHandler implements SchedulerParserInterface, EntityResolver {

 @SuppressWarnings("unused")
 private static final Logger logger = LoggerFactory.getLogger(SaxScheduleParser.class);
 private static final Map<string, string=""> doctypeMap = new HashMap<string, string="">();
 private HashMap<string, scheduleconf=""> hashConf;
 private ScheduleConf tempConf;
 private String tempVal;
 private InputStream is;

 static {
  doctypeMap.put( "http://agungbayuiswara.blogspot.com//DTD Scheduler Module 1.0".toUpperCase(), "config/scheduler.dtd");
 }

 public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
  if (publicId != null) 
   publicId = publicId.toUpperCase();

  InputSource source = null;
  try {
   String path = (String) doctypeMap.get(publicId);
   source = getInputSource(path, source);
  } catch (Exception e) {
   throw new SAXException(e.toString());
  }
  return source;
 }

 private InputSource getInputSource(String path, InputSource source) {
  if (path != null) {
   InputStream in = null;
   try {
    in = SaxScheduleParser.class.getClassLoader().getResourceAsStream(path);
    source = new InputSource(in);
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  return source;
 }

 public void initParser(String confLoc) {
  hashConf = new HashMap<string, scheduleconf="">();
  is = SaxScheduleParser.class.getClassLoader().getResourceAsStream(confLoc);
 }

 public SaxScheduleParser(String confLoc) {
  initParser(confLoc);
 }

 public HashMap<string, scheduleconf=""> startParse() {
  return parseDocument();
 }

 private HashMap<string, scheduleconf=""> parseDocument() {
  SAXParserFactory parserFactory = SAXParserFactory.newInstance();
  try {
   SAXParser saxParser = parserFactory.newSAXParser();
   saxParser.parse(is, this);
  } catch (SAXException se) {
   se.printStackTrace();
  } catch (ParserConfigurationException pce) {
   pce.printStackTrace();
  } catch (IOException ie) {
   ie.printStackTrace();
  }
  return hashConf;
 }

 public void startElement(String uri, String localName, String qName,
   Attributes attributes) throws SAXException {
  tempVal = "";
  if (qName.equalsIgnoreCase("scheduler")) {
   tempConf = new ScheduleConf();
   tempConf.setSchedulerId(attributes.getValue("id"));
   tempConf.setConcurent(new Boolean(attributes.getValue("concurrent")));
  }
 }

 public void characters(char[] ch, int start, int length)
   throws SAXException {
  tempVal = new String(ch, start, length);
 }

 public void endElement(String uri, String localName, String qName)
   throws SAXException {
  if (qName.equalsIgnoreCase("scheduler")) {
   hashConf.put(tempConf.getSchedulerId(), tempConf);
  } else if (qName.equalsIgnoreCase("handler")) {
   tempConf.setHandlerName(tempVal);
  } else if (qName.equalsIgnoreCase("cron")) {
   tempConf.setCron(tempVal);
  } else if (qName.equalsIgnoreCase("group")) {
   tempConf.setGroup(tempVal);
  }
 }
}

Mari kita breakdown code tersebut :
Parser

  • Sax Parser dapat merupakan turunan dari DefaultHandler, HandlerBase (deprecated pada java 1.6) atau handler lainnya yang terdapat pada package org.sax .kali ini saya akan menggunkan DefaultHandler sebagai base class.
  • Method yang harus kita override dari DefaultHandler tersebut untuk mendapatkan Element & attribute adalah startElement & endElement
  • startElement akan dieksekusi setiap menemui awal element seperti , dan dari awal element tersebut akan didapat attribute – attribute dari element tersebut id & concurrent dari element scheduler. method startElement biasa digunakan jika menemui element yang memiliki attribute & memiliki child element.
  •  endElement akan dieksekusi setiap parser menemu akhir element seperti . dari end element kita bisa mendapatkan isi dari element tersebut yang sebelum nya didapat dari method characters

Validasi

  • Untuk mem-validasi xml file perlu menambahkan doctype dan file yang berkesesuaian untuk memvalidasi file XML. Apabila anda menggunakan eclipse dengan DTD ini kita bisa memanfaatkan fasilitas autocomplete pada xml file yang kita buat jika XML file tersebut merujuk ke DTD file.
  • Pada java class harus mengimplementasikan EntityResolver yang merujuk file dimana DTD itu tersimpan, dan XML file akan di validasi dari oleh DTD tersebut. Implementasi validasi dari DTD dapat dilihat pada method resolveEntity yang mengembalikan Object dari InputSource DTD tersebut.

Dari hasil parsing yang disimpan pada object model, akan di proses sebagai sumber data untuk melakukan scheduler pada aplikasi.

Untuk lebih lengkap download source codenya pada : http://sax-dtd-example.googlecode.com/files/scheduler01.zip
aplikasi tersebut menggunakan maven untuk script build nya. Eksekusi mvn tomcat:run pada command prompt untuk menjalankan aplikasi ini.

Related article

Startup, dan Leverage dalam usaha

Kita tau belakangan ini banyak startup berguguran. Bahkan di sebuah…

Sekolah Anak

Beberapa hari lalu, istri bertanya kepada saya, kemana anak kami…

Istri, IRT atau Kerja atau Usaha?

Pernah ga cowo – cowo yang akan nikah berpikir, istri…

Discussion about this post

Leave a Reply

Your email address will not be published. Required fields are marked *

Type your search keyword, and press enter to search