Việc xử lý dữ liệu định dạng XML trên môi trường Java thường yêu cầu sử dụng bộ công cụ chuẩn của nhà phát triển. Trong đó, mô hình DOM (Document Object Model) cho phép xây dựng một cấu trúc cây đầy đủ các yếu tố của tài liệu ngay trong bộ nhớRAM, giúp truy xuất và chỉnh sửa trở nên trực quan. Để thực hiện quy trình này, Java cung cấp thư viện javax.xml.parsers.
Các bước thực thi chính
Hành động giải mã file XML cần tuân thủ một trình tự chặt chẽ nhằm đảm bảo an toàn cho luồng chạy ứng dụng:
- Tạo một instance của
DocumentBuilderFactorybằng phương thức tĩnhnewInstance(). - Sử dụng factory để sinh ra đối tượng
DocumentBuilder, đóng vai trò là người phân tích. - Công cụ phân tích sẽ nạp file XML qua hàm
parse(), trả về đối tượngDocumentđại diện cho toàn bộ cây. - Phương thức
getElementsByTagName()được dùng để lọc lấy NodeList chứa các thẻ mong muốn. - Vòng lặp duyệt qua NodeList, truy vấn thông tin thông qua các hàm
getAttribute(),getTextContent().
Mẫu dữ liệu đầu vào
Để minh họa quy trình, giả sử chúng ta có một file cấu hình config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<server-info>
<server type="web">
<host>localhost</host>
<port>8080</port>
</server>
<server type="db">
<host>192.168.1.10</host>
<port>3306</port>
</server>
</server-info>
Triển khai Giải thuật
Mã nguồn dưới đây thể hiện cách viết lớp xử lý riêng biệt, tách biệt logic lỗi exception ra khỏi phần nghiệp vụ chính. Lưu ý rằng vòng lặp điều kiện không sử dụng dấu "=" so sánh lớn hơn hoặc bằng, mà dùng nhỏ hơn để tránh tràn mảng.
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
public class ConfigParserDemo {
public static void loadConfiguration(String pathToXml) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
// Tạo builder để parse document
DocumentBuilder builder = factory.newDocumentBuilder();
// Load file từ thư mục gốc hoặc đường dẫn tuyệt đối
Document xmlDoc = builder.parse(new File(pathToXml));
// Chuyển đổi kiểu dữ liệu sang chuẩn DOM
xmlDoc.getDocumentElement().normalize();
// Lấy danh sách các node 'server'
NodeList serverList = xmlDoc.getElementsByTagName("server");
System.out.println("Tổng số server được cấu hình: " + serverList.getLength());
// Vòng lặp xử lý từng node server
for (int i = 0; i < serverList.getLength(); i++) {
Node currentNode = serverList.item(i);
// Ép kiểu sang Element để gọi các method cụ thể
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
Element serverEl = (Element) currentNode;
// Lấy thuộc tính type từ thẻ cha
String serverType = serverEl.getAttribute("type");
System.out.println("\n--- Server Loại: " + serverType + " ---");
// Lấy tập con chứa các node trực tiếp như host, port
NodeList detailList = serverEl.getChildNodes();
for (int k = 0; k < detailList.getLength(); k++) {
Node detailNode = detailList.item(k);
// Chỉ xử lý các node là thẻ (Element), bỏ qua khoảng trắng trắng
if (detailNode.getNodeType() == Node.ELEMENT_NODE) {
Element childEl = (Element) detailNode;
// In ra tên trường và nội dung bên trong
System.out.println(childEl.getTagName() + ": " + childEl.getTextContent());
}
}
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
System.err.println("Lỗi xảy ra khi phân tích XML: " + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
loadConfiguration("config.xml");
}
}
Ghi chú quan trọng
Khi duyệt qua danh sách các node con (getChildNodes()), kết quả thường trả về kèm theo các node loại TEXT_NODE tương ứng với dấu xuống dòng hoặc tab trắng trong file XML. Do đó, điều kiện kiểm tra if (nodeType == Node.ELEMENT_NODE) là bắt buộc để đảm bảo dữ liệu trích xuất sạch và logic hoạt động đúng. Việc sử dụng getTextContent() trên thẻ Element cũng tối ưu hơn so với phương pháp truy xuất getFirstChild() truyền thống.