一 简介
在Java中,可以使用多种方式来解析
(1)DOM
DOM是用与平台和语言无关的方式表示
因此在使用DOM这种方式来解析
优点: 整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种操作
缺点: 将整个文档调入内存(包括无用的节点),浪费时间和内存,如果
(2)SAX
由于DOM解析
SAX解析
优点:不用事先载入整个文档,占用资源(内存)少;使用SAX方式解析编写的代码要比使用DOM解析编写的代码少
缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素
(3)JDOM
使用JDOM来解析
优点:开源项目;比DOM容易理解
缺点:JDOM自身不包含解析器。它通常使用SAX2解析器来解析和验证输入
(4)DOM4J
DOM4J 是一个非常非常优秀的Java
由于DOM4J无论在性能方面还是代码编写方面都是很强大的,特别是当
优点:
开源项目
DOM4J是JDOM的一种智能分支,它合并了需要超出基本
具有性能优异、灵活性好、简单易用等特点
二 DOM解析
(1)在进行代码编写测试之前,需要准备一个
demo1.
(2)代码实例:
package cn.zifangsky.登录后复制
从上面的代码可以看出,在使用DOM来解析
创建一个文档构建器工厂(DocumentBuilderFactory)实例
通过上面的DocumentBuilderFactory生成一个新的文档构建器(DocumentBuilder)
使用上面的DocumentBuilder解析(parse)一个
通过Document获取指定id的节点或根据节点名获取所有符合条件的节点集合
遍历每个节点,可以获取该节点的属性、属性值等相关参数
如果该节点还存在子节点,可以根据上面的方式继续遍历它的所有子节点
(3)上面的代码输出如下:
此登录后复制
三 SAX解析
在进行本次测试时,并不引入其他
由于SAX解析
(1)解析处理器SAXParseHandler.java:
package cn.zifangsky. 0){ System.out.println("元素'" + qName + "'的属性是:"); for(int i=0;i 登录后复制
关于上面代码的一些含义我这里就不再做解释了,可以自行参考注释内容
(2)测试:
SAXParseTest.java文件:
package cn.zifangsky.登录后复制
从上面的代码可以看出,使用SAX解析
(3)上面测试的输出如下:
SAX解析开始 元素'user'的属性是: 属性名:id,属性值: 1
ii)同时准备一个Java实体类,恰好跟上面的
User.java:
package cn.zifangsky. ownPet; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getContact() { return contact; } public void setContact(String contact) { this.contact = contact; } protected List getOwnPet() { return ownPet; } protected void setOwnPet(List ownPet) { this.ownPet = ownPet; } @Override public String toString() { return "User [name=" + name + ", sex=" + sex + ", age=" + age + ", contact=" + contact + ", ownPet=" + ownPet + "]"; } }
iii)测试代码:
package cn.zifangsky. ownPet = new ArrayList(); SAXReader saxReader = new SAXReader(); try { Document document = saxReader.read(new File( children = rootElement.elements(); //获取根节点的子节点 //遍历 for(Element child : children){ String elementName = child.getName(); //节点名 String elementValue = child.getStringValue(); //节点值 switch (elementName) { case "name": user.setName(elementValue); break; case "sex": user.setSex(elementValue); break; case "age": user.setAge(Integer.valueOf(elementValue)); break; case "contact": user.setContact(elementValue); break; case "ownPet": ownPet.add(elementValue); break; default: break; } } user.setOwnPet(ownPet); } catch (Exception e) { e.printStackTrace(); } return user; } public static void main(String[] args) {登录后复制
经过前面的分析之后,上面这个代码也是很容易理解的:通过遍历节点,如果节点名跟Java类中的某个属性名相对应,那么就将节点值赋值给该属性
iv)上面的代码输出如下:
User [name=zifangsky, sex=男, age=100, contact=https://www.zifangsky.cn, ownPet=[旺财, 九头猫妖]]
(3)解析一个
DOM4JTest2:
package cn.zifangsky. elementList = element.elements(); // 当前节点的子节点List // 空格 StringBuffer spacebBuffer = new StringBuffer(""); for (int i = 0; i < level; i++) spacebBuffer.append(" "); String space = spacebBuffer.toString(); // 输出开始节点及其属性值 System.out.print(space + " attributes = element.attributes(); for (Attribute attribute : attributes) System.out.print(" " + attribute.getName() + "=\"" + attribute.getText() + "\""); // 有子节点 if (elementList.size() > 0) { System.out.println(">"); // 遍历并递归 for (Element child : elementList) { print(child, level + 1); } // 输出结束节点 System.out.println(space + "" + element.getName() + ">"); } else { // 如果节点没有文本则简化输出 if (element.getStringValue().trim().equals("")) System.out.println(" />"); else System.out.println(">" + element.getStringValue() + "" + element.getName() + ">"); } } public static void main(String[] args) { DOM4JTest2 test2 = new DOM4JTest2(); test2.parse("src/cn/zifangsky/登录后复制
这段代码同样没有什么新的东西,原理就是利用递归来不断进行解析输出,注意一下不同层次的节点的缩进即可。刚开始测试时建议用一些结构比较简单的代码,如上面的demo1.
demo3.
为什么我在标题上说的是尽可能原样输出,其原因就是上面那段解析代码在碰到下面这种
这段