XML3 - XML解析編程

解析方式 簡(jiǎn)介 優(yōu)點(diǎn) 缺點(diǎn)
DOM Document Object Model文檔對(duì)象模型,把整個(gè)XML文檔先加載到內(nèi)存中,形成樹狀結(jié)構(gòu) 節(jié)點(diǎn)與節(jié)點(diǎn)之間有關(guān)系,進(jìn)行增刪改非常方便 如果文檔非常大,加載到內(nèi)存中容易產(chǎn)生內(nèi)存溢出的問題
SAX Simple API for XML 基于事件驅(qū)動(dòng)的,邊讀邊解析 文檔大也不會(huì)有內(nèi)存溢出的問題,查找非常方便 不能進(jìn)行增刪改的操作
解析開發(fā)包 簡(jiǎn)介
JAXP javaSE的一部分,想做增刪改,只能用DOM方式。如果SAx,只能做查詢
Dom4j 企業(yè)都在用,DOM4J提供。增刪改查都可以做

JAXP解析

解析方式 解析器工廠類 解析器對(duì)象
DOM DocumentBuilderFactory DocumentBuilder
SAX SAXParserFactory SAXParser

JAXP的DOM解析

  1. 由解析器工廠類獲取解析器工廠
  2. 解析器工廠產(chǎn)生一個(gè)解析器
  3. 解析XML,獲得一個(gè)Document對(duì)象。Document parse(String uri)
  4. 回寫
    a 獲取回寫的工廠類TransformerFactory
    b 獲取回寫類transformer
    c transform(new DOMSource(document), new StreamResult("src/book2.xml"));
//獲取作者的文本內(nèi)容
public static void run1() throws ParserConfigurationException, SAXException, IOException{
        //獲取解析器工廠類
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //獲取解析器對(duì)象
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析XML的文檔,返回document對(duì)象
        Document document = builder.parse("src/book2.xml");
        //獲取作者元素對(duì)象的集合,返回NodeList
        NodeList nodelist = document.getElementsByTagName("作者");
        //循環(huán)遍歷,獲得每一個(gè)作者,打印文本的內(nèi)容
        for(int i = 0; i < nodelist.getLength(); i++){
            Node node = nodelist.item(i);
            System.out.println(node.getTextContent());
        }
    }

//在第二本下,在末尾添加子節(jié)點(diǎn),需要回寫類
public static void run2() throws Exception{
        //獲取工廠類
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //獲取解析類
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析XML,返回Document對(duì)象
        Document document = builder.parse("src/book2.xml");
        //獲取第二本書
        Node book2 = document.getElementsByTagName("書").item(1);
        //創(chuàng)建元素對(duì)象
        Element cat = document.createElement("毛");
        //設(shè)置文本內(nèi)容
        cat.setTextContent("我是貓");
        //把元素對(duì)象添加到第二本書下
        book2.appendChild(cat);

        //回寫
        //創(chuàng)建回寫類的工廠
        TransformerFactory transFactory = TransformerFactory.newInstance();
        //獲取回寫類
        Transformer transformer = transFactory.newTransformer();
        //調(diào)用回寫的方法
        transformer.transform(new DOMSource(document), new StreamResult("src/book2.xml"));
    }

/**
     * 獲取第一本書的屬性值
     * @throws Exception 
     */
    public static void run3() throws Exception{
        
        //獲取工廠類
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //解析器
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析
        Document document = builder.parse("src/book2.xml");
        //獲取作者,再獲取第二本書
        Node book1 = document.getElementsByTagName("書").item(0);
        //鄉(xiāng)下轉(zhuǎn)型
        Element book = (Element)book1;
        System.out.println(book.getAttribute("編號(hào)"));
    }

/**
     * 在作者標(biāo)簽之前,添加團(tuán)購(gòu)價(jià)標(biāo)簽
     * @throws Exception 
     */
    public static void run1() throws Exception{
        //獲取工廠類
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //解析器
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析
        Document document = builder.parse("src/book2.xml");
        //獲取作者,再獲取第二本書
        Node author = document.getElementsByTagName("作者").item(1);
        Node book2 = author.getParentNode();
        //創(chuàng)建元素
        Element tuan = document.createElement("團(tuán)購(gòu)價(jià)");
        //設(shè)置文本
        tuan.setTextContent("很便宜");
        //加入到作者之前
        book2.insertBefore(tuan, author);
        //回寫
        TransformerFactory factory2 = TransformerFactory.newInstance();
        Transformer transformer = factory2.newTransformer();
        transformer.transform(new DOMSource(document), new StreamResult("src/book2.xml"));
    }

JAXP 的 DOM 封裝

