国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

XML就是這么簡單

yacheng / 593人閱讀

什么是XML?

XML:extensiable markup language 被稱作可擴(kuò)展標(biāo)記語言

XML簡單的歷史介紹:

gml->sgml->html->xml

gml(通用標(biāo)記語言)–在不同的機(jī)器進(jìn)行通信的數(shù)據(jù)規(guī)范

sgml(標(biāo)準(zhǔn)通用標(biāo)記語言)

html(超文本標(biāo)記語言)

為什么我們需要使用XML呢?

①我們沒有XML這種語言之前,我們使用的是String作為兩個(gè)程序之間的通訊!現(xiàn)在問題就來了,如果我們傳輸?shù)氖菐в嘘P(guān)系型結(jié)構(gòu)的數(shù)據(jù),String怎么表達(dá)呢?String對關(guān)系型數(shù)據(jù)不擅長,要是描述起來也難免會有歧義的時(shí)候!關(guān)系型數(shù)據(jù)如圖下所示:

HTML語言本身就有缺陷

標(biāo)記都是固定的,不能自定義。HTML語言中有什么標(biāo)記就只能用什么標(biāo)記

HTML標(biāo)簽本身就缺少含義(tr標(biāo)簽里面什么內(nèi)容都能放進(jìn)去,不規(guī)范!!)

HTML沒有實(shí)現(xiàn)真正的國際化

XML文件就解決了以上的問題了,如果使用XML描述上述圖片的關(guān)系,是非常簡單的!

    
    <中國>
        <北京>
            <海淀>
            <豐臺>
        
        <湖南>
            <長沙>
            <岳陽>
        
        <湖北>
            <武漢>
            <荊州>
        
    

XML文件還能使用瀏覽器打開:

我們可以發(fā)現(xiàn)XML是可以描述很復(fù)雜的數(shù)據(jù)關(guān)系的

XML的用途

①:配置文件(例子:Tomcat的web.xml,server.xml......),XML能夠非常清晰描述出程序之間的關(guān)系

②:程序間數(shù)據(jù)的傳輸,XML的格式是通用的,能夠減少交換數(shù)據(jù)時(shí)的復(fù)雜性!

③:充當(dāng)小型數(shù)據(jù)庫,如果我們的數(shù)據(jù)有時(shí)候需要人工配置的,那么XML充當(dāng)小型的數(shù)據(jù)庫是個(gè)不錯(cuò)的選擇,程序直接讀取XML文件顯然要比讀取數(shù)據(jù)庫要快呢!

XML的技術(shù)架構(gòu)

XML被設(shè)計(jì)為“什么都不做”,XML數(shù)據(jù)或XML文檔只用于組織、存儲數(shù)據(jù),除此之外的數(shù)據(jù)生成、讀取、傳送、存取等等操作都與XML本身無關(guān)!

于是乎,想要操作XML,就需要用到XML之外的技術(shù)了

為XML定規(guī)則:現(xiàn)在一般使用DTD或Schema技術(shù),當(dāng)然了Schema技術(shù)更為先進(jìn)!

解析XML的數(shù)據(jù):一般使用DOM或者SAX技術(shù),各有各的優(yōu)點(diǎn)

提供樣式:XML一般用來存儲數(shù)據(jù)的,但設(shè)計(jì)者野心很大,也想用來顯示數(shù)據(jù)(但沒人用XML來顯示數(shù)據(jù)),就有了XSLT(eXtensiable Stylesheet Language Transformation)可擴(kuò)展樣式轉(zhuǎn)換語言

XML語法: 文檔聲明:

XML聲明放在XML的第一行

version----版本

encoding--編碼

standalone--獨(dú)立使用--默認(rèn)是no。standalone表示該xml是不是獨(dú)立的,如果是yes,則表示這個(gè)XML文檔時(shí)獨(dú)立的,不能引用外部的DTD規(guī)范文件;如果是no,則該XML文檔不是獨(dú)立的,表示可以引用外部的DTD規(guī)范文檔。

正確的文檔聲明格式,屬性的位置不能改變!

    
元素

首先在這里說明一個(gè)概念:在XML中元素和標(biāo)簽指的是同一個(gè)東西!不要被不同的名稱所迷惑了!

元素中需要值得注意的地方

XML元素中的出現(xiàn)的空格和換行都會被當(dāng)做元素內(nèi)容進(jìn)行處理

每個(gè)XML文檔必須有且只有一個(gè)根元素

元素必須閉合

大小寫敏感

不能交叉嵌套

不能以數(shù)字開頭

看起來好像有很多需要值得注意的地方,其實(shí)只需要記?。?strong>XML的語法是規(guī)范的!不要隨意亂寫!

屬性

屬性是作為XML元素中的一部分的,命名規(guī)范也是和XML元素一樣的!

    
    <中國 name="china">

    

