一、xml解析方式概叙
1、解析方法
XML解析方式分为两种:dom和sax
dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。
sax: (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
2、解析器
Crimson、Xerces 、Aelfred2
3、解析开发包
Jaxp、Jdom、dom4j
4、解析方法比较
1.dom方法
优点:使用dom解析xml文档,实现crud特别方便,操作速度也比较快。
缺点:使用dom解析xml文档,如果文件比较大,对内存消耗就特别大,极容易导致内存溢出,所以dom方式不适合操作大的xml文档。
2.sax方法
优点:解析速度快、对内存占用少,查找数据特别方便
缺点:只适合查找数据,不适合作增删改操作
二、使用jaxp解析
1、dom方法解析
1、方法介绍
javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
2、解析对象
book.xml
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<书架>
<书 name="yyyyyyy">
<售价>109</售价>
<售价>39元</售价>
<书名>Java就业培训教程</书名>
<作者>张孝祥</作者>
</书>
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
3、运用详情
package jaxp;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.junit.Test;
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;
public class Demo {
/**
* 使用jaxp操作xml文档
* @param args
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//1.获取工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//2.产生解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//3.解析xml文档,得到代表文档的document
Document document = builder.parse(new File("src/book.xml"));
//遍历
list(document);
}
//遍历,得到所有标签
public static void list(Node node){
//判断得到的结点是否为标签
if(node.getNodeType()==Node.ELEMENT_NODE){
System.out.println(node.getNodeName());
}
//进行遍历
NodeList list = node.getChildNodes();
for(int i=0;i<list.getLength();i++){
Node child = list.item(i);
list(child);
}
}
//------------------------对结点进行操作
//得到售价结点的值
@Test
public void read() throws Exception{
//1.获取工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
//2.得到第一个售价节点
NodeList list = document.getElementsByTagName("售价");
Node price = list.item(0);
//3.得到该结点的值
String value = price.getTextContent();
System.out.println(value);
}
//修改结点的值:<售价>39.00元</售价>改为109
@Test
public void update() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
Node price = document.getElementsByTagName("售价").item(0);
price.setTextContent("109");
//把内存中的document写到xml文档
TransformerFactory tf = TransformerFactory.newInstance();
//得到转换器
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
//向指定节点中增加孩子节点(售价节点)
@Test
public void add() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
//创建需要增加的节点
Node price = document.createElement("售价");
price.setTextContent("59元");
//得到需要增加的节点的父亲
Node parent = document.getElementsByTagName("书").item(0);
//把需要增加的节点挂到父结点上
parent.appendChild(price);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
//向指定位置上插入售价节点
@Test
public void add2() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
//新建要插入的结点
Node node = document.createElement("售价");
node.setTextContent("39元");
Node parent = document.getElementsByTagName("书").item(0);//获取要插入的父节点
parent.insertBefore(node, document.getElementsByTagName("书名").item(0));//在该节点的前边插入
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
//删除xml文档的售价结点
@Test
public void delete() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
Node node = document.getElementsByTagName("售价").item(2);
node.getParentNode().removeChild(node);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book1.xml")));
}
//--------------------------该标签属性
//操作xml文档属性
@Test
public void updateAttribute() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/book.xml"));
//操作xml文档的元素时,一般都把元素当作node对象,但是程序员如果发现node不好使时,就应把node强转成相应类型
Node node = document.getElementsByTagName("书").item(0);
Element book = null;
if(node.getNodeType()==Node.ELEMENT_NODE){ //在作结点转换之前,最好先判断结点类型
book = (Element)node;
}
//修改
book.setAttribute("name", "yyyyyyy");
//增加
book.setAttribute("password", "123");
//删除
book.removeAttribute("password");
TransformerFactory tf = TransformerFactory.newInstance();
Transformer ts = tf.newTransformer();
ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml")));
}
}
4、案例解析
资料
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<exam>
<student idcard="111" examid="222">
<name>张三</name>
<location>沈阳</location>
<grade>89</grade>
</student>
<student idcard="333" examid="444">
<name>李四</name>
<location>大连</location>
<grade>97</grade>
</student>
</exam>
要求
1.需求分析
2.详细设计
添加用户:
删除用户:
查询成绩:
3.程序实现
javaben:student.java
public class Student {
/* <student idcard="111" examid="222">
<name>张三</name>
<location>沈阳</location>
<grade>89</grade>
</student>
*/
private String idcard;
private String examid;
private String name;
private String location;
private double grade;
}
工具类:Utils.java
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
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.xml.sax.SAXException;
public class XmlUtils {
/**
* 工具类中的方法一般都是静态方法
* @return
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
//得到document
public static Document getDocument() throws ParserConfigurationException, SAXException, IOException{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new File("src/exam.xml"));
}
//将结果写入到xml文件
public static void write2Xml(Document document) throws TransformerException{
TransformerFactory factory = TransformerFactory.newInstance();
Transformer tf = factory.newTransformer();
tf.transform(new DOMSource(document), new StreamResult(new File("src/exam.xml")));
}
}
持久化操作:StudentsDao.java
import java.io.IOException;
import javax.management.RuntimeErrorException;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.shen.mode.Student;
import com.shen.utils.XmlUtils;
public class StudentsDao {
/*
<student idcard="111" examid="222">
<name>张三</name>
<location>沈阳</location>
<grade>89</grade>
</student>
*/
public void add(Student student){
try{
Document document = XmlUtils.getDocument();
//student_node //ctrl+1 rename in file
Element student_node = document.createElement("student");
student_node.setAttribute("examid", student.getExamid());
student_node.setAttribute("idcard", student.getIdcard());
Element name = document.createElement("name");
name.setTextContent(student.getName());
Element location = document.createElement("location");
location.setTextContent(student.getLocation());
Element grade = document.createElement("grade");
grade.setTextContent(student.getGrade()+"");
student_node.appendChild(name);
student_node.appendChild(location);
student_node.appendChild(grade);
//得到exam结点,并把student挂上去
document.getElementsByTagName("exam").item(0).appendChild(student_node);
XmlUtils.write2Xml(document);
}catch (Exception e) {
throw new RuntimeException(e);
}
}
public void delete(String name){
try {
Document document=XmlUtils.getDocument();
NodeList list=document.getElementsByTagName("name");
for(int i=0;i<list.getLength();i++)
{
Node node=list.item(i);
if(node.getTextContent().equals(name)){
node.getParentNode().getParentNode().removeChild(node.getParentNode());
XmlUtils.write2Xml(document);
return;
}
}
throw new RuntimeException("对不起,你要删除的学生不存在");//异常也是一个返回值
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Student find(String examid){
try{
Document document=XmlUtils.getDocument();
NodeList list=document.getElementsByTagName("student");
for (int i = 0; i < list.getLength(); i++) {
Element student=(Element)list.item(i);
String s_examid=student.getAttribute(examid);
if(s_examid.equals(examid))
{
//找到
Student s=new Student();
s.setExamid(student.getAttribute("examid"));
s.setExamid(student.getAttribute("idcard"));
s.setName(student.getElementsByTagName("name").item(0).getTextContent());
s.setLocation(student.getElementsByTagName("location").item(0).getTextContent());
s.setGrade(Double.parseDouble(student.getElementsByTagName("garde").item(0).getTextContent()));
return s;
}
}
return null;
}catch(Exception e){}
return null;
}
}
主方法:Main.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.shen.dao.StudentsDao;
import com.shen.mode.Student;
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("添加学生 (a) 查找学生(b) 删除学生(c)");
System.out.print("请输入操作类型:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String type = br.readLine();
if (type.equalsIgnoreCase("a")) {
// 添加学生
try {
System.out.print("请输入学生姓名:");
String name = br.readLine();
System.out.print("请输入学生准考证号:");
String examid = br.readLine();
System.out.print("请输入学生身份证号:");
String idcard = br.readLine();
System.out.print("请输入学生所在地:");
String location = br.readLine();
System.out.print("请输入学生成绩:");
String grade = br.readLine();
Student student = new Student();
student.setExamid(examid);
student.setGrade(Double.parseDouble(grade));
student.setIdcard(idcard);
student.setLocation(location);
student.setName(name);
StudentsDao dao = new StudentsDao();
dao.add(student);
System.out.println("恭喜,录入成功!!!");
} catch (Exception e) {
System.out.println("对不起,录入失败!!");
}
} else if (type.equalsIgnoreCase("b")) {
// 查找学生
System.out.println("请输入学生的准考证号:");
String examid=br.readLine();
StudentsDao dao=new StudentsDao();
Student student=dao.find(examid);
if(student==null){
System.out.println("对不起,你要查找的学生不存在!!!");
}else{
System.out.println("你要查找的学生信息如下:");
System.out.println("姓名:"+student.getName());
System.out.println("身份证:"+student.getIdcard());
System.out.println("准考证:"+student.getExamid());
System.out.println("所在地:"+student.getLocation());
System.out.println("成绩"+student.getGrade());
}
} else if (type.equalsIgnoreCase("c")) {
// 删除学生
try{
System.out.println("请输入要删除学生的姓名:");
String name=br.readLine();
StudentsDao dao=new StudentsDao();
dao.delete(name);
System.out.println("删除成功");
}catch(Exception e){System.out.println("删除失败");}
} else {
System.out.println("不支持此类操作!!!");
}
}
}
2、sax方法解析
1、方法介绍
在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
2、解析对象
book.xml
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<书架>
<书 name="yyyyyyy">
<售价>109</售价>
<售价>39元</售价>
<书名>Java就业培训教程</书名>
<作者>张孝祥</作者>
</书>
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
3、运用详情
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.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class Demo1 {
/**
*sax方式解析book1.xml文件
* @throws SAXException
* @throws ParserConfigurationException
* @throws IOException
*/
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//1.创建工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2.用工厂创建解析器
SAXParser sp = factory.newSAXParser();
//3.利用解析器得到reader
XMLReader reader = sp.getXMLReader();
//4、在解析xml文档之前,设置好事件处理器
reader.setContentHandler(new MyContentHandler2());
//4.利用reader读取 xml文档
reader.parse("src/book1.xml");
}
}
//用于获取第一个售价节点的值:<售价>109</售价>
class MyContentHandler2 extends DefaultHandler{
private boolean isOk = false;
private int index = 1;
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if(isOk==true && index==1){
System.out.println(new String(ch,start,length));
}
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
if(name.equals("售价")){
isOk = true;
}
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if(name.equals("售价")){
isOk = false;
index++;
}
}
}
//得到xml文档内容的事件处理器
class MyContentHandler implements ContentHandler{
//开始标签(Attributes表示属性)
public void startElement(String uri, String localName, String name,
Attributes atts) throws SAXException {
System.out.println("当前解析到了:" + name + ",这个标签是开始标签");
for(int i=0;i<atts.getLength();i++){
String attname = atts.getQName(i);
String attvalue = atts.getValue(i);
//打印出各个属性
System.out.println(attname + "=" + attvalue);
}
}
public void endElement(String uri, String localName, String name)
throws SAXException {
System.out.println("当前解析到了:" + name + ",这个标签是结束标签");
}
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println("当前解析到了内容:" + new String(ch,start,length));
}
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
}
public void endPrefixMapping(String prefix) throws SAXException {
// TODO Auto-generated method stub
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
}
public void processingInstruction(String target, String data)
throws SAXException {
// TODO Auto-generated method stub
}
public void setDocumentLocator(Locator locator) {
// TODO Auto-generated method stub
}
public void skippedEntity(String name) throws SAXException {
// TODO Auto-generated method stub
}
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
// TODO Auto-generated method stub
}
}
三、使用dom4j解析
注意:使用dom4j解析需要自己引入jar包,引入该包可能不够
1、解析对象
book.xml
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<书架>
<书 name="yyyyyyy">
<售价>109</售价>
<售价>39元</售价>
<书名>Java就业培训教程</书名>
<作者>张孝祥</作者>
</书>
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
2、实现代码
public class Main {
//读取xml文档数据:<书名>Java就业培训教程</书名>
@Test
public void read() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book.xml"));
Element root = document.getRootElement();
Element bookname = root.element("书").element("书名");
System.out.println(bookname.getText());
}
//<书 name="yyyyyyy">
@Test
public void readAttr() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book.xml"));
Element root = document.getRootElement();
String value = root.element("书").attributeValue("name");
System.out.println(value);
}
//向xml文档中添加<售价>19元</售价>
@Test
public void add() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book.xml"));
Element price = DocumentHelper.createElement("售价");
price.setText("19元");
document.getRootElement().element("书").add(price);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
writer.write(document); //utf-8
writer.close();
}
//修改:<售价>109</售价> 为209
@Test
public void update() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book1.xml"));
Element price = (Element) document.getRootElement().element("书").elements("售价").get(1);
price.setText("209元");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
writer.write(document); //utf-8
writer.close();
}
//删除:<售价>109</售价>
@Test
public void delete() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book.xml"));
Element price = (Element) document.getRootElement().element("书").elements("售价").get(0);
price.getParent().remove(price);
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
writer.write(document); //utf-8
writer.close();
}
//向指定位置增加售价结点
@Test
public void add2() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book.xml"));
Element price = DocumentHelper.createElement("售价");
price.setText("19元");
List list = document.getRootElement().element("书").elements();
list.add(1, price);
//格式化输出(保持原来的样式)
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
writer.write(document); //utf-8
writer.close();
}
}
3、使用xpath技术实现查找
1.代码示例
import java.io.File;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
public class Mais {
@Test
public void findWithXpath() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/book.xml"));
Element e = (Element) document.selectNodes("//书名").get(1);
System.out.println(e.getText());
}
}
2.运用举例
通过匹配用户信息进行登陆
users.xml
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user username="aaa" password="123"/>
<user username="bbb" password="123"/>
<user username="ccc" password="123"/>
</users>
login.java
@Test
public void findUser() throws Exception{
String username = "aaa";
String password = "1233";
SAXReader reader = new SAXReader();
Document document = reader.read(new File("src/users.xml"));
//single单一的
Element e = (Element) document.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']");
if(e!=null){
System.out.println("让用户登陆成功!!");
}else{
System.out.println("用户名和密码不正确!!");
}
}