Java SAX Parser භාවිතයෙන් විශාල XML ගොනු කාර්යක්ෂමව කියවමු | Efficient XML Parsing SC Guide

ආයුබෝවන් යාළුවනේ!
අද අපි කතා කරන්න යන්නේ software engineering ක්ෂේත්රයේ, විශේෂයෙන්ම Data Interchange වලදී ඉතා වැදගත් වන, ඒ වගේම ගොඩක් දෙනෙක්ට ප්රශ්නයක් වෙන ලොකු XML files handle කරන විදිය ගැන. සාමාන්යයෙන් XML කියද්දී ගොඩක් දෙනෙක්ට මතක් වෙන්නේ DOM Parser එක. ඒත් විශාල XML ගොනු එක්ක වැඩ කරනකොට DOM එකේ මතක ගැටලු (memory issues) එනවා. ඒකට තියෙන සුපිරි විසඳුමක් තමයි SAX Parser එක. මේ ලිපියෙන් අපි Java වල SAX Parser එකක් භාවිතයෙන් XML ගොනු කාර්යක්ෂමව parse කරන්නේ කොහොමද කියලා සවිස්තරාත්මකව බලමු.
අපි මේ ලිපිය අවසානය වෙනකොට, SAX Parser එක කියන්නේ මොකක්ද, ඒක වැඩ කරන්නේ කොහොමද, ඒ වගේම ප්රායෝගික උදාහරණයක් එක්ක Java වලින් SAX Parser එකක් implement කරන්නේ කොහොමද කියන එක ගැන ඔයාලට හොඳ අවබෝධයක් ලැබෙයි.
SAX Parser කියන්නේ මොකක්ද? (What is SAX Parser?)
SAX කියන්නේ Simple API for XML Parsing කියන එකේ කෙටි යෙදුමක්. මේක DOM (Document Object Model) Parser එකට වඩා හාත්පසින්ම වෙනස් ක්රමවේදයක්. DOM Parser එකකදී කරන්නේ, XML document එක සම්පූර්ණයෙන්ම මතකයට (memory) load කරලා, ඒක Object Tree එකක් විදියට නිරූපණය කරන එක. මේක කුඩා XML ගොනු වලට නම් ගැටලුවක් නැහැ. ඒත් Gigabytes ගණන් විශාල වෙන XML ගොනු වලදී DOM Parser එකට පුළුවන් ඔයාලගේ System එකේ RAM එක සම්පූර්ණයෙන්ම පාවිච්චි කරලා, System එක Slow කරන්න, සමහරවිට OutOfMemoryError එකක් පවා දෙන්න.
SAX Parser එකේදී මේ ප්රශ්නේ නැහැ. මොකද SAX කියන්නේ event-driven parser එකක්. ඒ කියන්නේ, SAX Parser එක XML document එක රේඛාවෙන් රේඛාව (line by line) කියවනවා. XML document එකේ යම් සිදුවීමක් (event) හමු වුන ගමන්, ඒ සිදුවීමට අදාළ ක්රියාවක් (action) කරන්න කියලා Parser එක අපිට දන්වනවා. මේ සිදුවීම් වලට උදාහරණ විදියට XML element එකක් පටන් ගැනීම (start of an element), element එකක් අවසන් වීම (end of an element), text data හමු වීම (character data) වගේ දේවල් දක්වන්න පුළුවන්. ඒ නිසා SAX Parser එක මුළු XML document එකම මතකයට load කරන්නේ නැහැ. මේක තමයි SAX Parser එකේ ප්රධානම වාසිය - අඩු මතක පරිභෝජනය (low memory footprint).
SAX Parser එක වැඩ කරන්නේ කොහොමද? (How SAX Parser Works?)
SAX Parser එක වැඩ කරන්නේ listener/callback model එකක් මත. ඒ කියන්නේ, Parser එක XML document එක කියවනකොට, යම් නිශ්චිත සිදුවීමක් හමු වුනාම, අදාළ callback method එක execute කරනවා. අපිට කරන්න තියෙන්නේ, ඒ methods override කරලා, අපිට අවශ්ය විදියට logic එක implement කරන එකයි. SAX API එකේ ප්රධාන callback methods කිහිපයක් මෙන්න:
startDocument()
: XML document එක කියවීම ආරම්භ කරන විට මේ method එක කැඳවනු ලැබේ.endDocument()
: XML document එක කියවීම අවසන් කරන විට මේ method එක කැඳවනු ලැබේ.startElement(String uri, String localName, String qName, Attributes attributes)
: XML element එකක් ආරම්භ වන විට මේ method එක කැඳවනු ලැබේ. මෙහිදී element එකේ නම (qName
) සහ attribute (attributes
) වැනි තොරතුරු ලබාගත හැක.endElement(String uri, String localName, String qName)
: XML element එකක් අවසන් වන විට මේ method එක කැඳවනු ලැබේ.characters(char[] ch, int start, int length)
: XML element එකක් ඇතුළේ ඇති text data හමු වන විට මේ method එක කැඳවනු ලැබේ.
මේ methods හරහා අපිට අවශ්ය දත්ත පමණක් extract කරගෙන, අනවශ්ය දත්ත ඉවත දැමීමට පුළුවන්. ඒ නිසා විශේෂයෙන්ම ලොකු XML files වලදී මේක ඉතා කාර්යක්ෂමයි.
Java එකේ SAX Parser එක Implementation කරමු (Implementing SAX Parser in Java)
හරි, දැන් අපි බලමු Java වලින් SAX Parser එකක් practical විදියට implement කරන්නේ කොහොමද කියලා. අපි පොඩි Example XML file එකක් හදලා, ඒක parse කරමු.
පියවර 1: Example XML File එක සකස් කරගනිමු (Create the Example XML File)
books.xml
කියලා file එකක් හදලා මේ content එක paste කරන්න:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date&n>
<description>A former architect battles an evil sorceress.</description>
</book>
</catalog>
පියවර 2: Custom SAX Handler Class එක සාදාගනිමු (Create Custom SAX Handler Class)
අපිට අවශ්ය වෙන්නේ org.xml.sax.helpers.DefaultHandler
class එක extend කරලා අපේම Handler class එකක් හදාගන්න එක. DefaultHandler
class එකේ SAX events වලට අදාළ methods හිස් (empty) implementations එක්ක තියෙනවා. අපිට අවශ්ය methods විතරක් override කරන්න පුළුවන්. අපි MySAXHandler.java
කියලා class එකක් හදමු.
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MySAXHandler extends DefaultHandler {
private boolean bTitle = false;
private boolean bAuthor = false;
private boolean bPrice = false;
// XML Document එක කියවීම ආරම්භ කරන විට
@Override
public void startDocument() throws SAXException {
System.out.println("Parsing Started...");
}
// XML Document එක කියවීම අවසන් කරන විට
@Override
public void endDocument() throws SAXException {
System.out.println("Parsing Ended.");
}
// Element එකක් ආරම්භ වන විට
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// System.out.println("Start Element: " + qName);
if (qName.equalsIgnoreCase("book")) {
String id = attributes.getValue("id");
System.out.println("\nBook ID : " + id);
} else if (qName.equalsIgnoreCase("title")) {
bTitle = true;
} else if (qName.equalsIgnoreCase("author")) {
bAuthor = true;
} else if (qName.equalsIgnoreCase("price")) {
bPrice = true;
}
}
// Element එකක් අවසන් වන විට
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// System.out.println("End Element: " + qName);
}
// Element එකක ඇති text content හමු වන විට
@Override
public void characters(char ch[], int start, int length) throws SAXException {
if (bTitle) {
System.out.println("Title : " + new String(ch, start, length));
bTitle = false;
} else if (bAuthor) {
System.out.println("Author : " + new String(ch, start, length));
bAuthor = false;
} else if (bPrice) {
System.out.println("Price : " + new String(ch, start, length));
bPrice = false;
}
}
}
මේ Code එකේ අපි කරන්නේ මොකක්ද කියලා පොඩ්ඩක් බලමු:
DefaultHandler
class එක extend කරනවා.- Boolean variables (
bTitle
,bAuthor
,bPrice
) තුනක් අරන් තියෙනවා, මොකදcharacters()
method එක කැඳවෙන්නේ Element Name එකට නෙවෙයි, ඒ Element එකේ value එකට නිසා. Element Name එකstartElement()
එකෙන් අඳුරගෙන, ඒකට අදාළ boolean variable එකtrue
කරනවා. startElement()
method එක ඇතුලේ, අපි<book>
element එක හමු වුනාම ඒකේid
attribute එක අරගෙන Print කරනවා. ඊට අමතරව<title>
,<author>
,<price>
වගේ elements හමු වුනාම අදාළ boolean variable එකtrue
කරනවා.characters()
method එක ඇතුලේ, අදාළ boolean variable එකtrue
නම්, අපි ඒ Element එකේ text content එක අරගෙන Print කරනවා. පස්සේ boolean variable එක ආයෙත්false
කරනවා.startDocument()
සහendDocument()
methods Parser එක පටන් ගන්නකොටයි, ඉවර වෙනකොටයි මොනවද වෙන්න ඕනේ කියලා පෙන්නන්න යොදාගෙන තියෙනවා.
පියවර 3: SAX Parser එක Execute කරන Main Class එක (Main Class to Execute SAX Parser)
දැන් අපි MySAXHandler
එක භාවිතයෙන් books.xml
file එක parse කරන main class එක ලියමු. SAXParserExample.java
කියලා class එකක් හදන්න.
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
public class SAXParserExample {
public static void main(String[] args) {
try {
// 1. SAXParserFactory එකක් ලබා ගන්න
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2. ඒකෙන් SAXParser එකක් හදාගන්න
SAXParser saxParser = factory.newSAXParser();
// 3. අපේ Custom Handler එක instantiate කරගන්න
MySAXHandler handler = new MySAXHandler();
// 4. XML file එක Parse කරන්න
saxParser.parse(new File("books.xml"), handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
මේ code එකේ වෙන්නේ මොකක්ද?
- මුලින්ම
SAXParserFactory.newInstance()
භාවිතයෙන්SAXParserFactory
එකක් හදාගන්නවා. මේක තමයි SAX Parser instances හදන්න Factory එක. - ඊළඟට,
factory.newSAXParser()
භාවිතයෙන්SAXParser
එකක් ලබාගන්නවා. මේක තමයි actual parser එක. - අපි කලින් හදාගත්තු
MySAXHandler
class එකේ object එකක් හදනවා. - අවසානයට,
saxParser.parse()
method එකට අපේ XML file එකේFile
object එකයි, අපේhandler
object එකයි දෙනවා. මේකෙන් XML file එක කියවීම ආරම්භ කරනවා.
ප්රතිදානය (Output)
මේ programs ටික compile කරලා run කරාම ඔයාලට මේ වගේ Output එකක් බලාගන්න පුළුවන්:
Parsing Started...
Book ID : bk101
Author : Gambardella, Matthew
Title : XML Developer's Guide
Price : 44.95
Book ID : bk102
Author : Ralls, Kim
Title : Midnight Rain
Price : 5.95
Parsing Ended.
ඔන්න ඔය විදියට තමයි Java වල SAX Parser එකක් භාවිතයෙන් XML file එකක් Parse කරන්නේ. මේක ඉතා සරල උදාහරණයක් වුනත්, මේ මූලික සංකල්පය භාවිතයෙන් ඔයාලට ඕනෑම සංකීර්ණ XML structure එකක් හැසිරවීමට හැකියාව ලැබෙනවා.
SAX භාවිතා කළ යුත්තේ කවදාද? (When to use SAX?)
SAX Parser එකේ වාසි තියෙන නිසා හැම වෙලාවෙම ඒක පාවිච්චි කරන්න ඕනෙද? නැහැ. මේකත් අනෙක් tools වගේම නිවැරදි තැනට පාවිච්චි කරන්න ඕනේ.
- විශාල XML ගොනු Parse කරන විට (Parsing Large XML Files): මේක තමයි SAX එකේ ප්රධානම භාවිතය. මතක ගැටලු අවම කරගන්න මේක උදව් වෙනවා.
- XML document එකේ යම් කොටසක් පමණක් අවශ්ය නම් (When Only a Part of XML is Needed): ඔයාලට මුළු XML document එකෙන්ම පොඩි දත්ත කොටසක් විතරක් අවශ්ය නම්, SAX එකෙන් අවශ්ය සිදුවීම් (events) විතරක් handle කරලා, අදාළ දත්ත විතරක් extract කරගන්න පුළුවන්.
- Streaming Data හැසිරවීමේදී (Handling Streaming Data): Real-time data streams වගේ තැන් වලදී, XML එක එනකොටම Parse කරන්න SAX එක ගොඩක් හොඳයි.
- Write Operations නොකරන විට (No Write Operations): SAX Parser එක කියවීම (read-only) සඳහා තමයි යොදාගන්නේ. XML document එකේ වෙනස්කම් කරන්න අවශ්ය නම්, DOM වගේ එකක් තමයි වඩා සුදුසු.
අවසන් වශයෙන්
හරි යාළුවනේ, මේ ලිපියෙන් අපි Java වල SAX Parser එක භාවිතයෙන් විශාල XML ගොනු කාර්යක්ෂමව Parse කරන්නේ කොහොමද කියලා විස්තරාත්මකව ඉගෙන ගත්තා. මතක තියාගන්න, SAX Parser එක කියන්නේ Memory efficient, event-driven parsing method එකක්. මේක DOM වගේ නෙවෙයි, මුළු document එකම memory එකට load කරන්නේ නැහැ. ඒ නිසා, ඔයාලා ලොකු XML files එක්ක වැඩ කරන Software Engineer කෙනෙක් නම්, SAX Parser එක කියන්නේ ඔයාලට නැතුවම බැරි tool එකක්.
මේ ලිපිය ඔයාලට ප්රයෝජනවත් වෙන්න ඇති කියලා හිතනවා. ඔයාලට මේ ගැන තියෙන අදහස්, ප්රශ්න, නැතිනම් ඔයාලා SAX Parser එක පාවිච්චි කරපු අත්දැකීම් පහලින් comment කරන්න! ඔයාලගේ අදහස් දැනගන්න අපි කැමතියි. ඒ වගේම මේක තව යාළුවන්ටත් බලන්න share කරන්නත් අමතක කරන්න එපා. ජයවේවා!