注釋

注釋和HTML的注釋是一樣的

    
CDATA

在編寫XML文件時(shí),有些內(nèi)容可能不想讓解析引擎解析執(zhí)行,而是當(dāng)作原始內(nèi)容處理。遇到此種情況,可以把這些內(nèi)容放在CDATA區(qū)里,對于CDATA區(qū)域內(nèi)的內(nèi)容,XML解析程序不會處理,而是直接原封不動的輸出

語法:

    
    
轉(zhuǎn)義字符

對于一些單個(gè)字符,若想顯示其原始樣式,也可以使用轉(zhuǎn)義的形式予以處理。

處理指令

處理指令,簡稱PI (processing instruction)。處理指令用來指揮解析引擎如何解析XML文檔內(nèi)容。

例如:

在XML文檔中可以使用xml-stylesheet指令,通知XML解析引擎,應(yīng)用css文件顯示xml文檔內(nèi)容。

    

XML代碼:



    
    
    
    
        
            廣州
        
        
            深圳
        
    

CSS代碼:

    
    
    guangzhou{
        font-size: 40px;
    }

效果:

JDK中的XML API

①:JAXP(The Java API For XML Processing):主要負(fù)責(zé)解析XML

②:JAXB(Java Architecture for XML Binding):主要負(fù)責(zé)將XML映射為Java對象

什么是XML解析

前面XML章節(jié)已經(jīng)說了,XML被設(shè)計(jì)為“什么都不做”,XML只用于組織、存儲數(shù)據(jù),除此之外的數(shù)據(jù)生成、讀取、傳送等等的操作都與XML本身無關(guān)!

XML解析就是讀取XML的數(shù)據(jù)!

XML解析方式

XML解析方式分為兩種:

①:dom(Document Object Model)文檔對象模型,是W3C組織推薦解析XML的一種方式

②:sax(Simple API For XML),它是XML社區(qū)的標(biāo)準(zhǔn),幾乎所有XML解析器都支持它!

XML解析操作

從上面的圖很容易發(fā)現(xiàn),應(yīng)用程序不是直接對XML文檔進(jìn)行操作的,而是由XML解析器對XML文檔進(jìn)行分析,然后應(yīng)用程序通過XML解析器所提供的DOM接口或者SAX接口對分析結(jié)果進(jìn)行操作,從而間接地實(shí)現(xiàn)了對XML文檔的訪問!

常用的解析器和解析開發(fā)包的關(guān)系如下所示

為什么有3種開發(fā)包?

jaxp開發(fā)包是JDK自帶的,不需要導(dǎo)入開發(fā)包。

由于sun公司的jaxp不夠完善,于是就被研發(fā)了Jdom。XML解析如果使用Jdom,需要導(dǎo)入開發(fā)包

dom4j是由于Jdom的開發(fā)人員出現(xiàn)了分歧,dom4j由Jdom的一批開發(fā)人員所研發(fā)。XML解析如果使用Jdom,需要導(dǎo)入開發(fā)包【現(xiàn)在用dom4j是最多的!】

jaxp

雖然jaxp解析XML的性能以及開發(fā)的簡易度是沒有dom4j好,但是jaxp不管怎么說都是JDK內(nèi)置的開發(fā)包,我們是需要學(xué)習(xí)的

DOM解析操作
DOM解析是一個(gè)基于對象的API,它把XML的內(nèi)容加載到內(nèi)存中,生成與XML文檔內(nèi)容對應(yīng)的模型!當(dāng)解析完成,內(nèi)存中會生成與XML文檔的結(jié)構(gòu)與之對應(yīng)的DOM對象樹,這樣就能夠根據(jù)樹的結(jié)構(gòu),以節(jié)點(diǎn)的形式對文檔進(jìn)行操作!

簡單來說:DOM解析會把XML文檔加載到內(nèi)存中,生成DOM樹的元素都是以對象的形式存在的!我們操作這些對象就能夠操作XML文檔了!

下面這樣圖就能很好地說明了,是怎么樣生成與XML文檔內(nèi)容對應(yīng)的DOM樹!

既然XML文檔的數(shù)據(jù)是帶有關(guān)系型的,那么生成的DOM樹的節(jié)點(diǎn)也是有關(guān)系的:

位于一個(gè)節(jié)點(diǎn)之上的節(jié)點(diǎn)是該節(jié)點(diǎn)的父節(jié)點(diǎn)(parent)

一個(gè)節(jié)點(diǎn)之下的節(jié)點(diǎn)是該節(jié)點(diǎn)的子節(jié)點(diǎn)(children)

同一層次,具有相同父節(jié)點(diǎn)的節(jié)點(diǎn)是兄弟節(jié)點(diǎn)(sibling)

