1. 簡介
XML 是互聯網上數據交換的一種流行格式。在處理 XML 數據時,通常會將它轉換為更易於使用的格式,以便進行進一步的處理。
在本教程中,我們將探討將 XML 解析為 HashMap 的不同方法,HashMap 是一種高效的數據檢索和操作數據結構。
2. 安裝配置
我們將使用不同的庫,將以下 XML 解析為 HashMap:
<employees>
<employee>
<id>654</id>
<firstName>John</firstName>
<lastName>Doe</lastName>
</employee>
<employee>
<id>776</id>
<firstName>Steve</firstName>
<lastName>Smith</lastName>
</employee>
</employees>
讓我們使用下面的POJO來存儲XML數據:
public class Employee {
private String id;
private String firstName;
private String lastName;
// standard getters and setters
}我們將會設置一個通用的測試方法,以驗證所有用例的結果:
void verify(Map<String, Employee> 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());
}
3. 使用 XStream 解析 XML
XStream 是一個第三方庫,用於將對象序列化和反序列化到和從 XML 中。 只需進行最小配置,XStream 就能賦予我們解析 XML 數據的能力。
我們將使用下面的 Maven 依賴項:
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.18</version>
</dependency>
我們將會創建一個新的 XStream 實例,並設置一些別名:
XStream xStream=new XStream();
xStream.alias("employees", List.class);
xStream.alias("employee", Employee.class);我們為 employees 元素設置了別名,以便將其解釋為 List。我們還為 employee 元素設置了別名,以便將其解釋為 Employee 對象。
我們將 添加權限,允許任何類型被反序列化,這是 XStream 用於將 XML 反序列化為對象列表所必需的:
xStream.addPermission(AnyTypePermission.ANY);讓我們解析 XML 字符串為包含 Employee 對象的列表,使用 XStream 的 fromXML() 方法:
List<Employee> employees = (List<Employee>) xStream.fromXML(xml);我們隨後將員工列表轉換為一個 Map,使用 id 作為鍵,並將 employee 對象本身作為值,使用流式操作:
employees.stream().collect(Collectors.toMap(Employee::getId, Function.identity()))4. 使用 Underscore-java 解析 XML
Underscore-java 是一套實用工具庫,提供廣泛的函數式編程和數據操作函數。它需要 Java 11 或更高版本。
我們將使用以下 Maven 依賴項:
<dependency>
<groupId>com.github.javadev</groupId>
<artifactId>underscore</artifactId>
<version>1.89</version>
</dependency>
讓我們使用 Underscore-java 的 fromXmlMap() 函數來解析 XML 字符串並將其轉換為嵌套的映射結構:
Map<String, Object> employeeList = (Map<String, Object>)U.fromXmlMap(xml).get("employees");
List<LinkedHashMap<String, String>> list=(List<LinkedHashMap<String,String>>)employeeList.get("employee");
parseXmlToMap(employeeMap, list);我們從結果映射中提取 employees 元素。然後,我們將結果的 LinkedHashMap 轉換為 HashMap:
void parseXmlToMap(Map<String, Employee> employeeMap, List<LinkedHashMap<String, String>> list) {
list.forEach(empMap -> {
Employee employee = new Employee();
for (Map.Entry<String, String> 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);
});
}一旦我們獲得了嵌套的映射結構,我們就會遍歷列表中每個 LinkedHashMap,代表每個員工的數據。然後我們創建一個新的 Employee 對象,並根據映射中的數據填充其字段。
5. 使用 Jackson 解析 XML
Jackson 是一個 Java 庫,它通過使用註解或自定義配置,無縫地將 XML 元素和屬性映射到 Java 對象。
我們將使用以下 Maven 依賴項:Maven 依賴項。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
XmlMapper 是一個專門用於 XML 數據的映射器,它允許我們讀取和寫入 XML。
XmlMapper xmlMapper = new XmlMapper();
Map<String, Object> map= xmlMapper.readValue(xml, Map.class);我們讀取 XML 數據並將其轉換為鍵值對的映射。 Jackson 動態解析 XML 並構建相應的映射結構。 我們從映射中提取員工元素的列表:
List<LinkedHashMap<String, String>> list= (List<LinkedHashMap<String, String>>) map.get("employee");我們隨後可以使用先前定義的相同的 parseXmlToMap()方法來提取員工的映射。
6. 使用 JAXB 解析 XML
JAXB 是 Java 架構 XML 綁定,它提供了一個綁定框架,該框架使用註解將 XML 元素和屬性映射到 Java。
我們將使用以下 Maven 依賴項:Maven 依賴項
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.3</version>
</dependency>
讓我們為 Employees 類設置以下註解,以幫助將其綁定到 Java 對象:
@XmlRootElement(name = "employees")
public class Employees {
private List<Employee> employeeList;
@XmlElement(name = "employee")
public List<Employee> getEmployeeList() {
return employeeList;
}
// standard setter
}讓我們創建一個 JAXBContext,用於管理 XML 數據與 Java 對象之間的綁定:
JAXBContext context = JAXBContext.newInstance(Employees.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Employees employees = (Employees) unmarshaller.unmarshal(new StringReader(xmlData));Unmarshaller負責根據JAXB類中定義的映射,將XML數據轉換為對象。
我們使用Java Streams,將員工列表轉換為一個Map,其中id作為鍵,employee對象本身作為值,如前面章節所示。
7. 使用 DOM 解析器和 XPath 解析 XML
DOM 解析器是一種無需任何第三方庫即可解析 XML 的方法。DOM 解析器支持 XPath,用於在 XML 中進行導航並提取數據。
讓我們創建一個用於生產 DOM 解析器的工廠,該工廠將用於解析 XML 文檔:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlData)));我們使用負責構建 XML 的 DOM 表示的構建器,將 XML 數據解析為 Document 對象。
然後,我們設置一個 XPath 實例來查詢 DOM:
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression xPathExpr = xpath.compile("/employees/employee");我們配置一個 XPath 實例,該實例編譯一個 XPath 表達式,用於在 XML 文檔中選擇所有 employee 元素,這些元素位於 employees 元素內。
讓我們評估 XPath 表達式在 doc 上檢索一個包含所有匹配的員工元素 NodeList。
NodeList nodes = (NodeList) xPathExpr.evaluate(doc, XPathConstants.NODESET);我們遍歷 NodeList,並將員工元素提取到一個 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);
}
8. 結論
在本文中,我們探討了將 XML 解析為 HashMap 的各種方法,HashMap 是一種用於存儲鍵值對的基本數據結構。
XStream 和 Underscore,由於其配置的簡單性,非常適合進行簡單的 XML 解析。
Jackson 可以無縫地將 XML 元素映射到 Java 對象,提供靈活性和易用性。
JAXB,憑藉其註解,在需要標準映射方法的情況下表現出色。
同時,使用 DOM 解析和 XPath 提供了對 XML 元素進行精細控制的能力。