SAX פרסר ב-Java מספק API לניתוח מסמכי XML. פרסר SAX שונה מ-DOM פרסר מכיוון שהוא לא טוען את כל ה-XML לזיכרון וקורא במסמך XML לפי סדרו.
SAX פרסר
javax.xml.parsers.SAXParser
מספק שיטה לפענח מסמך XML באמצעות מטפלי אירועים. כיתה זו מיישמת את הממשק XMLReader
ומספקת גרסאות מעומסות של שיטות parse()
לקריאת מסמך XML מקובץ, InputStream, SAX InputSource וכתובת מחרוזת URI. הפענוח האמיתי מתבצע על ידי המחלקה Handler. אנו צריכים ליצור מחלקת מטפל משלנו כדי לפענח את מסמך ה-XML. אנו צריכים ליישם את הממשק org.xml.sax.ContentHandler
כדי ליצור את מחלקות המטפל שלנו. ממשק זה מכיל שיטות חזרה שמקבלות הודעה כאשר אירוע מתרחש. לדוגמה StartDocument, EndDocument, StartElement, EndElement, CharacterData וכו '. org.xml.sax.helpers.DefaultHandler
מספק יישום ברירת מחדל של הממשק ContentHandler ואנו יכולים להרחיב את המחלקה הזו כדי ליצור את מטפלינו האישיים. מומלץ להרחיב את המחלקה הזו מכיוון שייתכן שנצטרך רק מספר מועט של השיטות ליישום. הרחבת המחלקה הזו תשמור על קוד המקור שלנו נקי וניתן לתחזוקה.
דוגמת מפענח SAX
בואו נקפוץ כעת אל דוגמת התוכנית של מפענח ה-SAX, אני אסביר תכונות שונות בעמק בהמשך. employees.xml
<?xml version="1.0" encoding="UTF-8"?>
<Employees>
<Employee id="1">
<age>29</age>
<name>Pankaj</name>
<gender>Male</gender>
<role>Java Developer</role>
</Employee>
<Employee id="2">
<age>35</age>
<name>Lisa</name>
<gender>Female</gender>
<role>CEO</role>
</Employee>
<Employee id="3">
<age>40</age>
<name>Tom</name>
<gender>Male</gender>
<role>Manager</role>
</Employee>
<Employee id="4">
<age>25</age>
<name>Meghna</name>
<gender>Female</gender>
<role>Manager</role>
</Employee>
</Employees>
**בקובץ ה-XML שלנו, שמאוחסן במערכת הקבצים במקום מסוים, ועל ידי הסתכלות בו, אנו יכולים להסיק כי הוא מכיל רשימת עובדים. כל עובד מכיל מאפיין id
ושדות age
, name
, gender
ו- role
. נשתמש ב-Analisi XML (SAX parser) כדי לנתח את ה-XML וליצור רשימת אובייקטים של עובדים. הנה אובייקט העובד המייצג את אלמנט העובד מתוך ה-XML.
package com.journaldev.xml;
public class Employee {
private int id;
private String name;
private String gender;
private int age;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString() {
return "Employee:: ID="+this.id+" Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender +
" Role=" + this.role;
}
}
בואו ניצור מחלקת עזר ל-Analisi XML, הנרחיבה את המחלקה DefaultHandler.
package com.journaldev.xml.sax;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.journaldev.xml.Employee;
public class MyHandler extends DefaultHandler {
// רשימה לאחסון אובייקטי עובד
private List empList = null;
private Employee emp = null;
private StringBuilder data = null;
// שיטת גישה לרשימת עוביינים
public List getEmpList() {
return empList;
}
boolean bAge = false;
boolean bName = false;
boolean bGender = false;
boolean bRole = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("Employee")) {
// יצירת עוביינים חדש והוספתו למפה
String id = attributes.getValue("id");
// אתחול אובייקט עובד והגדרת ה- id
emp = new Employee();
emp.setId(Integer.parseInt(id));
// אתחול של רשימה
if (empList == null)
empList = new ArrayList<>();
} else if (qName.equalsIgnoreCase("name")) {
// הגדרת ערכי boolean עבור השדות, שישמשו בהגדרת המשתנים של העוביין
bName = true;
} else if (qName.equalsIgnoreCase("age")) {
bAge = true;
} else if (qName.equalsIgnoreCase("gender")) {
bGender = true;
} else if (qName.equalsIgnoreCase("role")) {
bRole = true;
}
// יצירת המכניס לנתונים
data = new StringBuilder();
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (bAge) {
// אלמנט של גיל, הגדרת הגיל של העובין
emp.setAge(Integer.parseInt(data.toString()));
bAge = false;
} else if (bName) {
emp.setName(data.toString());
bName = false;
} else if (bRole) {
emp.setRole(data.toString());
bRole = false;
} else if (bGender) {
emp.setGender(data.toString());
bGender = false;
}
if (qName.equalsIgnoreCase("Employee")) {
// הוספת אוביין לרשימה
empList.add(emp);
}
}
@Override
public void characters(char ch[], int start, int length) throws SAXException {
data.append(new String(ch, start, length));
}
}
המחלקה שלי, MyHandler, מכילה את הרשימה של אוביינים Employee
כשדה עם שיטת גישה בלבד. אוביינים מתווספים במתודות טיפול בארועים. יש גם שדה של אוביין שישמש ליצירת אוביין ופעם שכל השדות יוגדרו, יתווסף לרשימת העובדים.
שיטות של Analisi XML שיש לדרג מחדש **
השיטות החשובות להתעלמות הם startElement()
, endElement()
ו־characters()
. SAXParser מתחיל לנתח את המסמך, כאשר נמצא איבר התחלה כלשהו, מתבצעת קריאה לשיטת startElement()
. אנו מציינים מחדש את השיטה זו כדי להגדיר משתנים בוליאניים שימושיים לזיהוי האיבר. גם אנו משתמשים בשיטה זו כדי ליצור אובייקט של Employee חדש בכל פעם שנמצא איבר התחלת Employee. עיינו באיך שמזהה המזהה נקרא כאן כדי להגדיר את שדה ה־id
של אובייקט ה Employee. שיטת characters()
נקראת כאשר מידע תווים נמצא על ידי SAXParser בתוך איבר. שים לב שמנתח SAX עשוי לחלק את הנתונים למספר קטעים ולקרוא לשיטת characters()
מספר פעמים (ראה את התיעוד של שיטת characters() במחלקת ContentHandler). לכן אנו משתמשים ב־StringBuilder כדי לשמור על הנתונים האלה באמצעות שימוש ב־append(). ה־endElement()
הוא המקום שבו אנו משתמשים בנתוני ה־StringBuilder כדי להגדיר מאפייני אובייקט של עובד ולהוסיף אובייקט של עובד לרשימה בכל פעם שמצאנו איבר סוף של עובד. להלן התוכנית הבדיקה שמשתמשת ב־MyHandler
לניתוח XML לרשימת אובייקטים של עובדים.
package com.journaldev.xml.sax;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import com.journaldev.xml.Employee;
public class XMLParserSAX {
public static void main(String[] args) {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
try {
SAXParser saxParser = saxParserFactory.newSAXParser();
MyHandler handler = new MyHandler();
saxParser.parse(new File("/Users/pankaj/employees.xml"), handler);
//קבל רשימת עובדים
List empList = handler.getEmpList();
//הדפס מידע עובד
for(Employee emp : empList)
System.out.println(emp);
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
}
כאן הפלט של התוכנית לעיל.
Employee:: ID=1 Name=Pankaj Age=29 Gender=Male Role=Java Developer
Employee:: ID=2 Name=Lisa Age=35 Gender=Female Role=CEO
Employee:: ID=3 Name=Tom Age=40 Gender=Male Role=Manager
Employee:: ID=4 Name=Meghna Age=25 Gender=Female Role=Manager
SAXParserFactory
מספקת שיטות יצרנות לקבלת מופע של SAXParser
. אנו מעבירים אובייקט קובץ לשיטת הניתוח יחד עם המופע של MyHandler כדי לטפל באירועי הקריאה לאחור. SAXParser מעט מבלבל בהתחלה אך אם אתה עובד על מסמך XML גדול, הוא מספק דרך יעילה יותר לקרוא XML מאשר DOM Parser. זהו הכל לגבי SAX Parser ב־Java.
ניתן להוריד את הפרויקט מה מאגר ה-GitHub שלנו.
התייחסות: SAXParser, DefaultHandler
Source:
https://www.digitalocean.com/community/tutorials/java-sax-parser-example