一個(gè)節(jié)點(diǎn)的下一個(gè)層次的節(jié)點(diǎn)集合是節(jié)點(diǎn)后代(descendant)

父、祖父節(jié)點(diǎn)及所有位于節(jié)點(diǎn)上面的,都是節(jié)點(diǎn)的祖先(ancestor)

在DOM解析中有幾個(gè)核心的操作接口:

Document【代表整個(gè)XML文檔,通過Document節(jié)點(diǎn)可以訪問XML文件中所有的元素內(nèi)容!】

Node【Node節(jié)點(diǎn)幾乎在XML操作接口中幾乎相當(dāng)于普通Java類的Object,很多核心接口都實(shí)現(xiàn)了它,在下面的關(guān)系圖可以看出!】

NodeList【代表著一個(gè)節(jié)點(diǎn)的集合,通常是一個(gè)節(jié)點(diǎn)中子節(jié)點(diǎn)的集合!】

NameNodeMap【表示一組節(jié)點(diǎn)和其唯一名稱對應(yīng)的一一對應(yīng)關(guān)系,主要用于屬性節(jié)點(diǎn)的表示(書上說是核心的操作接口,但我好像沒用到!呃呃呃,等我用到了,我再來填坑?。?/p>

節(jié)點(diǎn)之間的關(guān)系圖:

有人可能會很難理解,為什么Document接口比Node接口還小,呃呃呃,我是這樣想的:一個(gè)Document由無數(shù)個(gè)Node組成,這樣我也能把Document當(dāng)成是Node呀!如果實(shí)在想不通:人家都這樣設(shè)計(jì)了,你有種就不用?。?!(開玩笑的.....)

好的,不跟你們多bb,我們來使用一下Dom的方式解析XML文檔吧!

XML文檔代碼

    
    
        廣州
        深圳
        北京
        上海
    

根據(jù)XML解析的流程圖,我們先要獲取到解析器對象!


    public class DomParse {
    
        public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
    
            //API規(guī)范:需要用一個(gè)工廠來造解析器對象,于是我先造了一個(gè)工廠!
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    
            //獲取解析器對象
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    
            //獲取到解析XML文檔的流對象
            InputStream inputStream = DomParse.class.getClassLoader().getResourceAsStream("city.xml");
    
            //解析XML文檔,得到了代表XML文檔的Document對象!
            Document document = documentBuilder.parse(inputStream);
            
        }
    }

解析XML文檔的內(nèi)容用來干嘛?無非就是增刪改查遍歷,只要我們會對XML進(jìn)行增刪改查,那就說明我們是會使用DOM解析的!

遍歷

我們再來看一下XML文檔的內(nèi)容,如果我們要遍歷該怎么做?

可能我們會有兩種想法

①:從XML文檔內(nèi)容的上往下看,看到什么就輸出什么!【這正是SAX解析的做法】

②:把XML文檔的內(nèi)容分成兩部分,一部分是有子節(jié)點(diǎn)的,一部分是沒有子節(jié)點(diǎn)的(也就是元素節(jié)點(diǎn)?。?。首先我們判斷是否為元素節(jié)點(diǎn),如果是元素節(jié)點(diǎn)就輸出,不是元素節(jié)點(diǎn)就獲取到子節(jié)點(diǎn)的集合,再判斷子節(jié)點(diǎn)集合中的是否是元素節(jié)點(diǎn),如果是元素節(jié)點(diǎn)就輸出,如果不是元素節(jié)點(diǎn)獲取到該子節(jié)點(diǎn)的集合....好的,一不小心就遞歸了...

我們來對XML文檔遍歷一下吧,為了更好地重用,就將它寫成一個(gè)方法吧(也是能夠更好地用遞歸實(shí)現(xiàn)功能)

    public class DomParse {
    
        public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
    
            //API規(guī)范:需要用一個(gè)工廠來造解析器對象,于是我先造了一個(gè)工廠!
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    
            //獲取解析器對象
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    
            //獲取到解析XML文檔的File對象
            InputStream inputStream = DomParse.class.getClassLoader().getResourceAsStream("city.xml");
    
            //解析XML文檔,得到了代表XML文檔的Document對象!
            Document document = documentBuilder.parse(inputStream);
    
            //把代表XML文檔的document對象傳遞進(jìn)去給list方法
            list(document);
    
        }
    
    
        //我們這里就接收Node類型的實(shí)例對象吧!多態(tài)!!!
        private static void list(Node node) {
    
            //判斷是否是元素節(jié)點(diǎn),如果是元素節(jié)點(diǎn)就直接輸出
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                System.out.println(node.getNodeName());
            }
    
            //....如果沒有進(jìn)入if語句,下面的肯定就不是元素節(jié)點(diǎn)了,所以獲取到子節(jié)點(diǎn)集合
            NodeList nodeList = node.getChildNodes();
    
            //遍歷子節(jié)點(diǎn)集合
            for (int i = 0; i < nodeList.getLength(); i++) {
    
                //獲取到其中的一個(gè)子節(jié)點(diǎn)
                Node child = nodeList.item(i);
    
                //...判斷該子節(jié)點(diǎn)是否為元素節(jié)點(diǎn),如果是元素節(jié)點(diǎn)就輸出,不是元素節(jié)點(diǎn)就再獲取到它的子節(jié)點(diǎn)集合...遞歸了
    
                list(child);
            }
            
        }
    }

