引用maven
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
XPath语法
基本格式
- 斜杠(/)作为路径内部的分割符。
- “.”表示当前节点
- “..”表示当前节点的父节点
选择节点
- nodename(节点名称):表示选择该节点的所有子节点
- “/”:表示选择根节点
- “//”:表示选择任意位置的某个节点
- “@”: 表示选择某个属性
常用表达式
//node
选择所有node节点node1//node2
选择所有属于node1后代节点的node2,不管是不是直接的父子关系//node[@attribute]
选择具有attribute属性的所有node节点//node[@attribute='name']
选择具有attribute属性并且属性值等于name的所有node节点//node1[node2]
选择含有子节点node2的所有node1节点./node
选择当前节点下的所有node节点//node[@name='a' and @age='18']
选择具有name属性并且值等于a以及具有age属性并且值等于18的所有node节点//node[not(@name)]
选择没有name属性的所有node节点//node[not(@name or @age)]
选择不同时存在name和age属性的所有node节点//node1[not[node2]]
选择不含有node2子节点的所有node1节点
dom4j使用
命名空间
SAXReader sax = new SAXReader();
//声明一个map用于保存命名空间
Map<String,String> uris = new HashMap<String, String>();
//给命名空间取一个别名
uris.put("a", "http://test.aaa.cn");
//设置命名空间后再读取xml文档
sax.getDocumentFactory().setXPathNamespaceURIs(uris);
Document dom = sax.read("./xml2/a.xml");
//然后使用带有命名空间的前缀查询即可。
dom.selectNodes("//a:book");
注意: 因为DocumentFactory
是一个单例模式,所以不同的命名空间一定要使用不同的别名
单引号以及双引号问题
使用concat()函数
public static String concat(String str) {
if (str == null || str.trim().equals("")) {
return "concat(\"\",\"\")";
}
int pre = 0;
StringBuilder sb = new StringBuilder();
sb.append("concat(");
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c == '\'') {
String substring = str.substring(pre, i + 1);
sb.append("\"" + substring + "\",");
pre = i + 1;
} else if (c == '\"') {
String substring = str.substring(pre, i + 1);
sb.append("'" + substring + "',");
pre = i + 1;
}
}
if (pre != str.length()) {
String substring = str.substring(pre, str.length());
sb.append("\"" + substring + "\",");
}
sb.append("\"\")");
return sb.toString();
}
使用场景
String name = "a'b\"c";
dom.selectNodes("//node[@name=" + concat(name) + "]");
dom4j使用XPath语法API
String xPath = ...; //xpath表达式
Node node = ...; //节点
node.valueOf("@name"); //node节点的属性name的值
node.getText(); //node节点的text值
node.selectNodes(xPath); //根据xPath选择多个节点,不存在返回空集合
node.selectSingleNode(xPath); //根据xPath选择其中一个节点,不存在返回NULL
遇到的使用限制
如果节点非常多,不要使用xpath解析,而是使用dom4j的迭代器一个一个去迭代,然后放在LinkedList
集合中。否则,会爆内存。