Обработка XML документов бывает очень неудобной и затратной по времени, особенно это касается xml-кода, который на вход подается в виде строки. Поэтому приходится писать вспомогательные классы для обработки и правильного форматирования таких данных. Этим мы сегодня и займемся.
Форматирование XML в Java
XML является одним из наиболее популярных способов обмена данными между различными приложениями. Различные сообщения и данные могут быть переданы разными способами, например, в виде строки (объектом String). Так получилось и у меня, когда на вход приходила строка xml кода без форматирования и отступов. Чтобы справиться с этим я написал специальный утилитный класс. Его мы сегодня и разберем.
В прошлой статье мы научились преобразовать строку в Document и создавать String из Document. Теперь же рассмотрим как форматировать полученный в строке XML на примере ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; public class XmlStringFormatter { public static void main(String args[]) { // какая-то строка с неформатированным XML содержимым String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + "\n<Developer id=\"1\">\n" + "<name>Andrew</name><age>25</age><position>Middle</position>" + "<language>Java</language></Developer>"; Document document = convertStringToDocument(xmlString); // обычно используют indent = 4, но посмотрим пример с 6 System.out.println(toPrettyXmlString(6, document)); } // в переменной indent указываем уровень(величину) отступа public static String toPrettyXmlString(int indent, Document document) { try { // удаляем пробелы XPath xPath = XPathFactory.newInstance().newXPath(); NodeList nodeList = (NodeList) xPath.evaluate( "//text()[normalize-space()='']", document, XPathConstants.NODESET ); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); node.getParentNode().removeChild(node); } // устанавливаем настройки для красивого форматирования TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setAttribute("indent-number", indent); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // форматируем XML StringWriter stringWriter = new StringWriter(); transformer.transform(new DOMSource(document), new StreamResult(stringWriter)); // возвращаем строку с отформатированным XML return stringWriter.toString(); } catch (Exception e) { throw new RuntimeException(e); } } // метод для конвертации строки с XML разметкой в объект Document private static Document convertStringToDocument(String xml) { try { return DocumentBuilderFactory.newInstance() .newDocumentBuilder() .parse(new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")))); } catch (SAXException | IOException | ParserConfigurationException e) { e.printStackTrace(); } return null; } } |
Обратите внимание такие особенности программы:
- В методе
toPrettyXmlString()
мы можем указыватьindent
— значение отступа. - Также мы использовали XPath выражение для удаления пробелов в исходной строке.
- Воспользовались возможностями класса
javax.xml.transform.TransformerFactory
для определения параметров форматирования. Например, с помощью передачи параметруOutputKeys.OMIT_XML_DECLARATION
значения"yes"
указали, что хотим убрать XML declaration в переданном объектеDocument
.
Теперь запустим наш утилитный класс и смотрим на вывод в консоле:
1 2 3 4 5 6 |
<Developer id="1"> <name>Andrew</name> <age>25</age> <position>Middle</position> <language>Java</language> </Developer> |
Вот такой красивый и читабельный вид имеет преобразованная строка. Для того, чтобы посмотреть всю мощь и удобство представленного выше способа сделать Pretty Print XML в Java, попробуйте передать на вход большую неотформатированную строку с XML разметкой.
Следите за обновлениями и подписывайтесь на новые статьи.
В строке 53 нужно вместо
TransformerFactory transformerFactory = TransformerFactory.newInstance();
написать
TransformerFactory transformerFactory = new TransformerFactoryImpl();
Не во всех Имплементациях TransformerFactory есть поле «indent-number»