效果:

查詢

現(xiàn)在我要做的就是:讀取guangzhou這個(gè)節(jié)點(diǎn)的文本內(nèi)容!


    private static void read(Document document) {

        //獲取到所有名稱為guangzhou節(jié)點(diǎn)
        NodeList nodeList = document.getElementsByTagName("guangzhou");
        
        //取出第一個(gè)名稱為guangzhou的節(jié)點(diǎn)
        Node node = nodeList.item(0);
        
        //獲取到節(jié)點(diǎn)的文本內(nèi)容
        String value = node.getTextContent();

        System.out.println(value);

    }

效果:

增加

現(xiàn)在我想多增加一個(gè)城市節(jié)點(diǎn)(杭州),我需要這樣做:

    private static void add(Document document) {

        //創(chuàng)建需要增加的節(jié)點(diǎn)
        Element element = document.createElement("hangzhou");

        //向節(jié)點(diǎn)添加文本內(nèi)容
        element.setTextContent("杭州");

        //得到需要添加節(jié)點(diǎn)的父節(jié)點(diǎn)
        Node parent = document.getElementsByTagName("china").item(0);

        //把需要增加的節(jié)點(diǎn)掛在父節(jié)點(diǎn)下面去
        parent.appendChild(element);

    }

做到這里,我僅僅在內(nèi)存的Dom樹下添加了一個(gè)節(jié)點(diǎn),要想把內(nèi)存中的Dom樹寫到硬盤文件中,需要轉(zhuǎn)換器

獲取轉(zhuǎn)換器也十分簡單

        //獲取一個(gè)轉(zhuǎn)換器它需要工廠來造,那么我就造一個(gè)工廠
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        
        //獲取轉(zhuǎn)換器對象
        Transformer transformer = transformerFactory.newTransformer();

把內(nèi)存中的Dom樹更新到硬盤文件中的transform()方法就稍稍有些復(fù)雜了

它需要一個(gè)Source實(shí)例對象和Result的實(shí)例對象,這兩個(gè)接口到底是什么玩意???

于是乎,我就去查API,發(fā)現(xiàn)DomSource實(shí)現(xiàn)了Source接口,我們使用的不正是Dom解析嗎,再看看構(gòu)造方法,感覺就是它了!

而SteamResult實(shí)現(xiàn)了Result接口,有人也會想,DomResult也實(shí)現(xiàn)了Result接口啊,為什么不用DomResult呢?我們現(xiàn)在做的是把內(nèi)存中的Dom樹更新到硬盤文件中呀,當(dāng)然用的是StreamResult啦!

完整代碼如下:

    private static void add(Document document) throws TransformerException {

        //創(chuàng)建需要增加的節(jié)點(diǎn)
        Element element = document.createElement("hangzhou");

        //向節(jié)點(diǎn)添加文本內(nèi)容
        element.setTextContent("杭州");

        //得到需要添加節(jié)點(diǎn)的父節(jié)點(diǎn)
        Node parent = document.getElementsByTagName("china").item(0);

        //把需要增加的節(jié)點(diǎn)掛在父節(jié)點(diǎn)下面去
        parent.appendChild(element);

        //獲取一個(gè)轉(zhuǎn)換器它需要工廠來造,那么我就造一個(gè)工廠
        TransformerFactory transformerFactory = TransformerFactory.newInstance();

        //獲取轉(zhuǎn)換器對象
        Transformer transformer = transformerFactory.newTransformer();

        //把內(nèi)存中的Dom樹更新到硬盤中
        transformer.transform(new DOMSource(document),new StreamResult("city.xml"));
    }

效果:

剛剛增加的節(jié)點(diǎn)是在china節(jié)點(diǎn)的末尾處的,現(xiàn)在我想指定增加節(jié)點(diǎn)的在beijing節(jié)點(diǎn)之前,是這樣做的:


    private static void add2(Document document) throws TransformerException {

        //獲取到beijing節(jié)點(diǎn)
        Node beijing = document.getElementsByTagName("beijing").item(0);

        //創(chuàng)建新的節(jié)點(diǎn)
        Element element = document.createElement("guangxi");

        //設(shè)置節(jié)點(diǎn)的文本內(nèi)容
        element.setTextContent("廣西");

        //獲取到要創(chuàng)建節(jié)點(diǎn)的父節(jié)點(diǎn),
        Node parent = document.getElementsByTagName("china").item(0);

        //將guangxi節(jié)點(diǎn)插入到beijing節(jié)點(diǎn)之前!
        parent.insertBefore(element, beijing);

        //將內(nèi)存中的Dom樹更新到硬盤文件中
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult("city.xml"));
        
    }

