我彻底搜索了我的问题的答案,但没有得到它。我的任务就是这样的。我有一个 XML:
<?xml version="1.0" encoding="utf-8" ?>
<users>
<user id="1">
<login>james.bond</login>
<password>12345</password>
<enabled>true</enabled>
</user>
<user id="2">
<login>john.doe</login>
<password>67890</password>
<enabled>false</enabled>
</user>
</users>
我想将它解析为 HashMap,其中键和值应该是这样的(通过句点的节点名称作为键,这些节点的值作为映射中的值):
K: users.user.1.login V: james.bond
K: users.user.1.password V: 12345
等等...
就在我拥有的那一刻:
public Map<String, String> parse(File file) {
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
dbf.setIgnoringComments(true);
doc = db.parse(file);
} catch (ParserConfigurationException pce) {
System.out.println("Parser was not configured properly [LOG IT!]");
} catch (IOException io) {
System.out.println("Cannot read input file [LOG IT!]");
} catch (SAXException se) {
System.out.println("Problem parsing the file [LOG I!]");
} catch (IllegalArgumentException ae) {
System.out.println("Please specify an XML source [LOG IT!]");
}
Element root = doc.getDocumentElement();
return stepThrough(root);
}
private Map<String, String> stepThrough(Node node) {
String nodeName = node.getNodeName();
if (!nodeName.equals("#text")) {
buildedKey.append(nodeName).append(".");
}
if (node.getNodeValue() != null && !node.getNodeValue().matches("^\\W*$")) {
parsedMap.put(buildedKey.toString(),node.getNodeValue());
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.hasAttributes()) {
NamedNodeMap startAttr = node.getAttributes();
for (int i = 0; i < startAttr.getLength(); i++) {
Node attr = startAttr.item(i);
buildedKey.append(attr.getNodeValue()).append(".");
}
}
}
for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
stepThrough(child);
}
return parsedMap;
}
例如,我的 map 中有最后一个键: users.user.1.login.password.enabled.user.2.login.password.enabled
换句话说,所有节点名称都是串联的。
你愿意帮助我吗?谢谢!
P.S.:我有一个限制,我不能使用像 XStream 这样的库...
最佳答案
问题是您在所有遍历中使用相同的全局buildedKey
,并且当您从stepThrough
返回时,您没有删除添加的部分。简单的解决方案是将 buildedKey
作为参数传递,而不是使用全局变量:
private Map<String, String> stepThrough(Node node, String buildedKey) {
String nodeName = node.getNodeName();
if (!nodeName.equals("#text")) {
buildedKey += nodeName + ".";
}
if (node.getNodeValue() != null && !node.getNodeValue().matches("^\\W*$")) {
parsedMap.put(buildedKey,node.getNodeValue());
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.hasAttributes()) {
NamedNodeMap startAttr = node.getAttributes();
for (int i = 0; i < startAttr.getLength(); i++) {
Node attr = startAttr.item(i);
buildedKey += attr.getNodeValue() + ".";
}
}
}
for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
stepThrough(child, buildedKey);
}
return parsedMap;
}
此外,您最好使用 String
作为 buildedKey
而不是 StringBuilder
,因为 String
是不可变的,而您不可以想要破坏一个节点中的builtKey并在另一个节点中使用相同的破坏 key 。
关于java - 使用 DOM 将 XML 解析为 HashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14676423/