XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
wirter.write(Document);
package gz.itcast.a_dom4j_write;
import java.io.File;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/** * 讨论写出内容到xml文档的细节 * @author APPle * */
public class Demo2 {
/** * @param args */
public static void main(String[] args) throws Exception{
Document doc = new SAXReader().read(new File("./src/contact.xml"));
//指定文件输出的位置
FileOutputStream out = new FileOutputStream("e:/contact.xml");
/** * 1.指定写出的格式 */
OutputFormat format = OutputFormat.createCompactFormat(); //紧凑的格式.去除空格换行.项目上线的时候
//OutputFormat format = OutputFormat.createPrettyPrint(); //漂亮的格式.有空格和换行.开发调试的时候
/** * 2.指定生成的xml文档的编码 * 同时影响了xml文档保存时的编码 和 xml文档声明的encoding的编码(xml解析时的编码) * 结论: 使用该方法生成的xml文档避免中文乱码问题。 */
format.setEncoding("utf-8");
//1.创建写出对象
XMLWriter writer = new XMLWriter(out,format);
//2.写出对象
writer.write(doc);
//3.关闭流
writer.close();
}
}
增加:
DocumentHelper.createDocument() 增加文档
addElement("名称") 增加标签
addAttribute("名称",“值”) 增加属性
修改:
Attribute.setValue("值") 修改属性值
Element.addAtribute("同名的属性名","值") 修改同名的属性值
Element.setText("内容") 修改文本内容
删除
Element.detach(); 删除标签
Attribute.detach(); 删除属性
package gz.itcast.a_dom4j_write;
import java.io.File;
import java.io.FileOutputStream;
import org.dom4j.Attribute;
import org.dom4j.Document;
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;
/** * 修改xml内容 * 增加:文档,标签 ,属性 * 修改:属性值,文本 * 删除:标签,属性 * @author APPle * */
public class Demo3 {
/** * 增加:文档,标签 ,属性 */
@Test
public void test1() throws Exception{
/** * 1.创建文档 */
Document doc = DocumentHelper.createDocument();
/** * 2.增加标签 */
Element rootElem = doc.addElement("contactList");
//doc.addElement("contactList");
Element contactElem = rootElem.addElement("contact");
contactElem.addElement("name");
/** * 3.增加属性 */
contactElem.addAttribute("id", "001");
contactElem.addAttribute("name", "eric");
//把修改后的Document对象写出到xml文档中
FileOutputStream out = new FileOutputStream("e:/contact.xml");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(doc);
writer.close();
}
/** * 修改:属性值,文本 * @throws Exception */
@Test
public void test2() throws Exception{
Document doc = new SAXReader().read(new File("./src/contact.xml"));
/** * 方案一: 修改属性值 1.得到标签对象 2.得到属性对象 3.修改属性值 */
//1.1 得到标签对象
/* Element contactElem = doc.getRootElement().element("contact"); //1.2 得到属性对象 Attribute idAttr = contactElem.attribute("id"); //1.3 修改属性值 idAttr.setValue("003"); */
/** * 方案二: 修改属性值 */
//1.1 得到标签对象
/* Element contactElem = doc.getRootElement().element("contact"); //1.2 通过增加同名属性的方法,修改属性值 contactElem.addAttribute("id", "004"); */
/** * 修改文本 1.得到标签对象 2.修改文本 */
Element nameElem = doc.getRootElement().
element("contact").element("name");
nameElem.setText("李四");
FileOutputStream out = new FileOutputStream("e:/contact.xml");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(doc);
writer.close();
}
/** * 删除:标签,属性 * @throws Exception */
@Test
public void test3() throws Exception{
Document doc = new SAXReader().read(new File("./src/contact.xml"));
/** * 1.删除标签 1.1 得到标签对象 1.2 删除标签对象 */
// 1.1 得到标签对象
/* Element ageElem = doc.getRootElement().element("contact") .element("age"); //1.2 删除标签对象 ageElem.detach(); //ageElem.getParent().remove(ageElem); */
/** * 2.删除属性 2.1得到属性对象 2.2 删除属性 */
//2.1得到属性对象
//得到第二个contact标签
Element contactElem = (Element)doc.getRootElement().
elements().get(1);
//2.2 得到属性对象
Attribute idAttr = contactElem.attribute("id");
//2.3 删除属性
idAttr.detach();
//idAttr.getParent().remove(idAttr);
FileOutputStream out = new FileOutputStream("e:/contact.xml");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(doc);
writer.close();
}
}
问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦!!!
主要是用于快速获取所需的节点对象。
1)导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
2)使用xpath方法
List<Node> selectNodes("xpath表达式"); 查询多个节点对象
Node selectSingleNode("xpath表达式"); 查询一个节点对象
/ 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
// 相对路径 表示不分任何层次结构的选择元素。
* 通配符 表示匹配所有元素
[] 条件 表示选择什么条件下的元素
@ 属性 表示选择属性节点
and 关系 表示条件的与关系(等价于&&)
text() 文本 表示选择文本内容
3.5 案例
用户登录功能:
用户输入用户名和密码 -> 到“数据库”查询是否有对应的用户 ->
有: 则表示登录成功
没有: 则表示登录失败
用xml当做数据库
user.xml 用来存储用户的数据
package gz.itcast.b_xpath;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/** * xpath案例: 模拟用户登录效果 * @author APPle * */
public class Demo3 {
public static void main(String[] args)throws Exception{
//1.获取用户输入的用户名和密码
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name = br.readLine();
System.out.println("请输入密码:");
String password = br.readLine();
//2.到“数据库”中查询是否有对应的用户
//对应的用户: 在user.xml文件中找到一个
//name属性值为‘用户输入’,且password属性值为‘用户输入’的user标签
Document doc = new SAXReader().read(new File("./src/user.xml"));
Element userElem = (Element)doc.selectSingleNode("//user[@name='" +name +"' and @password='"+password+"']");
if(userElem!=null){
//登录成功
System.out.println("登录成功");
}else{
//登录失败
System.out.println("登录失败");
}
}
}
DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。
对内存要求比较要。
缺点: 不适合读取大容量的xml文件,容易导致内存溢出。
SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。
SAX解析工具- Sun公司提供的。内置在jdk中。org.xml.sax.*
核心的API:
SAXParser类: 用于读取和解析xml文件对象
parse(File f, DefaultHandler dh)方法: 解析xml文件
参数一: File:表示 读取的xml文件。
参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类
例如:{
1.创建SAXParser对象
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
2.调用parse方法
parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());
}
[一个类继承 class 类名(extends DefaultHandler) 在调用时创建传进去
DefaultHandler类的API:
void startDocument() : 在读到文档开始时调用
void endDocument() :在读到文档结束时调用
void startElement(String uri, String localName, String qName, Attributes attributes):
读到开始标签时调用
Attributes API:
int getLength() :获得长度
String getQName(int index) :通过索引获得属性名称
String getValue(int index) :通过索引获得属性的值
String getValue(String qName) :通过属性名称获得属性的值
void endElement(String uri, String localName, String qName) :读到结束标签时调用
void characters(char[] ch, int start, int length) : 读到文本内容时调用
package gz.itcast.c_sax;
import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/** * 第一个SAX读取xml文件程序 * @author APPle * */
public class Demo1 {
public static void main(String[] args) throws Exception{
//1.创建SAXParser对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//2.调用parse方法
/** * 参数一: xml文档 * 参数二: DefaultHandler的子类 */
parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());
}
}
package gz.itcast.c_sax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/** * SAX处理程序(如何解析xml文档) * @author APPle * */
public class MyDefaultHandler extends DefaultHandler {
/** * 开始文档时调用 */
@Override
public void startDocument() throws SAXException {
System.out.println("MyDefaultHandler.startDocument()");
}
/** * 开始标签时调用 * @param qName: 表示开始标签的标签名 * @param attributes: 表示开始标签内包含的属性列表 */
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("MyDefaultHandler.startElement()-->"+qName);
}
/** * 结束标签时调用 * @param qName: 结束标签的标签名称 */
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("MyDefaultHandler.endElement()-->"+qName);
}
/** * 读到文本内容的时调用 * @param ch: 表示当前读完的所有文本内容 * @param start: 表示当前文本内容的开始位置 * @param length: 表示当前文本内容的长度 * char[]( 张三 20) 100 * 98 2 */
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//得到当前文本内容
String content = new String(ch,start,length);
System.out.println("MyDefaultHandler.characters()-->"+content);
}
/** * 结束文档时调用 */
@Override
public void endDocument() throws SAXException {
System.out.println("MyDefaultHandler.endDocument()");
}
}
练习题
把xml文档信息封装到对象中
类:
public class Contact {
private String id;
private String name;
private String age;
private String phone;
private String email;
private String qq;
}
XML文件:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="03.contact.css"?>
<contactList>
<contact id="001">
<name>张三</name>
<age>20</age>
<phone>134222223333</phone>
<email>[email protected]</email>
<qq>432221111</qq>
</contact>
<contact id="003">
<name>lisi</name>
<age>20</age>
<phone>134222225555</phone>
<email>[email protected]</email>
<qq>432222222</qq>
</contact>
</contactList>
package gz.itcast.c_sax;
import java.io.File;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/** * 使用sax解析把 xml文档封装成对象 * @author APPle * */
public class Demo3 {
public static void main(String[] args)throws Exception {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
MyDefaultHandler3 handler = new MyDefaultHandler3();
parser.parse(new File("./src/contact.xml"), handler);
List<Contact> list = handler.getList();
for (Contact contact : list) {
System.out.println(contact);
}
}
}
package gz.itcast.c_sax;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/** * SAX处理程序 * @author APPle * */
public class MyDefaultHandler3 extends DefaultHandler {
//存储所有联系人对象
private List<Contact> list = new ArrayList<Contact>();
public List<Contact> getList(){
return list;
}
//保存一个联系人信息
private Contact contact;
/** * 思路: * 1)创建Contact对象 * 2)把每个contact标签内容存入到Contact对象 * 3)把Contact对象放入List中 */
//用于临时存储当前读到的标签名
private String curTag;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
curTag = qName;
//读取到contact的开始标签创建Contact对象
if("contact".equals(qName)){
contact = new Contact();
//设置id值
contact.setId(attributes.getValue("id"));
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//当前文本内容
String content = new String(ch,start,length);
if("name".equals(curTag)){
contact.setName(content);
}
if("age".equals(curTag)){
contact.setAge(content);
}
if("phone".equals(curTag)){
contact.setPhone(content);
}
if("email".equals(curTag)){
contact.setEmail(content);
}
if("qq".equals(curTag)){
contact.setQq(content);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//设置空时为了避免空格换行设置到对象的属性中
curTag = null;
//读到contact的结束标签放入List中
if("contact".equals(qName)){
list.add(contact);
}
}
}
DOM | SAX |
---|---|
原理: 一次性加载xml文档,不适合大容量的文件读取 | 原理: 加载一点,读取一点,处理一点。适合大容量文件的读取 |
DOM解析可以任意进行增删改查 | SAX解析只能读取 |
DOM解析任意读取任何位置的数据,甚至往回读 | SAX解析只能从上往下,按顺序读取,不能往回读 |
DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。 | SAX解析基于事件的编程方法。java开发编码相对复杂。 |