效果:

刪除

現(xiàn)在我要刪除的是beijing這個(gè)節(jié)點(diǎn)!


    private static void delete(Document document) throws TransformerException {

        //獲取到beijing這個(gè)節(jié)點(diǎn)
        Node node = document.getElementsByTagName("beijing").item(0);

        //獲取到父節(jié)點(diǎn),然后通過父節(jié)點(diǎn)把自己刪除了
        node.getParentNode().removeChild(node);

        //把內(nèi)存中的Dom樹更新到硬盤文件中
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult("city.xml"));


    }

效果:

修改

將guangzhou節(jié)點(diǎn)的文本內(nèi)容修改成廣州你好

    private static void update(Document document) throws TransformerException {

        //獲取到guangzhou節(jié)點(diǎn)
        Node node = document.getElementsByTagName("guangzhou").item(0);

        node.setTextContent("廣州你好");

        //將內(nèi)存中的Dom樹更新到硬盤文件中
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult("city.xml"));


    }

效果:

操作屬性

XML文檔是可能帶有屬性值的,現(xiàn)在我們要guangzhou節(jié)點(diǎn)上的屬性

    private static void updateAttribute(Document document) throws TransformerException {

        //獲取到guangzhou節(jié)點(diǎn)
        Node node = document.getElementsByTagName("guangzhou").item(0);

        //現(xiàn)在node節(jié)點(diǎn)沒有增加屬性的方法,所以我就要找它的子類---Element
        Element guangzhou = (Element) node;

        //設(shè)置一個(gè)屬性,如果存在則修改,不存在則創(chuàng)建!
        guangzhou.setAttribute("play", "gzchanglong");

        //如果要刪除屬性就用removeAttribute()方法


        //將內(nèi)存中的Dom樹更新到硬盤文件中
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult("city.xml"));


    }

效果:

SAX解析
SAX采用的是一種順序的模式進(jìn)行訪問,是一種快速讀取XML數(shù)據(jù)的方式。當(dāng)時(shí)候SAX解析器進(jìn)行操作時(shí),會觸發(fā)一系列事件SAX。采用事件處理的方式解析XML文件,利用 SAX 解析 XML 文檔,涉及兩個(gè)部分:解析器和事件處理器

sax是一種推式的機(jī)制,你創(chuàng)建一個(gè)sax 解析器,解析器在發(fā)現(xiàn)xml文檔中的內(nèi)容時(shí)就告訴你(把事件推給你). 如何處理這些內(nèi)容,由程序員自己決定。

當(dāng)解析器解析到聲明頭時(shí),會觸發(fā)事件。解析到元素頭時(shí)也會觸發(fā)事件!也就是說:當(dāng)使用SAX解析器掃描XML文檔(也就是Document對象)開始、結(jié)束,以及元素的開始、結(jié)束時(shí)都會觸發(fā)事件,根據(jù)不同事件調(diào)用相對應(yīng)的方法!

首先我們還是先拿到SAX的解析器再說吧!

        //要得到解析器對象就需要造一個(gè)工廠,于是我造了一個(gè)工廠
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        
        //獲取到解析器對象
        SAXParser saxParse = saxParserFactory.newSAXParser();

調(diào)用解析對象的解析方法的時(shí)候,需要的不僅僅是XML文檔的路徑!還需要一個(gè)事件處理器!

事件處理器都是由我們程序員來編寫的,它一般繼承DefaultHandler類,重寫如下5個(gè)方法:

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
    }

獲取解析器,調(diào)用解析器解析XML文檔的代碼:


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

        //要得到解析器對象就需要造一個(gè)工廠,于是我造了一個(gè)工廠
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();

        //獲取到解析器對象
        SAXParser saxParse = saxParserFactory.newSAXParser();

        //獲取到XML文檔的流對象
        InputStream inputStream = SAXParse.class.getClassLoader().getResourceAsStream("city.xml");

        saxParse.parse(inputStream, new MyHandler());

    }

