1. XML简介
XML(EXtensible Markup Language),可扩展标记语言
特点
XML与操作系统、编程语言的开发平台无关
实现不同系统之间的数据交换
作用
数据交互
配置应用程序和网站
2. XML文档结构
<?xml version="1.0" encoding="UTF-8"?> <books> <!--图书信息 --> <book id="bk101"> <author>王珊</author> <title>.NET高级编程</title> <description>包含C#框架和网络编程等</description> </book> <book id="bk102"> <author>李明明</author> <title>XML基础编程</title> <description>包含XML基础概念和基本作用</description> </book> </books>
3. XML标签
XML文档内容由一系列标签元素组成
<元素名 属性名 = “属性值”>元素内容</元素名>
空元素:
<name> </name> <name></name> <name/>
属性值用双引号包裹
一个元素可以有多个属性
属性值中不能直接包含<、“、&(不建议:‘、>)
4. XML编写注意事项
所有XML元素都必须有结束标签
XML标签对大小写敏感
XML必须正确的嵌套
同级标签以缩进对齐
元素名称可以包含字母、数字或其他的字符
元素名称不能以数字或者标点符号开始
元素名称中不能含空格
5. 转义符
XML中的转义符列表

当元素中出现很多特殊字符时,可以使用CDATA节,如:
<description> <![CDATA[讲解了元素<title>以及</title>的使用]]> </description>
6. 解析XML技术

