详解Java解析XML的四种方法—DOM/SAX/jdom/dom4j

最近在研究XML文件的生成和解析,网上资料很多,当然也参差不齐。写的没错误的通常是单独介绍了1种方法,介绍全的常常运行不起来。 小哆把4种方法汇总了一下,运行验证成功。 xml解析jar包免费下载:http://download.csdn.net/detail/sdsky1987/4083634 XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种叫DOM,另一种叫SAX。SAX是基于事件流的解析,DOM是基于XML文档树结构的解析。假设我们XML的内容和结构如下(demo.xml): [html] view plaincopyprint? <?target text?> m 23 f 22 1.DOM生成和解析XML文档 W3C 规范化了 DOM,它的主要优点是可移植性:它是作为一种 CORBA 接口定义的,被映射到很多语言。因此如果了解了 JavaScript 中的 DOM,也就知道了 Java、C++、Perl、Python 和其他语言中的 DOM。 解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。[java] view plaincopyprint?package cn.main.dom; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * DOM生成与解析XML文档 * * @author 莫小哆_ly 2012-2-20 */ public class DomDemo { /* * 解析器读入整个文档,然后构建一个驻留内存的树结构, * * 然后代码就可以使用 DOM 接口来操作这个树结构。 * * 优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能; * * 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间; * * 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU) */ // 表示整个HTML或 XML文档。从概念上讲,它是文档树的根,并提供对文档数据的基本访问 private Document document; /** * 创建DOM树 * * 要读入一个XML文档,首先要一个DocumentBuilder对象 */ public void init() { // 获取 DocumentBuilderFactory 的新实例 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 使用当前配置的参数创建一个新的 DocumentBuilder 实例 DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { e.printStackTrace(); } // 获取 DOM Document 对象的一个新实例来生成一个 DOM 树 this.document = builder.newDocument(); } /** * xml文档的写入操作 * * @param file */ public void createXml(File file) { // 创建DOM树 this.init(); // 创建XML根节点employees Element root = this.document.createElement("employees"); // Adds the node newChild to the end of the list of children of this // node. // If the newChild is already in the tree, it is first removed. this.document.appendChild(root); // 1.创建根节点的子节点employee Element employee = this.document.createElement("employee"); // 向根节点添加属性节点 Attr id = this.document.createAttribute("id"); id.setNodeValue("0001"); // 把属性节点对象,追加到达employee节点; employee.setAttributeNode(id); // 声明employee的子节点name Element name = this.document.createElement("name"); // 向XML文件name节点追加数据 name.appendChild(this.document.createTextNode("wanglp")); // 把子节点的属性追加到employee子节点中元素中 employee.appendChild(name); // 声明employee的子节点sex Element sex = this.document.createElement("sex"); // 向XML文件sex节点追加数据 sex.appendChild(this.document.createTextNode("m")); // 把子节点的属性追加到employee子节点中元素中 employee.appendChild(sex); // 声明employee的子节点age Element age = this.document.createElement("age"); // 向XML文件age节点追加数据 age.appendChild(this.document.createTextNode("25")); // 把子节点的属性追加到employee子节点中元素中 employee.appendChild(age); // employee节点定义完成,追加到root root.appendChild(employee); // 2.创建根节点的子节点employee employee = this.document.createElement("employee"); // 向根节点添加属性节点 id = this.document.createAttribute("id"); id.setNodeValue("0002"); // 把属性节点对象,追加到达employee节点; employee.setAttributeNode(id); // 声明employee的子节点name name = this.document.createElement("name"); // 向XML文件name节点追加数据 name.appendChild(this.document.createTextNode("huli")); // 把子节点的属性追加到employee子节点中元素中 employee.appendChild(name); // 声明employee的子节点sex sex = this.document.createElement("sex"); // 向XML文件sex节点追加数据 sex.appendChild(this.document.createTextNode("f")); // 把子节点的属性追加到employee子节点中元素中 employee.appendChild(sex); // 声明employee的子节点age age = this.document.createElement("age"); // 向XML文件age节点追加数据 age.appendChild(this.document.createTextNode("12")); // 把子节点的属性追加到employee子节点中元素中 employee.appendChild(age); // employee节点定义完成,追加到root root.appendChild(employee); // 获取 TransformerFactory 的新实例。 TransformerFactory tf = TransformerFactory.newInstance(); // 创建执行从 Source 到 Result 的复制的新 Transformer。能够将源树转换为结果树 Transformer transformer = null; try { transformer = tf.newTransformer(); } catch (TransformerConfigurationException e) { e.printStackTrace(); } // 设置转换中实际的输出属性 // 指定首选的字符编码 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); // indent="yes"|"no".指定了当输出结果树时,Transformer是否可以添加额外的空白 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 声明文件流 PrintWriter pw = null; try { pw = new PrintWriter(new FileOutputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("文件没有找到!"); } // 充当转换结果的持有者,可以为 XML、纯文本、HTML 或某些其他格式的标记 StreamResult result = new StreamResult(pw); // DOMSource implements Source DOMSource source = new DOMSource(document); try { // 将 XML Source 转换为 Result transformer.transform(source, result); } catch (TransformerException e) { e.printStackTrace(); System.out.println("生成XML文件失败!"); } System.out.println("生成XML文件成功!"); } /** * xml文档的读取操作 * * @param file */ public void parserXml(File file) { // 获取 DocumentBuilderFactory 的新实例 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 使用当前配置的参数创建一个新的 DocumentBuilder 实例 DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); // 将给定 URI的内容解析为一个 XML文档,并且返回一个新的 DOM Document 对象 document = builder.parse(file); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 获得文档根元素对对象; Element root = document.getDocumentElement(); // 获得文档根元素下一级子元素所有元素; NodeList nodeList = root.getChildNodes(); System.out.print(""); System.out.println(root.getNodeName()); if (null != root) { for (int i = 0; i < nodeList.getLength(); i++) { Node child = nodeList.item(i); // 输出child的属性; System.out.print(""); System.out.println(child); if (child.getNodeType() == Node.ELEMENT_NODE) { System.out.print(""); System.out.println(child.getAttributes().getNamedItem("id").getNodeValue()); } for (Node node = child.getFirstChild(); node != null; node = node.getNextSibling()) { if (node.getNodeType() == Node.ELEMENT_NODE) { if ("name".equals(node.getNodeName())) { System.out.print(""); System.out.println(node.getFirstChild().getNodeValue()); } } if (node.getNodeType() == Node.ELEMENT_NODE) { if ("sex".equals(node.getNodeName())) { System.out.print(""); System.out.println(node.getFirstChild().getNodeValue()); } } if (node.getNodeType() == Node.ELEMENT_NODE) { if ("age".equals(node.getNodeName())) { System.out.print(""); System.out.println(node.getFirstChild().getNodeValue()); } } if (node.getNodeType() == Node.ELEMENT_NODE) { if ("email".equals(node.getNodeName())) { System.out.print(""); System.out.println(node.getFirstChild().getNodeValue()); } } } } } System.out.println("解析完毕"); } /** * 测试 */ public static void main(String[] args) { // 为什么有类似于这样东西[#text:] // 原因是XML文件元素之间的空白字符也是一个元素,包含的空白 DomDemo dom = new DomDemo(); File file = new File("E://dom.xml"); dom.createXml(file); dom.parserXml(file); } } 2.SAX 解析XML文档为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少。[java] view plaincopyprint?package cn.main.sax; import java.io.File; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * SAX解析XML文档 * * startDocument(),endDocument(),startElement(),endElement(),characters() * * @author wanglp 2012-2-21 */ public class SAXParseDemo extends DefaultHandler { private String tagValue; // 标签值 // 开始解析XML文件 public void startDocument() throws SAXException { System.out.println("开始解析"); } // 结束解析XML文件 public void endDocument() throws SAXException { System.out.println("结束解析"); } // 解析元素 /** * 开始解析一个元素 * @param qName 标签名 * @param attributes 属性 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println(qName + "开始"); // 属性 if (attributes != null && attributes.getLength() != 0) { System.out.println("属性:"); for (int i = 0; i < attributes.getLength(); i++) { System.out.print(attributes.getQName(i) + "="); // 属性名 System.out.print(attributes.getValue(i) + " "); // 属性值 } System.out.println(); } } /** * 结束一个元素的解析 遇到结束标签时调用此方法 通常在此方法对标签取值并处理 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println(qName + "标签值:" + tagValue); System.out.println(qName + "结束"); } // 所有xml文件中的字符都会放到ch[]中 public void characters(char ch[], int start, int length) throws SAXException { tagValue = new String(ch, start, length).trim(); } public static void main(String[] args) { File file = new File("src/cn/main/example/demo.xml"); SAXParserFactory saxParFac = SAXParserFactory.newInstance(); try { SAXParser saxParser = saxParFac.newSAXParser(); saxParser.parse(file, new SAXParseDemo()); } catch (Exception e) { e.printStackTrace(); } } } 3.JDOM生成和解析XML 要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档。 导入jar包:jdom.jar[java] view plaincopyprint?package cn.main.jdom; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.jdom.Attribute; import org.jdom.Comment; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; /** * * jdom生成与解析XML文档 * * @author wanglp 2012-2-23 */ public class JdomDemo { Document document = new Document(); /** * 利用JDom进行xml文档的写入操作 */ public void createXml(File file) { // 1.创建元素 及 设置为根元素 Element employees = new Element("employees"); document.setContent(employees); // 2.创建注释 及 设置到根元素上 Comment commet = new Comment("this is my comment"); employees.addContent(commet); // 3.创建元素 Element element1 = new Element("employee"); // 3.1 设置元素的属性名及属性值 element1.setAttribute(new Attribute("id", "0001")); // 3.2 创建元素的属性名及属性值 Attribute nameAttr = new Attribute("name", "wanglp"); // 3.3 设置元素名及文本 Element sexEle = new Element("sex"); sexEle.setText("m"); // 设置到上层元素上 element1.addContent(sexEle); // 设置元素 Element ageEle = new Element("age"); ageEle.setText("22"); element1.addContent(ageEle); // 设置为根元素的子元素 employees.addContent(element1); // 将元素属性设置到元素上 element1.setAttribute(nameAttr); // 3.创建元素 Element element2 = new Element("employee"); // 3.1 设置元素的属性名及属性值 element2.setAttribute(new Attribute("id", "0002")); // 3.2 创建元素的属性名及属性值 Attribute name2Attr = new Attribute("name", "fox"); // 3.3 设置元素名及文本 Element sex2Ele = new Element("sex"); sex2Ele.setText("f"); // 设置到上层元素上 element2.addContent(sex2Ele); // 设置元素 Element age2Ele = new Element("age"); age2Ele.setText("21"); element2.addContent(age2Ele); // 设置为根元素的子元素 employees.addContent(element2); // 将元素属性设置到元素上 element2.setAttribute(name2Attr); Element element3 = new Element("employee"); element3.setText("title"); element3.addContent(new Element("name").addContent(new Element("hello"))); employees.addContent(element3); // 设置xml文档输出的格式 Format format = Format.getPrettyFormat(); XMLOutputter out = new XMLOutputter(format); // 将得到的xml文档输出到文件流中 try { out.output(document, new FileOutputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 利用JDom进行xml文档的读取操作 */ public void parserXml(File file) { // 建立解析器 SAXBuilder builder = new SAXBuilder(); try { // 将解析器与文档关联 document = builder.build(file); } catch (JDOMException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } // 读取根元素 Element root = document.getRootElement(); // 输出根元素的名字 System.out.println("<" + root.getName() + ">"); // 读取元素集合 List<?> employeeList = root.getChildren("employee"); for (int i = 0; i < employeeList.size(); i++) { Element ele = (Element) employeeList.get(i); // 得到元素的名字 System.out.println("<" + ele.getName() + ">"); // 读取元素的属性集合 List<?> empAttrList = ele.getAttributes(); for (int j = 0; j < empAttrList.size(); j++) { Attribute attrs = (Attribute) empAttrList.get(j); // 将属性的名字和值 并 输出 String name = attrs.getName(); String value = (String) attrs.getValue(); System.out.println(name + "=" + value); } try { Element sex = ele.getChild("sex"); System.out.println("" + sex.getText()); Element age = ele.getChild("age"); System.out.println("" + age.getText()); } catch (NullPointerException e) { System.out.println(ele.getTextTrim()); Element name = ele.getChild("name"); System.out.println("" + name.getName()); } System.out.println(""); } System.out.println(""); } /** * 测试 */ public static void main(String[] args) { JdomDemo jdom = new JdomDemo(); File file = new File("E://jdom.xml"); jdom.createXml(file); jdom.parserXml(file); } } 4.DOM4J生成和解析XML文档 DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。 导入jar包:dom4j-1.6.1.jar[java] view plaincopyprint?package cn.main.dom4j; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Iterator; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; /** * * dom4j生成与解析XML文档 * * @author wanglp 2012-2-23 */ public class Dom4jDemo { /** * 利用dom4j进行xml文档的写入操作 */ public void createXml(File file) { // XML 声明 自动添加到 XML文档中 // 使用DocumentHelper类创建文档实例(生成 XML文档节点的 dom4j API工厂类) Document document = DocumentHelper.createDocument(); // 使用addElement()方法创建根元素 employees(用于向 XML 文档中增加元素) Element root = document.addElement("employees"); // 在根元素中使用 addComment()方法添加注释"An XML Note" root.addComment("An XML Note"); // 在根元素中使用 addProcessingInstruction()方法增加一个处理指令 root.addProcessingInstruction("target", "text"); // 在根元素中使用 addElement()方法增加employee元素。 Element empElem = root.addElement("employee"); // 使用 addAttribute()方法向employee元素添加id和name属性 empElem.addAttribute("id", "0001"); empElem.addAttribute("name", "wanglp"); // 向employee元素中添加sex元素 Element sexElem = empElem.addElement("sex"); // 使用setText()方法设置sex元素的文本 sexElem.setText("m"); // 在employee元素中增加age元素 并设置该元素的文本。 Element ageElem = empElem.addElement("age"); ageElem.setText("25"); // 在根元素中使用 addElement()方法增加employee元素。 Element emp2Elem = root.addElement("employee"); // 使用 addAttribute()方法向employee元素添加id和name属性 emp2Elem.addAttribute("id", "0002"); emp2Elem.addAttribute("name", "fox"); // 向employee元素中添加sex元素 Element sex2Elem = emp2Elem.addElement("sex"); // 使用setText()方法设置sex元素的文本 sex2Elem.setText("f"); // 在employee元素中增加age元素 并设置该元素的文本。 Element age2Elem = emp2Elem.addElement("age"); age2Elem.setText("24"); // 可以使用 addDocType()方法添加文档类型说明。 // document.addDocType("employees", null, "file://E:/Dtds/dom4j.dtd"); // 这样就向 XML 文档中增加文档类型说明: // // 如果文档要使用文档类型定义(DTD)文档验证则必须有 Doctype。 try { XMLWriter output = new XMLWriter(new FileWriter(file)); output.write(document); output.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } /** * 利用dom4j进行xml文档的读取操作 */ public void parserXml(File file) { Document document = null; // 使用 SAXReader 解析 XML 文档 catalog.xml: SAXReader saxReader = new SAXReader(); try { document = saxReader.read(file); } catch (DocumentException e) { e.printStackTrace(); } // 将字符串转为XML // document = DocumentHelper.parseText(fileString); // 获取根节点 Element root = document.getRootElement(); // 打印节点名称 System.out.println("<" + root.getName() + ">"); // 获取根节点下的子节点遍历 Iterator<?> iter = root.elementIterator("employee"); // 遍历employee节点 while (iter.hasNext()) { // 获取当前子节点 Element empEle = (Element) iter.next(); System.out.println("<" + empEle.getName() + ">"); // 获取当前子节点的属性遍历 Iterator<?> attrList = empEle.attributeIterator(); while (attrList.hasNext()) { Attribute attr = (Attribute) attrList.next(); System.out.println(attr.getName() + "=" + attr.getValue()); } // 遍历employee节点下所有子节点 Iterator<?> eleIte = empEle.elementIterator(); while (eleIte.hasNext()) { Element ele = (Element) eleIte.next(); System.out.println("<" + ele.getName() + ">" + ele.getTextTrim()); } // 获取employee节点下的子节点sex值 // String sex = empEle.elementTextTrim("sex"); // System.out.println("sex:" + sex); } System.out.println("</" + root.getName() + ">"); } public static void main(String[] args) { Dom4jDemo dom4j = new Dom4jDemo(); File file = new File("e:/dom4j.xml"); // dom4j.createXml(file); dom4j.parserXml(file); } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值