public class JaxpDomUtil {
    /**
     * 通過path獲取document對(duì)象
     * @throws Exception 
     */
    public static Document getDocument(String path) throws Exception{
        //獲取工廠類
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //獲取解析器對(duì)象
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析XML
        Document document = builder.parse(path);
        return document;
    }
    
    public static void writeXML(Document document,String path) throws Exception{
        //獲得回寫類工廠
        TransformerFactory factory = TransformerFactory.newInstance();
        //獲得回寫類
        Transformer transformer = factory.newTransformer();
        //回寫
        transformer.transform(new DOMSource(document), new StreamResult(path));
    }
    
    public static void delete() throws Exception{
        //獲取文檔對(duì)象
        Document document = getDocument("src/book2.xml");
        //獲取貓
        Node cat = document.getElementsByTagName("毛").item(0);
        //獲取書(貓的父節(jié)點(diǎn))
        Node book = cat.getParentNode();
        //通過書刪除貓
        book.removeChild(cat);
        //回寫
        writeXML(document,"src/boo2.xml");
    }
    
    public static void main(String[] args) throws Exception {
        delete();
    }
    
}

JAXP的SAX解析 只能查詢

 由于SAX是基于時(shí)間驅(qū)動(dòng)的,所以要有 解析器 和 事件處理器

解析器

  1. 獲得解析器的工廠
  2. 獲取解析器對(duì)象
  3. 解析XML (XML文件地址,事件處理器)
 解析器采用SAX方式在解析某個(gè)XML文檔時(shí),它只要解析到XML文檔的一個(gè)組成部分,都會(huì)去調(diào)用事件處理器的一個(gè)方法,解析器在調(diào)用事件處理器的方法時(shí),會(huì)把當(dāng)前解析到的xml文件內(nèi)容作為方法的參數(shù)傳遞給事件處理器。
 事件處理器由程序員編寫,程序員通過事件處理器中方法的參數(shù),就可以很輕松地得到sax解析器解析到的數(shù)據(jù),從而可以決定如何對(duì)數(shù)據(jù)進(jìn)行處理。

事件處理器

  • 自己編寫類,繼承DefaultHandler,重寫三個(gè)方法
    • startDocument()
    • startElement() 重寫
    • characters() 重寫
    • endElement() 重寫
    • endDocument()
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

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



/**
 * SAX的入門
 * @author limaoquan
 *
 */
public class JaxpSaxTest {
    public static void main(String[] args) {
        
    }
    
    /**
     * 獲取所有解析的內(nèi)容
     * @throws Exception 
     * @throws ParserConfigurationException 
     */
    public static void run1() throws ParserConfigurationException, Exception{
        //獲取Sax的解析器工廠
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //獲取解析器
        SAXParser parser = factory.newSAXParser();
        //解析
        parser.parse("src/book2.xml", new MyHandler());
    }
    
}

/**
 * 獲取標(biāo)簽作者的文本內(nèi)容
 * @author limaoquan
 *
 */
class MyHandler2 extends DefaultHandler{

    private boolean flag = false;
    
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        if("作者".equals(qName)){
            flag = true;
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        
        String str = new String(ch, start, length);
        if(flag){
            System.out.println(str);
            }
    }
    
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        flag = false;
    }
    
}



class MyHandler extends DefaultHandler{

    /**
     * 只要一解析到開始標(biāo)簽的時(shí)候,默認(rèn)調(diào)用該方法
     */
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        System.out.println("開始標(biāo)簽:"+ qName);
    }

    /**
     * 只要解析到文本內(nèi)容,默認(rèn)調(diào)用該方法
     */
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        System.out.println("結(jié)束標(biāo)簽:"+qName);
    }

    /**
     * 解析到結(jié)束標(biāo)簽的時(shí)候,默認(rèn)調(diào)用該方法
     */
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        String str = new String(ch, start, length);
        System.out.println(str);
    }
    
}