DOM
基于XML文档树结构的解析
适用于多次访问的XML文档
特点:比较消耗资源
SAX
基于事件的解析
适用于大数据量的XML文档
特点:占用资源少,内存消耗小
DOM4J
非常优秀的Java XML API
性能优异、功能强大
开放源代码
7. DTD
DTD即文档类型定义--Document Type Definition
使每个XML文件可以携带一个自身格式的描述
一个DTD文档可能包含如下内容:
元素的定义规则
元素之间的关系规则
属性的定义规则
编写DTD文档
<?xml version="1.0"?> <!DOCTYPE poem [ <!ELEMENT poem (author,title,content) > <!ELEMENT author (#PCDATA)> <!ELEMENT title (#PCDATA)> <!ELEMENT content (#PCDATA)> ]> <poem> <author>王维</author> <title>鹿柴</title> <content>空山不见人,但闻人语声。返景入深林,复照青苔上。 </content> </poem>
8. DOM解析XML
DOM介绍
文档对象模型(Document Object Model)
DOM把XML文档映射成一个倒挂的树

常用接口介绍
DOM解析包:org.w3c.dom
访问DOM树节点
DOM解析XML文件步骤:
创建解析器工厂对象
解析器工厂对象创建解析器对象
解析器对象指定XML文件创建Document对象
以Document对象为起点操作DOM树
phone.xml
<?xml version="1.0" encoding="GB2312"?> <PhoneInfo> <Brand name="华为"> <Type name="P9"/> </Brand> <Brand name="苹果"> <Type name="Iphone6"/> <Type name="Iphone7"/> </Brand> </PhoneInfo>
ParseXmlDemo.java
package com.liqinglin.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;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
public class ParseXmlDemo {
    //收藏信息,xml对应的Document对象
    private Document document;
    //获得DOM树,获得Document对象
    public void getDom(){
        //获得解析器工厂
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        try {
            //根据解析器工厂获得解析器
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            //解析器来解析XML文件获得Document对象
            document = documentBuilder.parse("phone.xml");
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //获取手机品牌及型号相关信息
    public void showInfo(){
        //以Document数起点,先拿到所有的Brand节点
        NodeList brands = document.getElementsByTagName("Brand");
        //遍历brands,从中拿到每一个Brand节点
        for (int i = 0; i < brands.getLength(); i++){
            Node node = brands.item(i);
            Element eleBrand = (Element) node;
            String brandName = eleBrand.getAttribute("name");
            System.out.println(brandName);
            //继续查找,找每个Brands的子节点出来
            NodeList types = eleBrand.getChildNodes();
            for (int j = 0; j < types.getLength(); j++){
                Node typeNode = types.item(j);
                //判断该子节点是否是元素节点
                if(typeNode.getNodeType() == Node.ELEMENT_NODE){
                    Element typeEle = (Element) typeNode;
                    System.out.println("\t" + typeEle.getAttribute("name"));
                }
            }
        }
    }
    //为XML文件添加元素
    public void addEle(){
        //(1)创建<Brand>
        Element brand = document.createElement("Brand");
        //(2)为<Bradn>设置name属性取值为三星
        brand.setAttribute("name", "三星");
        Element type = document.createElement("Type");
        type.setAttribute("name", "NOTE2");
        //将Type作为Brand的子元素
        brand.appendChild(type);
        //将Brand放到PhoneInfo中去
        document.getElementsByTagName("PhoneInfo").item(0).appendChild(brand);
    }
    //保存XML文件(需要借助转换器 源:最新的dom树 --> 目的地:phone.xml,借助的输出流)
    public void saveXML(){
        //转换器工厂
        TransformerFactory factory = TransformerFactory.newInstance();
        //设置缩进
        factory.setAttribute("indent-number", 4);
        try {
            //获取转换器
            Transformer transformer = factory.newTransformer();
            //指定转换格式
            transformer.setOutputProperty(OutputKeys.ENCODING, "GB2312");
            transformer.setOutputProperty(OutputKeys.INDENT, "YES");
            DOMSource source = new DOMSource(document);
            OutputStream out = new FileOutputStream("phone.xml");
            StreamResult result = new StreamResult(new OutputStreamWriter(out, "GB2312"));
            transformer.transform(source, result);
        } catch (TransformerConfigurationException | FileNotFoundException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    //修改元素
    public void updateEle(){
        //获取所有的Brand
        NodeList brands = document.getElementsByTagName("Brand");
        for(int i = 0; i < brands.getLength(); i++){
            Node brand = brands.item(i);
            Element brandEle = (Element) brand;
            brandEle.setAttribute("id", i+"");
        }
        this.saveXML();
    }
    //删除 华为手机
    public void deleteEle(){
        //获取所有的Brand
        NodeList brands = document.getElementsByTagName("Brand");
        for(int i = 0; i < brands.getLength(); i++){
            Node brand = brands.item(i);
            Element brandEle = (Element) brand;
            if(brandEle.getAttribute("name").equals("华为")){
                brandEle.getParentNode().removeChild(brandEle);
            }
        }
        this.saveXML();
    }
    public static void main(String[] args) {
        ParseXmlDemo parseXmlDemo = new ParseXmlDemo();
        parseXmlDemo.getDom();
        parseXmlDemo.addEle();
        parseXmlDemo.showInfo();
        parseXmlDemo.updateEle();
        parseXmlDemo.deleteEle();
        parseXmlDemo.saveXML();
    }
}9. DOM4J
Document:定义XML文档
Element:定义XML元素
Text:定义XML文本节点
Attribute:定义了XML 的属性
……
Dom4jDemo.java
package com.liqinglin.test;
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;
import java.io.*;
import java.util.Iterator;
public class Dom4jDemo {
    private Document document;
    //获得document对象
    public void loadDocument(){
        SAXReader saxReader = new SAXReader();
        try {
            document = saxReader.read(new File("phone.xml"));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
    //显示手机的品牌及型号
    public void showInfo(){
        //获取XML根节点
        Element root = document.getRootElement();
        //获取所有的<Brand>
        Iterator eleBrands = root.elementIterator();
        while(eleBrands.hasNext()){
            Element brand = (Element) eleBrands.next();
            System.out.println(brand.attributeValue("name"));
            //获取所有的<Type>
            Iterator eleTypes = brand.elementIterator();
            while(eleTypes.hasNext()){
                Element type = (Element) eleTypes.next();
                System.out.println("\t" + type.attributeValue("name"));
            }
        }
    }
    //增加新的手机信息
    public void addNewPhone(){
        //获取XML根元素
        Element root = document.getRootElement();
        //创建<Brand>
        Element eleBrand = root.addElement("Brand");
        eleBrand.addAttribute("name", "三星");
        //创建<Type>
        Element eleType = eleBrand.addElement("Type");
        eleType.addAttribute("name", "SX123");
    }
    //修改节点
    public void updatePhone(){
        Element root = document.getRootElement();
        Iterator eleBrands = root.elementIterator();
        int id = 0;
        while(eleBrands.hasNext()){
            Element brand = (Element) eleBrands.next();
            id++;
            brand.addAttribute("id", id+"");
        }
        this.saveXML();
    }
    //删除节点
    public void deletePhone(){
        Element root = document.getRootElement();
        Iterator eleBrands = root.elementIterator();
        while(eleBrands.hasNext()){
            Element brand = (Element) eleBrands.next();
            if(brand.attributeValue("name").equals("华为")){
                brand.getParent().remove(brand);
            }
        }
        this.saveXML();
    }
    //修改xml文件
    public void  saveXML(){
        OutputFormat format = OutputFormat.createPrettyPrint();
        //format.setEncoding("GB2312");
        XMLWriter writer = null;
        try {
            writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream("phone.xml")), format);
            writer.write(document);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Dom4jDemo dom4jDemo = new Dom4jDemo();
        dom4jDemo.loadDocument();
        dom4jDemo.addNewPhone();
        dom4jDemo.updatePhone();
        dom4jDemo.deletePhone();
        dom4jDemo.saveXML();
        dom4jDemo.showInfo();
    }
}