Java වලින් XML වැඩ කරමු: DOM, SAX, JAXB - SC Guide

හෙලෝ! කොහොමද යාලුවනේ? ඔයාලා හැමෝම හොඳින් ඇති කියලා හිතනවා. අද අපි කතා කරන්න යන්නේ software development වලදි නැතුවම බැරි, ඒ වගේම ගොඩක් වැදගත් concept එකක් ගැන – ඒ තමයි XML (eXtensible Markup Language). විශේෂයෙන්ම Java applications වලදි XML handle කරන්නේ කොහොමද කියන එක තමයි අපේ focus එක.
අද කාලේ web services, configuration files, data exchange වගේ දේවල් වලදි XML වලට ලොකු තැනක් ලැබිලා තියෙනවා. ඉතින්, Java developer කෙනෙක් විදිහට XML properly handle කරන්න දැනගෙන ඉන්න එක අනිවාර්යයෙන්ම ඔයාලගේ skill set එකට ලොකු වටිනාකමක් එකතු කරයි. මේ article එකෙන් අපි XML කියන්නේ මොකක්ද කියලත්, ඒ වගේම Java වලදි XML parse කරන්න අපි පාවිච්චි කරන ප්රධාන methods තුනක් ගැනත්, ඒ කියන්නේ DOM (Document Object Model), SAX (Simple API for XML), සහ JAXB (Java Architecture for XML Binding) ගැනත් ගැඹුරින් කතා කරමු.
එහෙනම්, අපි පටන් ගමු නේද?
XML කියන්නේ මොකක්ද?
සරලවම කිව්වොත්, XML කියන්නේ structured data storage සහ transport කරන්න පාවිච්චි කරන markup language එකක්. මේක HTML වලට ටිකක් සමානයි වගේ පෙනුනත්, XML හදලා තියෙන්නේ data describe කරන්න මිසක් data display කරන්න නෙවෙයි. ඒ කියන්නේ, XML tags වලින් data එකේ තේරුම කියනවා මිසක්, ඒක browser එකක කොහොම පෙන්වන්නද කියන එක කියන්නේ නෑ.
XML වල ප්රධාන ලක්ෂණ කීපයක් තියෙනවා:
- eXtensible: ඔයාලට ඕන කරන විදිහට tags හදාගන්න පුළුවන්. ඒ කියන්නේ, HTML වල වගේ fix set of tags නෙවෙයි තියෙන්නේ.
- Self-describing: XML document එකක් බැලුවම ඒකේ තියෙන data මොනවද කියලා තේරුම් ගන්න පුළුවන්. (උදාහරණයක් විදිහට,
<student>
,<name>
වගේ tags නිසා). - Plain Text: මේක plain text format එකක් නිසා, ඕනම system එකකට read කරන්න, process කරන්න පුළුවන්.
සරල XML උදාහරණයක් බලමු:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="web">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
<book category="programming">
<title lang="en">Java Programming Basics</title>
<author>Jane Doe</author&n>
<year>2021</year>
<price>50.00</price>
</book>
</bookstore>
මේකෙන් තේරෙනවනේ XML කියන්නේ කොච්චර clear විදිහට data organize කරන්න පුළුවන් දෙයක්ද කියලා. ඉතින්, Java application එකක් ඇතුලේ මේ වගේ XML data එක්ක වැඩ කරන්නේ කොහොමද? එතනට තමයි XML Parsers කියන concept එක එන්නේ.
Java වලින් XML Parse කරන්නේ කොහොමද?
XML Parser එකක් කියන්නේ XML document එකක් කියවලා, ඒකේ තියෙන data අපිට Java code එකෙන් access කරන්න පුළුවන් විදිහට convert කරන tool එකක්. Java Platform, Standard Edition (Java SE) එකේම XML parsing වලට අවශ්ය library files අඩංගුයි. ප්රධාන විදි තුනක් තියෙනවා:
- DOM Parser: මේක XML document එකක් memory එකට load කරලා tree structure එකක් විදිහට හදනවා. හිතන්නකෝ, පොතක හැම පිටුවක්ම එකපාර මතක තියාගෙන ඕනම පිටුවකට ඉක්මනට යන්න පුළුවන් වගේ.
- SAX Parser: මේක event-driven parser එකක්. XML document එක stream එකක් විදිහට කියවනවා, tags හම්බවෙන හැම වෙලාවකම event එකක් fire කරනවා. මේක හරියට පොතක් පේළියෙන් පේළියට කියවනවා වගේ. කලින් කියවපු පේළියට ආයෙ යන්න බෑ.
- JAXB: මේක XML data, Java objects වලට map කරනවා. ඒ කියන්නේ, XML document එකේ තියෙන data කෙලින්ම Java object එකක properties විදිහට ගන්න පුළුවන්. හරියට, පොතක තියෙන details ටික object එකක attribute විදිහට කෙලින්ම store කරනවා වගේ.
එහෙනම්, මේ එක් එක් parser එක ගැන විස්තරාත්මකව බලමු.
DOM Parser එකෙන් XML හසුරුවමු
DOM (Document Object Model) parser එක XML document එකක් memory එකට load කරලා, ඒක XML tree structure එකක් විදිහට නිරූපණය කරනවා. මේ tree එකේ Nodes, Elements, Attributes, Text වගේ components තියෙනවා. මේ parser එක පාවිච්චි කරලා අපිට document එකේ ඕනම තැනකට ගිහින් data access කරන්න, modify කරන්න, නැත්නම් delete කරන්න පුළුවන්. ඒ වගේම අලුත් Nodes එකතු කරන්නත් පුළුවන්.
වාසි (Pros):
- XML document එකේ ඕනම කොටසකට random access කරන්න පුළුවන්.
- Document එක modify කරන්න ලේසියි.
- Document එකේ structure එක හොඳින් පෙන්වනවා.
අවාසි (Cons):
- ලොකු XML files වලට ගොඩක් memory පාවිච්චි කරනවා. මොකද මුළු document එකම memory එකට load කරන නිසා.
- Performance එක අඩු වෙන්න පුළුවන් ලොකු files වලදී.
හරි, අපි පොඩි උදාහරණයක් බලමු DOM Parser එකෙන් XML file එකක් read කරන්නේ කොහොමද කියලා.
මුලින්ම, අපි books.xml
කියලා XML file එකක් හදාගමු:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="B101">
<title>The Art of Programming</title>
<author>John Doe</author>
<year>2010</year>
<price>45.00</price>
</book>
<book id="B102">
<title>Data Structures in Java</title>
<author>Jane Smith</author>
<year>2015</year>
<price>55.00</price>
</book>
</books>
දැන් අපි මේක DOM parser එකෙන් read කරමු:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class DOMParserExample {
public static void main(String[] args) {
try {
File xmlFile = new File("books.xml");
// 1. Create a DocumentBuilderFactory
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
// 2. Create a DocumentBuilder
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
// 3. Parse the XML file into a Document object
Document doc = dBuilder.parse(xmlFile);
// Optional: Normalize the document to combine text nodes
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
// Get all 'book' elements
NodeList bookList = doc.getElementsByTagName("book");
System.out.println("----------------------------");
for (int temp = 0; temp < bookList.getLength(); temp++) {
Node node = bookList.item(temp);
System.out.println("\nCurrent Element :" + node.getNodeName());
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
System.out.println("Book ID : " + element.getAttribute("id"));
System.out.println("Title : " + element.getElementsByTagName("title").item(0).getTextContent());
System.out.println("Author : " + element.getElementsByTagName("author").item(0).getTextContent());
System.out.println("Year : " + element.getElementsByTagName("year").item(0).getTextContent());
System.out.println("Price : " + element.getElementsByTagName("price").item(0).getTextContent());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
මේ code එකෙන් මුලින්ම XML file එක read කරලා Document object එකක් හදනවා. ඊට පස්සේ ඒ Document object එකෙන් ඕන කරන Elements ටික getElementsByTagName()
method එකෙන් අරගෙන, ඒක ඇතුලේ තියෙන data getTextContent()
වලින් ගන්නවා. Attribute එකක් ගන්න නම් getAttribute()
පාවිච්චි කරනවා.
SAX Parser එකෙන් XML Stream කරන්න
SAX (Simple API for XML) parser එක DOM වලට වඩා වෙනස් විදිහකට තමයි XML handle කරන්නේ. SAX කියන්නේ event-driven, stream-based parser එකක්. ඒ කියන්නේ, XML document එක sequential විදිහට කියවනවා. XML tags, attributes, text content වගේ දේවල් හම්බවෙන හැම වෙලාවකම event එකක් fire කරනවා. ඒ event එකට අදාළ handler method එකක් implement කරලා අපිට අවශ්ය logic එක දාන්න පුළුවන්.
වාසි (Pros):
- ගොඩක් අඩු memory එකක් පාවිච්චි කරන්නේ. මොකද මුළු document එකම memory එකට load කරන්නේ නැති නිසා. ලොකු XML files වලට මේක ගොඩක් හොඳයි.
- Performance එක DOM වලට වඩා හොඳයි ලොකු files වලදී.
- Sequential access විතරක් අවශ්ය නම් වඩාත් කාර්යක්ෂමයි.
අවාසි (Cons):
- DOM වගේ random access කරන්න බෑ. Forward-only parser එකක්.
- Document එක modify කරන්න බෑ.
- Simple XML files වලට DOM වගේ සරල නෑ.
අපි කලින් පාවිච්චි කරපු books.xml
file එකම SAX parser එකෙන් read කරන්නේ කොහොමද කියලා බලමු.
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
public class SAXParserExample {
public static void main(String[] args) {
try {
File xmlFile = new File("books.xml");
// 1. Create a SAXParserFactory
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2. Create a SAXParser
SAXParser saxParser = factory.newSAXParser();
// 3. Create a custom handler
MySAXHandler handler = new MySAXHandler();
// 4. Parse the XML file using the handler
saxParser.parse(xmlFile, handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MySAXHandler extends DefaultHandler {
boolean isTitle = false;
boolean isAuthor = false;
boolean isYear = false;
boolean isPrice = false;
@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("Book ID : " + id);
} else if (qName.equalsIgnoreCase("title")) {
isTitle = true;
} else if (qName.equalsIgnoreCase("author")) {
isAuthor = true;
} else if (qName.equalsIgnoreCase("year")) {
isYear = true;
} else if (qName.equalsIgnoreCase("price")) {
isPrice = true;
}
}
@Override
public void endElement(String uri, String localName,
String qName) throws SAXException {
System.out.println("End Element :" + qName);
if (qName.equalsIgnoreCase("book")) {
System.out.println("----------------------------");
}
}
@Override
public void characters(char ch[], int start, int length) throws SAXException {
if (isTitle) {
System.out.println("Title : " + new String(ch, start, length));
isTitle = false;
} else if (isAuthor) {
System.out.println("Author : " + new String(ch, start, length));
isAuthor = false;
} else if (isYear) {
System.out.println("Year : " + new String(ch, start, length));
isYear = false;
} else if (isPrice) {
System.out.println("Price : " + new String(ch, start, length));
isPrice = false;
}
}
}
මේ code එකේ MySAXHandler
කියන class එක DefaultHandler
කියන class එක extend කරනවා. මේකෙදි අපිට startElement()
, endElement()
, characters()
වගේ methods override කරන්න වෙනවා. startElement()
කියන්නේ opening tag එකක් හම්බවුනාම fire වෙන event එක, endElement()
කියන්නේ closing tag එකක් හම්බවුනාම, characters()
කියන්නේ tag අතර තියෙන actual data හම්බවුනාම fire වෙන event එක. මේවා ඇතුලේ අපිට ඕන විදිහට logic ලියන්න පුළුවන්.
JAXB වලින් Java Object වලට XML බඳිමු
JAXB (Java Architecture for XML Binding) කියන්නේ XML document එකක තියෙන data කෙලින්ම Java objects වලට map කරන්න, නැත්නම් Java objects වල data XML document එකක් විදිහට generate කරන්න (marshal) පාවිච්චි කරන framework එකක්. මේක DOM සහ SAX වලට වඩා high-level abstraction එකක්. අපිට XML ගැන ගොඩක් හිතන්නේ නැතුව කෙලින්ම Java objects එක්ක වැඩ කරන්න පුළුවන්.
වාසි (Pros):
- XML document එක Java objects විදිහට represent කරන නිසා වැඩ කරන්න ලේසියි. Object-Oriented approach එකක්.
- Type-safe. Compiler එකෙන් data type errors අල්ලගන්න පුළුවන්.
- XML Schema එකක් තියෙනවා නම්, ඒකෙන් Java classes generate කරන්න පුළුවන්.
- Error handling සහ validation support කරනවා.
අවාසි (Cons):
- Simple XML documents වලට overkill වෙන්න පුළුවන්.
- Dependencies add වෙනවා (නමුත් Java SE 6 ඉඳන් මේක JDK එකේම අඩංගුයි).
අපි කලින් books.xml
එකේ තියෙන data, JAXB පාවිච්චි කරලා Java objects වලට map කරලා බලමු.
මුලින්ම, XML structure එකට අදාළ Java classes හදන්න ඕනේ. අපි Book
class එකක් හදමු.
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "book") // Maps this class to the <book> element
@XmlType(propOrder = { "title", "author", "year", "price" }) // Define element order in XML
public class Book {
private String id;
private String title;
private String author;
private int year;
private double price;
public Book() {
}
public Book(String id, String title, String author, int year, double price) {
this.id = id;
this.title = title;
this.author = author;
this.year = year;
this.price = price;
}
@XmlAttribute // Maps this to the 'id' attribute of <book>
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@XmlElement // Maps this to the <title> element
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@XmlElement // Maps this to the <author> element
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@XmlElement // Maps this to the <year> element
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@XmlElement // Maps this to the <price> element
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book [id=" + id + ", title=" + title + ", author=" + author +
", year=" + year + ", price=" + price + "]";
}
}
ඊට පස්සේ, books
root element එක define කරන්න BookStore
වගේ class එකක් ඕනේ. මේකේ Book
objects list එකක් තියෙන්න ඕනේ.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name = "books") // Maps this class to the <books> root element
public class BookStore {
private List<Book> books;
public BookStore() {
books = new ArrayList<>();
}
@XmlElement(name = "book") // Maps each <book> element to a Book object in the list
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
public void addBook(Book book) {
this.books.add(book);
}
@Override
public String toString() {
return "BookStore [books=" + books + "]";
}
}
දැන් අපි JAXB පාවිච්චි කරලා XML file එකක් Java objects වලට unmarshal කරන්නත්, Java objects වලින් XML file එකක් marshal කරන්නත් බලමු.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.List;
public class JAXBExample {
public static void main(String[] args) {
// Create some Book objects
Book book1 = new Book("B103", "Clean Code", "Robert C. Martin", 2008, 60.00);
Book book2 = new Book("B104", "Effective Java", "Joshua Bloch", 2018, 58.50);
BookStore bookStore = new BookStore();
bookStore.addBook(book1);
bookStore.addBook(book2);
// 1. Marshalling (Java Objects to XML)
try {
// Create JAXBContext object
JAXBContext jaxbContext = JAXBContext.newInstance(BookStore.class);
// Create Marshaller object
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// Set property to format output XML
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Marshal the BookStore object to a new XML file
File outputXml = new File("new_books.xml");
jaxbMarshaller.marshal(bookStore, outputXml);
jaxbMarshaller.marshal(bookStore, System.out); // Also print to console
System.out.println("\nnew_books.xml created successfully!");
} catch (JAXBException e) {
e.printStackTrace();
}
// 2. Unmarshalling (XML to Java Objects)
try {
// Create JAXBContext object for unmarshalling
JAXBContext jaxbContext = JAXBContext.newInstance(BookStore.class);
// Create Unmarshaller object
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
// Unmarshal the existing books.xml file to a BookStore object
File existingXml = new File("books.xml");
BookStore unmarshalledBookStore = (BookStore) jaxbUnmarshaller.unmarshal(existingXml);
System.out.println("\nBooks from books.xml:");
List<Book> books = unmarshalledBookStore.getBooks();
for (Book book : books) {
System.out.println(book);
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
මේ JAXB code එක ටිකක් දිගයි වගේ පෙනුනට, මේකෙන් අපේ වැඩේ කොච්චර ලේසිද කියලා පේනවා නේද? XML document එකේ structure එකට ගැලපෙන විදිහට Java classes හදලා, annotations (@XmlRootElement
, @XmlElement
, @XmlAttribute
) පාවිච්චි කරලා map කරාම, ඉතුරු ටික JAXB automatically handle කරනවා. Marshaller
පාවිච්චි කරලා Java object එක XML බවටත්, Unmarshaller
පාවිච්චි කරලා XML එක Java object බවටත් convert කරන්න පුළුවන්.
කවදද, කොහොමද පාවිච්චි කරන්නේ?
දැන් අපි DOM, SAX, JAXB ගැන ඉගෙන ගත්තා. ඉතින්, මේවායින් මොකක්ද පාවිච්චි කරන්න ඕනේ කියන එක ප්රශ්නයක් වෙන්න පුළුවන්. ඒක ඔයාලගේ project එකේ requirement එක අනුව තමයි තීරණය වෙන්නේ.
- DOM Parser:
- පාවිච්චි කරන්න ඕනේ: XML file එක සාපේක්ෂව කුඩා නම් (සාමාන්යයෙන් MB කීපයකට වඩා අඩු නම්).
- පාවිච්චි කරන්න ඕනේ: XML document එකේ random access කරන්න, modify කරන්න, නැත්නම් ඒකට අලුතින් data එකතු කරන්න අවශ්ය නම්.
- උදාහරණ: Configuration files, කුඩා data sets.
- SAX Parser:
- පාවිච්චි කරන්න ඕනේ: XML file එක ඉතා විශාල නම් (GB ගණන් වගේ).
- පාවිච්චි කරන්න ඕනේ: XML document එක read-only විදිහට sequential විදිහට process කරන්න අවශ්ය නම් (memory එක minimize කරමින්).
- උදාහරණ: Large log files, data streams.
- JAXB:
- පාවිච්චි කරන්න ඕනේ: XML document එකේ structure එක complex නම්, සහ ඒක Java objects වලට map කරලා object-oriented විදිහට වැඩ කරන්න අවශ්ය නම්.
- පාවිච්චි කරන්න ඕනේ: Type safety අවශ්ය නම් සහ XML data manipulation වලට වඩා business logic වලට focus කරන්න ඕනේ නම්.
- උදාහරණ: Web services (SOAP/REST), complex data structures, data persistence.
නිතර අසන ප්රශ්න (FAQs)
XML වලට වඩා JSON හොඳද?
මේක ගොඩක් දෙනෙක්ට තියෙන ප්රශ්නයක්. JSON (JavaScript Object Notation) අද කාලේ data exchange වලට ගොඩක් ජනප්රියයි, විශේෂයෙන්ම RESTful web services වලට. JSON, XML වලට වඩා light-weight සහ human-readable කියලා සමහර වෙලාවට කියනවා. ඒත් XML වලට තියෙනවා XML Schema, XSLT, XPath වගේ advanced features. Large enterprise systems වලට සහ complex data structures වලට XML තවමත් හොඳ choice එකක්. ඒක ඔයාලගේ project requirement එක මත තීරණය වෙන දෙයක්. දෙකම දැනගෙන ඉන්න එක තමයි හොඳම දේ!
JAXB වලට Alternatives තියෙනවද?
ඔව්, JAXB වලට අමතරව Apache Xerces, Jackson (JSON/XML support), XStream වගේ third-party libraries පාවිච්චි කරන්න පුළුවන්. ඒත් JAXB JDK එකේම එන නිසා ගොඩක් වෙලාවට මේක හොඳම option එකක් වෙනවා.
අවසන් වනවා...
හරි යාලුවනේ! අපි අද XML කියන්නේ මොකක්ද, ඒ වගේම Java වලදි DOM, SAX, JAXB කියන ප්රධාන XML parsing methods තුන පාවිච්චි කරන්නේ කොහොමද කියන එක ගැන ගැඹුරින් කතා කළා. මේ concepts ඔයාලගේ දෛනික software development වැඩ වලට කොච්චර වටිනවද කියන එක දැන් ඔයාලට තේරෙනවා ඇති.
මතක තියාගන්න, හොඳම parser එකක් කියලා එකක් නෑ. ඔයාලගේ project එකේ අවශ්යතාවය සහ XML file එකේ size එක, complexity එක වගේ දේවල් අනුව තමයි හොඳම option එක තීරණය වෙන්නේ. DOM, SAX, JAXB තුනටම ඒ අයගේම strengths සහ weaknesses තියෙනවා.
දැන් ඔයාලට පුළුවන් මේ concepts පාවිච්චි කරලා, ඔයාලගේ project වල XML වැඩ ලේසියෙන් කරන්න. මේ code examples ටික ඔයාලගේ IDE එකේ run කරලා experiment කරන්න. එතකොට තමයි හොඳටම concept එක grasp කරගන්න පුළුවන් වෙන්නේ.
මේ article එක ගැන ඔයාලගේ අදහස්, ප්රශ්න, නැත්නම් ඔයාලගේ අත්දැකීම් පහළින් comment එකක් දාලා බෙදාගන්න. ඔයාලගේ feedback එක අපිට ගොඩක් වටිනවා.
එහෙනම් තවත් අලුත් දෙයක් අරගෙන ඉක්මනටම හම්බවෙමු! ජය වේවා!