---恢复内容开始---
本文章讲解四种 XML 解析方式 :
DOM 和 SAX 为 Java提供的对 XML 解析的方式,不需要导入 jar 包
DOM4J 和 JDOM 是其他组织使用他们自己的方式解析 XML 文件,需要我们导入一些 jar 包
首先我们先看一下 XML 文件
<School> ----- 父节点 <student id="1"> ---- 子节点 <name>小红</name> --- 这个是student的子节点 <age>18</age> <sex>女</sex> <address>北京海定区五道口</address> </student> <student id="2"> ---- 子节点 <name>小明</name> <age>19</age> <sex>男</sex> <address>北京海定区上地</address> </student> </School>
下面的4种方法统一用上面的 XML 文件
第一种 DOM 解析 XML:
import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Test { public static void main(String[] args) { //创建一个 DocumentBuilderFactory 对象 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { //创建DocumentBuilder对象 DocumentBuilder db = dbf.newDocumentBuilder(); //通过DocumentBuilder的pares方法加载student.xml文件到当前项目下 Document document = db.parse("School.xml"); //获取所有 School 下的子节点的集合 NodeList nodeList = document.getElementsByTagName("student"); //获取nodeList的长度 //System.out.println(nodeList.getLength()); for(int i = 0 ; i < nodeList.getLength() ; i++){ System.out.println("**************第"+(i+1)+"名学生***************"); //通过item(i) 获取一个student节点,nodeList的索引值从 0 开始 Node stu = nodeList.item(i); /** * 第一种不知道student节点的属性和个数 */ //获取 student 的所有属性集合 /*NamedNodeMap attrs = stu.getAttributes(); for (int j = 0; j < attrs.getLength(); j++) { Node attr = attrs.item(j); System.out.println("属性名:\t"+attr.getNodeName()); System.out.println("属性值:\t"+attr.getNodeValue()); }*/ /** * 第二种 知道 student 节点的有且自能有一个 id 属性 */ //将student节点进行强制类型转换,转换为Element类型 /*Element stu = (Element)nodeList.item(i); //通过 getAttribute("id") 方法获取属性值 String attribute = stu.getAttribute("id"); System.out.println("id的属性值为:"+attribute);*/ //获取 student 所有子节点的集合 NodeList childNodes = stu.getChildNodes(); for (int j = 0; j < childNodes.getLength(); j++) { Node node = childNodes.item(j); //区分出 text 类型的node 以及 element 下来的 node if(node.getNodeType() == Node.ELEMENT_NODE){ //判断获取到的此节点的名称是否等于name if(node.getNodeName().equals("name")){ //System.out.println("姓名:\t"+node.getFirstChild().getNodeValue()); System.out.println("姓名:\t"+node.getTextContent()); /** * 说一说这两个的区别 * node.getFirstChild().getNodeValue() 获取一个子节点的值 并且该节点下不存在子节点,否则返回 null * node.getTextContent() 返回此节点下的所有后代 文本内容 */ } } } } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
第二种 SAX 解析 XML :
>>创建一个学生类用于接收解析的值
public class Student { private int id; private String name; private int age; private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
》》创建一个ASXParserHandler 类继承 DefaultHandler 类
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SAXParserHandler extends DefaultHandler { private int index=0; private String value=null; private Student stu = null; //为了存储Student 对象 private List<Student> list = new ArrayList<Student>(); public List<Student> getList() { return list; } /** * 标识解析开始 */ @Override public void startDocument() throws SAXException { super.startDocument(); //System.out.println("SAX解析开始"); } /** * 标识解析结束 */ @Override public void endDocument() throws SAXException { super.endDocument(); //System.out.println("SAX解析结束"); } /** * 解析 XML元素的 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //调用 DefaultHandler 类的 startElement 方法 super.startElement(uri, localName, qName, attributes); //开始解析 student元素的属性 if (qName.equals("student")) { stu = new Student(); //index++; //记录学生 id //System.out.println("===========开始遍历第"+index+"名学生的信息============="); //已知Student 元素下的属性名称,根据属性名称获取属性值 /*String vaule = attributes.getValue("id"); System.out.println(vaule);*/ //不知到 Student 元素下的属性名称和个数 for (int i = 0; i < attributes.getLength(); i++) { /*System.out.print("属性名称:"+attributes.getQName(i)); System.out.print("----属性值:"+attributes.getValue(i));*/ if (attributes.getQName(i).equals("id") ){ stu.setId(Integer.parseInt(attributes.getValue(i))); } } }else if (!qName.equals("School")){ /*System.out.print("\n节点名是:"+qName);*/ } } /** * 为了遍历xml结束标签 比如这样的 </name> */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if (qName.equals("student")) { //把学生对象添加到集合当中 list.add(stu); //System.out.println("\n============结束遍历第"+index+"名学生的信息============"); }else if (qName.equals("name")) { stu.setName(value); } } /** * 解析 XML中的内容 */ @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); value = new String(ch,start,length); /*if(!value.trim().equals("")){ System.out.print("----属性值是:"+value); }*/ } }
》》 解析类
public static void main(String[] args) { //1.通过SaxParserfactory的newInstance()方法获取一个 SAXParserFactory 实例 SAXParserFactory factory = SAXParserFactory.newInstance(); try { //2.通过 factory 获取 SAXParser 实例 SAXParser parser = factory.newSAXParser(); //创建SAXParserHandler 对象 SAXParserHandler handler = new SAXParserHandler(); //3. parser.parse("School.xml", handler); for (Student item : handler.getList()) { System.out.println(item.getName()); } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
送上SAX解析 XML 图一副:
第三种 JDOM 解析XML :
准备工作:
导入 Jar 包 jdom2-2.0.5.jar
下载地址:http://maven.outofmemory.cn/org.jdom/jdom2/2.0.5/
import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; public class JDOMTest { public static void main(String[] args) { //1.创建一个SAXBuilder 对象 SAXBuilder saxBuilder =new SAXBuilder(); //创建一个 InputStream 对象 InputStream is; try { //创建一个输入流,将 XML 文件加载到输入流 is = new FileInputStream("School.xml"); //当出现乱码情况,首先看 XML 当中的 encoding 是不是 utf-8 //不改变XML encoding 情况下,通过代码防止中文乱码 InputStreamReader isr = new InputStreamReader(is, "utf-8"); //通过saxBuilder的build方法,将输入流加载到 saxBuilder中 Document document = saxBuilder.build(isr); //通过 getRootElement 方法获取 XML 的根节点 Element element = document.getRootElement(); //获取跟节点下的子节点的集合 List<Element> stuList = element.getChildren(); for (Element item : stuList) { System.out.println("开始遍历第"+ (stuList.indexOf(item) + 1) +"一个学生的信息"); //获取student 属性集合 /*List<Attribute> attributes = item.getAttributes(); for (Attribute attribute : attributes) { System.out.print("属性名:"+attribute.getName()); System.out.println("\t属性值:"+attribute.getValue()); }*/ //对 Student节点的子节点以及节点值遍历 List<Element> children = item.getChildren(); for (Element stu : children) { if (stu.getName().equals("name")) { System.out.println("姓名是:"+stu.getValue()); } } } } catch (FileNotFoundException e) { e.printStackTrace(); }catch (JDOMException | IOException e) { e.printStackTrace(); } } }
第四种DOM4解析XML:
准备工作:
导入 jar 包 :dom4j-1.6.jar
下载地址:
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class Dom4jTest { public static void main(String[] args) { //创建一个 SAXReader 对象 SAXReader reader = new SAXReader(); try { //通过 reader 对象的 read 方法加载 School.XML文件 Document document = reader.read(new File("School.xml")); //通过document 对象 获取根节点 Element school = document.getRootElement(); //通过 Element 对象的 elementIterator 方法获取迭代器 Iterator it = school.elementIterator(); //遍历迭代器,获取根节点中的信息 while(it.hasNext()){ //获取到根节点下的一个子节点 Element student = (Element) it.next(); //获取子节点的属性名以及属性值 List<Attribute> list = student.attributes(); for (Attribute attribute : list) { //打印属性名称以及属性值 System.out.println("属性名:"+attribute.getName()+"\t属性值:"+attribute.getValue()); } //获取 跟节点下的一个子节点 的所有节点集合 Iterator itt = student.elementIterator(); //开始遍历这个节点的集合 while(itt.hasNext()){ //得到每一节点 Element studenChild = (Element)itt.next(); //打印节点名称以及节点值 System.out.println("节点名称:"+studenChild.getName()+"\t节点值:"+studenChild.getStringValue()); } } } catch (DocumentException e) { e.printStackTrace(); } } }
性能比较:
DOM :
优点:
1.形成了树结构,只观好理解,代码更容易编写
2.解析过程中树结构保留内存中,方便修改
缺点:
1.当 XML 文件较大时,对内存耗费比较大,容易影响解析性能并造成内存溢出
SAX:
优点:
1.采用事件驱动模式,对内存耗费比较小
2.适用于只需处理 XML 中数据时
缺点:
1.不宜编码
2.很难同时访问同一个 XML中的多处不同数据
JDOM:
1.仅仅使用具体类而不使用接口 简化了API 限制了JDOM 的灵活性
2.API 大量使用了 Collections 类
DOM4J:
1.JODM 的一种智能分支,它合并了许多超出基本XML 文档表示功能
2.DOM4J使用接口和抽象基本类方法,是一个优秀的Java XNL API
3.具有性能优异、灵活性好、功能强大和极端易用使用特点
4.是一个开放源代码的软件