1、XML解析学习笔记

来源:互联网 发布:oracle删除数据库过程 编辑:程序博客网 时间:2024/06/15 02:51


一、 XML简介

1.1  概述

XMLExtensible Markup language)在世界上的应用广泛性就如同眼镜在程序员中应用广泛性一样,它与HTML一样,都出生于SGML,可用于简单的数据存储。对我们即将要学习如何在Java中使用它的同志们来说,有一个很好的消息要告诉大家:它很简单易学。

与数据库老大们Access,SQL, Oracle不同,这些老大们提供了非常强大的数据分析、操作和存储能力,例如:索引,排序,增删改查,存储过程,游标,触发器等,XML能做到的,仅仅是展示和结构化数据信息而已,但是呢,非常简单使他与众不同。

J2EE开发中,我们经常会看到他们那苗条的身影:启动Tomcat初始化配置文件的时候,以及著名的strutshibernatespring框架中,他们是如何解析这些配置文件又是如何把他们转化为对象随心所欲的使用的呢?下面,我们就掀开她们的盖头,欣赏一下她们的容颜。

1.2 四种对XML的解析方式

Java生活中我们经常需要对XML进行解析以方便我们对数据进行操作,下面介绍在民间盛行的四种使用Java解析XML的方法,其中重点介绍DOM方式和DOM4J方式。

DOMJAXP Crimson解析器):W3CHTMLXML分析器制定的标准接口规范,基于树,可随机动态访问和更新文档的内容、结构、样式。

SAXsimple API for XML):不是W3C的标准,而是由XML-DEV邮件列表成员于1998年为Java语言开发的一种基于事件的简单API。基于事件,逐行解析,顺序访问XML文档,速度快,处理功能简单。

JDOM鉴于DOM的低效率,而SAX又不能随机处理XML文档,Jason HunterBrett McLaughlin2000年春天,开始创建一种能充分体现两者优势的API——JDOMJava-based DOM,基于JavaDOM),它是一个基于Java的对象模型,树状结构,能使读取、操作和写入XML文档,比DOM更高效,比SAX更强大,但由于使用了大量的类而不使用接口导致灵活性降低。

DOM4JDOM4J是一个易用的,开源的库,用于XML,XPath,XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX,JAXP。它提供了大量的接口,因此比JDOM更具有灵活性。

二、 预备知识

1.1 有关文档对象模型(DOM

DOM(文档对象模型)W3C实现了DOM操作的规范化,并为多种语言提供了操作DOM的接口,如CjavaJavascript等等。

对象模型的构建是以面向对象的思想为基础,通过对问题进行抽象,构造出一组相关的模型,从而能够全面地捕捉问题空间的信息而我们这里要介绍的文档对象模型通常是以树的形式对相关文档进行抽象,构建出由节点构成的文档树模型,从而实现更方便的对文档的各种操作。

节点:XML文档中的所有节点组成了一个文档树(或节点树)。XML文档中的每个元素、属性、文本等都代表着树中的一个节点。树起始于文档节点,并由此继续伸出枝条,直到处于这棵树最低级别的所有文本节点为止,常用节点类型如表2-1所示:

节点类型

附加说明

实例

元素节点(Element)

XML标记元素

<company>…</company>

属性节点(Attribute)

XML标记元素的属性

name=”ntcsoft”

文本节点(Text)

包括在XML标记中的文本段

工程师A

文档类型节点(DocumentType)

文档类型声明

!DOCTYPE…﹥

注释节点Comment

XmlComment类注释节点。

<!--文档注释-->

2-1

节点关系:下面我们从一个XML文档实例中了解一下各个节点之间的关系:

<company name="ntcsoft" >

  <department><employee position="developer">工程师A</employee></department>

  <department name="education"></department>

</company>

通过上面的XML文档,我们构建出如下树状文档对象模型,如图2-1所示:

2-1

1.2 DOM操作的各种招式

常用节点属性如表2-2所示:

属性

描述

nodeName

结点名称

nodeValue

结点内部值,通常只应用于文本结点

nodeType

节点类型对应的数字

parentNode

如果存在,指向当前结点的父亲结点

childNodes

子结点列表

firstChild

如果存在,指向当前元素的第一个子结点

lastChild

如果存在,指向当前元素的最后一个子结点

previousSibling

指向当前结点的前一个兄弟结点

nextSibling

指向当前结点的后一个兄弟结点

attributes

元素的属性列表

2-2

常用节点方法如表2-3所示:

操作类型

方法原型

描述

访问节点

getElementById(id)

根据ID属性查找元素节点

getElementsByName(name)

根据name属性查找元素集

getElementsByTagName(tagName)

根据元素标记名称查找元素集

创建节点

createElement(tagName)

创建元素节点

createTestNode(string)

创建文本节点

createAttribute(name)

创建属性节点

插入和添加节点

appendChild(newChild)

添加子节点到目标节点上

insertBefore(newChild,targetChild)

newChild节点插入到targetChild节点之前

复制节点

CloneNode(bool)

复制该节点,由bool确定是否复制子节点

删除和替换节点

removeChild(childName)

删除由childName指定的节点

replaceChild(newChild,oldChild)

newChild替换oldChild

属性节点操作

getAttribute(name)

返回目标对象指定属性名称为name的属性值

setAttribute(name,value)

修改目标节点指定属性名称为name的属性值为value

removeAttribute(name)

删除目标节点指定属性名称为name的属性

2-3

三、 实例解析XML

3.1 前情提要

A. 实例环境:windows xp3MyEclipse8.5JDK1.6

B. 环境搭建:

1. JDK的安装与配置可参考文档《JDK安装与环境变量配置》。

2. MyEclipse8.5的安装与使用请参考文档《Eclipse的安装与使用》。

3. MyEclipse下创建exercise工程,在src目录下创建文件名为Company.xmlXML文档,如图3-1

 

3-1

Company.xml源码如下:

<?xml version="1.0" encoding="UTF-8"?>

<company name="ntcsoft" address="河南省郑州市">

  <department deptNo="001" name="development">

<employee id="devHead" position="minister">许刚</employee>

<employee position="developer">工程师A</employee>

  </department>

  <department deptNo="002" name="education">

<employee position="minister" telephone="1234567">申林</employee>

<employee position="trainee">实习生A</employee>

  </department>

</company>

 

4. 在工程下创建domain包,用于存放实体类,在此包下创建如下实体类,如图3-2

 

3-2

Company.java主要源码如下:

public class Company {

private String name;

private String address;

private Department[]dept;

省略Seters and Getters…}

}

 

Department.java主要源码如下:

public class Department {

private String number;

private String name;

private Employee[] emp;

省略Seters and Getters…}

 

Employee.java主要源码如下:

