一、DOM4J
1、特点:最优秀的一个,集易用和性能于一身。开放源代码(需要导入外部jar包:dom4j-1.6.1.jar)2、场合:使用DOM4J
Attribute定义了XML的属性
| |
Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为,
| |
CDATA 定义了XML CDATA 区域
| |
CharacterData是一个标识借口,标识基于字符的节点。如CDATA,Comment, Text.
| |
Comment 定义了XML注释的行为
| |
定义了XML文档
| |
DocumentType 定义XML DOCTYPE声明
| |
Element定义XML 元素
| |
ElementHandler定义了 Element 对象的处理器
| |
Entity定义 XML entity
| |
Node为所有的dom4j中XML节点定义了多态行为
| |
NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate)
| |
ProcessingInstruction 定义 XML 处理指令.
| |
Text 定义XML 文本节点.
| |
Visitor 用于实现Visitor模式.
| |
XPath 在分析一个字符串后会提供一个XPath 表达式
|
SAXReader reader = new SAXReader(); Document doc = reader.read(File xmlfile);
List childNodes = doc.selectNodes("//Config/Child/ChildNode" );
for (Object obj:childNodes) {
Node childNode = (Node)obj;
String name = childNode.valueOf("@name" );
String text = childNode.getText();
}
一.Document对象相关
1 .读取XML文件,获得document对象.
SAXReader reader = new SAXReader();
Document document = reader.read(new File( "input.xml" ));
2 .解析XML形式的文本,得到document对象.
String text = "<members></members>" ;
Document document = DocumentHelper.parseText(text);
3 .主动创建document对象.
Document document = DocumentHelper.createDocument();
Element root = document.addElement("members" ); // 创建根节点
二.节点相关
1 .获取文档的根节点.
Element rootElm = document.getRootElement();
2 .取得某节点的单个子节点.
Element memberElm=root.element("member" ); // "member"是节点名
3 .取得节点的文字
String text=memberElm.getText();也可以用:
String text=root.elementText("name" );这个是取得根节点下的name字节点的文字.
4 .取得某节点下名为 "member" 的所有字节点并进行遍历.
List nodes = rootElm.elements("member" );
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
// do something
}
5 .对某节点下的所有子节点进行遍历.
for (Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
// do something
}
6 .在某节点下添加子节点.
Element ageElm = newMemberElm.addElement("age" );
7 .设置节点文字.
ageElm.setText("29" );
8 .删除某节点.
parentElm.remove(childElm);// childElm是待删除的节点,parentElm是其父节点
9 .添加一个CDATA节点.
Element contentElm = infoElm.addElement("content" );
contentElm.addCDATA(diary.getContent());
三.属性相关.
1 .取得某节点下的某属性
Element root=document.getRootElement();
Attribute attribute=root.attribute("size" ); // 属性名name
2 .取得属性的文字
String text=attribute.getText();也可以用:
String text2=root.element("name" ).attributeValue( "firstname" );这个是取得根节点下name字节点的属性firstname的值.
3 .遍历某节点的所有属性
Element root=document.getRootElement();
for (Iterator it=root.attributeIterator();it.hasNext();){
Attribute attribute = (Attribute) it.next();
String text=attribute.getText();
System.out.println(text);
}
4 .设置某节点的属性和文字.
newMemberElm.addAttribute("name" , "sitinspring" );
5 .设置属性的文字
Attribute attribute=root.attribute("name" );
attribute.setText("sitinspring" );
6 .删除某属性
Attribute attribute=root.attribute("size" ); // 属性名name
root.remove(attribute);
四.将文档写入XML文件.
1 .文档中全为英文,不设置编码,直接写入的形式.
XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ));
writer.write(document);
writer.close();
2 .文档中含有中文,设置编码格式写入的形式.(或以美化的格式输出到文件)
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("GBK" ); // 指定XML编码
XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ),format);
writer.write(document);
writer.close();
五.字符串与XML的转换
1 .将字符串转化为XML
String text = "<members> <member>sitinspring</member> </members>" ;
Document document = DocumentHelper.parseText(text);
2 .将文档或节点的XML转化为字符串.
SAXReader reader = new SAXReader();
Document document = reader.read(new File( "input.xml" ));
Element root=document.getRootElement();
String docXmlText=document.asXML();
String rootXmlText=root.asXML();
Element memberElm=root.element("member" );
String memberXmlText=memberElm.asXML();
dom4j API 包含一个解析 XML 文档的工具。本文中将使用这个解析器创建一个示例 XML 文档。清单 1 显示了这个示例 XML 文档,catalog.xml。
与 W3C DOM API 相比,使用 dom4j 所包含的解析器的好处是 dom4j 拥有本地的 XPath 支持。DOM 解析器不支持使用 XPath 选择节点。
/*DOM4J提供至少3种遍历节点的方法*/
//1) 枚举(Iterator)
// 枚举所有子节点
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
Element element = (Element) i.next();
// do something
}
// 枚举名称为foo的节点
for ( Iterator i = root.elementIterator(foo); i.hasNext();) {
Element foo = (Element) i.next();
// do something
}
// 枚举属性
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
Attribute attribute = (Attribute) i.next();
// do something
}
//2)递归
//递归也可以采用Iterator作为枚举手段,但文档中提供了另外的做法
public void treeWalk() {
treeWalk(getRootElement());
}
public void treeWalk(Element element) {
for (int i = 0, size = element.nodeCount(); i < size; i++) {
Node node = element.node(i);
if (node instanceof Element) {
treeWalk((Element) node);
} else { // do something....
}
}
}
//3) Visitor模式
//主要原理就是两种类互相保有对方的引用,并且一种作为Visitor去访问许多Visitable。只需要自定一个类实现Visitor接口即可。
public class MyVisitor extends VisitorSupport {
public void visit(Element element){
System.out.println(element.getName());
}
public void visit(Attribute attr){
System.out.println(attr.getName());
}
}
//调用: root.accept(new MyVisitor())
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文档
*/
public class Dom4jDemo {
/**
* 利用dom4j进行xml文档的写入操作
*/
public void createXml(File file) {
// XML 声明 <?xml version="1.0" encoding="UTF-8"?> 自动添加到 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 文档中增加文档类型说明:
// <!DOCTYPE employees SYSTEM "file://E:/Dtds/dom4j.dtd">
// 如果文档要使用文档类型定义(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);
}
}
/*修改xml文档*/
public static void modifyxml(){
//使用SAXReader去解析xml文件
SAXReader reader=new SAXReader();
Document document;
try {
File file =new File("C:\\workspace\\Test\\myxml.xml");
//获取document对象
document=reader.read(file);
//通过selectNodes寻找节点或者属性
List list=document.selectNodes("/student/call/@show");
Iterator it=list.iterator();
while(it.hasNext()){
//Attribute属性的操作方法
Attribute attribute=(Attribute)it.next();
if(attribute.getValue().equals("yes"))
{
attribute.setValue("no");
}
}
list =document.selectNodes("/student/call/name");
it=list.iterator();
while(it.hasNext()){
//标签内容的操作方法
Element nameElment=(Element)it.next();
nameElment.setText("studentname");
}
//删除某个节点是要用两层循环,因为删除当前节点必须用父节点去删除。
list=document.selectNodes("/student/call");
it=list.iterator();
while(it.hasNext()){
//获取父节点
Element scoreElement=(Element)it.next();
System.out.println(scoreElement);
@SuppressWarnings("unused")
//获取该父节点下面的需要查找的子节点
Iterator itera=scoreElement.elementIterator("English");
while(itera.hasNext()){
Element scoreEnglish=(Element)itera.next();
if(scoreEnglish.getText().equals("77")){
//利用父节点去删除
scoreElement.remove(scoreEnglish);
}
}
}
@SuppressWarnings("unused")
/*Iterator itera=document.getRootElement().elementIterator("call");
while(itera.hasNext()){
Element ele=(Element)itera.next();
System.out.println(ele);
}*/
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer;
try {
writer = new XMLWriter(new FileWriter("myxml.xml"),format);
writer.write(document);
writer.close();
}catch (IOException e) {
e.printStackTrace();
}catch (DocumentException e) {
e.printStackTrace();
}
}
二、JDOM
1、原理:纯Java的处理XML的API,要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX、DOM、Xanan文档。(需要导入外部jar包:jdom.jar)
2、优点:a、是基于树的处理XML的Java API,把树加载在内存中,具有DOM方式的优点。
b、没有向下兼容的限制,因此比DOM简单
c、可速度快,缺陷少
d、具有SAX的JAVA规则
3、 缺点:a、不能处理大于内存的文档。Dom方式的缺点
b、JDOM表示XML文档逻辑模型。不能保证每个字节真正变换。
c、针对实例文档不提供DTD与模式的任何实际模型。
d、不支持与DOM中相应遍历包
4、场合:在需要平衡时使用。JDOM具有树的便利,也有SAX的JAVA规则。
//导入jar包:jdom.jar 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文档
*/
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>" + sex.getText());
Element age = ele.getChild("age");
System.out.println("<age>" + age.getText());
} catch (NullPointerException e) {
System.out.println(ele.getTextTrim());
Element name = ele.getChild("name");
System.out.println("<name>" + name.getName());
}
System.out.println("</employee>");
}
System.out.println("</employees>");
}
/**
* 测试
*/
public static void main(String[] args) {
JdomDemo jdom = new JdomDemo();
File file = new File("E://jdom.xml");
jdom.createXml(file);
jdom.parserXml(file);
}
}
三、DOM
1、原理:DOM是基于树的结构,解析器读入-整个-文档,然后构建一个驻留内存的树结构,使用 DOM 接 口来操作这个树结构。2、优点:a、由于整棵树在内存中,便于操作,可以对xml文档随机访问
b、可以对xml文档进行删除、修改、重新排列等多种功能;访问效率高
c、较sax,dom使用也更简单。
3、缺点:a、整个文档必须一次性解析完(无用的节点也会解析),浪费时间和空间.
b、由于整个文档都需要载入内存,对于大文档成本高
4、 场合:小型xml文档;一旦解析了文档还需多次访问这些数据;
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文档的读取操作
*/
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("<employees>");
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("<test>");
System.out.println(child);
if (child.getNodeType() == Node.ELEMENT_NODE) {
System.out.print("<id>");
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("<name>");
System.out.println(node.getFirstChild().getNodeValue());
}
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("sex".equals(node.getNodeName())) {
System.out.print("<sex>");
System.out.println(node.getFirstChild().getNodeValue());
}
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("age".equals(node.getNodeName())) {
System.out.print("<age>");
System.out.println(node.getFirstChild().getNodeValue());
}
}
if (node.getNodeType() == Node.ELEMENT_NODE) {
if ("email".equals(node.getNodeName())) {
System.out.print("<email>");
System.out.println(node.getFirstChild().getNodeValue());
}
}
}
}
}
System.out.println("解析完毕");
}
/**
* 测试
*/
public static void main(String[] args) {
// 为什么有类似于这样东西[#text:]
// 原因是XML文件元素之间的空白字符也是一个元素,<employees></employees>包含的空白
DomDemo dom = new DomDemo();
File file = new File("E://dom.xml");
dom.createXml(file);
dom.parserXml(file);
}
}
四、SAX
1、原理:SAX类似流媒体,它基于事件驱动,当解析器发现元素开始、元素结束、文本、文档的开始或结束 等时,发送事件,程序员编写响应这些事件的代码,保存数据。无需将整个文档载入内存,使用者 只需要监听自己感兴趣的事件即可。2、优点:a、无需将整个xml文档载入内存,因此消耗内存少
b、SAX解析器代码比DOM解析器代码小,适于Applet,下载。
c、可以注册多个ContentHandler
3、缺点:a、不能随机的访问xml中的节点
b、只支持读,不能修改文档。非持久,事件过后,若没保存数据,那么数据就丢了
c、无状态性;从事件中只能得到文本,但不知该文本属于哪个元素
4、场合:大型xml文档;Applet;只需XML文档的少量内容,很少回头访问;
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;
/**
* startDocument(),endDocument(),startElement(),endElement(),characters()
*/
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();
}
}
}
五、资料(关于Xpath)
1、选取节点
XPath 使用路径表达式在 XML 文档中选取节点,节点是沿着路径或者 step 来选取的。
常见的路径表达式:
表达式 | 描述 |
nodename | 选取当前节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
实例
路径表达式 | 结果 |
bookstore | 选取 bookstore 元素的所有子节点 |
/bookstore | 选取根元素 bookstore |
bookstore/book | 选取bookstore 下名字为 book的所有子元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选取bookstore 下名字为 book的所有后代元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取所有名为 lang 的属性。 |
2、谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
实例
常见的谓语的一些路径表达式:
路径表达式 | 结果 |
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] | 选取所有 title 元素,要求这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取所有 bookstore 元素的 book 元素,要求book元素的子元素 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取所有 bookstore 元素中的 book 元素的 title 元素,要求book元素的子元素 price 元素的值须大于 35.00 |
3、选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
实例
路径表达式 | 结果 |
/bookstore/* | 选取 bookstore 元素的所有子节点 |
//* | 选取文档中的所有元素 |
//title[@*] | 选取所有带有属性的 title 元素。 |
4、选取若干路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
实例
路径表达式 | 结果 |
//book/title | //book/price | 选取所有 book 元素的 title 和 price 元素。 |
//title | //price | 选取所有文档中的 title 和 price 元素。 |
/bookstore/book/title|//price | 选取所有属于 bookstore 元素的 book 元素的 title 元素,以及文档中所有的 price 元素。 |
5、XPath 轴
轴可定义某个相对于当前节点的节点集。
轴名称 | 结果 |
ancestor | 选取当前节点的所有先辈(父、祖父等) |
ancestor-or-self | 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 |
attribute | 选取当前节点的所有属性 |
child | 选取当前节点的所有子元素。 |
descendant | 选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 选取文档中当前节点的结束标签之后的所有节点。 |
namespace | 选取当前节点的所有命名空间节点 |
parent | 选取当前节点的父节点。 |
preceding | 选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 选取当前节点之前的所有同级节点。 |
self | 选取当前节点。 |
6、路径
- 位置路径表达式
位置路径可以是绝对的,也可以是相对的。
绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:
- 绝对位置路径:
- 相对位置路径:
/step/step/...
step/step/...
每个步均根据当前节点集之中的节点来进行计算。
- 步(step)包括:
轴(axis):定义所选节点与当前节点之间的树关系
节点测试(node-test):识别某个轴内部的节点
零个或者更多谓语(predicate):更深入地提炼所选的节点集
步的语法:轴名称::节点测试[谓语]
实例
例子 | 结果 |
child::book | 选取所有属于当前节点的子元素的 book 节点 |
attribute::lang | 选取当前节点的 lang 属性 |
child::* | 选取当前节点的所有子元素 |
attribute::* | 选取当前节点的所有属性 |
child::text() | 选取当前节点的所有文本子节点 |
child::node() | 选取当前节点的所有子节点 |
descendant::book | 选取当前节点的所有 book 后代 |
ancestor::book | 选择当前节点的所有 book 先辈 |
ancestor-or-self::book | 选取当前节点的所有book先辈以及当前节点(假如此节点是book节点的话) |
child::*/child::price | 选取当前节点的所有 price 孙。 |
7、XPath 运算符
运算符 | 描述 | 实例 | 返回值 |
| | 计算两个节点集 | //book | //cd | 返回所有带有 book 和 ck 元素的节点集 |
+ | 加法 | 6 + 4 | 10 |
- | 减法 | 6 - 4 | 2 |
* | 乘法 | 6 * 4 | 24 |
div | 除法 | 8 div 4 | 2 |
= | 等于 | price=9.80 | 如果 price 是 9.80,则返回 true。 如果 price 是 9.90,则返回 fasle。 |
!= | 不等于 | price!=9.80 | 如果 price 是 9.90,则返回 true。 如果 price 是 9.80,则返回 fasle。 |
< | 小于 | price<9.80 | 如果 price 是 9.00,则返回 true。 如果 price 是 9.90,则返回 fasle。 |
<= | 小于或等于 | price<=9.80 | 如果 price 是 9.00,则返回 true。 如果 price 是 9.90,则返回 fasle。 |
> | 大于 | price>9.80 | 如果 price 是 9.90,则返回 true。 如果 price 是 9.80,则返回 fasle。 |
>= | 大于或等于 | price>=9.80 | 如果 price 是 9.90,则返回 true。 如果 price 是 9.70,则返回 fasle。 |
or | 或 | price=9.80 or price=9.70 | 如果 price 是 9.80,则返回 true。 如果 price 是 9.50,则返回 fasle。 |
and | 与 | price>9.00 and price<9.90 | 如果 price 是 9.80,则返回 true。 如果 price 是 8.50,则返回 fasle。 |
mod | 计算除法的余数 | 5 mod 2 | 1 |
大部分源代码来源于:http://blog.csdn.net/sdsky1987/article/details/7286306
部分资料来源于:http://sharep.blog.51cto.com/539048/170467
Dom4j大部分资料来源于:http://blog.csdn.net/dy_smile/article/details/5926811
Xpath部分内容来源于:http://nemogu.iteye.com/blog/1305503
本人整理而成