diff --git a/xml-2/pom.xml b/xml-2/pom.xml index 0f94588ba0..ccb84e1687 100644 --- a/xml-2/pom.xml +++ b/xml-2/pom.xml @@ -46,6 +46,16 @@ underscore ${underscore.version} + + com.thoughtworks.xstream + xstream + ${xstream.version} + + + com.sun.xml.bind + jaxb-impl + ${jaxb.version} + org.apache.xmlbeans xmlbeans @@ -82,6 +92,8 @@ 2.1.3 20230227 1.89 + 1.4.18 + 2.3.3 diff --git a/xml-2/src/main/java/com/baeldung/xml/tohashmap/Employee.java b/xml-2/src/main/java/com/baeldung/xml/tohashmap/Employee.java new file mode 100644 index 0000000000..c9c40e743a --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/tohashmap/Employee.java @@ -0,0 +1,31 @@ +package com.baeldung.xml.tohashmap; + +public class Employee { + private String id; + private String firstName; + private String lastName; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/xml-2/src/main/java/com/baeldung/xml/tohashmap/Employees.java b/xml-2/src/main/java/com/baeldung/xml/tohashmap/Employees.java new file mode 100644 index 0000000000..d2f2276e5c --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/tohashmap/Employees.java @@ -0,0 +1,21 @@ +package com.baeldung.xml.tohashmap; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "employees") +public class Employees { + + private List employeeList; + + @XmlElement(name = "employee") + public List getEmployeeList() { + return employeeList; + } + + public void setEmployeeList(List employeeList) { + this.employeeList = employeeList; + } +} \ No newline at end of file diff --git a/xml-2/src/main/java/com/baeldung/xml/tohashmap/XmlToHashMap.java b/xml-2/src/main/java/com/baeldung/xml/tohashmap/XmlToHashMap.java new file mode 100644 index 0000000000..ec651486ac --- /dev/null +++ b/xml-2/src/main/java/com/baeldung/xml/tohashmap/XmlToHashMap.java @@ -0,0 +1,124 @@ +package com.baeldung.xml.tohashmap; + +import java.io.IOException; +import java.io.StringReader; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.github.underscore.U; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.security.AnyTypePermission; + +public class XmlToHashMap { + + public Map xmlToHashMapUsingXstream(String xml) { + XStream xStream = new XStream(); + xStream.alias("employees", List.class); + xStream.alias("employee", Employee.class); + xStream.addPermission(AnyTypePermission.ANY); + List employees = (List) xStream.fromXML(xml); + return employees.stream() + .collect(Collectors.toMap(Employee::getId, Function.identity())); + } + + public Map xmlToHashMapUsingUnderscore(String xml) { + Map employeeMap = new HashMap<>(); + Map employeeList = (Map) U.fromXmlMap(xml) + .get("employees"); + List> list = (List>) employeeList.get("employee"); + parseXmlToMap(employeeMap, list); + return employeeMap; + } + + public Map xmlToHashMapUsingJackson(String xml) throws JsonProcessingException { + XmlMapper xmlMapper = new XmlMapper(); + Map employeeMap = new HashMap<>(); + Map map = xmlMapper.readValue(xml, Map.class); + List> list = (List>) map.get("employee"); + parseXmlToMap(employeeMap, list); + return employeeMap; + } + + public Map xmlToHashMapUsingJAXB(String xmlData) throws JAXBException { + JAXBContext context = JAXBContext.newInstance(Employees.class); + Unmarshaller unmarshaller = context.createUnmarshaller(); + Employees employees = (Employees) unmarshaller.unmarshal(new StringReader(xmlData)); + return employees.getEmployeeList() + .stream() + .collect(Collectors.toMap(Employee::getId, Function.identity())); + } + + public Map xmlToHashMapUsingDOMParserXpath(String xmlData) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(new InputSource(new StringReader(xmlData))); + + XPathFactory xPathfactory = XPathFactory.newInstance(); + XPath xpath = xPathfactory.newXPath(); + XPathExpression xPathExpr = xpath.compile("/employees/employee"); + NodeList nodes = (NodeList) xPathExpr.evaluate(doc, XPathConstants.NODESET); + + HashMap map = new HashMap<>(); + for (int i = 0; i < nodes.getLength(); i++) { + Element node = (Element) nodes.item(i); + Employee employee = new Employee(); + employee.setId(node.getElementsByTagName("id") + .item(0) + .getTextContent()); + employee.setFirstName(node.getElementsByTagName("firstName") + .item(0) + .getTextContent()); + employee.setLastName(node.getElementsByTagName("lastName") + .item(0) + .getTextContent()); + map.put(employee.getId(), employee); + } + return map; + } + + private static void parseXmlToMap(Map employeeMap, List> list) { + list.forEach(empMap -> { + Employee employee = new Employee(); + for (Map.Entry key : empMap.entrySet()) { + switch (key.getKey()) { + case "id": + employee.setId(key.getValue()); + break; + case "firstName": + employee.setFirstName(key.getValue()); + break; + case "lastName": + employee.setLastName(key.getValue()); + break; + default: + break; + } + } + employeeMap.put(employee.getId(), employee); + }); + } +} diff --git a/xml-2/src/main/resources/xml/xmltohashmap/test.xml b/xml-2/src/main/resources/xml/xmltohashmap/test.xml new file mode 100644 index 0000000000..ef0d12e2af --- /dev/null +++ b/xml-2/src/main/resources/xml/xmltohashmap/test.xml @@ -0,0 +1,12 @@ + + + 654 + John + Doe + + + 776 + Steve + Smith + + \ No newline at end of file diff --git a/xml-2/src/test/java/com/baeldung/xml/tohashmap/XmlToHashMapUnitTest.java b/xml-2/src/test/java/com/baeldung/xml/tohashmap/XmlToHashMapUnitTest.java new file mode 100644 index 0000000000..5e05dd3ccb --- /dev/null +++ b/xml-2/src/test/java/com/baeldung/xml/tohashmap/XmlToHashMapUnitTest.java @@ -0,0 +1,71 @@ +package com.baeldung.xml.tohashmap; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Map; + +import javax.xml.bind.JAXBException; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class XmlToHashMapUnitTest { + + private XmlToHashMap xmlToHashMap; + private static final String TEST_XML_PATH = "src/main/resources/xml/xmltohashmap/test.xml"; + + @BeforeEach + void setUp() { + xmlToHashMap = new XmlToHashMap(); + } + + @Test + void whenUsingXstream_thenHashMapShouldBeCreated() throws IOException { + Map employeeMap = xmlToHashMap.xmlToHashMapUsingXstream(getXml()); + verify(employeeMap); + } + + @Test + void whenUsingUnderscore_thenHashMapShouldBeCreated() throws IOException { + Map employeeMap = xmlToHashMap.xmlToHashMapUsingUnderscore(getXml()); + verify(employeeMap); + } + + @Test + void whenUsingJackson_thenHashMapShouldBeCreated() throws IOException { + Map employeeMap = xmlToHashMap.xmlToHashMapUsingJackson(getXml()); + verify(employeeMap); + } + + @Test + void whenUsingJAXB_thenHashMapShouldBeCreated() throws IOException, JAXBException { + Map employeeMap = xmlToHashMap.xmlToHashMapUsingJAXB(getXml()); + verify(employeeMap); + } + + @Test + void whenUsingDOMXpath_thenHashMapShouldBeCreated() throws Exception { + Map employeeMap = xmlToHashMap.xmlToHashMapUsingDOMParserXpath(getXml()); + verify(employeeMap); + } + + private void verify(Map employeeMap) { + Employee employee1 = employeeMap.get("654"); + Employee employee2 = employeeMap.get("776"); + Assertions.assertEquals("John", employee1 + .getFirstName()); + Assertions.assertEquals("Doe", employee1 + .getLastName()); + Assertions.assertEquals("Steve", employee2 + .getFirstName()); + Assertions.assertEquals("Smith", employee2 + .getLastName()); + } + + private String getXml() throws IOException { + return new String(Files.readAllBytes(Paths.get(TEST_XML_PATH))); + } +}