public class Employee {

private String name;

private String position;

private String telephone;

省略Seters and Getters…}

5. 在工程下创建xmpParsers包,用于存放解析器,如图3-3所示:

 

3-3

6. 在工程下创建parsersTest包,用于存放解析器测试类,如图3-4所示:

 

3-4

3.2 DOM方式解析XML

A. 概述:

DOMDocument Object Model文档对象模型),是W3CHTMLXML分析器制定的标准接口规范。

B. 特点:

独立于语言,跨平台(可以在各种编程和脚本语言中使用),需要将整个文档读入内存,在内存中创建文档树,可随即访问文档中的特定节点,对内存的要求比较高,经过测试,访问速度相对于其他解析方式较慢,适用于简单文档的随即处理。

C. 在解析过程中需要使用的包、接口和类:

//为文档对象模型 (DOM)提供接口 API(Java API for XML Processing (JAXP)) 

import org.w3c.dom.*;

//此类可以包含来自 XML解析器或应用程序的基本错误和警告信息

import org.xml.sax.SAXException;

//导入实体类

import domain.*;

//标准IO,用于输入输出工作

import java.io.*;

//用于从 XML文档获取 DOM文档实例并生成 DOM对象树的解析器

import javax.xml.parsers.*;

//用于创建将DOM文档树源对象转换为XML文档结果对象的转换器

import javax.xml.transform.*;

//构造DOM文档树源对象

import javax.xml.transform.dom.DOMSource;

//构造XML文档的结果对象

import javax.xml.transform.stream.StreamResult;

D. 读取本地XML文档解析并转换为对象的步骤:

1. 创建XML文件解析器:我们可以通过javax.xml.parsers包下的工厂类DocumentBuilderFactory创建XML文档的解析器。

//创建DocumentBuilderFactory工厂实例。

DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();

//通过文档创建工厂创建文档创建器

DocumentBuilder dBuilder = dbfactory.newDocumentBuilder();

2. 解析XML文件并把该文件转换为文档对象:通过文档创建器DocumentBuilderparse方法解析参数URL指定的XML文档,并返回一个Document对象。

Document doc = dBuilder.parse(url);

3. 操作该对象并获取数据。

E. 将对象转换为XML文件并写入本地的步骤:

1. 创建XML文档对象:

Document doc = dBuilder.newDocument();//通过文档创建器创建一个新的文档对象。

2. 把实体对象转换为节点对象添加到创建好的XML文档对象中:

Element root = doc.createElement(“company”);//建立根节点company

doc.appendChild(root);

3. 使用javax.xml.transform包下TransformerFactory类创建文档转换器。

TransformerFactory tFactory = TransformerFactory.newInstance();//创建转换器工厂实例

Transformer tFormer= tFactory.newTransformer();//创建转换器

4. 通过文档转换器将XML文档的源对象转换为可写入本地的结果对象,并写入本地。

DOMSource dSource = new DOMSource(doc);//DOM对象解析为转换器的输入源

//创建一个文件路径为filePath的文件对象,并将文件对象封装到结果集对象中

StreamResult sResult = new StreamResult(new File(filePath));

// 使用转换器将内存中的XML文档输入源转换为结果集输出到本地

tFormer.transform(dSource, sResult);

F. 处理XML文档步骤:

1. 读取本地XML文档。

2. 通过节点的各种操作方法对节点进行增加,修改,删除等操作。

3. 重新将XML文档写入本地。

G. 解析器DOMParser.java的全部源码:

/**

 * Parse XML document with DOM.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author ZhouYuan

 * @since 2010-9-24

 * @version 1.0

 */

//用于各种IO操作

import java.io.*;

//用于从 XML文档获取 DOM文档实例生成 DOM对象树的解析器

import javax.xml.parsers.*;

//用于创建将DOM文档树对象模型转换为XML文档模型的转换器

import javax.xml.transform.*;

//构造DOM文档树源对象

import javax.xml.transform.dom.DOMSource;

//构造XML文档的结果对象

import javax.xml.transform.stream.StreamResult;

//为文档对象模型 (DOM)提供接口API(Java API for XML Processing (JAXP)的组件) 

import org.w3c.dom.*;

//此类可以包含来自 XML解析器或应用程序的基本错误和警告信息

import org.xml.sax.SAXException;

//导入实体类

import domain.*;

/**

 * Parse XML document with DOM.*/