Dom4j

 Dom4j是一個(gè)簡(jiǎn)單、靈活的開放源代碼的庫(kù)
 使用Dom4j需要下載dom4j相應(yīng)的jar包
  • 查找標(biāo)簽文本
    • 創(chuàng)建解析器 new SAXReader()
    • 解析xml read()
    • 獲取根節(jié)點(diǎn) root = getRootElement()
    • 獲取所有指定標(biāo)簽的集合 root.elements(標(biāo)簽名)
    • 返回List集合,可以遍歷,或者getIndex() 獲取Element對(duì)象
    • 獲取文本內(nèi)容 getText()
  • 添加子節(jié)點(diǎn)
    • 創(chuàng)建解析器 new SAXReader()
    • 解析xml read()
    • 獲取根節(jié)點(diǎn) root = getRootElement()
    • 獲取所有指定標(biāo)簽的集合 root.elements(標(biāo)簽名)
    • 直接調(diào)用addElement()設(shè)置子節(jié)點(diǎn)
    • 使用setTest()設(shè)置文本
    • 回寫xml文件
  • 在指定位置添加子節(jié)點(diǎn)
    • 創(chuàng)建元素標(biāo)簽節(jié)點(diǎn) DocumentHelper.createElement()
    • 設(shè)置文本 setText()
    • 獲取所有指定標(biāo)簽的集合 root.elements(標(biāo)簽名), 返回list
    • 通過list.add(index, element), 在內(nèi)存中加入子元素
    • 回寫xml文件
  • 修改節(jié)點(diǎn)文本
    • 找到指定的節(jié)點(diǎn)
    • 修改文本內(nèi)容 setText()
  • 刪除節(jié)點(diǎn)
    • 找到要?jiǎng)h除的節(jié)點(diǎn)
    • 通過父節(jié)點(diǎn)調(diào)用remove()方法刪除
/**
     * 獲取作者的文本內(nèi)容
     * @throws Exception 
     */
    public static void run1() throws Exception{
        //獲取解析器對(duì)象
        SAXReader reader = new SAXReader();
        //解析XML,返回Document對(duì)象
        Document document = reader.read("src/book2.xml");
        //獲取根節(jié)點(diǎn)(書架標(biāo)簽)
        Element root = document.getRootElement();
        //獲取書的節(jié)點(diǎn),獲取第二本書
        List<Element> books = root.elements("書");
        Element book2 = books.get(1);
        //獲取作者的標(biāo)簽
        Element author = book2.element("作者");
        //獲取文本內(nèi)容
        String str = author.getText();
    }
    
    /**
     * 在第二本書下添加子節(jié)點(diǎn)
     * @throws Exception 
     */
    public static void run2() throws Exception{
        //獲取解析器對(duì)象
        SAXReader reader = new SAXReader();
        //解析XML 反回Document對(duì)象
        Document document = reader.read("src/book2.xml");
        //獲取根節(jié)點(diǎn)
        Element root = document.getRootElement();
        //獲取第二本書
        Element book2 = (Element)root.elements("書").get(1);
        // 可以直接在第二本書下添加節(jié)點(diǎn),設(shè)置文本內(nèi)容
        book2.addElement("貓").setText("你是貓");
        
        //創(chuàng)建漂亮的格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        
        
        //回寫
        XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"),format);
        writer.write(document);
        writer.close();
    }
    
    /**
     * 在第二本書的作者標(biāo)簽之前添加團(tuán)購(gòu)價(jià)的標(biāo)簽
     * @throws Exception 
     */
    public static void run3() throws Exception{
        //獲取解析器對(duì)象
        SAXReader reader = new SAXReader();
        //解析XML 反回Document對(duì)象
        Document document = reader.read("src/book2.xml");
        //獲取根節(jié)點(diǎn)
        Element root = document.getRootElement();
        //獲取第二本書
        Element book2 = (Element)root.elements("書").get(1);
        //獲取書下的所有子節(jié)點(diǎn),返回list集合
        List<Element> list = book2.elements();
        //創(chuàng)建元素對(duì)象 DocumentHelper類
        Element dog = DocumentHelper.createElement("狗");
        dog.setText("dagoudagou");
        //list.add(index,Element);
        list.add(1,dog);
        //回寫
        XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"));
        writer.write(document);
        writer.close();
    }
    
    /**
     * 刪除子節(jié)點(diǎn)
     * 刪除第二本書下的錨節(jié)點(diǎn)
     */
    public static void run4() throws Exception{
        //獲取解析器對(duì)象
        SAXReader reader = new SAXReader();
        //解析XML 反回Document對(duì)象
        Document document = reader.read("src/book2.xml");
        //獲取根節(jié)點(diǎn)
        Element root = document.getRootElement();
        //獲取貓
        Element book2 = (Element)root.elements("書").get(1);
        Element cat = book2.element("貓");
        //通過貓的父節(jié)點(diǎn)刪除貓
        book2.remove(cat);
        //回寫
        XMLWriter writer = new XMLWriter(new FileOutputStream("src/book2.xml"));
        writer.write(document);
        writer.close();
    }

Dom4j獲得Document對(duì)象的三種方式:

  • 讀取xml文檔
    SAXReader reader = new SAXReader();
    Document document = reader.read(new File("input.xml"));

  • 解析XML形式的文本
    String text = "<members></members>";
    Document document = DocumentHelper.parseText(text);

  • 主動(dòng)創(chuàng)建document對(duì)象
    Document document = DocumentHelper.createDocument();
    //創(chuàng)建根節(jié)點(diǎn)
    Element root = document.addElement("members");

