Java學習路線-45:XML快速入門(1)- XML、DTD、JAXP、Schema

第1 章 : XML入門

課時1 XML簡介

eXtensible Markup Language
主要使用1.0版本

語言 中文名稱 用途
html 標記型語言 顯示數據
xml 可擴展標記型語言 存儲數據

課時2 XML的應用

1、傳輸數據
2、表示有關係的數據
3、配置文件

課時3 XML的文檔聲明

(1)xml的文檔聲明
(2)定義元素(標籤)
(3)註釋
(4)特殊字符
(5)CDATA區
(6)PI指令

文件*.xml

1、xml的文檔聲明
必須寫在第一行第一列

<?xml version="1.0" encoding="gbk" ?>

屬性:
version 版本 1.0
encoding 編碼 gbk/utf-8
standalone 依賴其他文件 yes/no

課時4 XML中文亂碼問題解決

<?xml version="1.0" encoding="gbk" ?>
<person>
    <name>張三</name>
    <age>23</age>
</person>  

課時5 XML元素的定義

1、只能有一個根標籤
2、合理嵌套
3、空格和換行都會當做原始內容解析
4、有開始必須有結束

<person></person>  

5、標籤沒有內容,可以在標籤內結束

<person /> 

標籤命名規則
(1)區分大小寫
(2)不能以數字下劃線開頭
(3)不能以xml、XML、Xml等開頭
(4)不能包含空格和冒號
(5)標籤可以是中文

課時6 XML屬性的定義

html和xml都是標記型文檔,可以有屬性

<person id="001"></person>

屬性要求
(1)一個標籤可以有多個屬性
(2)屬性名稱不能相同
(3)屬性名稱與屬性值之間使用等號(=)
(4)屬性值使用引號(單引號或雙引號)包起來
(5)屬性名命名貴方和元素的命名規範一致

課時7 XML註釋

<!--  這裏是註釋 -->

註釋不能嵌套
註釋不能放到第一行

課時8 XML特殊字符

>&gt;
<&lt;

課時9 XML的CDATA區

可以解決多個字符都需要轉義的操作
特殊字符會當做文本內容

<![CDATA[ 內容 ]]>

課時10 XML的PI指令

Processing Instruction
可以在xml中設置樣式
只能對英文標籤起作用

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/css" href="./demo.css" ?>
<person>
    <name>張三</name>
    <age>23</age>
</person>  

demo.css

name{
    color: green;
}

課時11 XML約束簡介

1、xml語法總結
(1)所有xml元素都必須有關閉標籤
(2)xml標籤對大小寫敏感
(3)xml必須正確嵌套
(4)xml必須有且只有一個根元素
(5)xml屬性值需要加引號
(6)特殊字符必須轉義
(7)原樣輸出文本使用<![CDATA[]]>
(8)xml中的空格、回車換行在解析時會被保留

2、xml的約束
(1)dtd約束
(2)scheme約束

第2 章 : DTD(文檔類型定義)

課時12 DTD快速入門

文件*.dtd,使用idea打開會提示
文檔類型定義(DTD,Document Type Definition)

1、複雜元素:有子元素的元素

<!ELEMENT 元素名稱 (子元素)>

eg:
<!ELEMENT person (name,age)>

2、簡單元素

