Skip to content

Commit 401b1f6

Browse files
authored
BAEL-7016 (eugenp#15050)
* initial commit * initial commit * code cleanup * code cleanup * code cleanup * code cleanup * code review comments addressed * pom version * code review comments * formatting updated * updated as per code review comments
1 parent 743d60d commit 401b1f6

File tree

6 files changed

+271
-0
lines changed

6 files changed

+271
-0
lines changed

xml-2/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@
4646
<artifactId>underscore</artifactId>
4747
<version>${underscore.version}</version>
4848
</dependency>
49+
<dependency>
50+
<groupId>com.thoughtworks.xstream</groupId>
51+
<artifactId>xstream</artifactId>
52+
<version>${xstream.version}</version>
53+
</dependency>
54+
<dependency>
55+
<groupId>com.sun.xml.bind</groupId>
56+
<artifactId>jaxb-impl</artifactId>
57+
<version>${jaxb.version}</version>
58+
</dependency>
4959
<dependency>
5060
<groupId>org.apache.xmlbeans</groupId>
5161
<artifactId>xmlbeans</artifactId>
@@ -82,6 +92,8 @@
8292
<dom4j.version>2.1.3</dom4j.version>
8393
<json.version>20230227</json.version>
8494
<underscore.version>1.89</underscore.version>
95+
<xstream.version>1.4.18</xstream.version>
96+
<jaxb.version>2.3.3</jaxb.version>
8597
</properties>
8698

8799
</project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.baeldung.xml.tohashmap;
2+
3+
public class Employee {
4+
private String id;
5+
private String firstName;
6+
private String lastName;
7+
8+
public String getId() {
9+
return id;
10+
}
11+
12+
public void setId(String id) {
13+
this.id = id;
14+
}
15+
16+
public String getFirstName() {
17+
return firstName;
18+
}
19+
20+
public void setFirstName(String firstName) {
21+
this.firstName = firstName;
22+
}
23+
24+
public String getLastName() {
25+
return lastName;
26+
}
27+
28+
public void setLastName(String lastName) {
29+
this.lastName = lastName;
30+
}
31+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.baeldung.xml.tohashmap;
2+
3+
import java.util.List;
4+
5+
import javax.xml.bind.annotation.XmlElement;
6+
import javax.xml.bind.annotation.XmlRootElement;
7+
8+
@XmlRootElement(name = "employees")
9+
public class Employees {
10+
11+
private List<Employee> employeeList;
12+
13+
@XmlElement(name = "employee")
14+
public List<Employee> getEmployeeList() {
15+
return employeeList;
16+
}
17+
18+
public void setEmployeeList(List<Employee> employeeList) {
19+
this.employeeList = employeeList;
20+
}
21+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.baeldung.xml.tohashmap;
2+
3+
import java.io.IOException;
4+
import java.io.StringReader;
5+
import java.util.HashMap;
6+
import java.util.LinkedHashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.function.Function;
10+
import java.util.stream.Collectors;
11+
12+
import javax.xml.bind.JAXBContext;
13+
import javax.xml.bind.JAXBException;
14+
import javax.xml.bind.Unmarshaller;
15+
import javax.xml.parsers.DocumentBuilder;
16+
import javax.xml.parsers.DocumentBuilderFactory;
17+
import javax.xml.parsers.ParserConfigurationException;
18+
import javax.xml.xpath.XPath;
19+
import javax.xml.xpath.XPathConstants;
20+
import javax.xml.xpath.XPathExpression;
21+
import javax.xml.xpath.XPathExpressionException;
22+
import javax.xml.xpath.XPathFactory;
23+
24+
import org.w3c.dom.Document;
25+
import org.w3c.dom.Element;
26+
import org.w3c.dom.NodeList;
27+
import org.xml.sax.InputSource;
28+
import org.xml.sax.SAXException;
29+
30+
import com.fasterxml.jackson.core.JsonProcessingException;
31+
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
32+
import com.github.underscore.U;
33+
import com.thoughtworks.xstream.XStream;
34+
import com.thoughtworks.xstream.security.AnyTypePermission;
35+
36+
public class XmlToHashMap {
37+
38+
public Map<String, Employee> xmlToHashMapUsingXstream(String xml) {
39+
XStream xStream = new XStream();
40+
xStream.alias("employees", List.class);
41+
xStream.alias("employee", Employee.class);
42+
xStream.addPermission(AnyTypePermission.ANY);
43+
List<Employee> employees = (List<Employee>) xStream.fromXML(xml);
44+
return employees.stream()
45+
.collect(Collectors.toMap(Employee::getId, Function.identity()));
46+
}
47+
48+
public Map<String, Employee> xmlToHashMapUsingUnderscore(String xml) {
49+
Map<String, Employee> employeeMap = new HashMap<>();
50+
Map<String, Object> employeeList = (Map<String, Object>) U.fromXmlMap(xml)
51+
.get("employees");
52+
List<LinkedHashMap<String, String>> list = (List<LinkedHashMap<String, String>>) employeeList.get("employee");
53+
parseXmlToMap(employeeMap, list);
54+
return employeeMap;
55+
}
56+
57+
public Map<String, Employee> xmlToHashMapUsingJackson(String xml) throws JsonProcessingException {
58+
XmlMapper xmlMapper = new XmlMapper();
59+
Map<String, Employee> employeeMap = new HashMap<>();
60+
Map<String, Object> map = xmlMapper.readValue(xml, Map.class);
61+
List<LinkedHashMap<String, String>> list = (List<LinkedHashMap<String, String>>) map.get("employee");
62+
parseXmlToMap(employeeMap, list);
63+
return employeeMap;
64+
}
65+
66+
public Map<String, Employee> xmlToHashMapUsingJAXB(String xmlData) throws JAXBException {
67+
JAXBContext context = JAXBContext.newInstance(Employees.class);
68+
Unmarshaller unmarshaller = context.createUnmarshaller();
69+
Employees employees = (Employees) unmarshaller.unmarshal(new StringReader(xmlData));
70+
return employees.getEmployeeList()
71+
.stream()
72+
.collect(Collectors.toMap(Employee::getId, Function.identity()));
73+
}
74+
75+
public Map<String, Employee> xmlToHashMapUsingDOMParserXpath(String xmlData) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
76+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
77+
DocumentBuilder builder = factory.newDocumentBuilder();
78+
Document doc = builder.parse(new InputSource(new StringReader(xmlData)));
79+
80+
XPathFactory xPathfactory = XPathFactory.newInstance();
81+
XPath xpath = xPathfactory.newXPath();
82+
XPathExpression xPathExpr = xpath.compile("/employees/employee");
83+
NodeList nodes = (NodeList) xPathExpr.evaluate(doc, XPathConstants.NODESET);
84+
85+
HashMap<String, Employee> map = new HashMap<>();
86+
for (int i = 0; i < nodes.getLength(); i++) {
87+
Element node = (Element) nodes.item(i);
88+
Employee employee = new Employee();
89+
employee.setId(node.getElementsByTagName("id")
90+
.item(0)
91+
.getTextContent());
92+
employee.setFirstName(node.getElementsByTagName("firstName")
93+
.item(0)
94+
.getTextContent());
95+
employee.setLastName(node.getElementsByTagName("lastName")
96+
.item(0)
97+
.getTextContent());
98+
map.put(employee.getId(), employee);
99+
}
100+
return map;
101+
}
102+
103+
private static void parseXmlToMap(Map<String, Employee> employeeMap, List<LinkedHashMap<String, String>> list) {
104+
list.forEach(empMap -> {
105+
Employee employee = new Employee();
106+
for (Map.Entry<String, String> key : empMap.entrySet()) {
107+
switch (key.getKey()) {
108+
case "id":
109+
employee.setId(key.getValue());
110+
break;
111+
case "firstName":
112+
employee.setFirstName(key.getValue());
113+
break;
114+
case "lastName":
115+
employee.setLastName(key.getValue());
116+
break;
117+
default:
118+
break;
119+
}
120+
}
121+
employeeMap.put(employee.getId(), employee);
122+
});
123+
}
124+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<employees>
2+
<employee>
3+
<id>654</id>
4+
<firstName>John</firstName>
5+
<lastName>Doe</lastName>
6+
</employee>
7+
<employee>
8+
<id>776</id>
9+
<firstName>Steve</firstName>
10+
<lastName>Smith</lastName>
11+
</employee>
12+
</employees>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.baeldung.xml.tohashmap;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Paths;
6+
import java.util.ArrayList;
7+
import java.util.Map;
8+
9+
import javax.xml.bind.JAXBException;
10+
11+
import org.junit.jupiter.api.Assertions;
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
15+
class XmlToHashMapUnitTest {
16+
17+
private XmlToHashMap xmlToHashMap;
18+
private static final String TEST_XML_PATH = "src/main/resources/xml/xmltohashmap/test.xml";
19+
20+
@BeforeEach
21+
void setUp() {
22+
xmlToHashMap = new XmlToHashMap();
23+
}
24+
25+
@Test
26+
void whenUsingXstream_thenHashMapShouldBeCreated() throws IOException {
27+
Map<String, Employee> employeeMap = xmlToHashMap.xmlToHashMapUsingXstream(getXml());
28+
verify(employeeMap);
29+
}
30+
31+
@Test
32+
void whenUsingUnderscore_thenHashMapShouldBeCreated() throws IOException {
33+
Map<String, Employee> employeeMap = xmlToHashMap.xmlToHashMapUsingUnderscore(getXml());
34+
verify(employeeMap);
35+
}
36+
37+
@Test
38+
void whenUsingJackson_thenHashMapShouldBeCreated() throws IOException {
39+
Map<String, Employee> employeeMap = xmlToHashMap.xmlToHashMapUsingJackson(getXml());
40+
verify(employeeMap);
41+
}
42+
43+
@Test
44+
void whenUsingJAXB_thenHashMapShouldBeCreated() throws IOException, JAXBException {
45+
Map<String, Employee> employeeMap = xmlToHashMap.xmlToHashMapUsingJAXB(getXml());
46+
verify(employeeMap);
47+
}
48+
49+
@Test
50+
void whenUsingDOMXpath_thenHashMapShouldBeCreated() throws Exception {
51+
Map<String, Employee> employeeMap = xmlToHashMap.xmlToHashMapUsingDOMParserXpath(getXml());
52+
verify(employeeMap);
53+
}
54+
55+
private void verify(Map<String, Employee> employeeMap) {
56+
Employee employee1 = employeeMap.get("654");
57+
Employee employee2 = employeeMap.get("776");
58+
Assertions.assertEquals("John", employee1
59+
.getFirstName());
60+
Assertions.assertEquals("Doe", employee1
61+
.getLastName());
62+
Assertions.assertEquals("Steve", employee2
63+
.getFirstName());
64+
Assertions.assertEquals("Smith", employee2
65+
.getLastName());
66+
}
67+
68+
private String getXml() throws IOException {
69+
return new String(Files.readAllBytes(Paths.get(TEST_XML_PATH)));
70+
}
71+
}

0 commit comments

Comments
 (0)