- XML документ — DOM, SAXParser
- Чтение XML-файла
- Создание XML-файла
- Пример чтения и создания XML-файла
- Структура XML-файла
- Листинг класса Person
- Чтение XML-файла
- Создание XML-файла
- Листинг метода создания XML-файла
- Листинг процедуры сохранения XML-файла
- SAX-парсер, SAXParser
- Файл phonebook.xml
- Листинг SAXExample.java
- Скачать примеры
XML документ — DOM, SAXParser
Существуют две стратегии обработки XML документов: DOM (Document Object Model) и SAX (Simple API for XML). Основное их отличие связано с тем, что использование DOM позволяет читать и вносить изменения в существующий XML-документ, а также создавать новый. Стратегия использования SAX основывается на том, что содержимое XML-документа только анализируется. XML-текст может быть больших размеров: DOM должен весь документ «заглотить» и проанализировать, а SAX-парсер обрабатывает XML-документ последовательно и не требует дополнительной памяти.
Для работы с XML-файлами Java располагает достаточно большим набором инструментов, начиная от встроенных возможностей, которые предоставляет Core Java, и заканчивая большим набором разнообразного стороннего кода, оформленного в виде библиотек. Сначала рассмотрим использование DOM для чтения XML-файла и создания нового файла/документа. А в заключение будет приведено описание и применение SAX-парсера SAXParser.
XML документ представляет собой набор узлов (тегов). Каждый узел может иметь неограниченное количество дочерних узлов, которые, в свою очередь, также могут содержать потомков или не содержать их совсем. Таким образом строится дерево объектов. DOM — это объектная модель документа, которая представляет собой это дерево в виде специальных объектов/узлов org.w3c.dom.Node. Каждый узел Node соответствует своему XML-тегу и содержит полную информацию о том, что это за тег, какие он имеет атрибуты, какие дочерние узлы содержит внутри себя и т.д. На самой вершине этой иерархии находится org.w3c.dom.Document, который является корневым элементов дерева.
Чтение XML-файла
Получить объект Document XML-файла можно следующим образом :
DocumentBuilderFactory dbf; DocumentBuilder db ; Document doc; dbf = DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); doc = db.parse(new File("data.xml"));
Чтобы найти какой-либо узел в дереве можно использовать метод getElementsByTagName, который возвращает список всех элементов :
NodeList Document.getElementsByTagName(String name); . . . // Пример использования метода getElementsByTagName NodeList nodeList = doc.getElementsByTagName("tagname");
Метод getElementsByTagName является case-sensitive, т.е. различает прописные и строчные символы.
В цикле можно просмотреть все дочерние узлы. C помощью метода getAttributes можно узнать атрибуты узла. Метод getNodeType позволяет проверить тип узла :
NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) < // дочерний узел Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) < // атрибуты узла NamedNodeMap attributes = node.getAttributes(); Node nameAttrib; nameAttrib = attributes.getNamedItem("attrib_name"); System.out.println ("" + i + ". " + nameAttrib.getNodeValue()); >>
Создание XML-файла
Для создания нового объекта Document используйте следующий код :
DocumentBuilderFactory dbf; DocumentBuilder db ; Document doc; dbf = DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); doc = db.newDocument();
Элемент Element объекта Document создается с использованием метода createElement. Для определения значения элемента следует использовать метод setTextContent. Для добавления элемента в узловую запись используйте метод appendChild (Node). Элемент может содержать атрибуты. Чтобы добавить к элементу атрибут следует использовать метод setAttribute. Если элемент уже содержит атрибут, то его значение изменится.
Element org.w3c.dom.Document.createElement(String s) throws DOMException; void org.w3c.dom.Node.setTextContent(String text) throws DOMException; Node org.w3c.dom.Node.appendChild(Node newChild) throws DOMException; void org.w3c.dom.Element.setAttribute(String name, String value) throws DOMException; // Пример Element root = doc.createElement("Users"); Element user = doc.createElement("user"); user.setTextContent("Остап Бендер"); user.setAttribute ("book", "12 стульев"); root.appendChild(user); doc.appendChild(root);
В результате работы примера будет создан Document следующей структуры :
Пример чтения и создания XML-файла
Для чтения готового XML-файла и формирования нового файла создадим в IDE Eclipse простой проект XMLSample, структура которого представлена на следующем скриншоте.
Проект включает XML-файл «posts.xml» с исходными данными, создаваемый XML-файл данных «data.xml», класс Post.java, в который будут упаковываться отдельные записи массива данных и основной класс проекта XMLSample, который будет производить все необходимые действия.
Структура XML-файла
В качестве исходных данных используется XML-файл «posts.xml» из примеров разработчиков Sencha GXT 3.1.1. Структура XML-данных содержит корневой элемент и набор объектов/сущностей, представленных тегами .
Листинг класса Person
import java.util.Date; public class Post < private static int private int id; private String username; private String subject; private String forum; private Date date; public Post() < setId(ID++); >>
Класс Person имеет несколько полей. Идентификатор записи id определяется при создании объекта в конструкторе. Методы set/get не представлены в листинге.
Чтение XML-файла
Для чтения XML-файла в проекте используется метод readDataXML(), который создает список persons типа List, читает XML-файл данных и формирует объект doc типа Document. После этого в цикле создается массив данных. Вспомогательная функция getValue извлекает текст атрибута записи.
import org.w3c.dom.Node; import org.w3c.dom.Element; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; . . . public class XMLSample < private final String FILE_post = "posts.xml"; private Listposts; private String getValue(NodeList fields, int index) < NodeList list = fields.item(index).getChildNodes(); if (list.getLength() >0) < return list.item(0).getNodeValue(); >else < return ""; >> private void readDataXML() < posts = new ArrayList(); SimpleDateFormat sdf = null; DocumentBuilderFactory dbf = null; DocumentBuilder db = null; Document doc = null; try < sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dbf = DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); doc = null; FileInputStream fis = null; if (fileExists(FILE_post)) < try < fis = new FileInputStream(FILE_post); doc = db.parse(fis); >catch (FileNotFoundException e) < e.printStackTrace(); >> doc.getDocumentElement().normalize(); NodeList fields = null; NodeList nodeList = null; nodeList = doc.getElementsByTagName("row"); for (int s = 0; s < nodeList.getLength(); s++) < Node node = nodeList.item(s); if (node.getNodeType() == Node.ELEMENT_NODE) < Element el = (Element) node; fields = el.getElementsByTagName("field"); Post p = new Post(); p.setForum (getValue(fields, 0)); p.setDate (sdf.parse(getValue(fields,1))); p.setSubject (getValue(fields, 2)); p.setUsername(getValue(fields, 4)); posts.add(p); >> > catch (Exception e) < e.printStackTrace(); >> >
Следует обратить внимание, что для чтения значения атрибута записи (объекта Person) сначала получаем ссылку на массив тегов , и после этого по индексу в функции getValue извлекаем значение.
Создание XML-файла
Для создания нового XML-файла на основе массива posts подготовим два списка данных типа List : пользователей users и форумов forums. Эти два массива запишем в XML-файл.
Создание нового объекта Document и сохранение его в XML-файл в проекте выполняет метод writeDataXML :
Листинг метода создания XML-файла
private final String FILE_data = "data.xml"; private void writeDataXML() < DocumentBuilderFactory dbf = null; DocumentBuilder db = null; Document doc = null; try < dbf = DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); doc = db.newDocument(); Element e_root = doc.createElement("Posts"); e_root.setAttribute("lang", "en"); Element e_users = doc.createElement("Users"); Element e_forums = doc.createElement("Forums"); e_root.appendChild(e_users); e_root.appendChild(e_forums); doc.appendChild(e_root); if (posts.size() == 0) return; Listusers = new ArrayList(); List forums = new ArrayList(); for (int i = 0; i < posts.size(); i++)< if (!users.contains(posts.get(i).getUsername())) users.add(posts.get(i).getUsername()); if (!forums.contains(posts.get(i).getForum())) forums.add(posts.get(i).getForum()); >System.out.println(" пользователей : " + users.size()); for (String user : users) < Element e = doc.createElement("user"); e.setTextContent(user); e_users.appendChild (e); >System.out.println(" форумов : " + forums.size()); for (String forum : forums) < Element e = doc.createElement("forum"); e.setTextContent(forum); e_forums.appendChild (e); >> catch (ParserConfigurationException e) < e.printStackTrace(); >finally < // Сохраняем Document в XML-файл if (doc != null) writeDocument(doc, FILE_data); >>
Процедура сохранения объекта Document в XML-файл представлена отдельным методом writeDocument :
Листинг процедуры сохранения XML-файла
/** * Процедура сохранения DOM в файл */ private void writeDocument(Document document, String path) throws TransformerFactoryConfigurationError < Transformer trf = null; DOMSource src = null; FileOutputStream fos = null; try < trf = TransformerFactory.newInstance() .newTransformer(); src = new DOMSource(document); fos = new FileOutputStream(path); StreamResult result = new StreamResult(fos); trf.transform(src, result); >catch (TransformerException e) < e.printStackTrace(System.out); >catch (IOException e) < e.printStackTrace(System.out); >>
Если массив posts окажется пустым, то новый XML-файл должен будет иметь следующий вид :
SAX-парсер, SAXParser
SAX-парсеры используют для анализа XML-строки или извлечения из нее необходимой информации. Обычно SAX-парсеры требуют фиксированный объем памяти и не позволяют изменять содержимое. Для связи SAX-парсера с вызывающим приложением, как правило, используется функция обратного вызова.
Рассмотрим пример SAXExample.java с использованием класса SAXParser для анализа XML-текста, представленного файлом phonebook.xml, содержащего 3 записи и имеющего следующий вид :
Файл phonebook.xml
Остап Бендер ostap@12.com 999-987-6543 Киса Воробьянинов kisa@12.com 999-986-5432 Мадам Грицацуева madam@12.com 999-985-4321
Пакеты «javax.xml.parsers» и «org.xml.sax» включают набор классов для «разбора» XML в строковом представлении. К основным классам этих пакетов, с точки зрения разложения XML объекта на составляющие, относятся SAXParser и DefaultHandler.
В примере SAXExample.java создается класс handler типа DefaultHandler, в котором методы анализа XML-строки переопределяются. Все прозрачно.
Листинг SAXExample.java
import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SAXExample < final String fileName = "phonebook.xml"; final String TAG_NAME = "name"; DefaultHandler handler = new DefaultHandler() < boolean tagOn = false; // флаг начала разбора тега /** * Метод вызывается, когда SAXParser начинает * обработку тэга */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException < // Устанавливаем флаг для тега TAG_NAME tagOn = (qName.equalsIgnoreCase(TAG_NAME)); System.out.println("\t"); > /** * Метод вызывается, когда SAXParser считывает * текст между тэгами */ @Override public void characters(char ch[], int start, int length) throws SAXException < // Проверка флага if (tagOn) < // Флаг установлен System.out.println("\t\t" + new String(ch,start,length)); tagOn = false; >> @Override public void endElement(String uri, String localName, String qName) throws SAXException < super.endElement(uri, localName, qName); >@Override public void startDocument() throws SAXException < System.out.println("Начало разбора документа!"); >@Override public void endDocument() throws SAXException < System.out.println("Разбор документа завершен!"); >>; public SAXExample() < try < SAXParserFactory factory; factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); // Стартуем разбор XML-документа saxParser.parse(fileName, handler); >catch (Exception e) < e.printStackTrace(); >> public static void main(String args[]) < new SAXExample(); System.exit(0); >>
В результате выполнения примера использования SAXParser в консоль будут выведены следующие сообщения :
Начало разбора документа! Остап Бендер Киса Воробьянинов Мадам Грицацуева Разбор документа завершен!
Скачать примеры
Рассмотренные на странице примеры использования DOM для чтения и создания XML-документа, применения SAXParser’а для анализа XML-текста в виде проекта Eclipse можно скачать здесь (133 Кб).