節(jié)點(diǎn)對(duì)象

  • 獲取文檔的根節(jié)點(diǎn)
    Element root = document.getRootElement();

  • 取得某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)
    Element element = node.element("標(biāo)簽名")

  • 獲取節(jié)點(diǎn)的文字
    String text = node.getText();

  • 設(shè)置節(jié)點(diǎn)文字
    element.setText();

  • 取得某個(gè)節(jié)點(diǎn)下所有名為member的子節(jié)點(diǎn),并遍歷
    List nodes = rootElm.elements("member");
    for(iterator it = nodes.iterator();it.hasNext(); ){
    Element elem = (Element)it.next();
    //do something ...
    }

  • 對(duì)某節(jié)點(diǎn)下的所有子節(jié)點(diǎn)進(jìn)行遍歷
    for(iterator it = root.elementiterator();it.hasNext(); ){
    Element elem = (Element)it.next();
    //do something ...
    }

  • 在某個(gè)節(jié)點(diǎn)下添加子節(jié)點(diǎn)
    Element ageElm = newMemberElm.addElement("age");

  • 刪除某節(jié)點(diǎn)
    parentElm.remove(childElm);

  • 添加一個(gè)CDATA節(jié)點(diǎn)
    Element contenElm = infoElm.addElement("content");
    contentElm.addCDATA(diary.getContent());

節(jié)點(diǎn)對(duì)象的屬性

  • 取得某節(jié)點(diǎn)下的某屬性
    Element root = document.getRootElement();
    //屬性名name
    Attribute attribute = root.attribute("size");

  • 取得屬性的文字
    String text = attribute.getText();

  • 刪除某屬性
    Attribute attribute = root.attribute("size");
    root.remove(attribute);

  • 遍歷某節(jié)點(diǎn)的所有屬性
    Element root = document.getRootElement();
    for(Iterator it = root.attributeIterator(); it.hasNext();){
    Attribute attribute = (Attribute)it.next();
    String text = attribute.getText();
    System.out.println(text);
    }

  • 設(shè)置某節(jié)點(diǎn)的屬性和文字
    newMemberElm.addAttribute("name","sitinspring");

  • 設(shè)置屬性的文字
    attribute.setText("sitinspring");

將文檔寫入XML文件

  • 文檔中全為英文,不設(shè)置編碼,直接寫入
    XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
    writer.write(document); //此document為之前建立的Document對(duì)象
    writer.close();

  • 文檔中有中文,設(shè)置編碼格式
    OutputFormat format = OutputFormat.createPrettyPrint();
    //指定XML編碼
    format.setEncoding("GBK");
    XMLWriter writer = new XMLWriter(new FileWriter("output.xml"),format);
    writer.write(document); //此document為之前建立的Document對(duì)象
    writer.close();

Dom4j在指定位置插入節(jié)點(diǎn)

Step:

  1. 得到插入位置的節(jié)點(diǎn)列表(list)
  2. 調(diào)用list.add(index,element), 由index決定element的插入位置
  3. Element元素可以通過DocumentHelpler對(duì)象得到
Element aaa = DocumentHelper.createElement("aaa");
aaa.setText("aaa");

List list = root.element("書").elements();
list.add(1,aaa);

//更新document

字符串與XML的轉(zhuǎn)換

  • 字符串轉(zhuǎn)化為XML
    String text = "<members><member>setinsping</member></members>";
    Document document = DocumentHelper.parseText(text);

  • 將文檔或節(jié)點(diǎn)的XML轉(zhuǎn)化為字符串

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

String docXmlText = document.asXML();

String rootXmlText = root.asXML();
Element memberElm = root.element("member");
String memberXmlText  = memberElm.asXML();

Dom4j對(duì)XPATH的支持

  導(dǎo)入包 jaxen-1.1-beta-6.jar

只能使用Node中的兩個(gè)方法:

  • selectNodes()
  • selectNode()

Xpath的語(yǔ)法

- /AAA/BBB/CCC    獲取的CCC的節(jié)點(diǎn)
- //BBB    無(wú)論層級(jí)關(guān)系,所有的BBB都找到
- //DDD/BBB    所有DDD下的BBB元素
- /AAA/CCC/*    CCC下的所有元素
- /*/*/*/BBB      所有有3個(gè)祖元素的BBB元素
- //*     所有元素
- /AAA/BBB[1]     AAA下的第一個(gè)BBB
- /AAA/BBB[last()]    AAA下最后一個(gè)BBB
- //@id    id屬性
- //BBB[@name]    選擇有name屬性的BBB元素
- //BBB[@*]    選擇有任意屬性的BBB元素
- //BBB[note(@*)]    選擇沒有屬性的BBB元素
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容