Try English version of Quizful



Раздаем бесплатные Q! подробности в группе Quizful.Alpha-test
Партнеры
Рекрутерам: Прескрининг кандидатов about
Топ контрибуторов
loading
loading
Знаете ли Вы, что

Список полученных сертификатов находится на странице Вашего профиля. Сертификаты можно распечатать или разместить на Вашем сайте.

Лента обновлений
ссылка 20:57:36
Комментарий от Recrut_rf:
Спасибо, сохранил функцию, может пригодится когда - ни...
ссылка 20:53:59
Добавлен вопрос в тест ASP.NET - Основы
ссылка 08:41:09
Комментарий от Krosster:
Гарний сайт для новачків. Правда деякі питання підступн...
ссылка Apr 22 22:06
Добавлен вопрос в тест SQL - Средний уровень
ссылка Apr 22 10:13
Комментарий от Entrery:
вроде выбрал ООП в сишарпе, а тут вопросы по джаве...
Статистика

Тестов: 153, вопросов: 8596. Пройдено: 402470 / 1961086.

Простой SAX парсер на Java

head tail Статья
категория
Java
дата11.08.2009
авторMUTOgen
голосов30

Во многих задачах возникает необходимость использования разного рода xml файлов в различных целях. Я не буду пытаться объять необъятное, а расскажу по своему опыту для чего мне все это понадобилось.

Java, пожалуй, мой самый любимый язык программирования. К тому же эта любовь укрепляется тем, что решить можно любую задачу и придумывать велосипеда не придется.

Так вот, понадобилось мне создать такую связку клиент-сервер, работающую с БД, которая бы позволяла клиенту удаленно вносить записи в БД сервера. Само собой должны быть проверки вводимых данных и т.д. и т.п., но речь не об этом.

В качестве принципа работы я, не долго думая, избрал передачу информации в виде xml файла. Вида следующего:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<doc>
<id>3</id>
<fam>Иванов</fam>
<name>Иван</name>
<otc>Иванович</otc>
<dateb>10-03-2005</dateb>
<datep>10-03-2005</datep>
<datev>10-03-2005</datev>
<datebegin>09-06-2009</datebegin>
<dateend>10-03-2005</dateend>
<vdolid>1</vdolid>
<specid>1</specid>
<klavid>1</klavid>
<stav>2.0</stav>
<progid>1</progid>
</doc>

Чтобы проще было читать дальше, скажу лишь что это информация о врачах учреждений. Фамилия, имя, отчество, уникальных id, и так далее. В общем ряд данных. Далее этот файл благополучно попадал на серверную сторону, и тут начинался разбор файла.

Из двух вариантов разбора(SAX vs DOM) я выбрал SAX ввиду того, что он пошустрее работает, и он первым мне попался в руки :)

Итак. Как известно, для успешной работы с парсером нам необходимо переопределить нужные нам методы DefaultHandler'а. Для начала подключим необходимые пакеты.


import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.*;

Теперь можно начать писать наш парсер


public class SAXPars extends DefaultHandler {
  ...
}

Начнем с метода startDocument(). Он, как понятно из названия, реагирует на событие начала документа. Сюда можно повесить различные действия по выделению памяти например или по сбросу значений, но наш пример довольно прост, поэтому просто обозначим начало работы соотвествующим сообщением:


@Override
public void startDocument() throws SAXException {
  System.out.println("Start parse XML...");
}

Далее. Парсер идет по документу, встречает элемент его структуры. Начинает работать метод startElement(). Причем на самом деле вид его такой: startElement(String namespaceURI, String localName, String qName, Attributes atts). Здесь namespaceURI — это пространство имен, localName — локальное имя элемента, qName- это комбинация локального имени с пространством имен (разделяется двоеточием) и atts — атрибуты данного элемента. В нашем случае все просто. Достаточно воспользоваться qName'ом и кинуть его в некоторую служебную строку thisElement. Тем самым мы помечаем в каком элементе в данный момент мы находимся.


@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
  thisElement = qName; 
}

Далее, встретив элемент мы доходим до его значения. Здесь включается метод characters(). Он имеет вид: characters(char[] ch, int start, int length). Ну тут все понятно. ch — это массив содержащий собственной саму строку-значение внутри данного элемента. start и length — служебные числа обозначающие точку старта в строке и длину.


