1. dom解析
DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该
结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。
dom解析优点:
首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像SAX那样是一次性的处理。DOM使用起来也要简单得多。
实例:
节点信息类
public class Employee {
private String name;
private String sex;
private int age;
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;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((sex == null) ? 0 : sex.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (sex == null) {
if (other.sex != null)
return false;
} else if (!sex.equals(other.sex))
return false;
return true;
}
@Override
public String toString() {
return "Employee [name=" + name + ", sex=" + sex + ", age=" + age + "]";
}
public Employee(String name, String sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
public Employee() {
super();
}
}
dom解析类:
public class DomXmlParse {
public Document document;
public DomXmlParse() {
init();
}
public void init() {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder documentBuilder;
documentBuilder = documentBuilderFactory.newDocumentBuilder();
this.document = documentBuilder.newDocument();
} catch (ParserConfigurationException e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
public void createXml(List<Employee> list, String rootName, String fileName) {
Element root = this.document.createElement(rootName);
this.document.appendChild(root);
if (null != list && list.size() > 0) {
for (Employee detail : list) {
Element employee = createEmploy(detail);
root.appendChild(employee);
}
}
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
DOMSource domSource = new DOMSource(this.document);
transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
StreamResult streamResult = new StreamResult(pw);
transformer.transform(domSource, streamResult);
System.out.println("创建xml文件成功");
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
public Element createEmploy(Employee employee){
Element employeElement = this.document.createElement("employee");
Element nameElement = this.document.createElement("name");
nameElement.appendChild(this.document.createTextNode(employee.getName()));
employeElement.appendChild(nameElement);
Element sexElement = this.document.createElement("sex");
sexElement.appendChild(this.document.createTextNode(employee.getSex()));
employeElement.appendChild(sexElement);
Element ageElement = this.document.createElement("age");
ageElement.appendChild(this.document.createTextNode(String.valueOf(employee.getAge())));
employeElement.appendChild(ageElement);
return employeElement;
}
public void parseXml(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(fileName);
NodeList nodeList = document.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println("节点类型:"+nodeList.item(i).getNodeType());
System.out.println("节点名:"+nodeList.item(i).getNodeName()
+ ":" + "文本值"+nodeList.item(i).getTextContent());
Node nodeP = nodeList.item(i);
NodeList nodeInfo = nodeP.getChildNodes();
for (int j = 0; j < nodeInfo.getLength(); j++) {
System.out.println("节点类型:"+nodeInfo.item(j).getNodeType());
System.out.println("节点名:"+nodeInfo.item(j).getNodeName()
+ ":" + "文本值"+nodeInfo.item(j).getTextContent());
Node node = nodeInfo.item(j);
NodeList enodeMeta = node.getChildNodes();
for (int k = 0; k < enodeMeta.getLength(); k++) {
System.out.println("节点类型:"+enodeMeta.item(k).getNodeType());
System.out.println("节点名:"+enodeMeta.item(k).getNodeName()
+ ":" + "文本值"+enodeMeta.item(k).getTextContent());
}
}
}
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());
}
}
}
测试
List<Employee> listEmployees = new ArrayList<Employee>();
@Before
public void init(){
Employee employee1 = new Employee("张三", "m", 20);
Employee employee2 = new Employee("李四", "d", 30);
Employee employee3 = new Employee("王武", "x", 40);
Employee employee4 = new Employee("大方", "g", 50);
listEmployees.add(employee1);
listEmployees.add(employee2);
listEmployees.add(employee3);
listEmployees.add(employee4);
}
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void test1(){
DomXmlParse domXmlParse = new DomXmlParse();
String fileName = "D:"+File.separator+"test"+File.separator+"xml"+File.separator+"employeeDom.xml";
domXmlParse.createXml(listEmployees, "employees", fileName);
domXmlParse.parseXml(fileName);
}
生成的xml文档结构
<?xml version="1.0" encoding="GB2312" standalone="no"?>
<employees>
<employee>
<name>张三</name>
<sex>m</sex>
<age>20</age>
</employee>
<employee>
<name>李四</name>
<sex>d</sex>
<age>30</age>
</employee>
<employee>
<name>王武</name>
<sex>x</sex>
<age>40</age>
</employee>
<employee>
<name>大方</name>
<sex>g</sex>
<age>50</age>
</employee>
</employees>
2. sax解析
SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。
SAX对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX这种扩展能力得到了更好的体
现。但用SAX解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。
sax解析事件回调类:
public class SaxHandler extends DefaultHandler {
private HashMap<String, String> map = null;
private List<HashMap<String, String>> list = null;
/**
* 正在解析的元素的标签
*/
private String currentTag = null;
/**
* 正在解析的元素的值
*/
private String currentValue = null;
private String nodeName = null;
public List<HashMap<String, String>> getList(){
return list;
}
public SaxHandler(String nodeName) {
this.nodeName = nodeName;
}
@Override
public void startDocument() throws SAXException {
// TODO 当读到一个开始标签的时候,会触发这个方法
list = new ArrayList<HashMap<String,String>>();
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// TODO 当遇到文档的开头的时候,调用这个方法
if(name.equals(nodeName)){
map = new HashMap<String, String>();
}
if(attributes != null && map != null){
for(int i = 0; i < attributes.getLength();i++){
map.put(attributes.getQName(i), attributes.getValue(i));
}
}
currentTag = name;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO 这个方法用来处理在XML文件中读到的内容
if(currentTag != null && map != null){
currentValue = new String(ch, start, length);
if(currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")){
map.put(currentTag, currentValue);
}
}
currentTag=null;
currentValue=null;
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
// TODO 在遇到结束标签的时候,调用这个方法
if(name.equals(nodeName)){
list.add(map);
map = null;
}
super.endElement(uri, localName, name);
}
}
sax解析类:
public abstract class SaxXmlParse{
public static List<HashMap<String, String>> _readXml(InputStream input, String nodeName){
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
SaxHandler handler = new SaxHandler(nodeName);
parser.parse(input, handler);
input.close();
return handler.getList();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
测试:
<span style="white-space:pre"> </span>@Test
public void saxTest(){
String fileName = "D:"+File.separator+"test"+File.separator+"xml"+File.separator+"employeeDom.xml";
try {
FileInputStream input = new FileInputStream(fileName);
List<HashMap<String, String>> list = SaxXmlParse._readXml(input, "employees");
for(HashMap<String, String> p : list){
System.out.println(p.toString());
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3. JDom解析
JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快。由于是第一个Java特定模型,JDOM一直得到大力推广和促进。正在考虑通过“Java规
范请求JSR-102”将它最终用作“Java标准扩展”。从2000年初就已经开始了JDOM开发。
JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些
已经熟悉这些类的Java开发者的使用。
JDOM文档声明其目的是“使用20%(或更少)的精力解决80%(或更多)Java/XML问题”(根据学习曲线假定为20%)。JDOM对于大多数Java/XML应用程序来说当然是有的,
并且大多数开发者发现API比DOM容易理解得多。JDOM还包括对程序行为的相当广泛检查以防止用户做任何在XML中无意义的事。然而,它仍需要您充分理解XML以便做一些
超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习DOM或JDOM接口都更有意义的工作。
JDom解析类:
public class JDomXmlParse {
@SuppressWarnings("unchecked")
public void parseXml(String fileName) {
try {
InputStream in = new FileInputStream(fileName);
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(in);
Element root = document.getRootElement();
System.out.println(root.getName());
List<Element> nodes = root.getChildren();
for(Element element : nodes){
String name = element.getChildText("name");
String age = element.getChildText("age");
String sex = element.getChildText("sex");
System.out.println(name);
System.out.println(age);
System.out.println(sex);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试:
@Test
public void jdomTest(){
String fileName = "D:"+File.separator+"test"+File.separator+"xml"+File.separator+"employeeDom.xml";
JDomXmlParse jDomXmlParse = new JDomXmlParse();
jDomXmlParse.parseXml(fileName);
}
4. dom4j解析
虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用
于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能。从2000下半年开始,它就一直处于开发之
中。
为支持所有这些功能,DOM4J使用接口和抽象基本类方法。DOM4J大量使用了API中的Collections类,但是在许多情况下,它还提供一些替代方法以允许更好的性能或更直接
的编码方法。直接好处是,虽然DOM4J付出了更复杂的API的代价,但是它提供了比JDOM大得多的灵活性。
在添加灵活性、XPath集成和对大文档处理的目标时,DOM4J的目标与JDOM是一样的:针对Java开发者的易用性和直观操作。它还致力于成为比JDOM更完整的解决方案,实
现在本质上处理所有Java/XML问题的目标。在完成该目标时,它比JDOM更少强调防止不正确的应用程序行为。
DOM4J是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java软件都在
使用DOM4J来读写XML,特别值得一提的是连Sun的JAXM也在用DOM4J.
dom解析类:
public class Dom4jXmlParse {
@SuppressWarnings("rawtypes")
public void parseXml(String fileName) throws DocumentException {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(fileName);
Element root = document.getRootElement();
System.out.println(root.getName());
for(Iterator iterator = root.elementIterator() ; iterator.hasNext();){
Element element = (Element) iterator.next();
System.out.println(element.getName());
for(Iterator childIterator = element.elementIterator() ; childIterator.hasNext();){
Element childElement = (Element) childIterator.next();
System.out.println(childElement.getName()+":"+childElement.getText());
}
}
}
/**
* 用Visitor模式解析
* @param fileName
* @throws DocumentException
*/
public void visitorParseXml(String fileName) throws DocumentException{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(fileName);
Visitor visitor = new Visitor();
document.accept(visitor);
}
}
dom4j支持用Visitor模式访问节点,属性,只要继承类VisitorSupport的Visitor,
注意,这个Visitor是自动遍历所有子节点的。如果是root.accept(MyVisitor),将遍历
子节点
public class Visitor extends VisitorSupport{
@Override
public void visit(Element element) {
if(element.isTextOnly()){
System.out.println(element.getName()+"--"+element.getText());
}else{
System.out.println(element.getName());
}
}
@Override
public void visit(Attribute attribute) {
System.out.println(attribute.getName() + "--" +attribute.getText());
}
}
测试
@Test
public void dom4jTest() throws DocumentException{
String fileName = "D:"+File.separator+"test"+File.separator+"xml"+File.separator+"employeeDom.xml";
Dom4jXmlParse dom4jXmlParse = new Dom4jXmlParse();
dom4jXmlParse.parseXml(fileName);
}
@Test
/**
* Visitor方式解析xml文件
* @throws DocumentException
*/
public void dom4jVisitorTest() throws DocumentException{
String fileName = "D:"+File.separator+"test"+File.separator+"xml"+File.separator+"employeeDom.xml";
Dom4jXmlParse dom4jXmlParse = new Dom4jXmlParse();
dom4jXmlParse.visitorParseXml(fileName);
}