public class DOMParser {

DocumentBuilderFactory dbfactory  //创建DocumentBuilderFactory工厂实例。

= DocumentBuilderFactory.newInstance();

DocumentBuilder dBuilder;

/**

 * XML文档:

 * 从本地读取XML文件,并将XML文档转换为Java对象。

 * @param url将要读取的XML文件的路径

 * @return 返回转换成功的Company对象*/

public Company readXML(String url){

//创建公司对象

Company comp = new Company();

try {

dBuilder = dbfactory.newDocumentBuilder();

/*

  * Document 接口表示整个 HTML XML文档。

* parse方法:解析 URI指定的 XML文档,返回一个新的 DOM Document对象。*/

Document doc = dBuilder.parse(url);

//得到文档的根元素company

Element root = doc.getDocumentElement();

//读取XML文档中的公司信息,并为公司对象设置相关属性。

comp.setAddress(root.getAttribute("address"));

comp.setName(root.getAttribute("name"));

//通过getElementsByTagName读取XML文档中的所有root节点下的department节点。

NodeList depts = root.getElementsByTagName("department");

//创建Department对象数组

Department[] deptList = new Department[depts.getLength()];

/*

 * 读取部门信息,并将部门对象添加至公司对象中。 */

for(int i = 0;i < depts.getLength();i++){

Department dept = new Department();

//使用NodeListitem()方法遍历节点,item(int index)方法可以返回集合中的第 index个项。

Element deptEmt = (Element) depts.item(i);

dept.setName(deptEmt.getAttribute("name"));

dept.setNumber(deptEmt.getAttribute("deptNo"));

//通过getElementsByTagName读取XML文档中的所有deptEmt节点下的employee节点

NodeList emps = deptEmt.getElementsByTagName("employee");

//创建Employee对象数组

Employee[] empList = new Employee[emps.getLength()];

/*

 * 读取雇员信息,并将雇员对象添加至部门对象中。*/

for(int j = 0;j < emps.getLength();j++){

Employee emp = new Employee();

//XML中的employee节点转换为Employee对象emp

Element empEmt = (Element) emps.item(j);

 

emp.setName(empEmt.getTextContent());

emp.setPosition(empEmt.getAttribute("position"));

emp.setTelephone(empEmt.getAttribute("telephone"));

//emp对象添加至Employee对象数组empList

empList[j]=emp;

//将对象数组empList添加至部门对象dept的对象数组属性emp中。

dept.setEmp(empList);

}

//dept对象添加至Department对象数组deptList中。

deptList[i]=dept;

/* 将对象数组deptList添加至公司对象comp的对象数组属性deptList中,

 * 并返回该公司对象。*/

comp.setDept(deptList);

}

} catch (ParserConfigurationException e) {

e.printStackTrace();

}catch (SAXException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return comp;

}

/**

 * XML文档:

 * java对象转换为XML文档,并将文档写入本地

 * @param url将要写入本地的XML文件的路径

 * @param comp需要转换的公司对象

 * @return 返回文档在本地的绝对路径*/

public String writeXML(String url,Company comp){

try {

dBuilder = dbfactory.newDocumentBuilder(); //通过文档创建工厂创建文档创建器,

Document doc = dBuilder.newDocument();//并通过文档创建器创建一个新的文档对象。

Element root = doc.createElement("company");//建立根节点company

//将根结点添加到文档中

doc.appendChild(root);

 

/*

 * 通过循环将公司对象中的部门对象数组转换成部门节点,

 * 并根据部门对象的属性设置部门节点的香瓜那属性,

 * 最后将该部门节点添加至相应的公司节点中 */

for(int i = 0;i < comp.getDept().length;i++){

Department dept = comp.getDept()[i];

Element deptEmt = doc.createElement("department");

deptEmt.setAttribute("deptNo", dept.getNumber());

deptEmt.setAttribute("name", dept.getName());

/*

 * 通过循环将部门对象中的员工对象数组转换成员工节点,

 * 并根据员工对象的属性设置员工节点的相关属性,

 * 最后将该员工节点添加至相应的部门节点中 */

for(int j = 0;j < dept.getEmp().length;j++){

Employee emp = dept.getEmp()[j];

Element empEmt = doc.createElement("employee");

empEmt.setAttribute("position", emp.getPosition());

empEmt.setAttribute("telphone", emp.getTelephone());

Text tNode = doc.createTextNode(emp.getName());

empEmt.appendChild(tNode);

deptEmt.appendChild(empEmt);

}

root.appendChild(deptEmt);

}

 

docToXML(doc, url);

} catch (ParserConfigurationException e) {

e.printStackTrace();

}

return url;

}

/**

 * DOM树对象转换为可以写入本地的XML文档对象

 * @param doc需要转换的DOM对象

 * @param filePath转换后的XML文档存放的

 * @return 写入成功返回true,转换过程中出现异常返回false

 */

public boolean docToXML(Document doc,String filePath){

//XML文档输出到指定的文件

try {

TransformerFactory tFactory = TransformerFactory.newInstance();//创建转换器工厂实例

Transformer tFormer= tFactory.newTransformer();//创建转换器

DOMSource dSource = new DOMSource(doc);//创建DOM输入源

StreamResult sResult = new StreamResult(new File(filePath));//创建输出流

//设置写入XML文件的编码、空白符和版本

tFormer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");

tFormer.setOutputProperty(OutputKeys.INDENT,"yes");

tFormer.setOutputProperty(OutputKeys.VERSION,"1.0");

tFormer.transform(dSource, sResult); // 将内存中的XML文档转换输出到本地

} catch (TransformerConfigurationException e) {

e.printStackTrace();

return false;

}catch (TransformerException e) {

e.printStackTrace();

return false;

}

return true;

}

/**

 * 处理XML文档:

 * 1.修改company节点的address属性为"郑州市金水区文化路与丰产路交叉口向东50SOHO世纪城"

 * 2.修改工程师A的名字为王工程师

 * 3."许刚"添加telephone属性,并将值设置为7654321

 * 4.删除"申林"telephone属性

 *  5.删除名字为"实习生A"employee节点

 * @param inUrl要处理的XML文档的url

 * @param outUrl处理后的XML文档存放的的url

 */

public void XMLHandle(String inUrl,String outUrl){

try {

//获得XML文档的树对象

dBuilder = dbfactory.newDocumentBuilder();

dbfactory.setIgnoringElementContentWhitespace(true);

Document doc = dBuilder.parse(inUrl);

Element company = doc.getDocumentElement();//获得根节点

NodeList emps = company.getElementsByTagName("employee");//获得所有employee节点

//1.修改company节点的address属性

company.setAttribute("address", "郑州市金水区文产路交叉口向东50SOHO世纪城");

//2.修改工程师A的名字为王工程师

//Element emp = (Element) company.getFirstChild().getLastChild();

Element emp = (Element) emps.item(1);

emp.replaceChild(doc.createTextNode("王工程师"),emp.getFirstChild());

//3."许刚"添加telephone属性,并将值设置为7621

emp = (Element) emps.item(0);

emp.setAttribute("telephone", "7654321");

//4.删除"申林"telephone属性

emp = (Element) emps.item(2);

emp.removeAttribute("telephone");

//5.删除名字为"实习生A"employee节点

emp.getParentNode().removeChild(emps.item(3));

//重新写入修改后的XML文档

docToXML(doc,outUrl);

} catch (ParserConfigurationException e) {

e.printStackTrace();

}catch (SAXException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

H. 测试类DOMParserTest.java源码如下

package parsersTest;

/**

 * Test parsers.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author ZhouYuan

 * @since 2010-9-24

 * @version 1.0

 */

//导入解析器

import xmlParsers.DOMParser;

//导入实体类

import domain.Company;

import domain.Department;

import domain.Employee;

 

/**

 * Test DOMParser. */

public class DOMParserTest {

public static void main(String args[]){

//实例化解析器

DOMParser dp = new DOMParser();

//XML测试方法

Company comp = dp.readXML("src/Company.xml");

System.out.println("公司名称:"+comp.getName());

System.out.println("公司地址:"+comp.getAddress());

for(int i =0; i < comp.getDept().length; i++){

Department department = comp.getDept()[i];

System.out.println("\t部门编号:"+department.getNumber()

+"\t部门名称:"+department.getName());

for(int j = 0; j < department.getEmp().length; j++){

Employee employee = department.getEmp()[j];

System.out.println("\t\t部门成员:\n\t\t\t姓名:"+employee.getName()

+"\t职位:"+employee.getPosition()

+"\t联系方式:"+employee.getTelephone());

}

}

//XML测试方法

dp.writeXML("d:\\company.xml", comp);

//处理XML测试方法

dp.XMLHandle("src/Company.xml", "e:\\company.xml");

}

}

3.3  DOM4J方式解析XML

A. 概述:

DOM4J是一个易用的,开源的库,用于XML,XPath,XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX,JAXP

B. 特点:

它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。

它具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件

C. XMLPath简介:

XPath 是一门在 XML文档中查找信息的语言,可用来在 XML文档中对元素和属性进行遍历。XPath使用路径表达式来选取 XML文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

1. 常用的路径表达式和实例,如表3-1所示:

表达式

附加说明

实例

nodename

选取此节点的所有子节点

company:选择company元素的所有子节点

/

从根节点选取

/company:选择根元素company

//

从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置

//employee:选择所有employee子元素,不论它们在文档中什么位置

.

选取当前节点

当前节点为company时:.//employee表示选取company节点下节点名称为employee的所有子节点

..

选取当前节点的父节点

当前节点为employee时:..表示employee的父节点department

@

选取属性

//@lang:选择所有属性名为lang的属性节点,不论它们在文档中什么位置

3-1

2. 常用谓语选择器,如表3-2所示:

实例

说明

/department/employee[1]

选取department 元素的第一个 employee元素。

/department/employee [last()]

选择department元素下的最后一个employee子元素

/department/employee [last()-1]

选择department元素下的倒数第二个employee子元素

/department/employee [position()<3]

选取最前面的两个属于 department元素的子元素的 employee元素。

//employee[@telephone]

选取所有拥有名为 telephone的属性的 employee元素。

//department[employee='实习生A']

选取所有 department元素,且其中子元素 employee的文本内容为实习生A

3-2

D. 在解析过程中需要使用的包、接口和类:

1. 需要导入的3个外部JAR包,如图3-5所示。dom4j-1.6.1.jar可从sourceforge网站上获得;jaxen.jar可从java2s上获得,saxpath.jar也可从java2s上获得,以上jar包同时也可从服务器上获得。

 

3-5

2. 在解析过程中需要使用的包、接口和类:

//使用dom4j解析xml文档的辅助类

import org.dom4j.*;

//需要使用util包下的list接口和Iterator接口

import java.util.*;

//java标准输入输出控制

import java.io.*;

//用于创建使用各种方式读取XML源和以各种方式输出XML源的解析器

import org.dom4j.io.*;

 

//导入实体类

import domain.Company;

import domain.Department;

import domain.Employee;

E. 读取本地XML文档解析并转换为对象的步骤:

该步骤与DOM方式解析XML类似,只不过使用的API和操作方式不同。剑理一致,招式不同。

1. 创建负责把XML文档源文件解析为文档对象树的解析器。

//使用org.dom4j.io.包下DOM4J已经配置好的SAXReader读取XML文档。

SAXReader reader = new SAXReader();

//设置读取文件的编码为UTF-8

reader.setEncoding("utf-8");

//读取url指定的xml文件并返回一个新的DOM4Jdocument对象

Document doc = reader.read(url);

2. 使用list方式和iterator方式遍历节点:

List方式:

//通过Elementelements("nodeName")方法获得子节点并返回一个java标准列表List<Element> emps = deptEmt.elements("employee");

//根据得到的列表大小创建Employee对象数组

Employee[] empList = new Employee[emps.size()];

 

Iterator方式:

//生成遍历department节点下名称为employee的所有元素节点的迭代器

Iterator empIte = root.elementIterator("department");

Element empEmt = (Element) empIte.next();

3. 遍历节点后将节点信息存储在java对象的实体类中,并返回该对象

F. java实体类对象转换为DOM4J文档对象并写入本地的步骤:

1. 创建XML文档对象

//使用DOM4JDocumentHelper类的静态方法createDocument()创建一个XML文档对象。

Document doc = DocumentHelper.createDocument();

2. 使用DOM4J提供的节点操作方法创建节点对象并将java实体类对象中的信息存放至节点对象中。

3. XML对象转换和格式化后写入本地

//使用org.dom4j.io包下的XMLWriter类将DOM4J的文档树对象转换为XML流文件并格式化输出。

XmlWriter xmlWriter;

//创建有格式和缩进的格式化输出对象

OutputFormat format = OutputFormat.createPrettyPrint();

//创建紧凑的无空白符和缩进的格式化输出对象

//OutputFormat format = OutputFormat.createCompactFormat();

format.setEncoding("UTF-8");

//将新的文件输出流对象和格式化对象封装进实例化的XMLWriter对象中

xmlWriter = new XMLWriter(new FileOutputStream(filePath),format);

//使用xmlWriter将文档对象写入本地并关闭

xmlWriter.write(doc);

xmlWriter.close();

G. 使用XpathDOM4J的节点处理方法处理文档:

1. 读取本地XML文档并转换为Document对象

2. 使用XPath获得需要处理的节点,并修改文档对象模型。

3. 将处理好的文档写入本地。

I. 解析器DOM4JParser.java的全部源码:

/**

 * Parse XML document with DOM4J.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author ZhouYuan

 * @since 2010-9-24

 * @version 1.0

 */

package xmlParsers;

//使用dom4j解析xml文档的辅助类

import org.dom4j.*;

//需要使用util包下的list接口和Iterator接口

import java.util.*;

//java标准输入输出控制

import java.io.*;

//用于创建使用各种方式读取XML源和以各种方式输出XML源的解析器

import org.dom4j.io.*;

 

//导入实体类

import domain.Company;

import domain.Department;

import domain.Employee;

 

 

/**

 * Parse XML document with DOM4J.*/

public class DOM4JParser{

/**

 * 使用List方式遍历XML文档

 * @param url XML文件路径

 * @return 返回Company对象

 * @throws DocumentException使用SAXReader读取XML文档时需要处理该异常

 */

@SuppressWarnings("unchecked")

public Company readXMLInList(String url)throws DocumentException{

//创建公司对象

Company comp = new Company();

//使用org.dom4j.io.包下DOM4J已经配置好的SAXReader读取XML文档。

SAXReader reader = new SAXReader();

reader.setEncoding("utf-8");//设置读取文件的编码为UTF-8

Document doc = reader.read(url); //读取url指定的xml文件

//得到文档的根元素company

Element root = doc.getRootElement();

//使用ElementattributeValue(String arg)方法读取XML文档中的公司信息,并为公司对象设置相关属性。

comp.setAddress(root.attributeValue("address"));

comp.setName(root.attributeValue("name"));

//通过elements(String arg)方法读取XML文档中的所有root节点下的department节点并返回一个List 

List<Element> depts = root.elements("department");

//创建Department对象数组

Department[] deptList = new Department[depts.size()];

//读取部门信息,并将部门对象添加至公司对象中。 

for(int i = 0;i < depts.size();i++){

Department dept = new Department();

//使用Listget(int index)方法遍历List,返回列表中的第 每一项。

Element deptEmt = depts.get(i);

dept.setName(deptEmt.attributeValue("name"));

dept.setNumber(deptEmt.attributeValue("deptNo"));

//通过Elementelements("nodeName")方法获得子节点并返回一个java标准列表对象

List<Element> emps = deptEmt.elements("employee");

//根据得到的列表大小创建Employee对象数组

Employee[] empList = new Employee[emps.size()];

/*

 * 读取雇员信息,并将雇员对象添加至部门对象中。*/

for(int j = 0;j < emps.size();j++){

Employee emp = new Employee();

//XML中的employee节点转换为Employee对象emp,并设置对象属性。

Element empEmt = emps.get(j);

emp.setName(empEmt.getText());

emp.setPosition(empEmt.attributeValue("position"));

emp.setTelephone(empEmt.attributeValue("telephone"));

//emp对象添加至Employee对象数组empList

empList[j]=emp;

//将对象数组empList添加至部门对象dept的对象数组属性emp中。

dept.setEmp(empList);

}

//dept对象添加至Department对象数组deptList中。

deptList[i]=dept;

/* 将对象数组deptList添加至公司对象comp的对象数组属性deptList中,

 * 并返回该公司对象。*/

comp.setDept(deptList);

}

return comp;

}

/**

 * 使用Iterator方式遍历XML文档

 * @param url XML文件路径

 * @return 返回Company对象

 * @throws DocumentException使用SAXReader读取XML文档时需要处理该异常

 */

@SuppressWarnings("unchecked")

public Company readXMLInIterator(String url)throws DocumentException{

//创建公司对象

Company comp = new Company();

//使用org.dom4j.io.包下DOM4J已经配置好的SAXReader读取XML文档。

SAXReader reader = new SAXReader();

reader.setEncoding("utf-8");//设置读取文件的编码为UTF-8

Document doc = reader.read(url); //读取url指定的xml文件

//得到文档的根元素company

Element root = doc.getRootElement();

//使用ElementattributeValue(String arg)方法读取XML文档中的公司信息,并为公司对象设置相关属性。

comp.setAddress(root.attributeValue("address"));

comp.setName(root.attributeValue("name"));

//创建Department对象数组

Department[] deptList = new Department[(root.elements("department")).size()];

/*

 * 本段代码解释:读取部门信息,并将部门对象添加至公司对象中。

 * for循环语句解释:生成遍历root节点下名称为department的所有元素节点的迭代器 */

for(Iterator deptIte = root.elementIterator("department");deptIte.hasNext();){

int i=0 ,j=0;//数组下标标志值

Department dept = new Department();

//使用Listget(int index)方法遍历List,返回集合中的第 每一项。

Element deptEmt = (Element) deptIte.next();

dept.setName(deptEmt.attributeValue("name"));

dept.setNumber(deptEmt.attributeValue("deptNo"));

//创建Employee对象数组

Employee[] empList = new Employee[deptEmt.elements("employee").size()];

/*

 * 本段代码:读取雇员信息,并将雇员对象添加至部门对象中。

 * for循环语句:生成遍历deptEmt节点下名称为employee的所有元素节点的迭代器  */

for(Iterator empIte = root.elementIterator("department");deptIte.hasNext();){

Employee emp = new Employee();

//XML中的employee节点转换为Employee对象emp

Element empEmt = (Element) empIte.next();

emp.setName(empEmt.getText());

emp.setPosition(empEmt.attributeValue("position"));

emp.setTelephone(empEmt.attributeValue("telephone"));

//emp对象添加至Employee对象数组empList

empList[j]=emp;j++;

//将对象数组empList添加至部门对象dept的对象数组属性emp中。

dept.setEmp(empList);

}

//dept对象添加至Department对象数组deptList中。

deptList[i]=dept;i++;

/* 将对象数组deptList添加至公司对象comp的对象数组属性deptList中,

 * 并返回该公司对象。*/

comp.setDept(deptList);

}

return comp;

}

 

/**

 * java实体类对象转换为DOM4J文档对象并写入本地

 * @param url文档写入路径

 * @param comp需要转换的java实体类对象

 * @return 成功时返回写入文件的url,失败时返回字符串Some Exception Occurred

 */

public String writeXML(String url,Company comp){

Document doc = DocumentHelper.createDocument(); //通过文档帮助工具创建一个新的文档对象。

Element root = doc.addElement("company")

.addAttribute("name", comp.getName())

.addAttribute("address", comp.getAddress());//建立根节点company并添加至文档中

 

/*

 * 通过循环将公司对象中的部门对象数组转换成部门节点,

 * 并根据部门对象的属性设置部门节点的相关属性,

 * 最后将该部门节点添加至相应的公司节点中 */

for(int i = 0;i < comp.getDept().length;i++){

Department dept = comp.getDept()[i];

Element deptEmt = root.addElement("department")

.addAttribute("deptNo", dept.getNumber())

.addAttribute("name", dept.getName());

/*

 * 通过循环将部门对象中的员工对象数组转换成员工节点,

 * 并根据员工对象的属性设置员工节点的相关属性,

 * 最后将该员工节点添加至相应的部门节点中 */

for(int j = 0;j < dept.getEmp().length;j++){

Employee emp = dept.getEmp()[j];

deptEmt.addElement("employee")

.addAttribute("position", emp.getPosition())

.addAttribute("telephone", emp.getTelephone())

.addText(emp.getName());

}

}

//将文档对象写入本地

if(docToXML(doc,url)){

System.out.println("文件写入成功");return url;

}else{

System.out.println("文件写入失败");return "Some Exception Occurred";}

}

/**

 * DOM树对象转换为可以写入本地的XML文档对象

 * @param doc需要转换的DOM对象

 * @param filePath转换后的XML文档存放的

 * @return 写入成功返回true,转换过程中出现异常返回false

 */

public boolean docToXML(Document doc,String filePath){

try {

// 使用org.dom4j.io包下的XMLWriter类将DOM4J的文档树对象转换为XML流文件并格式化输出。

XMLWriter xmlWriter;

//创建有格式和缩进的格式化输出对象

OutputFormat format = OutputFormat.createPrettyPrint();

//创建紧凑的无空白符和缩进的格式化输出对象

//OutputFormat format = OutputFormat.createCompactFormat();

//设置XML文档的输出编码

format.setEncoding("UTF-8");

//format.setIndent(true);

//format.setNewlines(true);

//将新的文件输出流对象和格式化对象封装进实例化的XMLWriter对象中

xmlWriter = new XMLWriter(new FileOutputStream(filePath),format);

//使用xmlWriter将文档对象写入本地

xmlWriter.write(doc);

xmlWriter.close();

return true;

} catch (IOException e) {

e.printStackTrace();

return false;

}

}

/**

 * 处理XML文档:

 * 1.修改属性:修改company节点的address属性为"郑州市金水区文化路与丰产路交叉口向东50SOHO世纪城"

 * 2.修改文本节点:工程师A的名字为王工程师

 * 3.添加属性:为"许刚"添加telephone属性,并将值设置为7654321

 * 4.删除属性:删除"申林"telephone属性

 *  5.删除节点:删除名字为"实习生A"employee节点

 * @param inUrl要处理的XML文档的url

 * @param outUrl处理后的XML文档存放的的url

 */

@SuppressWarnings("unchecked")

public void XMLHandle(String inUrl,String outUrl){

 

//获得XML文档的树对象

SAXReader reader = new SAXReader();

reader.setEncoding("utf-8");

Document doc;

try {

doc = reader.read(inUrl);

 

Element company = doc.getRootElement();//获得根节点

List empList = company.selectNodes("//employee");//获得所有的employee节点

//1.修改company节点的address属性

company.attributeValue("address", "郑州市金水区文产路交叉口向东50SOHO世纪城");

//2.修改工程师A的名字为王工程师

Node developer = (Node) empList.get(1);

developer.setText("王工程师");

 

//3."许刚"添加telephone属性,并将值设置为7654321

Element xugang = (Element) empList.get(0);

xugang.addAttribute("telephone", "7654321");

 

//4.删除"申林"telephone属性

Element shenlin = (Element) doc.selectSingleNode("//department[2]//employee[1]");

shenlin.remove(shenlin.attribute("telephone"));

//5.删除名字为"实习生A"employee节点

Element shiXiSheng = (Element) doc.selectSingleNode("//department[2]//employee[2]");

Element par = (Element) shiXiSheng.getParent();

par.remove(shiXiSheng);

 

//重新写入修改后的XML文档

docToXML(doc,outUrl);

System.out.println("----------------Success----------------");

} catch (DocumentException e) {

System.out.println("----------------fail----------------");

e.printStackTrace();

}

}

}

J. 测试类DOM4JParserTest.java源码如下

package parsersTest;

/**

 * Test DOM4JParser.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author ZhouYuan

 * @since 2010-9-24

 * @version 1.0

 */

//解析过程中可能抛出此异常

import org.dom4j.DocumentException;

//导入解析器

import xmlParsers.DOM4JParser;

//导入实体类

import domain.Company;

import domain.Department;

import domain.Employee;

 

public class DOM4JParserTest {

 

public static void main(String args[])throws DocumentException{

//实例化解析器

DOM4JParser d4jp = new DOM4JParser();

//使用ListXML测试方法

Company comp = d4jp.readXMLInList("D:\\Company.xml");

System.out.println("公司名称:"+comp.getName());

System.out.println("公司地址:"+comp.getAddress());

for(int i =0; i < comp.getDept().length; i++){

Department department = comp.getDept()[i];

System.out.println("\t部门编号:"+department.getNumber()

+"\t部门名称:"+department.getName());

for(int j = 0; j < department.getEmp().length; j++){

Employee employee = department.getEmp()[j];

System.out.println("\t\t部门成员:\n\t\t\t姓名:"+employee.getName()

+"\t职位:"+employee.getPosition()

+"\t联系方式:"+employee.getTelephone());

}

}

//使用IteratorXML测试方法

comp = d4jp.readXMLInList("src/Company.xml");

System.out.println("公司名称:"+comp.getName());

System.out.println("公司地址:"+comp.getAddress());

for(int i =0; i < comp.getDept().length; i++){

Department department = comp.getDept()[i];

System.out.println("\t部门编号:"+department.getNumber()

+"\t部门名称:"+department.getName());

for(int j = 0; j < department.getEmp().length; j++){

Employee employee = department.getEmp()[j];

System.out.println("\t\t部门成员:\n\t\t\t姓名:"+employee.getName()

+"\t职位:"+employee.getPosition()

+"\t联系方式:"+employee.getTelephone());

}

}

//XML测试方法

d4jp.writeXML("D:\\company.xml", comp);

//处理XML测试方法

d4jp.XMLHandle("src/Company.xml", "F:\\company.xml");

}

}

四、 实战

A. 创建一个新的工程,并创建如下所示的XML实例和对应的实体类对象。

Company.xml源码如下:

<?xml version="1.0" encoding="utf-8"?>

<bookstore>

<book category="database">

  <title lang="中文">数据库系统概论</title>

  <author sex="">萨师煊</author>

  <author>王珊</author>

  <year>2000</year>

</book>

 

<book category="datastructer">

  <title lang="CH">数据结构</title>

  <author email="yanweimin@qq.com">严蔚敏</author>

  <year>2004</year>

  <price>16.00</price>

</book>

 

<book category="java">

  <title lang="英文">JAVA2核心技术卷1</title>

  <author>Cay S. Horstmann</author>

  <author>Cary Cornell</author>

  <year>2006</year>

  <price>88.00</price>

</book>

</bookstore>

B. XML文件读取:使用DOM方式和DOM4J方式读取该XML文件并转换为JAVA实体类对象输出。

C. XML文件写入:使用DOM方式和DOM4J方式将JAVA实体类对象转换为XML文件写入本地。

D. XML文件操作:

1. 增加bookstore节点的address属性,并设置属性值为"河南新华书店"

2. 为数据库系统概论这本书增加price节点,节点值为25.1

3. 修改数据库系统概论的lang属性值为"CH"

4. 修改严蔚敏的名字为"YanWeiMin"

5. 删除类别为java的节点,及其子节点。

6. 删除数据结构这本书作者的email属性

五、 结束语

因本人能力有限,文档中不免有许多不足之处,希望大家能够指出,共同讨论,共同进步。

Yesterday already passed, tomorrrow unknown, live in present!

Just do it!

六、解析XML的四种方式

 

 

XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便。对于XML本身的语法知识与技术细节,需要阅读相关的技术文献,这里面包括的内容有DOM(Document Object Model),DTD(Document Type Definition),SAX(Simple API for XML),XSD(Xml Schema Definition),XSLT(Extensible Stylesheet Language Transformations),具体可参阅w3c官方网站文档http://www.w3.org获取更多信息。

 

XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种叫SAX,另一种叫DOMSAX是基于事件流的解析,DOM是基于XML文档树结构的解析。假设我们XML的内容和结构如下:

<?xml version="1.0" encoding="UTF-8"?>
<employees>
  <employee>
    <name>ddviplinux</name>
    <sex>m</sex>
    <age>30</age>
  </employee>
</employees>

 

本文使用JAVA语言来实现DOMSAXXML文档生成与解析。
首先定义一个操作XML文档的接口XmlDocument它定义了XML文档的建立与解析的接口。

 

package com.alisoft.facepay.framework.bean;
/**
*
* @author hongliang.dinghl
* 定义XML文档建立与解析的接口
*/
public interface XmlDocument {
/**
* 建立XML文档
* @param fileName 文件全路径名称
*/
public void createXml(String fileName);
/**
* 解析XML文档
* @param fileName 文件全路径名称
*/
public void parserXml(String fileName);
}

 

1. DOM生成和解析XML文档

 

XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用DOM 接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。

 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
*
* @author hongliang.dinghl
* DOM生成与解析XML文档
*/
public class DomDemo implements XmlDocument {
    private Document document;
    private String fileName;
public void init() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
this.document = builder.newDocument();
} catch (ParserConfigurationException e) {
System.out.println(e.getMessage());
}
}
public void createXml(String fileName) {
Element root = this.document.createElement("employees");
this.document.appendChild(root);


Element employee = this.document.createElement("employee");


Element name = this.document.createElement("name");
name.appendChild(this.document.createTextNode("丁宏亮"));
employee.appendChild(name);


Element sex = this.document.createElement("sex");
sex.appendChild(this.document.createTextNode("m"));
employee.appendChild(sex);


Element age = this.document.createElement("age");
age.appendChild(this.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, "gb2312");
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 void parserXml(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(fileName);
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++) {
System.out.println(employeeMeta.item(k).getNodeName()
+ ":" + employeeMeta.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());
}
}
}

 

2. SAX生成和解析XML文档

 

为解决DOM的问题,出现了SAXSAX,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;

 

 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.ParserConfigurationException;
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;
/**
*
* @author hongliang.dinghl
* SAX文档解析
*/
public class SaxDemo implements XmlDocument {
public void createXml(String fileName) {
System.out.println("<<"+filename+">>");
}

public 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));
}
}

