1、xml
XML是一种通用的数据交换格式,它的平台无关性、语言无关性、系统无关性、给数据集成与交互带来了极大的方便。本文主要使用DOM解析、SAX解析、JDOM解析、DOM4J解析等四种方式解析XML。
2 、DMO
2.1特性
优点:
1、形成了树结构,有助于更好的理解、掌握,且代码容易编写。
2、解析过程中,树结构保存在内存中,方便修改。
3、
缺点:
1、由于文件是一次性读取,所以对内存的耗费比较大。
2、如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。
2.2 示例
package xml;
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;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
/**
* <p>
* DOM生成与解析XML文档
* <p>
* 优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能
* <p>
* 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间; 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。
*
* @author pp
*/
public class DomDemo {
// 创建xml到指定文件中
public static void createXml(String fileName) throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
Element root = document.createElement("employees");
document.appendChild(root);
/* 子节点(可以包含多个) */
Element employee = document.createElement("employee");
Element name = document.createElement("name");
name.appendChild(document.createTextNode("丁宏亮"));
employee.appendChild(name);
Element sex = document.createElement("sex");
sex.appendChild(document.createTextNode("m"));
employee.appendChild(sex);
Element age = document.createElement("age");
age.appendChild(document.createTextNode("30"));
employee.appendChild(age);
/* 把字节点放入根节点 */
root.appendChild(employee);
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
StreamResult result = new StreamResult(pw);
transformer.transform(source, result);
System.out.println("生成XML文件成功!");
} catch (TransformerConfigurationException e) {
System.out.println(e.getMessage());
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (TransformerException e) {
System.out.println(e.getMessage());
}
}
public static void parserXml(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(fileName);
/*
* 第一个for为了获取root(根)元素,第二个才开始获取元素 与Dom4j相比多了此步骤
*/
NodeList employees = document.getChildNodes();
for (int i = 0; i < employees.getLength(); i++) {
Node employee = employees.item(i);
NodeList employeeInfo = employee.getChildNodes();
for (int j = 0; j < employeeInfo.getLength(); j++) {
Node node = employeeInfo.item(j);
NodeList employeeMeta = node.getChildNodes();
for (int k = 0; k < employeeMeta.getLength(); k++) {
Node node2 = employeeMeta.item(k);
if (node2 instanceof Element) {
System.out.println(node2.getNodeName()+ ":" + node2.getTextContent());
}
if (k == employeeMeta.getLength() - 1) {
System.out.println("-------------");
}
}
}
}
System.out.println("解析完毕");
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (ParserConfigurationException e) {
System.out.println(e.getMessage());
} catch (SAXException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
3、SAX
3.1
优点:
1、采用事件驱动模式,对内存耗费比较小。
2、适用于只处理XML文件中的数据时。
缺点:
1、编码比较麻烦。
2、很难同时访问XML文件中的多处不同数据。
3.2
package xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
/**
* <p>SAX文档解析
* <p>优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。
* <p>缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素
* @author pp
*/
public class SaxDemo {
public static void createXml(String fileName) {
//创建一个 SAXTransformerFactory 类对象
SAXTransformerFactory tff = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
try {
//通过 SAXTransformerFactory 对象创建一个 TransformerHandler 对象
TransformerHandler handler = tff.newTransformerHandler();
//通过 TransformerHandler 对象创建一个 Transformer 对象
Transformer tr = handler.getTransformer();
//设置生成的 XML 文件编码格式
tr.setOutputProperty(OutputKeys.ENCODING, "utf-8");
//设置生成的 XML 文件自动换行
tr.setOutputProperty(OutputKeys.INDENT, "yes");
//如果不存在,就创建一个新的 XML 文件
File file = new File(fileName);
if (!file.exists()) {
file.createNewFile();
}
//创建一个Result 对象,并且使其与 TransformerHandler 对象关联
Result result = new StreamResult(new FileOutputStream(file));
handler.setResult(result);
//利用 handler 对象进行 XML 文件内容的编写
//打开 document
handler.startDocument();
//为了创建节点属性和属性值
AttributesImpl atts = new AttributesImpl();
//根节点开始标签
handler.startElement("", "", "School", atts);
//atts.clear(); //清空 atts 的值
//设置属性和属性值
atts.addAttribute("", "", "id", "", "1");
//子节点开始标签
handler.startElement("", "", "student", atts);
atts.clear(); //清空子节点设的值
//字节点下name节点开始标签
handler.startElement("", "", "name", atts);
String name="pwx";
handler.characters(name.toCharArray(), 0, name.length());
//字节点下name节点结束标签
handler.endElement("", "", "name");
//子节点结束标签
handler.endElement("", "", "student");
//根节点结束标签
handler.endElement("", "", "School");
//关闭 document
handler.endDocument();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
public static void parserXml(String fileName) {
SAXParserFactory saxfac = SAXParserFactory.newInstance();
try {
SAXParser saxparser = saxfac.newSAXParser();
InputStream is = new FileInputStream(fileName);
saxparser.parse(is, new MySAXHandler());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MySAXHandler extends DefaultHandler {
boolean hasAttribute = false;
Attributes attributes = null;
public void startDocument() throws SAXException {
System.out.println("文档开始打印了");
}
public void endDocument() throws SAXException {
System.out.println("文档打印结束了");
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equals("employees")) {
return;
}
if (qName.equals("employee")) {
System.out.println(qName);
}
if (attributes.getLength() > 0) {
this.attributes = attributes;
this.hasAttribute = true;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (hasAttribute && (attributes != null)) {
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println(attributes.getQName(0)
+ attributes.getValue(0));
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println(new String(ch, start, length));
}
}
4、JDom
4.1 特征:
1、仅使用具体类,而不使用接口。
2、API大量使用了Collections类。
4.2 Mven依赖
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1.3</version>
</dependency>
4.3 示例
package xml;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
/**
* JDOM 生成与解析XML文档
* @author pp
*/
public class JDomDemo extends XmlDocument {
public static void createXml(String fileName) {
Document document;
Element root;
root=new Element("employees");
document=new Document(root);
Element employee=new Element("employee");
root.addContent(employee);
Element name=new Element("name");
name.setText("ddvip");
employee.addContent(name);
Element sex=new Element("sex");
sex.setText("m");
employee.addContent(sex);
Element age=new Element("age");
age.setText("23");
employee.addContent(age);
XMLOutputter XMLOut = new XMLOutputter();
try {
XMLOut.output(document, new FileOutputStream(fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void parserXml(String fileName) {
SAXBuilder builder=new SAXBuilder(false);
try {
Document document=builder.build(fileName);
Element employees=document.getRootElement();
List<?> employeeList=employees.getChildren("employee");
for(int i=0;i<employeeList.size();i++){
Element employee=(Element)employeeList.get(i);
List<?> employeeInfo=employee.getChildren();
for(int j=0;j<employeeInfo.size();j++){
System.out.println(((Element)employeeInfo.get(j)).getName()+":"+((Element)employeeInfo.get(j)).getValue());
}
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5、DOM4J
5.1 特征
1、JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能。
2、它使用接口和抽象基本类方法。
3、具有性能优异、灵活性好、功能强大和极端易用的特点。
4、是一个开放源码的文件
5.2 Maven依赖
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6</version>
</dependency>
5.3 示例
package xml;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
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;
/**
* <p>Dom4j 生成XML文档与解析XML文档
* <p>DOM4J 是一个非常非常优秀的Java XML API
* @author pp
*/
public class Dom4jDemo extends XmlDocument {
public static void createXml(String fileName){
Document document = DocumentHelper.createDocument();
Element employees=document.addElement("employees");
Element employee=employees.addElement("employee");
Element name= employee.addElement("name");
name.setText("pp");
Element sex=employee.addElement("sex");
sex.setText("man");
Element age=employee.addElement("age");
age.setText("18");
try {
Writer fileWriter=new FileWriter(fileName);
XMLWriter xmlWriter=new XMLWriter(fileWriter);
xmlWriter.write(document);
xmlWriter.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public static void parserXml(String fileName) {
File inputXml=new File(fileName);
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(inputXml);
Element employees=document.getRootElement();
for(Iterator<?> i = employees.elementIterator(); i.hasNext();){
Element employee = (Element) i.next();
for(Iterator<?> j = employee.elementIterator(); j.hasNext();){
Element node=(Element) j.next();
System.out.println(node.getName()+":"+node.getText());
}
}
} catch(DocumentException e) {
System.out.println(e.getMessage());
}
}
}
6、总结
DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J。
JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。
SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。