事件處理器的代碼:

    public class MyHandler extends DefaultHandler {
        @Override
        public void startDocument() throws SAXException {
            System.out.println("我開始來掃描啦!?。?!");
        }
    
        @Override
        public void endDocument() throws SAXException {
    
            System.out.println("我結(jié)束了?。。?!");
        }
    
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

            //如果要解析出節(jié)點(diǎn)屬性的內(nèi)容,也非常簡單,只要通過attributes變量就行了!

            //輸出節(jié)點(diǎn)的名字!
            System.out.println(qName);
        }
    
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
    
            System.out.println(qName);
        }
    
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
    
            System.out.println(new String(ch,start,length));
        }
    }

我們發(fā)現(xiàn),事件處理器的代碼都非常簡單,然后就如此簡單地就能夠遍歷整個(gè)XML文檔了!

如果要查詢多帶帶的某個(gè)節(jié)點(diǎn)的內(nèi)容也是非常簡單的喲!只要在startElement()方法中判斷名字是否相同即可!

現(xiàn)在我只想查詢guangzhou節(jié)點(diǎn)的內(nèi)容:

    //定義一個(gè)標(biāo)識量,用于指定查詢某個(gè)節(jié)點(diǎn)的內(nèi)容
    boolean flag = false;

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

        //如果節(jié)點(diǎn)名稱是guangzhou,我才輸出,并且把標(biāo)識量設(shè)置為true
        if (qName == "guangzhou") {
            System.out.println(qName);
            flag = true;
        }
    }


    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        //只有在flag為true的情況下我才輸出文本的內(nèi)容
        if (flag == true) {
            System.out.println(new String(ch, start, length));

        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        //在執(zhí)行到元素的末尾時(shí),不要忘了將標(biāo)識量改成false
        if (qName == "guangzhou" && flag == true) {
            System.out.println(qName);
            flag = false;

        }
    }

效果:

DOM和SAX解析的區(qū)別:

DOM解析讀取整個(gè)XML文檔,在內(nèi)存中形成DOM樹,很方便地對XML文檔的內(nèi)容進(jìn)行增刪改。但如果XML文檔的內(nèi)容過大,那么就會導(dǎo)致內(nèi)存溢出!

SAX解析采用部分讀取的方式,可以處理大型文件,但只能對文件按順序從頭到尾解析一遍,不支持文件的增刪改操作

DOM和SAX解析有著明顯的差別,什么時(shí)候使用DOM或者SAX就非常明了了。

dom4j

Dom4j是一個(gè)非常優(yōu)秀的Java XML API,具有性能優(yōu)異、功能強(qiáng)大和極易使用的特點(diǎn)。

為什么需要有dom4j

dom缺點(diǎn):比較耗費(fèi)內(nèi)存

sax缺點(diǎn):只能對xml文件進(jìn)行讀取,不能修改,添加,刪除

dom4j:既可以提高效率,同時(shí)也可以進(jìn)行crud操作

因?yàn)閐om4j不是sun公司的產(chǎn)品,所以我們開發(fā)dom4j需要導(dǎo)入開發(fā)包

獲取dom4j的解析器

使用dom4j對XML文檔進(jìn)行增刪改查,都需要獲取到dom4j的解析器

        //獲取到解析器
        SAXReader saxReader = new SAXReader();

        //獲取到XML文件的流對象
        InputStream inputStream = DOM4j.class.getClassLoader().getResourceAsStream("1.xml");

        //通過解析器讀取XML文件
        Document document = saxReader.read(inputStream);
        
獲取Document對象

我們都知道,Document代表的是XML文檔,一般我們都是通過Document對象開始,來進(jìn)行CRUD(增刪改查)操作的!

獲取Document對象有三種方式:

①:讀取XML文件,獲得document對象(這種最常用)

SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));

②:解析XML形式的文本,得到document對象

    
    String text = "";
    Document document=DocumentHelper.parseText(text);

③:主動創(chuàng)建document對象.

Document document =DocumentHelper.createDocument();

//創(chuàng)建根節(jié)點(diǎn)
Element root = document.addElement("members");
CRUD的重要一句話:

讀取XML文檔的數(shù)據(jù),都是通過Document獲取根元素,再通過根元素獲取得到其他節(jié)點(diǎn)的,從而進(jìn)行操作!

如果XML的結(jié)構(gòu)有多層,需要一層一層地獲??!

查詢
    @Test
    public void read() throws DocumentException {

        //獲取到解析器
        SAXReader saxReader = new SAXReader();

        //獲取到XML文件的流對象
        InputStream inputStream = dom4j11.class.getClassLoader().getResourceAsStream("1.xml");
   
        //通過解析器讀取XML文件
        Document document = saxReader.read(inputStream);

        //獲取得到根節(jié)點(diǎn)
        Element root = document.getRootElement();

        //獲取得到name節(jié)點(diǎn)
        Element name = root.element("name");

        //得到了name節(jié)點(diǎn),就可以獲取name節(jié)點(diǎn)的屬性或者文本內(nèi)容了!
        String text = name.getText();

        String attribute = name.attributeValue("littleName");

        System.out.println("文本內(nèi)容是:" + text);
        System.out.println("屬性內(nèi)容是:" + attribute);
        
    }