3. DOM4J生成和解析XML文档

DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java 软件都在使用DOM4J 来读写XML,特别值得一提的是连Sun JAXM 也在用DOM4J

 

 

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;  
/**
*  
* @author hongliang.dinghl
* Dom4j 生成XML文档与解析XML文档
*/
public class Dom4jDemo implements XmlDocument {
public 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("ddvip");
Element sex=employee.addElement("sex");
sex.setText("m");
Element age=employee.addElement("age");
age.setText("29");
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 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());
}
System.out.println("dom4j parserXml");
}
}

4. JDOM生成和解析XML  

为减少DOMSAX的编码量,出现了JDOM;优点:20-80原则,极大减少了代码量。使用场合:要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX(最常用)、DOMXanan文档。

 

import java.io.FileNotFoundException;

import java.io.FileOutputStream;  
import java.io.IOException;  
import java.util.List;  
import org.jdom.Document;  
import org.jdom.Element;  
import org.jdom.JDOMException;  
import org.jdom.input.SAXBuilder;  
import org.jdom.output.XMLOutputter;  

/**
*  
* @author hongliang.dinghl
* JDOM 生成与解析XML文档
*  
*/
public class JDomDemo implements XmlDocument {
public 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 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++){

                   iElement 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 解析 XML

dom4j 是一种解析 XML文档的开放源代码 XML框架。本文介绍如何使用包含在 dom4j中的解析器创建并修改 XML文档。

dom4j API 包含一个解析 XML文档的工具。本文中将使用这个解析器创建一个示例 XML文档。

 

清单 1. 示例 XML 文档(catalog.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<catalog>

<!--An XML Catalog-->

<?target instruction?>

    <journal title="XML Zone" publisher="IBM developerWorks">

        <article level="Intermediate" date="December-2001">

            <title>Java configuration with XML Schema</title>

            <author>

                <firstname>Marcello</firstname>

                <lastname>Vitaletti</lastname>

            </author>

         </article>

    </journal>

</catalog>

 

然后使用同一个解析器修改 catalog.xml,清单2 是修改后的XML 文档,catalog-modified.xml

清单 2. 修改后的XML 文档(catalog-modified.xml

<?xml version="1.0" encoding="UTF-8"?>

<catalog>

<!--An XML catalog-->

<?target instruction?>

    <journal title="XML Zone" publisher="IBM developerWorks">

        <article level="Introductory" date="October-2002">

            <title>Create flexible and extensible XML schemas</title>

            <author>

                <firstname>Ayesha</firstname>

                <lastname>Malik</lastname>

            </author>

        </article>

    </journal>

</catalog>

 

W3C DOM API 相比,使用 dom4j 所包含的解析器的好处是dom4j 拥有本地的XPath 支持。DOM解析器不支持使用 XPath选择节点。

本文包括以下几个部分:

预先设置

创建文档

修改文档

预先设置

这个解析器可以从 http://dom4j.org 获取。通过设置使 dom4j-1.4/dom4j-full.jar能够在 classpath中访问,该文件中包括 dom4j类、XPath引擎以及 SAXDOM接口。如果已经使用了 JAXP解析器中包含的 SAXDOM接口,向 classpath中增加 dom4j-1.4/dom4j.jardom4j.jar包括dom4j 类和XPath 引擎,但是不含SAX DOM 接口。

 

创建文档

本节讨论使用 dom4j API 创建 XML 文档的过程,并创建示例XML 文档catalog.xml

使用 import 语句导入dom4j API 类:

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

 

使用 DocumentHelper 类创建一个文档实例。 DocumentHelper 是生成 XML文档节点的 dom4j API工厂类。

 Document document = DocumentHelper.createDocument();

 

使用 addElement() 方法创建根元素 catalog addElement() 用于向XML 文档中增加元素。

Element catalogElement = document.addElement("catalog");

 

catalog 元素中使用addComment() 方法添加注释“An XML catalog”。

 catalogElement.addComment("An XML catalog");

 

catalog 元素中使用addProcessingInstruction() 方法增加一个处理指令。

catalogElement.addProcessingInstruction("target","text");

 

catalog 元素中使用addElement() 方法增加journal 元素。

Element journalElement =  catalogElement.addElement("journal");

 

使用 addAttribute() 方法向 journal 元素添加title publisher 属性。

journalElement.addAttribute("title", "XML Zone");

journalElement.addAttribute("publisher", "IBM developerWorks");

 

article 元素中添加journal 元素。

Element articleElement=journalElement.addElement("article");

 

article 元素增加level date 属性。

articleElement.addAttribute("level", "Intermediate");

articleElement.addAttribute("date", "December-2001");

 

article 元素中增加title 元素。

Element titleElement=articleElement.addElement("title");

 

使用 setText() 方法设置 article 元素的文本。

titleElement.setText("Java configuration with XML Schema");

 

article 元素中增加author 元素。

Element authorElement=articleElement.addElement("author");

 

author 元素中增加firstname 元素并设置该元素的文本。

Element  firstNameElement=authorElement.addElement("firstname");

firstNameElement.setText("Marcello");

 

author 元素中增加lastname 元素并设置该元素的文本。

Element lastNameElement=authorElement.addElement("lastname");

lastNameElement.setText("Vitaletti");

 

可以使用 addDocType()方法添加文档类型说明。

document.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd");

 

这样就向 XML 文档中增加文档类型说明:

<!DOCTYPE catalog SYSTEM "file://c:/Dtds/catalog.dtd">

 

如果文档要使用文档类型定义(DTD)文档验证则必须有Doctype

XML 声明 <?xml version="1.0" encoding="UTF-8"?>自动添加到 XML文档中。

清单 3 所示的例子程序 XmlDom4J.java 用于创建XML 文档catalog.xml

清单 3. 生成 XML 文档catalog.xml 的程序(XmlDom4J.java

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.dom4j.io.XMLWriter;

import java.io.*;

public class XmlDom4J{

    public void generateDocument(){

        Document document = DocumentHelper.createDocument();

        Element catalogElement = document.addElement("catalog");

        catalogElement.addComment("An XML Catalog");

        catalogElement.addProcessingInstruction("target","text");

        Element journalElement =  catalogElement.addElement("journal");

        journalElement.addAttribute("title", "XML Zone");

        journalElement.addAttribute("publisher", "IBM developerWorks");

        Element articleElement=journalElement.addElement("article");

        articleElement.addAttribute("level", "Intermediate");

        articleElement.addAttribute("date", "December-2001");

        Element  titleElement=articleElement.addElement("title");

        titleElement.setText("Java configuration with XML Schema");

        Element authorElement=articleElement.addElement("author");

        Element  firstNameElement=authorElement.addElement("firstname");

        firstNameElement.setText("Marcello");

        Element lastNameElement=authorElement.addElement("lastname");

        lastNameElement.setText("Vitaletti");

        document.addDocType("catalog",null,"file://c:/Dtds/catalog.dtd");

        try{

            XMLWriter output = new XMLWriter(

                                         new FileWriter(new File("c:/catalog/catalog.xml")));

            output.write( document );

            output.close();

    } catch(IOException e){

        System.out.println(e.getMessage());

    }

    }

    public static void main(String[] argv){

        XmlDom4J dom4j=new XmlDom4J();

        dom4j.generateDocument();

    }

}

 

 

这一节讨论了创建 XML 文档的过程,下一节将介绍使用 dom4j API 修改这里创建的 XML文档。

修改文档

这一节说明如何使用 dom4j API 修改示例 XML 文档catalog.xml

使用 SAXReader 解析 XML 文档catalog.xml

 SAXReader saxReader = new SAXReader();

 Document document = saxReader.read(inputXml);

 

SAXReader 包含在 org.dom4j.io包中。

inputXml 是从 c:/catalog/catalog.xml创建的 java.io.File。使用XPath 表达式从article 元素中获得level 节点列表。如果level 属性值是“Intermediate”则改为“Introductory”。

 List list = document.selectNodes("//article/@level" );

 Iterator iter=list.iterator();

 while(iter.hasNext()){

     Attribute attribute=(Attribute)iter.next();

     if(attribute.getValue().equals("Intermediate"))

     attribute.setValue("Introductory");

 }

 

获取 article 元素列表,从article 元素中的title 元素得到一个迭代器,并修改title 元素的文本。

 list = document.selectNodes("//article" );

 iter=list.iterator();

 while(iter.hasNext()){

     Element element=(Element)iter.next();

     Iterator iterator=element.elementIterator("title");

     while(iterator.hasNext()){

         Element titleElement=(Element)iterator.next();

         if(titleElement.getText().equals("Java configuration with XML Schema"))

         titleElement.setText("Create flexible and extensible XML schema");

     }

}

 

通过和 title 元素类似的过程修改author 元素。

清单 4 所示的示例程序 Dom4JParser.java 用于把catalog.xml 文档修改成catalog-modified.xml 文档。

清单 4. 用于修改catalog.xml 的程序(Dom4Jparser.java

import org.dom4j.Document;

import org.dom4j.Element;

import org.dom4j.Attribute;

import java.util.List;

import java.util.Iterator;

import org.dom4j.io.XMLWriter;

import java.io.*;

import org.dom4j.DocumentException;

import org.dom4j.io.SAXReader;

public class Dom4JParser{

public void modifyDocument(File inputXml){

    try{

        SAXReader saxReader = new SAXReader();

        Document document = saxReader.read(inputXml);

        List list = document.selectNodes("//article/@level" );

        Iterator iter=list.iterator();

        while(iter.hasNext()){

            Attribute attribute=(Attribute)iter.next();

            if(attribute.getValue().equals("Intermediate"))

            attribute.setValue("Introductory");

        }

        list = document.selectNodes("//article/@date" );

        iter=list.iterator();

        while(iter.hasNext()){

            Attribute attribute=(Attribute)iter.next();

            if(attribute.getValue().equals("December-2001"))

            attribute.setValue("October-2002");

        }

        list = document.selectNodes("//article" );

        iter=list.iterator();

        while(iter.hasNext()){

            Element element=(Element)iter.next();

            Iterator iterator=element.elementIterator("title");

            while(iterator.hasNext()){

                Element titleElement=(Element)iterator.next();

                if(titleElement.getText().equals("Java configuration with XMLSchema"))

                titleElement.setText("Create flexible and extensible XML schema");

            }

        }

        list = document.selectNodes("//article/author" );

        iter=list.iterator();

        while(iter.hasNext()){

            Element element=(Element)iter.next();

            Iterator iterator=element.elementIterator("firstname");

            while(iterator.hasNext()){

                Element firstNameElement=(Element)iterator.next();

                if(firstNameElement.getText().equals("Marcello"))

                firstNameElement.setText("Ayesha");

            }

        }

        list = document.selectNodes("//article/author" );

        iter=list.iterator();

        while(iter.hasNext()){

            Element element=(Element)iter.next();

            Iterator iterator=element.elementIterator("lastname");

            while(iterator.hasNext()){

                Element lastNameElement=(Element)iterator.next();

                if(lastNameElement.getText().equals("Vitaletti"))

                lastNameElement.setText("Malik");

            }

        }

        XMLWriter output = new XMLWriter(

                               new FileWriter( new File("c:/catalog/catalog-modified.xml") ));

        output.write( document );

        output.close();

    } catch(DocumentException e) {

        System.out.println(e.getMessage());

    } catch(IOException e){

        System.out.println(e.getMessage());

    }

}

public static void main(String[] argv){

    Dom4JParser dom4jParser=new Dom4JParser();

    dom4jParser.modifyDocument(new File("c:/catalog/catalog.xml"));

}

}

 

这一节说明了如何使用 dom4j 中的解析器修改示例 XML 文档。这个解析器不使用DTD 或者模式验证XML 文档。如果XML 文档需要验证,可以解释用dom4j JAXP SAX 解析器。

 

结束语

包含在 dom4j 中的解析器是一种用于解析XML 文档的非验证性工具,可以与JAXPCrimsonXerces集成。本文说明了如何使用该解析器创建和修改 XML文档。

 

0 0