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);
我們將為 XML 中的 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 對象本身作為值,使用 streams:
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’s 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 依賴項:
<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 依賴項:
<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,該上下文用於管理 Java 對象和 XML 數據之間的綁定:
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 作為鍵,員工對象本身作為值,如之前所述。
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 元素內的所有 employee 元素。
讓我們在 doc 上評估 XPath 表達式,以檢索一個 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 元素進行精細控制。