Привет %username%.
Сегодняшней темой будет парсинг XML. Существуют две стратегии обработки XML документов: SAX и DOM.
SAX парсеры предлагают потоковую обработку данных основанную на событиях.
DOM парсеры преобразуют XML в дерево объектов, с которыми можно будет работать.
Рассмотрим пример простейшего SAX парсера.
Пусть у нас есть XML документ:
Код обработки документа может выглядеть следующим образом:
Поясняю код. Мы описываем класс MyParser, который будет обрабатывать события чтения данных. Выделено 5 событий:
SAX парсер постепенно читает файл XML. И когда набирается достаточное количество данных (считался тег с атрибутами) вызывает метод нашего класса. Когда данные уже отработаны, они в принципе не нужны и поэтому постепенно удаляются из памяти.
Такая методика позволяет обрабатывать достаточно большие XML(возможно размером несколько мегабайт/гигабайт). Это главное достоинство SAX парсеров. Скорость и возможность обрабатывать большие объемы данных.
Главный недостаток - сложный код в случае сложной структуре XML файла. То есть если XML простой и линейный, то его легко анализировать SAX-парсером. Для XML со сложной структурой придется по возиться с алгоритмизацией.
Вернемся к примеру.
1-ое событие - начали обрабатывать документ. Наступает лишь раз в момент, когда мы начали анализировать файл. На этом этапе можно производить первичную инициализацию данных
2-ое событие - открылся тег. На этом этапе мы знаем имя тега и его атрибуты. Мы не знаем ни как глубоко вложен элемент, ни сколько там ещё внутри. Если это надо, то нужно обрабатывать алгоритмически
3-е событие - данные. Реальные данные между открытым и закрытым тегами. Нам дают массив символов, делайте с ним что хотите
4-ое событие - закрываем тег. Теперь мы знаем, тег закрыт, можем что-нибудь обработать алгоритмически
5-ое событие - документ обработан. Освобождаем лишние ресурсы, делаем пост обработку, если она нужна. Короче радуемся жизни, т.к. мы такие молодцы - обработали документ.
В итоге программа выведет :
Надеюсь пример кому-нибудь помог.
Спасибо за внимание.
UPD: Сделал репозиторий на github, где буду выкладывать примеры для статей.
Исходники примера можно взять тут:
https://github.com/png-tech/PngJavaSamples/blob/master/SimpleExamples/src/png/samples/xml/saxread/
Сегодняшней темой будет парсинг XML. Существуют две стратегии обработки XML документов: SAX и DOM.
SAX парсеры предлагают потоковую обработку данных основанную на событиях.
DOM парсеры преобразуют XML в дерево объектов, с которыми можно будет работать.
Рассмотрим пример простейшего SAX парсера.
Пусть у нас есть XML документ:
<?xml version="1.0" encoding="windows-1251"?> <books> <book id="1"> <title>Компьютерные сети</title> <autor>Олифер</autor> </book> <book id="2"> <title>Вычислительные сети сети</title> <autor>Кто-то ещё</autor> </book> </books>
Код обработки документа может выглядеть следующим образом:
package javaxmltest; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParser; // SAX import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * * @author nicolay */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true); factory.setNamespaceAware(false); SAXParser parser; InputStream xmlData = null; try { xmlData = new FileInputStream("books.xml"); parser = factory.newSAXParser(); parser.parse(xmlData, new MyParser()); } catch (FileNotFoundException e) { e.printStackTrace(); // обработки ошибки, файл не найден } catch (ParserConfigurationException e) { e.printStackTrace(); // обработка ошибки Parser } catch (SAXException e) { e.printStackTrace(); // обработка ошибки SAX } catch (IOException e) { e.printStackTrace(); // обработка ошибок ввода } } } // http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/helpers/DefaultHandler.html class MyParser extends DefaultHandler { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("Тег: "+qName); if(qName.equals("book")) System.out.println("id книги "+attributes.getValue("id")); // System.out.println(attributes.getLength()); super.startElement(uri, localName, qName, attributes); } @Override public void characters(char[] c, int start, int length) throws SAXException { super.characters(c, start, length); for(int i=start;i< start+length;++i) System.err.print(c[i]); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("Тег разобран: "+qName); super.endElement(uri,localName, qName); } @Override public void startDocument() throws SAXException { System.out.println("Начало разбора документа!"); super.startDocument(); } @Override public void endDocument() throws SAXException { super.endDocument(); System.out.println("Разбор документа окончен!"); } }Код можно получить тут: https://github.com/png-tech/PngJavaSamples/blob/master/SimpleExamples/src/png/samples/xml/saxread/XmlSaxReadSample.java
Поясняю код. Мы описываем класс MyParser, который будет обрабатывать события чтения данных. Выделено 5 событий:
- старт документ
- открытие тега
- данные внутри тега
- закрытие тега
- заканчиваем обработку документа
SAX парсер постепенно читает файл XML. И когда набирается достаточное количество данных (считался тег с атрибутами) вызывает метод нашего класса. Когда данные уже отработаны, они в принципе не нужны и поэтому постепенно удаляются из памяти.
Такая методика позволяет обрабатывать достаточно большие XML(возможно размером несколько мегабайт/гигабайт). Это главное достоинство SAX парсеров. Скорость и возможность обрабатывать большие объемы данных.
Главный недостаток - сложный код в случае сложной структуре XML файла. То есть если XML простой и линейный, то его легко анализировать SAX-парсером. Для XML со сложной структурой придется по возиться с алгоритмизацией.
Вернемся к примеру.
1-ое событие - начали обрабатывать документ. Наступает лишь раз в момент, когда мы начали анализировать файл. На этом этапе можно производить первичную инициализацию данных
2-ое событие - открылся тег. На этом этапе мы знаем имя тега и его атрибуты. Мы не знаем ни как глубоко вложен элемент, ни сколько там ещё внутри. Если это надо, то нужно обрабатывать алгоритмически
3-е событие - данные. Реальные данные между открытым и закрытым тегами. Нам дают массив символов, делайте с ним что хотите
4-ое событие - закрываем тег. Теперь мы знаем, тег закрыт, можем что-нибудь обработать алгоритмически
5-ое событие - документ обработан. Освобождаем лишние ресурсы, делаем пост обработку, если она нужна. Короче радуемся жизни, т.к. мы такие молодцы - обработали документ.
В итоге программа выведет :
Начало разбора документа! Тег: books Тег: book id книги 1 Тег: title Тег разобран: title Компьютерные сети Тег: autor Тег разобран: autor Олифер Тег разобран: book Тег: book id книги 2 Тег: title Тег разобран: title Вычислительные сети сети Тег: autor Тег разобран: autor Кто-то ещё Тег разобран: book Тег разобран: books Разбор документа окончен!
Надеюсь пример кому-нибудь помог.
Спасибо за внимание.
UPD: Сделал репозиторий на github, где буду выкладывать примеры для статей.
Исходники примера можно взять тут:
https://github.com/png-tech/PngJavaSamples/blob/master/SimpleExamples/src/png/samples/xml/saxread/
Спасибо за статью.
ОтветитьУдалитьНе за что))))
УдалитьБольшое спасибо за простое и понятное описание.
ОтветитьУдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьThe best ! Спасибо. Понял на вашем примере.
ОтветитьУдалитьНачало разбора документа!
ОтветитьУдалитьТег: books
Тег: book
id книги 1
Тег: title
Тег разобран: title
Тег: autor
Тег разобран: autor
Компьютерные сети
Тег разобран: book
Олифер
Тег: book
id книги 2
Тег: title
Вычислительные сети сети
Тег разобран: title
Кто-то ещё
Тег: autor
Тег разобран: autor
Тег разобран: book
Тег разобран: books
Разбор документа окончен!
У меня он так парсит. ничего понять не могу. Куда смотреть подскажите?
Информации для анализа маловато, но рискну предположить, что проблема в кодировке файла, который вы анализируете. То есть символы не верной кодировки не выводятся на консоль, или выводятся пробелами, или как-то ещё. Предлагаю воспользоваться отладчиком(debuger) для обнаружения проблемы. В методы класса MyParser поставить точки останова(break point) и посмотреть кто и сколько раз эти методы вызывает и с какими параметрами.
УдалитьСпасибо большое, только у вас всё понял
ОтветитьУдалитьАга, я так само))) Большое спасибо!
Удалитьу меня из-за factory.setValidating(true) выдавало ошибку "no validating saxparser implementation available".
ОтветитьУдалитьубрал - и все заработало. возможно тут прикол в том, что пишу под андроида, не знаю.
возможно :) под андройдом писать не приходилось :)
Удалить