@Override
public void characters(char[] ch, int start, int length) throws SAXException {
  if (thisElement.equals("id")) {
     doc.setId(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("fam")) {
     doc.setFam(new String(ch, start, length));
  }
  if (thisElement.equals("name")) {
     doc.setName(new String(ch, start, length));
  }
  if (thisElement.equals("otc")) {
     doc.setOtc(new String(ch, start, length));
  }
  if (thisElement.equals("dateb")) {
     doc.setDateb(new String(ch, start, length));
  }
  if (thisElement.equals("datep")) {
     doc.setDatep(new String(ch, start, length));
  }
  if (thisElement.equals("datev")) {
     doc.setDatev(new String(ch, start, length));
  }
  if (thisElement.equals("datebegin")) {
     doc.setDatebegin(new String(ch, start, length));
  }
  if (thisElement.equals("dateend")) {
     doc.setDateend(new String(ch, start, length));
  }
  if (thisElement.equals("vdolid")) {
     doc.setVdolid(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("specid")) {
     doc.setSpecid(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("klavid")) {
     doc.setKlavid(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("stav")) {
     doc.setStav(new Float(new String(ch, start, length)));
  }
  if (thisElement.equals("progid")) {
     doc.setProgid(new Integer(new String(ch, start, length)));
  }
}

Ах, да. Чуть не забыл. В качестве объекта куда буду скидываться напарсенные данные выступает объект типа Doctors. Этот класс определен и имеет все необходимые сеттеры-геттеры.

Далее очевидно элемент заканчивается и за ним идет следующий. За окончание отвечает endElement(). Она сигнализирует нам что элемент закончился и можно что-нибудь сделать в это время. Так и поступим. Очистим Element.


@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
  thisElement = "";
}

Пройдя таким образом весь документ, мы придем к концу файла. Сработает endDocument(). В нем мы можем высвободить память, сделать какую-то диагностичесую печать и т.д. В нашем случае просто напишем о том что парсинг заканчивается.


@Override
public void endDocument() {
  System.out.println("Stop parse XML...");
}

Таким образом мы получили класс для парсинга xml нашего формата. Вот полный текст:


import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.*;

public class SAXPars extends DefaultHandler{

Doctors doc = new Doctors();
String thisElement = "";

public Doctors getResult(){
  return doc;
}

@Override
public void startDocument() throws SAXException {
  System.out.println("Start parse XML...");
}

@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
  thisElement = qName; 
}

@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
  thisElement = "";
}

@Override
public void characters(char[] ch, int start, int length) throws SAXException {
  if (thisElement.equals("id")) {
     doc.setId(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("fam")) {
     doc.setFam(new String(ch, start, length));
  }
  if (thisElement.equals("name")) {
     doc.setName(new String(ch, start, length));
  }
  if (thisElement.equals("otc")) {
     doc.setOtc(new String(ch, start, length));
  }
  if (thisElement.equals("dateb")) {
     doc.setDateb(new String(ch, start, length));
  }
  if (thisElement.equals("datep")) {
     doc.setDatep(new String(ch, start, length));
  }
  if (thisElement.equals("datev")) {
     doc.setDatev(new String(ch, start, length));
  }
  if (thisElement.equals("datebegin")) {
     doc.setDatebegin(new String(ch, start, length));
  }
  if (thisElement.equals("dateend")) {
     doc.setDateend(new String(ch, start, length));
  }
  if (thisElement.equals("vdolid")) {
     doc.setVdolid(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("specid")) {
     doc.setSpecid(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("klavid")) {
     doc.setKlavid(new Integer(new String(ch, start, length)));
  }
  if (thisElement.equals("stav")) {
     doc.setStav(new Float(new String(ch, start, length)));
  }
  if (thisElement.equals("progid")) {
     doc.setProgid(new Integer(new String(ch, start, length)));
  }
}

@Override
public void endDocument() {
  System.out.println("Stop parse XML...");
}
}

Надеюсь топик помог легко представить суть работы SAX парсера.

Не судите строго первую статью:) Надеюсь она была хоть кому-то полезна.

UPD: Чтобы запустить данный парсер, можно воспользоваться таким кодом:


SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
SAXPars saxp = new SAXPars();

parser.parse(new File("..."), saxp);

---------------
Автор: MUTOgen

Если Вам понравилась статья, проголосуйте за нее

Голосов: 30  loading...
giroy   dreamx_max   ilia   oleger   nightvanilla   MUTOgen   haykm   ldkfa   JinSem   rogi   andrey_z91h   iRisha   lg_qzfl   flame27   Bag   temak   Aye_Aye   igar   volodymyrpr   Vit_alI   GSYU   andreysuhoverka   Alena17   vona   bal_gena   excolo   StateItPrimitiv   Ladymage   lila0612   antycrab