From e7c98a942913263d19c5a562f2454769c7ced3d3 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 29 Apr 2025 18:13:27 -0400 Subject: [PATCH] Merge from remote --- .../com/baeldung/xml/XMLDocumentWriter.java | 36 ++++++ .../xml/attribute/Dom4jTransformer.java | 49 +++++++++ .../xml/attribute/JaxpTransformer.java | 60 ++++++++++ .../xml/attribute/JooxTransformer.java | 38 +++++++ .../xml/attribute/jmh/AttributeBenchMark.java | 71 ++++++++++++ .../java/com/baeldung/xml/jibx/Customer.java | 53 +++++++++ .../java/com/baeldung/xml/jibx/Identity.java | 14 +++ .../java/com/baeldung/xml/jibx/Person.java | 25 +++++ .../java/com/baeldung/xml/jibx/Phone.java | 14 +++ .../xml/xml2pdf/XmlToPdfConverter.java | 55 ++++++++++ .../com/baeldung/xmlhtml/Application.java | 10 ++ .../java/com/baeldung/xmlhtml/Constants.java | 22 ++++ .../freemarker/FreemarkerTransformer.java | 40 +++++++ .../baeldung/xmlhtml/helpers/XMLRunner.java | 11 ++ .../xmlhtml/helpers/jaxb/JAXBHelper.java | 76 +++++++++++++ .../xmlhtml/jaxp/JaxpTransformer.java | 103 ++++++++++++++++++ .../xmlhtml/mustache/MustacheTransformer.java | 30 +++++ .../xmlhtml/pojo/jaxb/html/ExampleHTML.java | 38 +++++++ .../xmlhtml/pojo/jaxb/html/elements/Body.java | 29 +++++ .../jaxb/html/elements/CustomElement.java | 18 +++ .../xmlhtml/pojo/jaxb/html/elements/Meta.java | 30 +++++ .../jaxb/html/elements/NestedElement.java | 17 +++ .../xmlhtml/pojo/jaxb/xml/XMLExample.java | 20 ++++ .../pojo/jaxb/xml/elements/Ancestor.java | 28 +++++ .../pojo/jaxb/xml/elements/DescendantOne.java | 19 ++++ .../jaxb/xml/elements/DescendantThree.java | 18 +++ .../pojo/jaxb/xml/elements/DescendantTwo.java | 17 +++ .../xmlhtml/stax/StaxTransformer.java | 99 +++++++++++++++++ xml-2/src/main/resources/customer-binding.xml | 26 +++++ xml-2/src/main/resources/xml/attribute.xml | 5 + .../main/resources/xml/attribute_expected.xml | 5 + xml-2/src/main/resources/xml/in.xml | 11 ++ xml-2/src/main/resources/xml/jaxb.html | 14 +++ xml-2/src/main/resources/xml/jaxp.html | 13 +++ xml-2/src/main/resources/xml/stax.html | 15 +++ .../main/resources/xmltopdf/data-input.xml | 26 +++++ xml-2/src/main/resources/xmltopdf/style.xsl | 75 +++++++++++++ .../xml/attribute/Dom4jProcessorUnitTest.java | 69 ++++++++++++ .../xml/attribute/JaxpProcessorUnitTest.java | 47 ++++++++ .../xml/attribute/JooxProcessorUnitTest.java | 69 ++++++++++++ .../baeldung/xml/jibx/CustomerUnitTest.java | 52 +++++++++ .../xml2pdf/XmlToPdfConverterUnitTest.java | 47 ++++++++ 42 files changed, 1514 insertions(+) create mode 100644 xml-2/src/main/java/com/baeldung/xml/XMLDocumentWriter.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/attribute/Dom4jTransformer.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/attribute/JaxpTransformer.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/attribute/JooxTransformer.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/attribute/jmh/AttributeBenchMark.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/jibx/Customer.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/jibx/Identity.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/jibx/Person.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/jibx/Phone.java create mode 100644 xml-2/src/main/java/com/baeldung/xml/xml2pdf/XmlToPdfConverter.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/Application.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/Constants.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/freemarker/FreemarkerTransformer.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/jaxp/JaxpTransformer.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/mustache/MustacheTransformer.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java create mode 100644 xml-2/src/main/java/com/baeldung/xmlhtml/stax/StaxTransformer.java create mode 100644 xml-2/src/main/resources/customer-binding.xml create mode 100644 xml-2/src/main/resources/xml/attribute.xml create mode 100644 xml-2/src/main/resources/xml/attribute_expected.xml create mode 100644 xml-2/src/main/resources/xml/in.xml create mode 100644 xml-2/src/main/resources/xml/jaxb.html create mode 100644 xml-2/src/main/resources/xml/jaxp.html create mode 100644 xml-2/src/main/resources/xml/stax.html create mode 100644 xml-2/src/main/resources/xmltopdf/data-input.xml create mode 100644 xml-2/src/main/resources/xmltopdf/style.xsl create mode 100644 xml-2/src/test/java/com/baeldung/xml/attribute/Dom4jProcessorUnitTest.java create mode 100644 xml-2/src/test/java/com/baeldung/xml/attribute/JaxpProcessorUnitTest.java create mode 100644 xml-2/src/test/java/com/baeldung/xml/attribute/JooxProcessorUnitTest.java create mode 100644 xml-2/src/test/java/com/baeldung/xml/jibx/CustomerUnitTest.java create mode 100644 xml-2/src/test/java/com/baeldung/xml/xml2pdf/XmlToPdfConverterUnitTest.java diff --git a/xml-2/src/main/java/com/baeldung/xml/XMLDocumentWriter.java b/xml-2/src/main/java/com/baeldung/xml/XMLDocumentWriter.java new file mode 100644 index 0000000000..7dc9872d2b --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/XMLDocumentWriter.java @@ -0,0 +1,36 @@ +package com.baeldung.xml; + +import org.w3c.dom.Document; + +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +public class XMLDocumentWriter { + + public void write(Document document, String fileName, boolean excludeDeclaration, boolean prettyPrint) { + try(FileWriter writer = new FileWriter(new File(fileName))) { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + if(excludeDeclaration) { + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + } + if(prettyPrint) { + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + } + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } catch (TransformerConfigurationException e) { + throw new IllegalStateException(e); + } catch (TransformerException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/attribute/Dom4jTransformer.java b/xml-2/src/main/java/com/baeldung/xml/attribute/Dom4jTransformer.java new file mode 100644 index 0000000000..631cf80cb0 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/attribute/Dom4jTransformer.java @@ -0,0 +1,49 @@ +package com.baeldung.xml.attribute; + +import org.dom4j.*; +import org.dom4j.io.DocumentSource; +import org.dom4j.io.SAXReader; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; + +public class Dom4jTransformer { + private final Document input; + + public Dom4jTransformer(String resourcePath) throws DocumentException, SAXException { + // 1- Build the doc from the XML file + SAXReader xmlReader = new SAXReader(); + xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false); + xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + this.input = xmlReader.read(resourcePath); + } + + public String modifyAttribute(String attribute, String oldValue, String newValue) throws TransformerException, TransformerException { + // 2- Locate the node(s) with xpath, we can use index and iterator too. + String expr = String.format("//*[contains(@%s, '%s')]", attribute, oldValue); + XPath xpath = DocumentHelper.createXPath(expr); + List nodes = xpath.selectNodes(input); + // 3- Make the change on the selected nodes + for (int i = 0; i < nodes.size(); i++) { + Element element = (Element) nodes.get(i); + element.addAttribute(attribute, newValue); + } + // 4- Save the result to a new XML doc + TransformerFactory factory = TransformerFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + Transformer xformer = factory.newTransformer(); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + Writer output = new StringWriter(); + xformer.transform(new DocumentSource(input), new StreamResult(output)); + return output.toString(); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/attribute/JaxpTransformer.java b/xml-2/src/main/java/com/baeldung/xml/attribute/JaxpTransformer.java new file mode 100644 index 0000000000..ef2f9dc822 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/attribute/JaxpTransformer.java @@ -0,0 +1,60 @@ +package com.baeldung.xml.attribute; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +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.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +public class JaxpTransformer { + + private Document input; + + public JaxpTransformer(String resourcePath) throws SAXException, IOException, ParserConfigurationException { + // 1- Build the doc from the XML file + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + this.input = factory.newDocumentBuilder() + .parse(resourcePath); + } + + public String modifyAttribute(String attribute, String oldValue, String newValue) + throws XPathExpressionException, TransformerFactoryConfigurationError, TransformerException, TransformerConfigurationException { + // 2- Locate the node(s) with xpath + XPath xpath = XPathFactory.newInstance() + .newXPath(); + NodeList nodes = (NodeList) xpath.evaluate(String.format("//*[contains(@%s, '%s')]", attribute, oldValue), this.input, XPathConstants.NODESET); + // 3- Make the change on the selected nodes + for (int i = 0; i < nodes.getLength(); i++) { + Element value = (Element) nodes.item(i); + value.setAttribute(attribute, newValue); + } + // Stream api syntax + // IntStream + // .range(0, nodes.getLength()) + // .mapToObj(i -> (Element) nodes.item(i)) + // .forEach(value -> value.setAttribute(attribute, newValue)); + // 4- Save the result to a new XML doc + TransformerFactory factory = TransformerFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + Transformer xformer = factory.newTransformer(); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + Writer output = new StringWriter(); + xformer.transform(new DOMSource(this.input), new StreamResult(output)); + return output.toString(); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/attribute/JooxTransformer.java b/xml-2/src/main/java/com/baeldung/xml/attribute/JooxTransformer.java new file mode 100644 index 0000000000..d36d60ec59 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/attribute/JooxTransformer.java @@ -0,0 +1,38 @@ +package com.baeldung.xml.attribute; + +import org.joox.JOOX; +import org.joox.Match; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.transform.TransformerFactoryConfigurationError; +import java.io.IOException; + +import static org.joox.JOOX.$; + +public class JooxTransformer { + + private final Document input; + + public JooxTransformer(String resourcePath) throws SAXException, IOException { + // 1- Build the doc from the XML file + DocumentBuilder builder = JOOX.builder(); + input = builder.parse(resourcePath); + } + + public String modifyAttribute(String attribute, String oldValue, String newValue) throws TransformerFactoryConfigurationError { + // 2- Select the document + Match $ = $(input); + // 3 - Find node to modify + String expr = String.format("//*[contains(@%s, '%s')]", attribute, oldValue); + $ + // .find("to") or with xpath + .xpath(expr) + .get() + .stream() + .forEach(e -> e.setAttribute(attribute, newValue)); + // 4- Return result as String + return $.toString(); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/attribute/jmh/AttributeBenchMark.java b/xml-2/src/main/java/com/baeldung/xml/attribute/jmh/AttributeBenchMark.java new file mode 100644 index 0000000000..849b6ef945 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/attribute/jmh/AttributeBenchMark.java @@ -0,0 +1,71 @@ +package com.baeldung.xml.attribute.jmh; + +import com.baeldung.xml.attribute.Dom4jTransformer; +import com.baeldung.xml.attribute.JaxpTransformer; +import com.baeldung.xml.attribute.JooxTransformer; +import org.dom4j.DocumentException; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathExpressionException; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class AttributeBenchMark { + + public static void main(String[] args) throws RunnerException { + Options opt = new OptionsBuilder().include(AttributeBenchMark.class.getSimpleName()) + .forks(1) + .build(); + new Runner(opt).run(); + } + + @Benchmark + public String dom4jBenchmark() throws DocumentException, TransformerException, SAXException { + String path = this.getClass() + .getResource("/xml/attribute.xml") + .toString(); + Dom4jTransformer transformer = new Dom4jTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + + return transformer.modifyAttribute(attribute, oldValue, newValue); + } + + @Benchmark + public String jooxBenchmark() throws IOException, SAXException { + String path = this.getClass() + .getResource("/xml/attribute.xml") + .toString(); + JooxTransformer transformer = new JooxTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + + return transformer.modifyAttribute(attribute, oldValue, newValue); + } + + @Benchmark + public String jaxpBenchmark() + throws TransformerException, ParserConfigurationException, SAXException, IOException, XPathExpressionException { + String path = this.getClass() + .getResource("/xml/attribute.xml") + .toString(); + JaxpTransformer transformer = new JaxpTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + + return transformer.modifyAttribute(attribute, oldValue, newValue); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/jibx/Customer.java b/xml-2/src/main/java/com/baeldung/xml/jibx/Customer.java new file mode 100644 index 0000000000..a660451080 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/jibx/Customer.java @@ -0,0 +1,53 @@ +/* + * Customer.java 06.06.2008 + * + * Copyright 2008 Stefan Jäger + * + */ +package com.baeldung.xml.jibx; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +public class Customer { + private Person person; + private String city; + + private Phone homePhone; + private Phone officePhone; + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Phone getHomePhone() { + return homePhone; + } + + public void setHomePhone(Phone homePhone) { + this.homePhone = homePhone; + } + + public Phone getOfficePhone() { + return officePhone; + } + + public void setOfficePhone(Phone officePhone) { + this.officePhone = officePhone; + } + + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/jibx/Identity.java b/xml-2/src/main/java/com/baeldung/xml/jibx/Identity.java new file mode 100644 index 0000000000..15aab4e417 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/jibx/Identity.java @@ -0,0 +1,14 @@ +package com.baeldung.xml.jibx; + +public class Identity { + + long customerId; + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/jibx/Person.java b/xml-2/src/main/java/com/baeldung/xml/jibx/Person.java new file mode 100644 index 0000000000..43af659319 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/jibx/Person.java @@ -0,0 +1,25 @@ +/* + * Person.java 06.06.2008 + * + * Copyright 2008 Stefan Jäger + * + */ +package com.baeldung.xml.jibx; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +public class Person extends Identity { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/jibx/Phone.java b/xml-2/src/main/java/com/baeldung/xml/jibx/Phone.java new file mode 100644 index 0000000000..783f2ee6fb --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/jibx/Phone.java @@ -0,0 +1,14 @@ +package com.baeldung.xml.jibx; + +public class Phone { + + private String number; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/xml2pdf/XmlToPdfConverter.java b/xml-2/src/main/java/com/baeldung/xml/xml2pdf/XmlToPdfConverter.java new file mode 100644 index 0000000000..c65080b106 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/xml2pdf/XmlToPdfConverter.java @@ -0,0 +1,55 @@ +package com.baeldung.xml.xml2pdf; + +import com.itextpdf.text.Document; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.pdf.PdfWriter; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.MimeConstants; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class XmlToPdfConverter { + + public static void convertXMLtoPDFUsingFop(String xmlFilePath, String xsltFilePath, String pdfFilePath) throws Exception { + // Initialize FOP + FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI()); + FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); + + // Specify output stream for PDF + try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(new File(pdfFilePath).toPath()))) { + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out); + // Create Transformer from XSLT + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(new StreamSource(new File(xsltFilePath))); + // Apply transformation + Source src = new StreamSource(new File(xmlFilePath)); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(src, res); + } + } + + public static void convertXMLtoPDFUsingIText(String xmlFilePath, String pdfFilePath) throws Exception { + try (FileOutputStream outputStream = new FileOutputStream(pdfFilePath)) { + Document document = new Document(); + PdfWriter.getInstance(document, outputStream); + document.open(); + // Read XML content and add it to the Document + String xmlContent = new String(Files.readAllBytes(Paths.get(xmlFilePath))); + document.add(new Paragraph(xmlContent)); + document.close(); + } + } +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/Application.java b/xml-2/src/main/java/com/baeldung/xmlhtml/Application.java new file mode 100644 index 0000000000..063a833810 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/Application.java @@ -0,0 +1,10 @@ +package com.baeldung.xmlhtml; + +import com.baeldung.xmlhtml.helpers.XMLRunner; + +public class Application { + + public static void main(String[] args) { + XMLRunner.doWork(); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/Constants.java b/xml-2/src/main/java/com/baeldung/xmlhtml/Constants.java new file mode 100644 index 0000000000..88fc5637df --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/Constants.java @@ -0,0 +1,22 @@ +package com.baeldung.xmlhtml; + +public class Constants { + + public static final String XML_FILE_IN = "src/main/resources/xml/in.xml"; + public static final String JAXB_FILE_OUT = "src/main/resources/xml/jaxb.html"; + public static final String JAXP_FILE_OUT = "src/main/resources/xml/jaxp.html"; + public static final String STAX_FILE_OUT = "src/main/resources/xml/stax.html"; + + public static final String EXCEPTION_ENCOUNTERED = "Generic exception! Error: "; + + public static final String LINE_BREAK = System.getProperty("line.separator"); + public static final String WHITE_SPACE = " "; + + public static final String DOCUMENT_START = "Document parsing has begun!"; + public static final String DOCUMENT_END = "Document parsing has ended!"; + public static final String ELEMENT_START = "Element parsing has begun!"; + public static final String ELEMENT_END = "Element parsing has ended!"; + + public static final String BREAK = "\n"; + public static final String TAB = "\t"; +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/freemarker/FreemarkerTransformer.java b/xml-2/src/main/java/com/baeldung/xmlhtml/freemarker/FreemarkerTransformer.java new file mode 100644 index 0000000000..9e992699cc --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/freemarker/FreemarkerTransformer.java @@ -0,0 +1,40 @@ +package com.baeldung.xmlhtml.freemarker; + +import com.baeldung.xmlhtml.stax.StaxTransformer; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; + +public class FreemarkerTransformer { + private StaxTransformer staxTransformer; + private String templateDirectory; + private String templateFile; + + public FreemarkerTransformer(StaxTransformer staxTransformer, String templateDirectory, String templateFile) { + this.staxTransformer = staxTransformer; + this.templateDirectory = templateDirectory; + this.templateFile = templateFile; + } + + public String html() throws IOException, TemplateException { + 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); + return output.toString(); + } + } +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java b/xml-2/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java new file mode 100644 index 0000000000..f0fe308e38 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java @@ -0,0 +1,11 @@ +package com.baeldung.xmlhtml.helpers; + + +import com.baeldung.xmlhtml.helpers.jaxb.JAXBHelper; + +public class XMLRunner { + + public static void doWork() { + JAXBHelper.example(); + } +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java b/xml-2/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java new file mode 100644 index 0000000000..740d5990b2 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java @@ -0,0 +1,76 @@ +package com.baeldung.xmlhtml.helpers.jaxb; + +import com.baeldung.xmlhtml.pojo.jaxb.html.ExampleHTML; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Body; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.CustomElement; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Meta; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.NestedElement; +import com.baeldung.xmlhtml.pojo.jaxb.xml.XMLExample; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; + +import java.io.File; + +import static com.baeldung.xmlhtml.Constants.*; + +public class JAXBHelper { + + private static void print(String xmlContent) { + System.out.println(xmlContent); + } + + private static Unmarshaller getContextUnmarshaller(Class clazz) { + Unmarshaller unmarshaller = null; + try { + JAXBContext context = JAXBContext.newInstance(clazz); + unmarshaller = context.createUnmarshaller(); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return unmarshaller; + } + + private static Marshaller getContextMarshaller(Class clazz) { + Marshaller marshaller = null; + try { + JAXBContext context = JAXBContext.newInstance(clazz); + marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshaller.setProperty("jaxb.fragment", Boolean.TRUE); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return marshaller; + } + + public static void example() { + try { + XMLExample xml = (XMLExample) JAXBHelper.getContextUnmarshaller(XMLExample.class).unmarshal(new File(XML_FILE_IN)); + JAXBHelper.print(xml.toString()); + ExampleHTML html = new ExampleHTML(); + + Body body = new Body(); + CustomElement customElement = new CustomElement(); + NestedElement nested = new NestedElement(); + CustomElement child = new CustomElement(); + + customElement.setValue("descendantOne: " + xml.getAncestor().getDescendantOne().getValue()); + child.setValue("descendantThree: " + xml.getAncestor().getDescendantTwo().getDescendantThree().getValue()); + nested.setCustomElement(child); + + body.setCustomElement(customElement); + body.setNestedElement(nested); + + Meta meta = new Meta(); + meta.setTitle("example"); + html.getHead().add(meta); + html.setBody(body); + + JAXBHelper.getContextMarshaller(ExampleHTML.class).marshal(html, new File(JAXB_FILE_OUT)); + + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + } +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/jaxp/JaxpTransformer.java b/xml-2/src/main/java/com/baeldung/xmlhtml/jaxp/JaxpTransformer.java new file mode 100644 index 0000000000..3c288122a3 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/jaxp/JaxpTransformer.java @@ -0,0 +1,103 @@ +package com.baeldung.xmlhtml.jaxp; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import javax.xml.XMLConstants; +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 java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; + +public class JaxpTransformer { + + private Document input; + private DocumentBuilderFactory factory; + + public JaxpTransformer(String resourcePath) throws ParserConfigurationException, IOException, SAXException { + // 1- Build the doc from the XML file + factory = DocumentBuilderFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + input = factory + .newDocumentBuilder() + .parse(resourcePath); + } + + public String html() throws ParserConfigurationException, TransformerException, IOException { + Element xml = input.getDocumentElement(); + Document doc = factory + .newDocumentBuilder() + .newDocument(); + //Build Map + Map map = buildMap(xml); + //Head + Element html = doc.createElement("html"); + html.setAttribute("lang", "en"); + Element head = buildHead(map, doc); + html.appendChild(head); + //Body + Element body = buildBody(map, doc); + html.appendChild(body); + doc.appendChild(html); + return String.format("%n%s", applyTransformation(doc)); + } + + private String applyTransformation(Document doc) throws TransformerException, IOException { + 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)); + return output.toString(); + } + } + + private Map buildMap(Element 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()); + return map; + } + + private Element buildHead(Map map, Document doc) { + Element head = doc.createElement("head"); + Element title = doc.createElement("title"); + title.setTextContent(map.get("heading")); + head.appendChild(title); + return head; + } + + private Element buildBody(Map map, Document doc) { + 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); + return body; + } + +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/mustache/MustacheTransformer.java b/xml-2/src/main/java/com/baeldung/xmlhtml/mustache/MustacheTransformer.java new file mode 100644 index 0000000000..e449e74c3b --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/mustache/MustacheTransformer.java @@ -0,0 +1,30 @@ +package com.baeldung.xmlhtml.mustache; + +import com.baeldung.xmlhtml.stax.StaxTransformer; +import com.github.mustachejava.DefaultMustacheFactory; +import com.github.mustachejava.Mustache; +import com.github.mustachejava.MustacheFactory; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +public class MustacheTransformer { + private StaxTransformer staxTransformer; + private String templateFile; + + public MustacheTransformer(StaxTransformer staxTransformer, String templateFile) { + this.staxTransformer = staxTransformer; + this.templateFile = templateFile; + } + + public String html() throws IOException { + MustacheFactory mf = new DefaultMustacheFactory(); + Mustache mustache = mf.compile(templateFile); + try (Writer output = new StringWriter()) { + mustache.execute(output, staxTransformer.getMap()); + output.flush(); + return output.toString(); + } + } +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java new file mode 100644 index 0000000000..4ab9c31508 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java @@ -0,0 +1,38 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html; + +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Body; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Meta; +import jakarta.xml.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +@XmlType(propOrder = {"head", "body"}) +@XmlRootElement(name = "html") +public class ExampleHTML { + + private List head = new ArrayList<>(); + + private Body body; + + public ExampleHTML() { } + + public List getHead() { + return head; + } + + @XmlElementWrapper(name = "head") + @XmlElement(name = "meta") + public void setHead(List head) { + this.head = head; + } + + public Body getBody() { + return body; + } + + @XmlElement(name = "body") + public void setBody(Body body) { + this.body = body; + } +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java new file mode 100644 index 0000000000..bc4486b927 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java @@ -0,0 +1,29 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import jakarta.xml.bind.annotation.XmlElement; + +public class Body { + + private CustomElement customElement; + + public CustomElement getCustomElement() { + return customElement; + } + + @XmlElement(name = "p") + public void setCustomElement(CustomElement customElement) { + this.customElement = customElement; + } + + private NestedElement nestedElement; + + public NestedElement getNestedElement() { + return nestedElement; + } + + @XmlElement(name = "div") + public void setNestedElement(NestedElement nestedElement) { + this.nestedElement = nestedElement; + } + +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java new file mode 100644 index 0000000000..7227843f61 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java @@ -0,0 +1,18 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import jakarta.xml.bind.annotation.XmlValue; + +public class CustomElement { + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java new file mode 100644 index 0000000000..9ae7bfea27 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java @@ -0,0 +1,30 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlValue; + +public class Meta { + + private String title; + + public String getTitle() { + return title; + } + + @XmlAttribute(name = "title") + public void setTitle(String title) { + this.title = title; + } + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java new file mode 100644 index 0000000000..0cd22f73df --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java @@ -0,0 +1,17 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import jakarta.xml.bind.annotation.XmlElement; + +public class NestedElement { + + private CustomElement customElement; + + public CustomElement getCustomElement() { + return customElement; + } + + @XmlElement(name = "p") + public void setCustomElement(CustomElement customElement) { + this.customElement = customElement; + } +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java new file mode 100644 index 0000000000..ef489ef643 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java @@ -0,0 +1,20 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml; + +import com.baeldung.xmlhtml.pojo.jaxb.xml.elements.Ancestor; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "xmlexample") +public class XMLExample { + + private Ancestor ancestor; + + @XmlElement(name = "ancestor") + public void setAncestor(Ancestor ancestor) { + this.ancestor = ancestor; + } + + public Ancestor getAncestor() { + return ancestor; + } +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java new file mode 100644 index 0000000000..ab5e762b61 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java @@ -0,0 +1,28 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import jakarta.xml.bind.annotation.XmlElement; + +public class Ancestor { + + private DescendantOne descendantOne; + private DescendantTwo descendantTwo; + + public DescendantOne getDescendantOne() { + return descendantOne; + } + + @XmlElement(name = "descendantOne") + public void setDescendantOne(DescendantOne descendantOne) { + this.descendantOne = descendantOne; + } + + public DescendantTwo getDescendantTwo() { + return descendantTwo; + } + + @XmlElement(name = "descendantTwo") + public void setDescendantTwo(DescendantTwo descendantTwo) { + this.descendantTwo = descendantTwo; + } +} + diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java new file mode 100644 index 0000000000..f4b6ea99d5 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java @@ -0,0 +1,19 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import jakarta.xml.bind.annotation.XmlValue; + +public class DescendantOne { + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} + diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java new file mode 100644 index 0000000000..fb81e26f01 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java @@ -0,0 +1,18 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import jakarta.xml.bind.annotation.XmlValue; + +public class DescendantThree { + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java new file mode 100644 index 0000000000..19c337a142 --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java @@ -0,0 +1,17 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import jakarta.xml.bind.annotation.XmlElement; + +public class DescendantTwo { + + private DescendantThree descendantThree; + + public DescendantThree getDescendantThree() { + return descendantThree; + } + + @XmlElement(name = "descendantThree") + public void setDescendant(DescendantThree descendantThree) { + this.descendantThree = descendantThree; + } +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xmlhtml/stax/StaxTransformer.java b/xml-2/src/main/java/com/baeldung/xmlhtml/stax/StaxTransformer.java new file mode 100644 index 0000000000..d7762f3c1f --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xmlhtml/stax/StaxTransformer.java @@ -0,0 +1,99 @@ +package com.baeldung.xmlhtml.stax; + +import javax.xml.stream.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; + +public class StaxTransformer { + + private Map map; + + public StaxTransformer(String resourcePath) throws IOException, XMLStreamException { + 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 = buildMap(input); + } finally { + if (input != null) { + input.close(); + } + } + } + + public String html() throws XMLStreamException, IOException { + try (Writer output = new StringWriter()) { + XMLStreamWriter writer = XMLOutputFactory + .newInstance() + .createXMLStreamWriter(output); + //Head + writer.writeDTD(""); + writer.writeCharacters(String.format("%n")); + writer.writeStartElement("html"); + writer.writeAttribute("lang", "en"); + writer.writeCharacters(String.format("%n")); + writer.writeStartElement("head"); + writer.writeCharacters(String.format("%n")); + writer.writeDTD(""); + writer.writeCharacters(String.format("%n")); + writer.writeStartElement("title"); + writer.writeCharacters(map.get("heading")); + writer.writeEndElement(); + writer.writeCharacters(String.format("%n")); + writer.writeEndElement(); + writer.writeCharacters(String.format("%n")); + //Body + writer.writeStartElement("body"); + writer.writeCharacters(String.format("%n")); + writer.writeStartElement("p"); + writer.writeCharacters(map.get("from")); + writer.writeEndElement(); + writer.writeCharacters(String.format("%n")); + writer.writeStartElement("p"); + writer.writeCharacters(map.get("content")); + writer.writeEndElement(); + writer.writeCharacters(String.format("%n")); + writer.writeEndElement(); + writer.writeCharacters(String.format("%n")); + writer.writeEndDocument(); + writer.writeCharacters(String.format("%n")); + writer.flush(); + return output.toString(); + } + } + + private Map buildMap(XMLStreamReader input) throws XMLStreamException { + Map tempMap = new HashMap<>(); + while (input.hasNext()) { + input.next(); + if (input.isStartElement()) { + if (input + .getLocalName() + .equals("heading")) { + tempMap.put("heading", input.getElementText()); + } + if (input + .getLocalName() + .equals("from")) { + tempMap.put("from", String.format("from: %s", input.getElementText())); + } + if (input + .getLocalName() + .equals("content")) { + tempMap.put("content", input.getElementText()); + } + } + } + return tempMap; + } + + public Map getMap() { + return map; + } +} diff --git a/xml-2/src/main/resources/customer-binding.xml b/xml-2/src/main/resources/customer-binding.xml new file mode 100644 index 0000000000..c1a80366ef --- /dev/null +++ b/xml-2/src/main/resources/customer-binding.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml-2/src/main/resources/xml/attribute.xml b/xml-2/src/main/resources/xml/attribute.xml new file mode 100644 index 0000000000..c8fa3f1071 --- /dev/null +++ b/xml-2/src/main/resources/xml/attribute.xml @@ -0,0 +1,5 @@ + + + john@email.com + mary@email.com + \ No newline at end of file diff --git a/xml-2/src/main/resources/xml/attribute_expected.xml b/xml-2/src/main/resources/xml/attribute_expected.xml new file mode 100644 index 0000000000..1d5d7b0cea --- /dev/null +++ b/xml-2/src/main/resources/xml/attribute_expected.xml @@ -0,0 +1,5 @@ + + + john@email.com + mary@email.com + \ No newline at end of file diff --git a/xml-2/src/main/resources/xml/in.xml b/xml-2/src/main/resources/xml/in.xml new file mode 100644 index 0000000000..6fcb404012 --- /dev/null +++ b/xml-2/src/main/resources/xml/in.xml @@ -0,0 +1,11 @@ + + + + Yo + + + DustyOrb + + + + \ No newline at end of file diff --git a/xml-2/src/main/resources/xml/jaxb.html b/xml-2/src/main/resources/xml/jaxb.html new file mode 100644 index 0000000000..80b894cff7 --- /dev/null +++ b/xml-2/src/main/resources/xml/jaxb.html @@ -0,0 +1,14 @@ + + + + + + +

descendantOne: Yo

+
+

descendantThree: + DustyOrb +

+
+ + diff --git a/xml-2/src/main/resources/xml/jaxp.html b/xml-2/src/main/resources/xml/jaxp.html new file mode 100644 index 0000000000..5392eef509 --- /dev/null +++ b/xml-2/src/main/resources/xml/jaxp.html @@ -0,0 +1,13 @@ + + + + + +

descendantOne: Yo

+
+

descendantThree: + DustyOrb +

+
+ + diff --git a/xml-2/src/main/resources/xml/stax.html b/xml-2/src/main/resources/xml/stax.html new file mode 100644 index 0000000000..01951dc7de --- /dev/null +++ b/xml-2/src/main/resources/xml/stax.html @@ -0,0 +1,15 @@ + + + + + +

descendantOne: Yo

+
+

+ descendantThree: + DustyOrb + +

+
+ + \ No newline at end of file diff --git a/xml-2/src/main/resources/xmltopdf/data-input.xml b/xml-2/src/main/resources/xmltopdf/data-input.xml new file mode 100644 index 0000000000..385fcf661c --- /dev/null +++ b/xml-2/src/main/resources/xmltopdf/data-input.xml @@ -0,0 +1,26 @@ + + + + + + Death and the Penguin + Andrey Kurkov + 10.99 + + + Kobzar + Taras Shevchenko + 8.50 + + + + + + + Voroshilovgrad + Serhiy Zhadan + 12.99 + + + + diff --git a/xml-2/src/main/resources/xmltopdf/style.xsl b/xml-2/src/main/resources/xmltopdf/style.xsl new file mode 100644 index 0000000000..a0c5fbb49a --- /dev/null +++ b/xml-2/src/main/resources/xmltopdf/style.xsl @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + Bookstore Inventory + + + + + + + + + + Bookstore ID + + + Book ID + + + Title + + + Author + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml-2/src/test/java/com/baeldung/xml/attribute/Dom4jProcessorUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/attribute/Dom4jProcessorUnitTest.java new file mode 100644 index 0000000000..ae385fe62b --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/attribute/Dom4jProcessorUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.xml.attribute; + +import org.dom4j.DocumentException; +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.xpath.XPathExpressionException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.xmlunit.assertj.XmlAssert.assertThat; + +/** + * Unit test for {@link Dom4jTransformer}. + */ +public class Dom4jProcessorUnitTest { + + @Test + public void givenXmlWithAttributes_whenModifyAttribute_thenGetXmlUpdated() throws TransformerFactoryConfigurationError, TransformerException, DocumentException, SAXException { + String path = getClass().getResource("/xml/attribute.xml") + .toString(); + Dom4jTransformer transformer = new Dom4jTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + + String result = transformer.modifyAttribute(attribute, oldValue, newValue); + + assertThat(result).hasXPath("//*[contains(@customer, 'false')]"); + } + + @Test + public void givenTwoXml_whenModifyAttribute_thenGetSimilarXml() throws IOException, TransformerFactoryConfigurationError, TransformerException, URISyntaxException, DocumentException, SAXException { + String path = getClass().getResource("/xml/attribute.xml") + .toString(); + Dom4jTransformer transformer = new Dom4jTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + String expectedXml = new String(Files.readAllBytes((Paths.get(getClass().getResource("/xml/attribute_expected.xml") + .toURI())))); + + String result = transformer + .modifyAttribute(attribute, oldValue, newValue) + .replaceAll("(?m)^[ \t]*\r?\n", "");//Delete extra spaces added by Java 11 + + assertThat(result).and(expectedXml) + .areSimilar(); + } + + @Test + public void givenXmlXee_whenInit_thenThrowException() throws IOException, SAXException, ParserConfigurationException, XPathExpressionException, TransformerFactoryConfigurationError, TransformerException { + String path = getClass().getResource("/xml/xee_attribute.xml") + .toString(); + + assertThatThrownBy(() -> { + + new Dom4jTransformer(path); + + }).isInstanceOf(DocumentException.class); + } + +} diff --git a/xml-2/src/test/java/com/baeldung/xml/attribute/JaxpProcessorUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/attribute/JaxpProcessorUnitTest.java new file mode 100644 index 0000000000..46c954aee0 --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/attribute/JaxpProcessorUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.xml.attribute; + +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.xpath.XPathExpressionException; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.xmlunit.assertj.XmlAssert.assertThat; + +/** + * Unit test for {@link JaxpTransformer}. + */ +public class JaxpProcessorUnitTest { + + @Test + public void givenXmlWithAttributes_whenModifyAttribute_thenGetXmlUpdated() throws IOException, SAXException, ParserConfigurationException, XPathExpressionException, TransformerFactoryConfigurationError, TransformerException { + String path = getClass().getResource("/xml/attribute.xml") + .toString(); + JaxpTransformer transformer = new JaxpTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + + String result = transformer.modifyAttribute(attribute, oldValue, newValue); + + assertThat(result).hasXPath("//*[contains(@customer, 'false')]"); + } + + @Test + public void givenXmlXee_whenInit_thenThrowException() throws IOException, SAXException, ParserConfigurationException, XPathExpressionException, TransformerFactoryConfigurationError, TransformerException { + String path = getClass().getResource("/xml/xee_attribute.xml") + .toString(); + + assertThatThrownBy(() -> { + + new JaxpTransformer(path); + + }).isInstanceOf(SAXParseException.class); + } + +} diff --git a/xml-2/src/test/java/com/baeldung/xml/attribute/JooxProcessorUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/attribute/JooxProcessorUnitTest.java new file mode 100644 index 0000000000..3a249e6dd7 --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/attribute/JooxProcessorUnitTest.java @@ -0,0 +1,69 @@ +package com.baeldung.xml.attribute; + +import org.junit.jupiter.api.Test; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.xpath.XPathExpressionException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.xmlunit.assertj.XmlAssert.assertThat; + +/** + * Unit test for {@link JooxTransformer}. + */ +public class JooxProcessorUnitTest { + + @Test + public void givenXmlWithAttributes_whenModifyAttribute_thenGetXmlUpdated() throws IOException, SAXException, TransformerFactoryConfigurationError { + String path = getClass().getResource("/xml/attribute.xml") + .toString(); + JooxTransformer transformer = new JooxTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + + String result = transformer.modifyAttribute(attribute, oldValue, newValue); + + assertThat(result).hasXPath("//*[contains(@customer, 'false')]"); + } + + @Test + public void givenTwoXml_whenModifyAttribute_thenGetSimilarXml() throws IOException, TransformerFactoryConfigurationError, URISyntaxException, SAXException { + String path = getClass().getResource("/xml/attribute.xml") + .toString(); + JooxTransformer transformer = new JooxTransformer(path); + String attribute = "customer"; + String oldValue = "true"; + String newValue = "false"; + String expectedXml = new String(Files.readAllBytes((Paths.get(getClass().getResource("/xml/attribute_expected.xml") + .toURI())))); + + String result = transformer + .modifyAttribute(attribute, oldValue, newValue) + .replaceAll("(?m)^[ \t]*\r?\n", "");//Delete extra spaces added by Java 11 + + assertThat(result).and(expectedXml) + .areSimilar(); + } + + @Test + public void givenXmlXee_whenInit_thenThrowException() throws IOException, SAXException, ParserConfigurationException, XPathExpressionException, TransformerFactoryConfigurationError, TransformerException { + String path = getClass().getResource("/xml/xee_attribute.xml") + .toString(); + + assertThatThrownBy(() -> { + + new JooxTransformer(path); + + }).isInstanceOf(SAXParseException.class); + } + +} diff --git a/xml-2/src/test/java/com/baeldung/xml/jibx/CustomerUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/jibx/CustomerUnitTest.java new file mode 100644 index 0000000000..9a4b5bc14b --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/jibx/CustomerUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.xml.jibx; + +import org.jibx.runtime.BindingDirectory; +import org.jibx.runtime.IBindingFactory; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.io.InputStream; + +import static junit.framework.Assert.assertEquals; + +public class CustomerUnitTest { + + @Test + public void whenUnmarshalXML_ThenFieldsAreMapped() throws JiBXException, FileNotFoundException { + IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); + IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); + Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); + + assertEquals("Stefan Jaeger", customer.getPerson().getName()); + assertEquals("Davos Dorf", customer.getCity()); + + } + + @Test + public void WhenUnmarshal_ThenMappingInherited() throws JiBXException, FileNotFoundException { + IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); + IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); + Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); + + assertEquals(12345, customer.getPerson().getCustomerId()); + + } + + @Test + public void WhenUnmarshal_ThenPhoneMappingRead() throws JiBXException, FileNotFoundException { + IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); + IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); + Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); + + assertEquals("234678", customer.getHomePhone().getNumber()); + + } +} diff --git a/xml-2/src/test/java/com/baeldung/xml/xml2pdf/XmlToPdfConverterUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/xml2pdf/XmlToPdfConverterUnitTest.java new file mode 100644 index 0000000000..6d4a4f8bda --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/xml2pdf/XmlToPdfConverterUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.xml.xml2pdf; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class XmlToPdfConverterUnitTest { + + private static final String BASE_PATH = "src/main/resources/xmltopdf/"; + + private static final String STYLE_XSL = BASE_PATH + "style.xsl"; + private static final String DATA_XML_INPUT = BASE_PATH + "data-input.xml"; + private static final String DATA_PDF_OUTPUT = BASE_PATH + "data-output.pdf"; + + // Comment out this method if you need to keep the outputted PDF file. + @AfterEach + public void teardown() { + new File(DATA_PDF_OUTPUT).delete(); + } + + @Test + public void givenXmlFile_whenConvertToPdfUsingFop_thenPdfGenerated() throws Exception { + // Execute XML to PDF conversion + XmlToPdfConverter.convertXMLtoPDFUsingFop(DATA_XML_INPUT, STYLE_XSL, DATA_PDF_OUTPUT); + // Check if PDF file was created + File pdfFile = new File(DATA_PDF_OUTPUT); + assertTrue(pdfFile.exists()); + assertTrue(pdfFile.isFile()); + assertTrue(pdfFile.length() > 0); + + } + + @Test + public void givenXmlFile_whenConvertToPdfUsingIText_thenPdfGenerated() throws Exception { + // Execute XML to PDF conversion + XmlToPdfConverter.convertXMLtoPDFUsingIText(DATA_XML_INPUT, DATA_PDF_OUTPUT); + // Check if PDF file was created + File pdfFile = new File(DATA_PDF_OUTPUT); + assertTrue(pdfFile.exists()); + assertTrue(pdfFile.isFile()); + assertTrue(pdfFile.length() > 0); + } + +}