使用 dom4j 处理 xml (上)
Posted home-artchy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 dom4j 处理 xml (上)相关的知识,希望对你有一定的参考价值。
解决问题需要,自己简单学习了一下dom4j 的基本用法:
(1)读取 xml 文件;
(2)修改 xml 文件。
需要的 jar 包:
dom4j-xxx.jar (可以在 https://dom4j.github.io/ 下载)(不含 jaxen-xxx.jar)
jaxen-xxx.jar (这个 jar 在 jdom 的下载(http://www.jdom.org/downloads/index.html)压缩文件中有)(如果用到 xpath,就必须引入此包,否则报 ClassNotFoundException)
1、读 xml 文件
(1)首先创建一个 xml 文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!-- data info: --> <!-- There‘re three classrooms where students from both class3 and class4 take courses in. --> <!-- type equals 1, means the person is a teacher; 2 means student --> <classes> <classrooms> <classroom name="J5C302"></classroom> <classroom name="J5C301"></classroom> <classroom name="J1C103"></classroom> </classrooms> <persons> <person type="1" name="AnYe Cao" cls="03" age="32">-------</person> <person type="2" name="YiQing Zhang" cls="03" age="24" id="01130082">++++++++</person> <person type="2" name="Ting Zhang" cls="03" age="22" id="01130081"></person> <person type="2" name="ZhiHui Li" cls="03" age="23" id="01130065"></person> <person type="2" name="LiuYang Pang" cls="03" age="24" id="01130066"></person> <person type="2" name="DongYe Li" cls="03" age="21" id="01130068"></person> <person type="1" name="XueLi Chen" cls="04" age="15"></person> <person type="2" name="ShengJun Ma" cls="04" age="27" id="01130092"></person> <person type="2" name="Yan Cao" cls="04" age="20" id="01130099"> <a>aaa</a> </person> <dog>wang</dog> </persons> </classes>
(2)然后将文件读进内存并解析成 Document 对象:
1 String filePath = "src/operxml/xmlfiles/classes.xml"; //这里是从本地的工程路径下读取 2 3 SAXReader saxReader = new SAXReader(); 4 Document document = saxReader.read(new File(filePath));
(3)之后就是分析 Document 对象,比如具备某种特征的元素有多少个啊;比如获取某个节点的属性值啊。
因为之前学习过 JQuery 选择器和 jsoup 来解析 html 文件,一上来就找有没有类似 jsoup 的那种筛选元素的API,发现只有一个 elementByID ,然而也没有理想中的效果!!
1 Element elem = document.elementByID("01130082"); 2 System.out.println(elem); //elementByID 一直返回 null,元素有 id 属性,但就是找不到;网上说需要加个DTD什么的,没搞明白,以后再补。
接下来说几个能用的:
1 //1、遍历某个元素下的子元素(也可以使用elementIterator 迭代) 2 List<Element> elements = root.element("persons").elements(); //只能一级一级查找,如果路径深了就…… 3 System.out.println(elements.get(0).getPath()); //取元素的xpath 4 for(Element ele : elements) 5 { 6 System.out.println(ele.asXML()); //转换xml成字符串 7 //System.out.println(ele.attributeValue("name") + ele.getText()); //读取当前元素的 name 属性及其中的文本 8 }
1 //2、通过 xpath获取指定节点 2 List<Node> nodes = root.selectNodes("/classes/persons/person"); //返回匹配 xpath 的所有后代节点;还有俩重载方法,好像还可以根据指定的比较规则去重 3 for(Node node : nodes) 4 { 5 System.out.println(node.asXML()); 6 System.out.println(node.getStringValue()); //与getText()好像一样;相当于Element的 getText() 7 System.out.println(node.selectSingleNode("@type").asXML()); //因为属性一般不会重复,所以只取一个 8 System.out.println(node.selectSingleNode("@type").getText()); //获取属性值 9 }
(4)小结:
a. Element 与 Node 的区别 Element 强调的是部分与 xml 这个整体的关系,一个xml 文件是由一个个元素组成的。文档中可以出现哪些元素,什么类型的元素,都可能受 dtd, xsd约束的。一个元素指的大概就是一对闭合的标签,以及标签内的属性、文本。 Node 可以说弱化了类型的说法,分得更细。它可以是一个元素,也可以是元素的属性,还可以是元素中的文本,甚至是注释,所以有注释节点,文本节点,元素节点的说法。 举个例子: <class> <!-- 这是采矿 3 班的数据 --> <student name="xiaoming">小小明</student> <student name="xiaohong">小小红</student> </class> 例子中,整个class 可以看成一个元素,其下有两个子元素。 例子中,整个class元素可以看成一个节点,节点中还包含一个注释节点,以及两个student 节点,每个student 节点还包含一个属性节点和文本节点。
b. getText() 和 getStringValue 的区别
举个例子:
Node singleNode = root.selectSingleNode("persons");
System.out.println(singleNode.getText()); //因为persons中都是子元素,并没有属于自己的innerText,所以取到的是空白符
System.out.println(singleNode.getStringValue()); //在persons以及persons的后代(不仅仅是子元素)元素中找innerText
2、修改 xml 文件
就是修改 Document 对象中的 Element (修改 子元素、属性、文本)。
a.修改 元素中的 元素
1 @Test 2 public void modifyAndWrite() throws Exception 3 { 4 String filePath = "src/operxml/xmlfiles/classes.xml"; 5 6 SAXReader saxReader = new SAXReader(); 7 Document document = null; 8 document = saxReader.read(new File(filePath)); 9 document.setXMLEncoding("UTF-8"); 10 Element root = document.getRootElement(); 11 12 List<Element> elements = root.element("classrooms").elements("classroom"); 13 Element ele0 = elements.get(0); 14 Element ele_cp = ele0.createCopy(); // 15 ele_cp.addAttribute("level", "Lv999"); 16 ele_cp.remove(ele_cp.attribute("name")); 17 ele_cp.attributeValue("level", "Lv001"); 18 ele_cp.setText("miao"); 19 20 ele0.getParent().add(ele_cp); 21 ele0.getParent().remove(elements.get(1)); //将当前元素 从 直接父 元素中删除
b.修改 元素中的 节点
1 //01 从nodes中删除,nodes只是一个副本,此处删除并不会从Document中删除 2 List<Node> nodes = root.selectNodes("//mt:person" ); 3 nodes.remove(2); 4 for(Node tmpNode : nodes) 5 { 6 Node node = tmpNode.selectSingleNode("@id"); 7 if(null == node || (null != node && !node.getText().startsWith("0113008"))) 8 { 9 // 02 将此节点从其父节点中删除;如果此节点为根节点,则将其从Document中删除 10 tmpNode.detach(); 11 continue; 12 } 13 } 14 15 // 03 只能从Element中删除 直接 子节点(如果不是直接子节点,则用detach) 16 root.remove(root.selectSingleNode("//mc:persons")); 17 18 // 在document中删除了某些节点后,变化并不能同步到 nodes中;nodes可以作为之前的一个副本 19 // 将节点从Document中删除: Element.remove(Node) 或 Node.detach() 20 21 22 System.out.println(document.asXML()); 23 Node nod = root.selectSingleNode("//bme:classroom"); 24 Node nod_cp = (Node) nod.clone(); 25 nod_cp.selectSingleNode("@name").setName("nm"); //属性节点setName 无效; 26 nod_cp.selectSingleNode("@name").setText("eee"); //相当于设置该属性节点所在元素的 该属性值。使用之前最好判断一下有没有这个属性节点,不然就是空指针。 27 nod_cp.setName("clsroom"); //元素节点 修改元素的标签名、文本值 28 nod_cp.setText("ddd"); 29 nod.getParent().add(nod_cp); //node.getParent 得到的是node 所在的元素。所以修改 xml 是对 Element 的修改。Node 本身没提供多少方法。
c. 将 Document 对象写入 xml 文件
1 FileWriter fileWriter = new FileWriter(new File(filePath)); 2 //1、这样输出没有格式 3 // document.write(fileWriter); 4 // fileWriter.flush(); 5 // fileWriter.close(); 6 7 //2、有格式地输出 8 OutputFormat printFormat = OutputFormat.createPrettyPrint(); 9 printFormat.setEncoding("UTF-8"); 10 printFormat.setIndent(" "); 11 XMLWriter xmlWriter = new XMLWriter(fileWriter, printFormat); 12 xmlWriter.write(document); 13 xmlWriter.flush(); 14 fileWriter.close(); 15 xmlWriter.close(); 16 17 // SAXWriter saxWriter = new SAXWriter(); //SAXWriter不是用来将document写进硬盘的 18 // saxWriter.write(document);
3、总结 + 闲话
(1)基本用法主要就是几个常用的类: SAXReader、Document、Element、Node、OutputFormat、XMLWriter。
(2)修改 xml 文件,就是 读进来并解析成 Document对象,然后修改这个 Document 对象,再把 Document 对象写进xml文件;并不是直接在 xml 文件上改。
(3)xpath 功能很强,有些类似于 jquery 选择器。
以上是关于使用 dom4j 处理 xml (上)的主要内容,如果未能解决你的问题,请参考以下文章