今天想在使用 dom4j 选择节点时,顺便去重,可没有单独去重的方法;倒是有一个可以去重的,还必须提供一个 xpath 作为 排序和去重 的依据。
1、xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<tasks>
<task name="work" delay="0" period="43200"></task>
<task name="sleep" delay="3600" period="43200"></task>
<task name="play" delay="120" period="604800"></task>
<task name="play" delay="120" period="604800"></task>
</tasks>
2、用到的方法及参数说明:
selectNodes 有 3 个重载方法,一个参数的、两个参数的,三个参数的。
selectNode(String xpath1, String xpath2, String boolVal)
(1)xpath1:用来在文本中选择节点,并会返回一个结果集(List<Node>)。
(2)xpath2:站在结果中某个节点的角度,指出排序和去重的依据。
(3)0boolVal: 参数为 true 时,会对选择的结果进行去重处理。
呃……似乎有点不好理解,看例子吧。
3、测试代码及结果
Document doc = new SAXReader().read(new File("src/operxml/xmlfiles/tasks.xml")); // 01、选择所有的 task 节点,按照节点的 name 属性排序,结果去重。
List<Node> tasks = doc.selectNodes("//task", "@name", true);
tasks.forEach(tn -> System.out.println(tn.asXML()));
结果:
<task name="play" delay="120" period="604800"/>
<task name="sleep" delay="3600" period="43200"/>
<task name="work" delay="0" period="43200"/>
// 02、获取所有的任务名,按任务名排序和去重
//List<Node> taskNames = doc.selectNodes("//task/@name", "@name", true); //怎么选都只有一个节点。
List<Node> taskNames = doc.selectNodes("//task/@name", "../@name", true); //结果集中的节点是 task/@name,并没有什么属性可以用来排序;可以使用其父节点(task)的 name 属性来给结果排序
taskNames.forEach(tn -> System.out.println(tn.asXML()));
结果:
name="play"
name="sleep"
name="work"
// 03、获取所有的任务名,按延迟排序和去重
List<Node> taskNames = doc.selectNodes("//task/@name", "../@delay", true); // 第二个参数作为排序依据、去重依据(很明显是根据 delay 排序的;与 02 相比较:02 中 name 有相同的,去重后只剩一个,03 中delay 各不相同。)
taskNames.forEach(tn -> System.out.println(tn.asXML()));
结果:
name="work"
name="play"
name="play"
name="sleep"