XML文件如下:

    
         
        zhongfucheng
        20
    

效果:

多層結(jié)構(gòu)的查詢:

        //獲取得到根節(jié)點(diǎn)
        Element root = document.getRootElement();

        //一層一層地獲取到節(jié)點(diǎn)
        Element element = root.element("guangdong").element("guangzhou").element("luogang");

        String value = element.getText();

        System.out.println(value);

XML文件和結(jié)果:

增加

在DOM4j中要對內(nèi)存中的DOM樹寫到硬盤文件中,也是要有轉(zhuǎn)換器的支持的!

dom4j提供了XMLWriter供我們對XML文檔進(jìn)行更新操作,一般地創(chuàng)建XMLWriter的時(shí)候我們都會給出兩個(gè)參數(shù),一個(gè)是Writer,一個(gè)是OutputFormat

這個(gè)OutputFormat有什么用的呢?其實(shí)就是指定回寫XML的格式和編碼格式。細(xì)心的朋友會發(fā)現(xiàn),上面我們在jaxp包下使用dom解析的Transformer類,把內(nèi)存中的DOM樹更新到文件硬盤中,是沒有格式的!不信倒回去看看!這個(gè)OutputFormat就可以讓我們更新XML文檔時(shí)也能帶有格式

        //創(chuàng)建帶有格式的對象
        OutputFormat outputFormat = OutputFormat.createPrettyPrint();

        //設(shè)置編碼,默認(rèn)的編碼是gb2312,讀寫的編碼不一致,會導(dǎo)致亂碼的!
        outputFormat.setEncoding("UTF-8");

        //創(chuàng)建XMLWriter對象
        XMLWriter xmlWriter = new XMLWriter(new FileWriter("2.xml"), outputFormat);

        //XMLWriter對象寫入的是document
        xmlWriter.write(document);

        //關(guān)閉流
        xmlWriter.close();

下面我們就為在person節(jié)點(diǎn)下新創(chuàng)建一個(gè)name節(jié)點(diǎn)吧,完整的代碼如下:!


    @Test
    public void add() throws Exception {

        //獲取到解析器
        SAXReader saxReader = new SAXReader();

        //獲取到XML文件的流對象
        InputStream inputStream = dom4j11.class.getClassLoader().getResourceAsStream("1.xml");

        //通過解析器讀取XML文件
        Document document = saxReader.read(inputStream);

        //創(chuàng)建出新的節(jié)點(diǎn),為節(jié)點(diǎn)設(shè)置文本內(nèi)容
        Element newElement = DocumentHelper.createElement("name");
        newElement.setText("ouzicheng");

        //獲取到根元素
        Element root = document.getRootElement();

        //把新創(chuàng)建的name節(jié)點(diǎn)掛在根節(jié)點(diǎn)下面
        root.add(newElement);

        //創(chuàng)建帶有格式的對象
        OutputFormat outputFormat = OutputFormat.createPrettyPrint();

        //設(shè)置編碼,默認(rèn)的編碼是gb2312,讀寫的編碼不一致,會導(dǎo)致亂碼的!
        outputFormat.setEncoding("UTF-8");

        //創(chuàng)建XMLWriter對象
        XMLWriter xmlWriter = new XMLWriter(new FileWriter("2.xml"), outputFormat);

        //XMLWriter對象寫入的是document
        xmlWriter.write(document);

        //關(guān)閉流
        xmlWriter.close();


    }

效果如下,是有格式的!

在指定的位置增加節(jié)點(diǎn)!現(xiàn)在我想的就是在age屬性前面添加節(jié)點(diǎn)!

        //創(chuàng)建一個(gè)新節(jié)點(diǎn)
        Element element = DocumentHelper.createElement("name");
        element.setText("ouzciheng");

        //獲取得到person下所有的節(jié)點(diǎn)元素!
        List list = document.getRootElement().elements();

        //將節(jié)點(diǎn)添加到指定的位置上
        list.add(1, element);

效果圖:

修改

XMLWriter和獲取Document對象的代碼我就不貼出來了,反正都是一樣的了!

        //獲取得到age元素
        Element age = document.getRootElement().element("age");
        age.setText("9999");

效果如下:

刪除

XMLWriter和獲取Document對象的代碼我就不貼出來了,反正都是一樣的了!

        //獲取得到age節(jié)點(diǎn)
        Element age = document.getRootElement().element("age");

        //得到age節(jié)點(diǎn)的父節(jié)點(diǎn),使用父節(jié)點(diǎn)的remove刪除age節(jié)點(diǎn)!
        age.getParent().remove(age);

效果:

