SAX Parser или Simple API for XMLсуществует уже много лет и изначально был разработкой Дэвида Меггинсона до наступления нового тысячелетия. В те дни приходилось загружать Java-версию SAX с личного сайта Дэвида. Это переросло в проект SAX, прежде чем его наконец добавили в Java Standard Edition 1.4.
SAX — это потоковый интерфейс для XML, что означает, что приложения получают уведомления о событиях об обработке XML-документа, элемента и атрибута, в последовательном порядке, начиная с верхней части документа и заканчивая закрытием элемента ROOT. Это означает, что он чрезвычайно эффективен при обработке XML за линейное время, не предъявляя слишком больших требований к системной памяти.
1. Настройка
Этот XML-файл также содержит XML-атрибуты и дочерние элементы.
<users><user id="100"><firstname>Tom</firstname><lastname>Hanks</lastname></user><user id="101"><firstname>Lokesh</firstname><lastname>Gupta</lastname></user><user id="102"><firstname>HowToDo</firstname><lastname>InJava</lastname></user></users>
2. Создание Java POJO
Класс User имеет простые атрибуты для хранения информации, считанной из XML-файла.
public class User {private int id;private String firstName;private String lastName;//Setters, getters}
3. Обработчик событий SAX
Обработчик событий получает события для каждого события во время операции чтения посредством обратных вызовов методов следующих функций:
- startElement()
- endElement()
Внутри функций мы можем использовать оператор if, чтобы узнать, какой элемент в данный момент обрабатывается, а затем извлечь необходимую информацию.
import java.util.ArrayList;import java.util.Stack;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;public class UserParserHandler extends DefaultHandler {//This is the list which shall be populated while parsing the XML.private ArrayList userList = new ArrayList();//As we read any XML element we will push that in this stackprivate Stack elementStack = new Stack();//As we complete one user block in XML, we will push the User instance in userListprivate Stack objectStack = new Stack();public void startDocument() throws SAXException {//System.out.println("start of the document : ");}public void endDocument() throws SAXException {//System.out.println("end of the document document : ");}public void startElement(String uri, String localName, String qName, Attributes attributes)throws SAXException {//Push it in element stackthis.elementStack.push(qName);//If this is start of 'user' element then prepare a new User instance and push it in object stackif("user".equals(qName)) {//New User instanceUser user = new User();//Set all required attributes in any XML element here itselfif(attributes != null && attributes.getLength() == 1) {user.setId(Integer.parseInt(attributes.getValue(0)));}this.objectStack.push(user);}}public void endElement(String uri, String localName, String qName) throws SAXException {//Remove last added elementthis.elementStack.pop();//User instance has been constructed so pop it from object stack and push in userListif("user".equals(qName)) {User object =(User) this.objectStack.pop();this.userList.add(object);}}/*** This will be called everytime parser encounter a value node*/public void characters(char[] ch, int start, int length) throws SAXException {String value = new String(ch, start, length).trim();if(value.length() == 0) {return; // ignore white space}//handle the value based on to which element it belongsif("firstName".equals(currentElement())) {User user =(User) this.objectStack.peek();user.setFirstName(value);} else if("lastName".equals(currentElement())) {User user =(User) this.objectStack.peek();user.setLastName(value);}}/*** Utility method for getting the current element in processing*/private String currentElement() {return(String) this.elementStack.peek();}//Accessor for userList objectpublic ArrayList getUsers() {return userList;}}
4. Чтение XML-файла
Класс обработчика устанавливается как обработчик содержимого для XMLReader с помощью метода reader.setContentHandler(handler). Считыватель принимает входной XML в различных формах, принятый как аргумент конструктора InputSource. Наконец, мы используем метод reader.parse() для чтения содержимого XML.
import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.XMLReaderFactory;public class UserParser {public ArrayList parseXml(InputStream in) {//Create an empty link of users initiallyArrayList<User> users = new ArrayList<>();try {//Create default handler instanceUserParserHandler handler = new UserParserHandler();//Create parser from factoryXMLReader reader = XMLReaderFactory.createXMLReader();//Register handler with parserreader.setContentHandler(handler);//Create an input source from the XML input streamInputSource source = new InputSource(in);//parse the documentreader.parse(source);//populate the parsed users list in above created empty list; You can return from here also.users = handler.getUsers();} catch(SAXException e) {e.printStackTrace();} catch(IOException e) {e.printStackTrace();} finally {}return users;}}
5. Демонстрация
Давайте напишем код, чтобы проверить, действительно ли работает наш обработчик.
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.util.ArrayList;public class SaxParserDemo {public static void main(String[] args) throws FileNotFoundException {//Locate the fileFile xmlFile = new File("D:/temp/sample.xml");//Create the parser instanceUserParser parser = new UserParser();//Parse the fileArrayList<User> users = parser.parseXml(new FileInputStream(xmlFile));//Verify the resultSystem.out.println(users);}}
Вывод программы.
[100:Tom:Hanks, 101:Lokesh:Gupta, 102:HowToDo:InJava]