一、dom4j解析xml
二、删改xml文档
三、xPath技术
四、SAX解析xml
一、dom4j解析xml
xml 是一种可可扩展标记语言,用于标记电子文件使其具有结构性的标记语言。标记指计算机能理解得信息符号,通过此种标记,计算机之间可以处理包含各种的信息。也可以用来标记数据,定义数据类型,是一种允用户对自己的标记语言进行定义的源语言。xml文件除了给开发者看,更多情况是程序读取xml文件的内容
-
xml解析的方式:
1、DOM解析
-
1)JAXP
2)JDOM
3)Dom4J(三大框架的默认读取xml工具就是Dom4J)
2、SAX解析
- 1)Sax
dom4j是一个Java的XML API,用来读写XML文件的。Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。
xml解析器把解析xml文档时,把xml文件的各个部分的内容封装成对象,我们通过这些对象来操作xml文档,这种方法叫做DOM解析(DOM编程)
-
Document树只有一个根标签。树上分分子,叫节点Node()
节点的信息(封装在Node对象):
-
1、节点名称
2、节点类型(标签节点,属性节点,文本节点,注释节点)
节点类型
-
1、标签节点: 封装在Element对象
标签名称
2、属性节点: 封装在Attribute对象
属性名称
属性值
3、文本节点: 封装在Text对象
文本内容
调用dom4j的类,需要导入dom4j的jar包。
下载dom4j.jar
dom4j解析xml主要用到的类和方法主要有:
//SAXReader creates a DOM4J tree from SAX parsing events.
//SAXReader 从解析xml文件,创建一个dom4J树
SAXReader sax = new SAXReader();
Document doc = sax.read()
//Returns the root Element for this document.
//返回一个根标签
Element rootElement = doc.getRootElement();
//后面,就主要是Element标签的操作。
//Returns the attributes that this element contains as a List
//返回一个属性列表
public List attributes()
//Returns an iterator over all this elements child elements.
//返回子标签的迭代器
public Iterator elementIterator()
//返回根据子标签的名字,返回子标签的文本内容
public String elementText(String name)
相应的代码:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* Description:
* 使用domj4解析xml文件
*
* @author Lee
* */
public class Parser {
/**
* Description :
* 使用dom4j的SAXReader类解析xml文件
*
* */
public static void test1(){
/*
* SAXReader creates a DOM4J tree from SAX parsing events.
* */
SAXReader sax = new SAXReader();
try{
/*
* Reads a document from a given stream.
* return a newly document instance.
* 从输入流中读取一个ducument实例,并返回。
* Document对象,代表一个完整xml文档。
* 通过Document对象可以得到其下面的其他节点对象,通过节点对象获取相应的信息。
* */
Document doc = sax.read(
new FileInputStream(
"C:\\Users\\lenovopc\\workspace\\"
+ "Demo\\src\\prop.xml"));
//获取根元素
Element rootElement = doc.getRootElement();
//获取根元素的迭代器
Iterator iterator = rootElement.elementIterator();
while(iterator.hasNext()){
//获取子元素
Element subElement = (Element)iterator.next();
/*
* This returns the attribute value for the attribute with the given name
* and any namespace or null if there is no such attribute
* or the empty string if the attribute value is empty.
*
* */
//获取子元素的id属性的值
String id = subElement.attributeValue("id");
//或许子元素的孙元素的值
String name = subElement.elementText("name");
String sex = subElement.elementText("sex");
System.out.println("id="+id+",name="+name+",sex="+sex);
}
}catch(IOException e){
e.printStackTrace();
}catch(DocumentException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
test1();
}
}
二、删改xml文档
dom4j删改xml主要用到的类和方法主要有:
//XMLWriter takes a DOM4J tree and formats it to a stream as XML.
//XMLWriter 将一个dom4j树,格式化输出成一个xml文档
public class XMLWriter extends XMLFilterImpl implements LexicalHandler
//This will print the Document to the current Writer.
public void write(Document doc) throws IOException
//创建一个DOM4J树
public final class DocumentHelper extends Object
public static Document createDocument()
//1、增加:
DocumentHelper.createDocument() //增加文档
addElement("名称") //增加标签
addAttribute("名称",“值”) //增加属性
//2、修改:
Attribute.setValue("值") //修改属性值
Element.addAtribute("同名的属性名","值") //修改同名的属性值
Element.setText("内容") //修改文本内容
//3、删除
Element.detach(); //删除标签
Attribute.detach(); //删除属性
package com.xml;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
/**
* Description:
* 使用dom4j修改xml文件
*
* @author Lee
* */
public class Modify {
/**
* Description:
* 创建一个document对象,添加标签、属性,并输出成一个xml文件
*
*
* */
public static void test1(){
//创一个document对象
Document doc = DocumentHelper.createDocument();
//添加一个根标签(有且仅有一个根标签)
Element rootElt = doc.addElement("Students");
//为根标签添加子标签
Element subElt1 = rootElt.addElement("student");
Element subElt2 = rootElt.addElement("student");
//为子标签添加属性
subElt1.addAttribute("id", "1");
subElt2.addAttribute("id", "2");
//为子标签添加文本
subElt1.addText("lee");
subElt2.addText("wang");
//指定xml格式,编码
OutputFormat format = OutputFormat.createPrettyPrint();
//OutputFormat fotmat = OutputFormat.createCompactFormat();
format.setEncoding("utf-8");
//输出该xml文档
XMLWriter writer = null;
try{
writer = new XMLWriter(
new FileOutputStream("./newprop.xml"),format);
//将document对象输出成一个xml文件
writer.write(doc);
}catch(IOException e){
e.printStackTrace();
}finally{
//关闭资源
try{
writer.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
/**
* Description:
* 修改,删除xml文件内容
*
* */
public static void test2(){
//修改属性、文本
//方法一:获得标签对象, 获得属性对象,修改属性对象的值
//elt.attribute().setValue("");
//方法二:获取标签对象,添加一个同名属性的犯法,来修改属性对象的值
//elt.addAttribute();
//删除标签,属性,文本
//elt.detach();自我移除 parentElt.remove(childElt);通过父标签移除子标签
//读取想要修改的xml文件
SAXReader reader = new SAXReader();
Document doc = null;
try{
doc = reader.read(new FileInputStream("./newprop.xml"));
}catch(IOException |DocumentException e){
e.printStackTrace();
}
//获取根标签
Element rootElt = doc.getRootElement();
//获取所有子标签(这里并不是通用的方法,是建立在我们已经知道只有两个标签)
List<?> subElt = rootElt.elements();
Element subElt1 = (Element)subElt.get(0);
Element subElt2 = (Element)subElt.get(1);
//获取标签属性的对象,修改属性对象的值
subElt1.attribute("id").setValue("0");
//也可以通过添加同名属性来修改标签属性
//subElt1.addAttribute("id","0");
//修改标签文本值,同时也可以修改为空字符,以达到删除文本的目的
subElt1.setText("huang");
//获取标签的属性对象,调用detach()方法删除该属性对象
subElt2.attribute("id").detach();
//或者通过标签对象调用remove()方法传入属相对象,删除该属性对象
//subElt2.remove(subElt2.attribute("id"));
//标签对象通过调用detach()方法,移除标签对象本身
subElt2.detach();
//也可以通过父标签remove()方法,移除子标签
//rootElt.remove(subElt2);
//设置文本编码,格式
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
//将document对象输出为xml文件
XMLWriter writer = null;
try{
writer = new XMLWriter(
new FileOutputStream("./newprop.xml"),format);
writer.write(doc);
}catch(IOException e){
e.printStackTrace();
}finally{
//关闭资源
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
test1();
//test2();
}
}
三、xPath技术
XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。
主要用于快速获取所需要的节点对象。xpath是一门xml文档中查找信息语言,xpath可以用来xml文档中对元素和属性进行遍历。
dom4j内置支持xpath技术
调用xPath的类,需要导入xPath的jar包。可以在dom4j的jar包中找得到
\\dom4j-1.6.1\lib\jaxen-1.1-beta-6.jar
简单xPath语法
/ 绝对路径 表示从xml的根位置开始子元素
// 相对路径 表示不分任何层次结构的选择元素
* 通配符 表示匹配所有元素
[] 条件 表示选择什么条件下元素
@ 属性 通过前缀@来指定
and 且关系
简单的例子:
[1] 代表第一个
[last()] 代表最后一个
//BBB[@*] 代表所有有属性的BBB元素
//BBB[not(@*)] 代表所有没有属性的BBB元素
//BBB[@id='b1'] 带表所有id属性且值为B1的BB元素
//name/text() 代表所有name标签节点的文本
//student/name[text='lee'] 代表所有student标签下name标签文本内容为lee的name标签(然后。通过name标签对象获取父标签对象)
关于xpath语法见于官方网站…](http://www.zvon.org/xxl/XPathTutorial/Output_chi)
xPath主要用到的方法
List<Node> selectNodes("xpath表达式"); //查询多个节点对象
Node selectSingleNode("xpath表达式"); //查询一个节点对象
package com.xml;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/**
* Description:
* 使用xPath技术
*
* @author lee
*
* */
public class XPath {
/**
* Description:
* xPath技术快速找到需要的节点
*
* */
public static void test1(){
//xpath的表达式就是xpath的语法
//List<Node> document.selectNodes("xpath的表达式");
//Node document.selectSingleNode("xpath的表达式");
//读取xml文档
Document doc = null;
try{
doc = new SAXReader().read(new FileInputStream("./newprop.xml"));
}catch(IOException |DocumentException e){
e.printStackTrace();
}
//通过xPath技术,快速地找到所需要的节点
// //student[@id='2'] -> 找到第一个有id属性且值为2的student标签节点
Element stuElt1 = (Element)doc.selectSingleNode("//student[@id='2']");
if(stuElt1!=null)
stuElt1.setText("huang");
else
System.out.println("未找到该标签");
// //student[text()='lee'] -> 找到第一个文本内容为lee的student标签节点
Element stuElt2 = (Element)doc.selectSingleNode("//student[text()='lee']");
if(stuElt2!=null)
stuElt2.setText("zeng");
else
System.out.println("未找到该标签!");
//指定编码,格式
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
//将documen对象苏输出成xml文档
XMLWriter writer = null;
try{
writer = new XMLWriter(new FileOutputStream("./newprop.xml"),format);
writer.write(doc);
}catch(IOException e){
e.printStackTrace();
}finally{
try{
writer.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
test1();
}
}
程序所生成,调用xml文件内容:
<?xml version="1.0" encoding="utf-8"?>
<Students>
<student id="1">lee</student>
<student id="2">wang</student>
</Students>
四、SAX解析xml
SAX,全称Simple API for XML,既是一种接口,也是一种软件包。它是一种XML解析的替代方法。SAX不同于DOM解析,它逐行扫描文档,一边扫描一边解析。
由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,相比DOM解析原理(一次性把xml文档加载进内存然后在内存中构建documen树。不适合读取大容量的文件,容易导致内存溢出。),对于大型文档的解析是个巨大优势。实际上,sax解析是基于事件的编程方法,当调用SAXParser的parse()方法去解析一个xml文档的时候,该方法会会从xml文件中,从上到下逐步地读取,当读取到相应的内容时就会调用像相应的方法。
而我们需要做的就是,实现DefaultHandler接口的方法。实现方法,在遇到相应内容时,做出相应的处理。
SAX解析主要用到的类和方法
//以下,是DefaultHandler接口的关键方法
//Receive notification of the beginning of the document.
//当开始读取整个document树时调用该方法
public void startDocument() throws SAXException
//Receive notification of the end of the document.
//当结束读取document树时调用该方法
public void endDocument() throws SAXException
//Receive notification of the start of an element.
//当读取到开始标签时调用该方法
public void startElement(String uri,
String localName,
String qName,
Attributes attributes)
throws SAXException
//Receive notification of the end of an element.
//当读到结束标签时调用该方法
public void endElement(String uri,
String localName,
String qName)
throws SAXException
//Receive notification of character data inside an element.
//读到文本内容时会调用该方法
public void characters(char[] ch,
int start,
int length)
throws SAXException
例如,我们将xml原因输出在控制台中。
package com.xml;
import java.io.FileInputStream;
import java.io.IOException;
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;
/**
* Description:
* 用sax解析xml文件
*
* @author lee
* */
public class SAX {
/**
* Description:
* sax解析xml文件
* */
public static void test1(){
//创建一个SAXParser对象
//SAXParser的构造方法是protected的,需要通过调用工厂类创建SAXParser类
SAXParser parser = null;
try{
//构造一个SAXParser对象
parser = SAXParserFactory.newInstance().newSAXParser();
}catch(SAXException | ParserConfigurationException e){
e.printStackTrace();
}
//传入一个实现SAX2 事件处理程序的默认基类的类,来解析xml文件
try{
parser.parse(new FileInputStream("./newprop.xml"), new MyDefaultHandler());
}catch(SAXException |IOException e){
e.printStackTrace();
}
}
/**
* Description:
* 主方法
*
* */
public static void main(String[] args) {
test1();
}
}
/**
* Description:
* Application writers can extend this class
* when they need to implement only part of an interface;
* parser writers can instantiate this class to provide default handlers
* when the application has not supplied its own.
*
* 实际上,sax解析是基于事件的编程方法,当调用SAXParser的parse()方法去解析一个xml文档的时候,
* 该方法会会从xml文件中,从上到下逐步地读取,当读取到相应的内容时就会调用像相应的方法。
* 而我们需要做的就是,实现DefaultHandler接口的方法。实现方法,在遇到相应内容时,做出相应的处理。
*
* 例如,现在我们需要实现将整个xml文档输出在控制台中。
* @author lee
* */
class MyDefaultHandler extends DefaultHandler{
//创建一个StringBuffer实例来装整个xml
StringBuffer xml = new StringBuffer();
//表示当前读取到的内容
String current = "";
/**
* Description:
* 当开始读取整个document树时调用该方法
*
* */
@Override
public void startDocument(){
}
/**
* Description:
* 当结束读取document树时调用该方法
*
* */
@Override
public void endDocument(){
//在结束整个document文档时,输出xml
System.out.println(xml);
}
/**
* Description:
* 当读取到开始标签时调用该方法
*
* @param qName 表示标签名
* @param attributes 表示标签属性列表
*
* */
@Override
public void startElement(String uri, String localName,String qName,Attributes attributes) throws SAXException{
//赋值当前标签的名字
current = qName;
//添加开始标签名字
xml.append("<"+qName);
//添加标签属性
for(int i=0;i<attributes.getLength();i++){
xml.append(" "+attributes.getQName(i)+"="+attributes.getValue(i));
}
xml.append(">");
}
/**
* Description:
* 当读到结束标签时调用该方法
*
* @param qName 表示结束标签的名字
*
* */
@Override
public void endElement(String uri, String localname, String qName){
//结束标签时,当前标签名字赋值为空
current = "";
//添加结束标签名字
xml.append("<"+qName+">");
}
/**
* Description:
* 读到文本内容时会调用该方法
*
* @param ch 表示当前读取到的所有的文本内容
* @param start 表示当前读取的文本内容的开始位置
* @param length 表示当前读取的文本内容的长度
*
* */
@Override
public void characters(char[] ch, int start,int length){
//获取当前读取的文本内容
String text = new String(ch,start,length);
//添加文本内容
xml.append(text);
}
}