XPATH 什么是XPATH
XPath 是一門在 XML 文檔中查找信息的語言。XPath 用于在 XML 文檔中通過元素和屬性進(jìn)行導(dǎo)航。
為什么我們需要用到XPATH

上面我們使用dom4j的時(shí)候,要獲取某個(gè)節(jié)點(diǎn),都是通過根節(jié)點(diǎn)開始,一層一層地往下尋找,這就有些麻煩了

如果我們用到了XPATH這門語言,要獲取得到XML的節(jié)點(diǎn),就非常地方便了!

快速入門

使用XPATH需要導(dǎo)入開發(fā)包jaxen-1.1-beta-7,我們來看官方的文檔來入門吧。

XPATH的文檔非常國際化啊,連中文都有

XPATH文檔中有非常多的實(shí)例,非常好學(xué),對著來看就知道了!

我們來用XPATH技術(shù)讀取XML文件的信息吧,XML文檔如下:

之前,我們是先獲取根節(jié)點(diǎn),再獲取guangdong節(jié)點(diǎn)再獲取guangzhou節(jié)點(diǎn),然后才能讀取tianhe節(jié)點(diǎn)或者luogang節(jié)點(diǎn)的,下面我們來看一下使用XPATH可以怎么的便捷!

        //直接獲取到luogang節(jié)點(diǎn)
        org.dom4j.Node node =  document.selectSingleNode("http://luogang");

        //獲取節(jié)點(diǎn)的內(nèi)容
        String value = node.getText();

        System.out.println(value);

效果:

獲取什么類型的節(jié)點(diǎn),XPATH的字符串應(yīng)該怎么匹配,查文檔就知道了,這里就不再贅述了。!

如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號:Java3y

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/110367.html

相關(guān)文章

  • Tomcat就是這么簡單

    摘要:什么是簡單的說就是一個(gè)運(yùn)行的網(wǎng)絡(luò)服務(wù)器,底層是的一個(gè)程序,它也是和的一個(gè)容器。在瀏覽器地址欄輸入如果能夠出現(xiàn)頁面,說明配置成功了注意如果在使用時(shí)出現(xiàn)了很大原因就是和的版本不匹配。 什么是Tomcat Tomcat簡單的說就是一個(gè)運(yùn)行JAVA的網(wǎng)絡(luò)服務(wù)器,底層是Socket的一個(gè)程序,它也是JSP和Serlvet的一個(gè)容器。 為什么我們需要用到Tomcat 如果你學(xué)過html,css,...

    Winer 評論0 收藏0
  • Maven就是這么簡單

    摘要:軟件項(xiàng)目的管理就會變得簡單很多。比如說的驅(qū)動程序,,在是獲取不到的,就需要手工上傳到里是倉庫組,在里沒有這個(gè)概念,是特有的。 什么是Maven Maven是一個(gè)采用純Java編寫的開源項(xiàng)目管理工具, Maven采用了一種被稱之為Project Object Model (POM)概念來管理項(xiàng)目,所有的項(xiàng)目配置信息都被定義在一個(gè)叫做POM.xml的文件中.. Maven是一款跨平臺的項(xiàng)目...

    leonardofed 評論0 收藏0
  • Java3y文章目錄導(dǎo)航

    摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...

    KevinYan 評論0 收藏0
  • Spring【依賴注入】就是這么簡單

    摘要:前言在的第二篇中主要講解了模塊的使用容器創(chuàng)建對象的問題,模塊主要是解決對象的創(chuàng)建和對象之間的依賴關(guān)系,因此本博文主要講解如何使用容器來解決對象之間的依賴關(guān)系回顧以前對象依賴我們來看一下我們以前關(guān)于對象依賴,是怎么的歷程直接對象在最開始,我們 前言 在Spring的第二篇中主要講解了Spring Core模塊的使用IOC容器創(chuàng)建對象的問題,Spring Core模塊主要是解決對象的創(chuàng)建和...

    Lyux 評論0 收藏0
  • Spring AOP就是這么簡單

    摘要:是一種特殊的增強(qiáng)切面切面由切點(diǎn)和增強(qiáng)通知組成,它既包括了橫切邏輯的定義也包括了連接點(diǎn)的定義。實(shí)際上,一個(gè)的實(shí)現(xiàn)被拆分到多個(gè)類中在中聲明切面我們知道注解很方便,但是,要想使用注解的方式使用就必須要有源碼因?yàn)槲覀円? 前言 只有光頭才能變強(qiáng) 上一篇已經(jīng)講解了Spring IOC知識點(diǎn)一網(wǎng)打盡!,這篇主要是講解Spring的AOP模塊~ 之前我已經(jīng)寫過一篇關(guān)于AOP的文章了,那篇把比較重要的知...

    Jacendfeng 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<