- XML документ — DOM, SAXParser
- Чтение XML-файла
- Создание XML-файла
- Пример чтения и создания XML-файла
- Структура XML-файла
- Листинг класса Person
- Чтение XML-файла
- Создание XML-файла
- Листинг метода создания XML-файла
- Листинг процедуры сохранения XML-файла
- SAX-парсер, SAXParser
- Файл phonebook.xml
- Листинг SAXExample.java
- Скачать примеры
- Create XML Document in Java
- Create DocumentBuilderFactory
- Create new Document
- Create XML Document Root Element
- Create Child XML Element
- Transform XML Document to String
- Create XML Document Complete Example
- Related Posts:
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 Кб).
Create XML Document in Java
With this short blog post I am going to share with you how to create XML document using Java.
Often we need to send HTTP Post request that contains JSON or XML payload. Earlier I have shared a blog post on different ways to create JSON Payload by converting Java objects into JSON. Below is an example of how to use DocumentBuilder from javax.xml.parsers to construct XML document from scratch.
In the example below we are going to create a very simple XML document of the below structure. Once you are able to create this simple XML document, you will be able to enhance it with new elements as needed.
Create DocumentBuilderFactory
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
Create new Document
DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document doc = docBuilder.newDocument();
Create XML Document Root Element
// Create Person root element Element personRootElement = doc.createElement( "Person" ); doc.appendChild( personRootElement );
Create Child XML Element
// Create First Name Element Element firstNameElement = doc.createElement( "FirstName" ); firstNameElement.appendChild( doc.createTextNode( "Sergey" ) ); personRootElement.appendChild( firstNameElement );
and we will create a second child element right away:
// Create Last Name Element Element lastNameElement = doc.createElement( "LastName" ); lastNameElement.appendChild( doc.createTextNode( "Kargopolov" ) ); personRootElement.appendChild( lastNameElement );
Transform XML Document to String
// Transform Document to XML String TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); StringWriter writer = new StringWriter(); transformer.transform( new DOMSource( doc ), new StreamResult( writer ) );
and we can now get value of String, so that we can use it as we need. For example we can send it as a body of HTTP Request to our RESTful Web Services API endpoint.
// Get the String value of final xml document personXMLStringValue = writer.getBuffer().toString();
and this is it! I will paste a complete example in a single class file below.
Create XML Document Complete Example
Below is a complete example in the form of single public static void main function. You should be able to run it as is.
package com.appsdeveloperblog.xml; import java.io.StringWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * * @author skargopolov */ public class PersonXMLDocument < public static void main(String[] args) < String personXMLStringValue = null; DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); try < DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document doc = docBuilder.newDocument(); // Create Person root element Element personRootElement = doc.createElement("Person"); doc.appendChild(personRootElement); // Create First Name Element Element firstNameElement = doc.createElement("FirstName"); firstNameElement.appendChild(doc.createTextNode("Sergey")); personRootElement.appendChild(firstNameElement); // Create Last Name Element Element lastNameElement = doc.createElement("LastName"); lastNameElement.appendChild(doc.createTextNode("Kargopolov")); personRootElement.appendChild(lastNameElement); // Transform Document to XML String TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); StringWriter writer = new StringWriter(); transformer.transform(new DOMSource(doc), new StreamResult(writer)); // Get the String value of final xml document personXMLStringValue = writer.getBuffer().toString(); >catch (ParserConfigurationException | TransformerException e) < e.printStackTrace(); >System.out.println("personXMLStringValue = " + personXMLStringValue); > >
I hope this short and simple example of how to create xml document in Java was helpful to you!
If you have questions please comment below. Hopefully myself or other web site visitors will be able to help you out.
Also, checkout the below list of books that will help you learn how to work with XML in Java.