<!ELEMENT 元素名稱 (#PCDATA)>

eg:
<!ELEMENT age (#PCDATA)>

3、引入dtd文件

<!DOCTYPE person SYSTEM "demo.dtd">

示例

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE person SYSTEM "demo.dtd">
<person>
    <name>張三</name>
    <age>23</age>
</person>

demo.dtd

<!ELEMENT person (name, age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>

課時13 DTD的三種引入方式

1、引入外部

<!DOCTYPE 根元素名稱 SYSTEM "dtd路徑">

2、引入內部

<!DOCTYPE 根元素名稱 [
        <!ELEMENT person (name, age)>
        <!ELEMENT name (#PCDATA)>
        <!ELEMENT age (#PCDATA)>
]>

3、使用網絡

<!DOCTYPE 根元素名稱 PUBLIC "DTD名稱" "DTD路徑URL">

課時14 使用DTD定義元素

語法

<!ELEMENT 元素名 約束>

1、簡單元素:沒有子元素的元素

<!ELEMENT 元素名 (#PCDATA)>

(#PCDATA) 字符串(需要加括號)
EMPTY 元素爲空
ANY 任意

2、複雜元素

<!ELEMENT 元素名 (子元素)>

(1)子元素出現次數
+ 一次或多次
? 零次或一次
* 零次或多次

(2)子元素分隔符
逗號隔開:表示出現順序
豎線隔開:表示任意一個

eg:

<!ELEMENT person (name+, age?, sex, school*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex EMPTY>
<!ELEMENT school ANY>

課時15 使用DTD定義屬性

語法

<! ATTLIST 元素名稱
    屬性名稱 屬性類型 屬性的約束
>

1、屬性類型
(1)CDATA 字符串
(2)(a|b|c) 枚舉
(3)ID 值只能以字母或下劃線開頭

2、屬性的約束
(1)#REQUIRED 屬性必須存在
(2)#IMPLIED 屬性可有可無
(3)#FIXED 屬性必須是固定值
(4)默認值 不寫屬性做爲默認值

eg:

<!ATTLIST 頁面作者
    姓名 CDATA #REQUIRED
    年齡 CDATA #IMPLIED
    職位 CDATA #FIXED 作者
    愛好 CDATA 寫作
>

課時16 定義實體

語法

定義
<!ENTITY 實體名稱 "實體值">

使用
&實體名稱

實體需要定義在內部dtd

課時17 W3C的案例

https://www.w3school.com.cn/dtd/dtd_examples.asp

第3 章: XML解析之JAXP

課時18 XML解析簡介

1、dom方式解析xml過程:
根據xml的層級結構,在內存中分配一個樹形結構
把xml中每部分都封裝成對象

(1)優點:方便實現增、刪、改操作
(2)缺點:如果文件過大,造成內存溢出

2、sax方式解析xml過程:
採用事件驅動,邊讀邊解析,從上到下,一行一行的解析,
解析到一個對象,把對象名稱返回

(1)優點:不會造成內存溢出,實現查詢
(2)缺點:不能實現增、刪、改操作

課時19 JAXP API的查看

dom和sax解析器:
(1)sun公司 jaxp
(2)dom4j組織 dom4j(實際開發)
(3)jdom組織 jdom

1、jaxp
jaxp是javese一部分
javax.xml.parses

interface Node{
    // 添加節點
    public Node appendChild(Node newChild);

    // 移除節點
    public Node removeChild(Node oldChild);

    // 獲取父節點
    public Node getParentNode();

    // 返回文本內容
    public String getTextContent()

}

interface NodeList{
    // 通過下標獲取具體值
    public Node item(int index);

    // 得到集合長度
    public int getLength();
}

interface Document extends Node{
    // 獲取標籤
    public NodeList getElementsByTagName(String tagname);

    // 創建標籤
    public Element createElement(String tagName);

    // 創建文本
    public Text createTextNode(String data);

}

abstract DocumentBuilder{
    public Document parse(File f)
}

abstract DocumentBuilderFactory{
    public static DocumentBuilderFactory newInstance()
    public abstract DocumentBuilder newDocumentBuilder()
}

abstract class SAXParser{}

abstract class SAXParserFactory{}

課時20-21 使用JAXP查詢節點

示例:查詢xml中所有name值

demo.xml

<?xml version="1.0" encoding="utf-8" ?>
<list>
    <person>
        <name>張三</name>
        <age>23</age>
    </person>
    <person>
        <name>李四</name>
        <age>24</age>
    </person>
</list>
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class Demo {
    /**
     * 1、創建解析器工廠
     * 2、根據解析器工廠創建解析器
     * 3、解析xml返回document
     *
     */
    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        DocumentBuilder builder = factory.newDocumentBuilder();

        Document document = builder.parse("demo.xml");

        NodeList list = document.getElementsByTagName("name");

        for (int i = 0; i < list.getLength(); i++) {
            Node node = list.item(i);
            String name = node.getTextContent();
            System.out.println(name);
            // 張三 李四
        }
    }
}

課時22 使用JAXP添加節點

在person節點下添加sex子節點

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        // 創建解析器工廠
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // 根據解析器工廠創建解析器
        DocumentBuilder builder = factory.newDocumentBuilder();

        // 解析xml返回document
        Document document = builder.parse("demo.xml");

        NodeList list = document.getElementsByTagName("person");

        // 獲取第一個元素
        Node node = list.item(0);

        // 創建一個元素
        Element element = document.createElement("sex");
        Text text = document.createTextNode("女");

        // 添加創建的元素到節點
        element.appendChild(text);
        node.appendChild(element);

        // 回寫到硬盤
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult("demo.xml"));
    }
}

課時23-24 使用JAXP修改、刪除節點

xml讀取和保存的工具類

package util;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

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 java.io.IOException;

public class DocumentUtil {
    public static Document loadXml(String filename) throws ParserConfigurationException, IOException, SAXException {
        // 創建解析器工廠
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // 根據解析器工廠創建解析器
        DocumentBuilder builder = factory.newDocumentBuilder();

        // 解析xml返回document
        return builder.parse(filename);
    }

    public static void dumpXml(String filename, Document document) throws TransformerException {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult(filename));
    }
}

import org.w3c.dom.*;
import util.DocumentUtil;

public class Demo {

    public static void main(String[] args) throws Exception {
        String filename = "demo.xml";
        // 讀取
        Document document = DocumentUtil.loadXml(filename);

        // 查詢節點
        NodeList list = document.getElementsByTagName("name");
        Node node = list.item(0);

        // 設置節點內容
        node.setTextContent("大壯");

        // 刪除節點
        Node parentNode = node.getParentNode();
        parentNode.removeChild(node);

        // 回寫到硬盤
        DocumentUtil.dumpXml(filename, document);
    }
}

課時25 使用JAXP遍歷節點

使用遞歸遍歷

import org.w3c.dom.*;
import util.DocumentUtil;

public class Demo {
    public static void listElement(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++) {
            listElement(list.item(i));
        }
    }

    public static void main(String[] args) throws Exception {
        String filename = "demo.xml";
        // 讀取
        Document document = DocumentUtil.loadXml(filename);

        listElement(document);
    }
}

第4 章 : Schema:基於XML的DTD替代者

課時26 Schema的介紹

dtd語法

<!ELEMENT 元素名稱 約束>

scheme符合xml語法
一個xml可以有多個scheme,使用名稱空間區分
dtd有PCDAT類型scheme支持更多數據類型
scheme語法更加複雜

Schema 教程
https://www.w3school.com.cn/schema/index.asp

課時27 Schema的開發過程

文件*.xsd

1、屬性

<!-- 表示約束文件 -->
xmlns="http://www.w3.org/2001/XMLSchema"

<!-- 約束文件命名空間 url地址保證不會重複 -->
targetNamespace="http://www.w3school.com.cn"

<!-- 質量良好 -->
elementFormDefault="qualified"

2、複雜元素

<complexType>
    <sequence>
        <element name="name" type="string"></element>
        <element name="age" type="int"></element>
    </sequence>
</complexType>

3、引入約束文檔

表示被約束文檔,別名xsi
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

路徑地址
xsi:schemaLocation="http://www.w3school.com.cn demo.xsd">

完整示例
demo.xsd

<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.w3school.com.cn"
        elementFormDefault="qualified">
    <element name="person">
        <complexType>
            <sequence>
                <element name="name" type="string"></element>
                <element name="age" type="int"></element>
            </sequence>
        </complexType>
    </element>
</schema>

引入xsd文件

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://www.w3school.com.cn"
      xsi:schemaLocation="http://www.w3school.com.cn demo.xsd">
        <name>張三</name>
        <age>23</age>
</person>

課時28 Schema約束API查看

sequence 表示元素出現順序
all 只能出現一次
choice 出現任意一個
maxOccurs=“unbounded” 出現次數沒有限制
any 任意元素

複雜元素中定義屬性

<attribute name="age" type="int" use="required"></attribute>

引入多個schema,可以給每個schema取別名

課時29 sax解析的過程

dom 內存虛擬樹形結構
sax 事件驅動,邊讀邊解析

package org.xml.sax;

public class HandlerBase{
    public void startElement (String name, AttributeList attributes);
    public void characters (char ch[], int start, int length);
    public void endElement (String name);
}


package org.xml.sax.helpers;

public class DefaultHandler{
    public void startElement (String uri, String localName,
                              String qName, Attributes attributes)    

    public void endElement (String uri, String localName, String qName)
    public void characters (char ch[], int start, int length)
}

課時30 使用Schema的sax方式操作xml

demo.xml

<?xml version="1.0" encoding="UTF-8"?>

<person> 
    <name>張三</name>  
    <age>23</age> 
</person>

使用jaxp的sax解析只能進行查詢操作


import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class Demo {
    
    public static void main(String[] args) throws Exception {

        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        // 傳入事件處理類
        parser.parse("demo.xml", new MyDefaultHandler());

    }
}

/**
 * 自定義事件處理
 */
class MyDefaultHandler extends DefaultHandler {

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        System.out.println(qName);
    }

    @Override
    public void endElement(String uri, String localName, String qName) {
        System.out.println(qName);
    }

    @Override
    public void characters(char[] ch, int start, int length) {
        System.out.println(new String(ch, start, length));
    }
}

發佈了1418 篇原創文章 · 獲贊 370 · 訪問量 130萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章