如何在 Java 中將 XML 解析為 HashMap
一、簡介
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 以及從 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);
讓我們使用 XStream 的fromXML()
方法**將 XML 字串解析為Employee
物件列表**:
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 依賴項:
<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 是用於 XML 綁定的 Java 架構,它支援使用註解將 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
,用於管理 XML 資料和 Java 物件之間的綁定:**
JAXBContext context = JAXBContext.newInstance(Employees.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Employees employees = (Employees) unmarshaller.unmarshal(new StringReader(xmlData));
Unmarshaller
負責根據類別中 JAXB 註解定義的對應將 XML 資料轉換為物件。
我們將員工清單轉換為Map
,並使用id
作為鍵,使用employee
物件本身作為值,使用 Java Streams,如前面部分中所做的那樣。
7. 使用 DOM 解析器和 XPath 解析 XML
DOM Parser 是一種無需任何第三方函式庫即可解析 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 文件中的employees
元素中的所有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);
}
八、結論
在本文中,我們探討了將 XML 解析為HashMap
的多種方法,HashMap 是用於儲存鍵值對的基本資料結構。
XStream 和 Underscore 以其最少的配置,非常適合簡單的 XML 解析。
Jackson 將 XML 元素無縫地對應到 Java 對象,提供靈活性和易用性。
JAXB 及其註釋在需要標準化映射方法的場景中表現出色。
同時,使用 XPath 的 DOM 解析提供了對 XML 元素的細粒度控制。
與往常一樣,範例的程式碼可以在 GitHub 上找到。