Конвертиране на XML в HTML в Java

1. Въведение

В този урок ще опишем как да конвертирате XML в HTML, използвайки общи библиотеки на Java и механизми за шаблони - JAXP, StAX, Freemarker и Mustache .

2. XML към Unmarshal

Нека започнем с прост XML документ, който ще демаршалираме в подходящо Java представяне, преди да го преобразуваме в HTML. Ще имаме предвид няколко ключови цели:

  1. Запазете един и същ XML за всички наши проби
  2. Създайте синтактично и семантично валиден HTML5 документ в края
  3. Преобразувайте всички XML елементи в текст

Нека използваме обикновено известие на Jenkins като примерния XML:

  [email protected] Build #7 passed Success: The Jenkins CI build passed 

И това е доста лесно. Той включва корен елемент и някои вложени елементи.

Ще се стремим да премахнем всички уникални XML тагове и да разпечатаме двойки ключ-стойност, когато създаваме нашия HTML файл.

3. JAXP

Java Architecture for XML Processing (JAXP) е библиотека, която е предназначена да разшири функционалността на популярния SAX Parser с допълнителна поддръжка на DOM. JAXP предоставя възможност за маршал и демаршал на XML дефинирани обекти в и от POJO с помощта на SAX Parser . Ще се възползваме и от вградените помощници на DOM.

Нека добавим зависимостта Maven за JAXP към нашия проект:

 javax.xml jaxp-api 1.4.2  

3.1. Демаркиране с помощта на DOM Builder

Нека започнем с първо демаркиране на нашия XML файл в обект Java Element :

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); factory.setFeature("//apache.org/xml/features/disallow-doctype-decl", true); Document input = factory .newDocumentBuilder() .parse(resourcePath); Element xml = input.getDocumentElement(); 

3.2. Извличане на съдържанието на XML файла в карта

Сега нека да изградим Карта със съответното съдържание на нашия XML файл:

Map map = new HashMap(); map.put("heading", xml.getElementsByTagName("heading") .item(0) .getTextContent()); map.put("from", String.format("from: %s", xml.getElementsByTagName("from") .item(0) .getTextContent())); map.put("content", xml.getElementsByTagName("content") .item(0) .getTextContent());

3.3. Маршалиране с помощта на DOM Builder

Маршалирането на нашия XML в HTML файл е малко по-ангажирано.

Нека подготвим документ за прехвърляне , който ще използваме за изписване на HTML:

Document doc = factory .newDocumentBuilder() .newDocument(); 

След това ще попълним документа с елементите в нашата карта :

Element html = doc.createElement("html"); Element head = doc.createElement("head"); html.setAttribute("lang", "en"); Element title = doc.createElement("title"); title.setTextContent(map.get("heading")); head.appendChild(title); html.appendChild(head); Element body = doc.createElement("body"); Element from = doc.createElement("p"); from.setTextContent(map.get("from")); Element success = doc.createElement("p"); success.setTextContent(map.get("content")); body.appendChild(from); body.appendChild(success); html.appendChild(body); doc.appendChild(html); 

И накрая, нека маршалираме нашия обект Document, използвайки TransformerFactory :

TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); try (Writer output = new StringWriter()) { Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new DOMSource(doc), new StreamResult(output)); }

Ако извикаме output.toString () , ще получим HTML представяне.

Имайте предвид, че някои от допълнителните функции и атрибути, които сме задали в нашата фабрика, са взети от препоръките на проекта OWASP, за да се избегне инжектирането на XXE .

4. StAX

Друга библиотека, която можем да използваме, е Streaming API за XML (StAX). Подобно на JAXP, StAX съществува отдавна - от 2004 г.

Останалите две библиотеки опростяват синтактичния анализ на XML файлове. Това е чудесно за прости задачи или проекти, но по-малко, когато трябва да повторим или да имаме изричен и фин контрол върху саморазбора на елементите . Това е мястото, където StAX е полезен.

Нека добавим зависимостта Maven за API StAX към нашия проект:

 javax.xml.stream stax-api 1.0-2  

4.1. Демаркиране с помощта на StAX

Ще използваме прост поток за управление на итерация, за да съхраняваме XML стойности в нашата карта :

XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE); factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); XMLStreamReader input = null; try (FileInputStream file = new FileInputStream(resourcePath)) { input = factory.createXMLStreamReader(file); Map map = new HashMap(); while (input.hasNext()) { input.next(); if (input.isStartElement()) { if (input.getLocalName().equals("heading")) { map.put("heading", input.getElementText()); } if (input.getLocalName().equals("from")) { map.put("from", String.format("from: %s", input.getElementText())); } if (input.getLocalName().equals("content")) { map.put("content", input.getElementText()); } } } } finally { if (input != null) { input.close(); } }

4.2. Маршалиране с помощта на StAX

Сега, нека използваме нашата карта и запишем HTML :

try (Writer output = new StringWriter()) { XMLStreamWriter writer = XMLOutputFactory .newInstance() .createXMLStreamWriter(output); writer.writeDTD(""); writer.writeStartElement("html"); writer.writeAttribute("lang", "en"); writer.writeStartElement("head"); writer.writeDTD(""); writer.writeStartElement("title"); writer.writeCharacters(map.get("heading")); writer.writeEndElement(); writer.writeEndElement(); writer.writeStartElement("body"); writer.writeStartElement("p"); writer.writeCharacters(map.get("from")); writer.writeEndElement(); writer.writeStartElement("p"); writer.writeCharacters(map.get("content")); writer.writeEndElement(); writer.writeEndElement(); writer.writeEndDocument(); writer.flush(); }

Както в примера за JAXP, можем да извикаме output.toString (), за да получим HTML представяне.

5. Използване на Template Engines

Като алтернатива на писането на HTML представяне можем да използваме механизми за шаблони. В екосистемата на Java има множество опции. Нека разгледаме някои от тях.

5.1. Използване на Apache Freemarker

Apache FreeMarker е базиран на Java механизъм за шаблони за генериране на текстови резултати (HTML уеб страници, имейли, конфигурационни файлове, изходен код и др.) Въз основа на шаблони и променящи се данни.

За да го използваме, ще трябва да добавим зависимостта на марката към нашия проект Maven:

 org.freemarker freemarker 2.3.29 

Първо, нека създадем шаблон, използвайки синтаксиса на FreeMarker:

    ${heading}   

${from}

${content}

Сега, нека използваме повторно нашата карта и попълваме пропуските в шаблона:

Configuration cfg = new Configuration(Configuration.VERSION_2_3_29); cfg.setDirectoryForTemplateLoading(new File(templateDirectory)); cfg.setDefaultEncoding(StandardCharsets.UTF_8.toString()); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); cfg.setLogTemplateExceptions(false); cfg.setWrapUncheckedExceptions(true); cfg.setFallbackOnNullLoopVariable(false); Template temp = cfg.getTemplate(templateFile); try (Writer output = new StringWriter()) { temp.process(staxTransformer.getMap(), output); }

5.2. Използване на мустаци

Mustache is a logic-less template engine. Mustache can be used for HTML, config files, source code — pretty much anything. It works by expanding tags in a template using values provided in a hash or object.

To use it, we'll need to add the mustache dependency to our Maven project:

 com.github.spullara.mustache.java compiler 0.9.6 

Let's start creating a template using the Mustache syntax:

    {{heading}}   

{{from}}

{{content}}

Now, let's fill the template with our map:

MustacheFactory mf = new DefaultMustacheFactory(); Mustache mustache = mf.compile(templateFile); try (Writer output = new StringWriter()) { mustache.execute(output, staxTransformer.getMap()); output.flush(); }

6. The Resulting HTML

In the end, with all our code samples, we'll get the same HTML output:

    Build #7 passed   

from: [email protected]

Success: The Jenkins CI build passed

7. Conclusion

In this tutorial, we've learned the basics of using JAXP, StAX, Freemarker, and Mustache to convert XML into HTML.

For more information about XML in Java, check out these other great resources right here on Baeldung:

  • Deserializing XML to Objects in XStream
  • Serializing Objects to XML in XStream
  • Java XML Libraries

Както винаги, пълните примерни кодове, които се виждат тук, са достъпни в GitHub.