程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中應用DOM和SAX解析XML文件的辦法示例

Java中應用DOM和SAX解析XML文件的辦法示例

編輯:關於JAVA

Java中應用DOM和SAX解析XML文件的辦法示例。本站提示廣大學習愛好者:(Java中應用DOM和SAX解析XML文件的辦法示例)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中應用DOM和SAX解析XML文件的辦法示例正文


dom4j引見
  dom4j的項目地址:http://sourceforge.net/projects/dom4j/?source=directory

  dom4j是一個簡略的開源庫,用於處置XML、 XPath和XSLT,它基於Java平台,應用Java的聚集框架,周全集成了DOM,SAX和JAXP。

 

dom4j的應用
  下載了dom4j項目以後,解緊縮,將其jar包(我確當前版本叫做dom4j-1.6.1.jar)參加class path上面。

  (Properties->Java Build Path -> Add External JARs...)。

  以後便可以應用其供給的API停止編程。

 

法式實例1
  第一個法式,用Java代碼生成xml文檔,代碼以下:

package com.example.xml.dom4j;

import java.io.FileOutputStream;
import java.io.FileWriter;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

/**
 * dom4j框架進修 應用dom4j框架創立xml文檔並輸入保留
 * 
 */
public class Dom4JTest1
{

  public static void main(String[] args) throws Exception
  {
    // 第一種方法:創立文檔,並創立根元素
    // 創立文檔:應用了一個Helper類
    Document document = DocumentHelper.createDocument();

    // 創立根節點並添加進文檔
    Element root = DocumentHelper.createElement("student");
    document.setRootElement(root);

    // 第二種方法:創立文檔並設置文檔的根元素節點
    Element root2 = DocumentHelper.createElement("student");
    Document document2 = DocumentHelper.createDocument(root2);

    // 添加屬性
    root2.addAttribute("name", "zhangsan");
    // 添加子節點:add以後就前往這個元素
    Element helloElement = root2.addElement("hello");
    Element worldElement = root2.addElement("world");

    helloElement.setText("hello Text");
    worldElement.setText("world text");

    // 輸入
    // 輸入到掌握台
    XMLWriter xmlWriter = new XMLWriter();
    xmlWriter.write(document);

    // 輸入到文件
    // 格局
    OutputFormat format = new OutputFormat("  ", true);// 設置縮進為4個空格,而且另起一行動true
    XMLWriter xmlWriter2 = new XMLWriter(
        new FileOutputStream("student.xml"), format);
    xmlWriter2.write(document2);

    // 另外一種輸入方法,記得要挪用flush()辦法,不然輸入的文件中顯示空白
    XMLWriter xmlWriter3 = new XMLWriter(new FileWriter("student2.xml"),
        format);
    xmlWriter3.write(document2);
    xmlWriter3.flush();
    // close()辦法也能夠

  }
}

 

  法式Console輸入:

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

  生成的一個xml文檔:

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

<student name="zhangsan">
  <hello>hello Text</hello>
  <world>world text</world>
</student>

 

法式實例2
  法式實例2,讀入xml文檔並剖析,將其內容輸入。

  起首,待剖析的文檔以下:

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

<students name="zhangsan">
  <hello name="lisi">hello Text1</hello>
  <hello name="lisi2">hello Text2</hello>
  <hello name="lisi3">hello Text3</hello>
  <world name="wangwu">world text1</world>
  <world name="wangwu2">world text2</world>
  <world >world text3</world>
</students>
 

package com.example.xml.dom4j;

import java.io.File;
import java.util.Iterator;
import java.util.List;

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

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;

/**
 * dom4j框架進修: 讀取並解析xml
 * 
 * 
 */
public class Dom4JTest2
{
  public static void main(String[] args) throws Exception
  {
    SAXReader saxReader = new SAXReader();

    Document document = saxReader.read(new File("students.xml"));

    // 獲得根元素
    Element root = document.getRootElement();
    System.out.println("Root: " + root.getName());

    // 獲得一切子元素
    List<Element> childList = root.elements();
    System.out.println("total child count: " + childList.size());

    // 獲得特命名稱的子元素
    List<Element> childList2 = root.elements("hello");
    System.out.println("hello child: " + childList2.size());

    // 獲得名字為指命名稱的第一個子元素
    Element firstWorldElement = root.element("world");
    // 輸入其屬性
    System.out.println("first World Attr: "
        + firstWorldElement.attribute(0).getName() + "="
        + firstWorldElement.attributeValue("name"));

    System.out.println("迭代輸入-----------------------");
    // 迭代輸入
    for (Iterator iter = root.elementIterator(); iter.hasNext();)
    {
      Element e = (Element) iter.next();
      System.out.println(e.attributeValue("name"));

    }

    System.out.println("用DOMReader-----------------------");
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    // 留意要用完全類名
    org.w3c.dom.Document document2 = db.parse(new File("students.xml "));

    DOMReader domReader = new DOMReader();

    // 將JAXP的Document轉換為dom4j的Document
    Document document3 = domReader.read(document2);

    Element rootElement = document3.getRootElement();

    System.out.println("Root: " + rootElement.getName());

  }

}


  代碼運轉後輸入:

Root: students
total child count: 6
hello child: 3
first World Attr: name=wangwu
迭代輸入-----------------------
lisi
lisi2
lisi3
wangwu
wangwu2
null
用DOMReader-----------------------
Root: students


SAX解析XML
上面是SAX完成實體解析的步調
//上面應用XMLReader 來解析
(一)第一步:新建一個工場類SAXParserFactory,代碼以下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:讓工場類發生一個SAX的解析類SAXParser,代碼以下:
SAXParser parser = factory.newSAXParser();
(三)第三步:從SAXPsrser中獲得一個XMLReader實例,代碼以下:
XMLReader reader = parser.getXMLReader();
(四)第四步:把本身寫的handler注冊到XMLReader中,普通最主要的就是ContentHandler,代碼以下:
reader.setContentHandler(this);
(五)第五步:將一個xml文檔或許資本釀成一個java可以處置的InputStream流後,解析正式開端,代碼以下:
reader.parse(new InputSource(is));
 
 
//上面應用SAXParser來解析
(一)第一步:新建一個工場類SAXParserFactory,代碼以下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:讓工場類發生一個SAX的解析類SAXParser,代碼以下:
SAXParser parser = factory.newSAXParser();
(三)第三步:將一個xml文檔或許資本釀成一個java可以處置的InputStream流後,解析正式開端,代碼以下:
parser.parse(is,this);
估量年夜家都看到了ContentHandler ,上面詳細的講下
解析開端之前,須要向XMLReader/SAXParser 注冊一個ContentHandler,也就是相當於一個事宜監聽器,在ContentHandler中界說了許多辦法
//設置一個可以定位文檔內容事宜產生地位的定位器對象
public void setDocumentLocator(Locator locator)
 
//用於處置文檔解析開端事宜
public void startDocument()throws SAXException
 
//處置元素開端事宜,從參數中可以取得元素地點稱號空間的uri,元素稱號,屬性類表等信息
public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException
 
//處置元素停止事宜,從參數中可以取得元素地點稱號空間的uri,元素稱號等信息
public void endElement(String namespacesURI , String localName , String qName) throws SAXException
 
//處置元素的字符內容,從參數中可以取得內容
public void characters(char[] ch , int start , int length)  throws SAXException
趁便引見下XMLReader中的辦法。
//注冊處置XML文檔解析事宜ContentHandler
public void setContentHandler(ContentHandler handler)
 
//開端解析一個XML文檔
public void parse(InputSorce input) throws SAXException

年夜概的講的差不多了  接上去開端講授解析的步調
我們照樣用上一章的代碼
起首 我們創立一個Person類  用來存儲用戶的信息

package com.example.demo; 
 
import java.io.Serializable; 
 
public class Person implements Serializable { 
 
  /** 
   * 
   */ 
  private static final long serialVersionUID = 1L; 
  private String _id; 
  private String _name; 
  private String _age; 
 
  public String get_id() { 
    return _id; 
  } 
 
  public void set_id(String _id) { 
    this._id = _id; 
  } 
 
  public String get_name() { 
    return _name; 
  } 
 
  public void set_name(String _name) { 
    this._name = _name; 
  } 
 
  public String get_age() { 
    return _age; 
  } 
 
  public void set_age(String _age) { 
    this._age = _age; 
  } 
} 

接上去  我們要完成一個ContentHandler 用來解析XML
完成一個ContentHandler 普通須要上面幾個步調
1、聲明一個類,繼續DefaultHandler。DefaultHandler是一個基類,這個類外面簡略完成了一個ContentHandler。我們只須要重寫外面的辦法便可。
2、重寫 startDocument() 和 endDocument(),普通將正式解析之前的初始化放到startDocument()外面,掃尾的任務放到endDocument()外面。
3、重寫startElement(),XML解析器碰到XML外面的tag時就會挪用這個函數。常常在這個函數內是經由過程對localName的值停止斷定而操作一些數據。
4、重寫characters()辦法,這是一個回調辦法。解析器履行完startElement()後,解析節點的內容後就會履行這個辦法,而且參數ch[]就是節點的內容。
5、重寫endElement()辦法,這個辦法與startElement()絕對應,解析完一個tag節點後,履行這個辦法,解析一個tag後,挪用這個處置復原和消除相干信息
起首   新建一個類 繼續DefaultHandler 偏重寫以下幾個辦法

public class SAX_parserXML extends DefaultHandler { 
 
  /** 
   * 當開端解析xml文件的聲明的時刻就會觸發這個事宜, 可以做一些初始化的任務 
   * */ 
  @Override 
  public void startDocument() throws SAXException { 
    // TODO Auto-generated method stub 
    super.startDocument(); 
     
  } 
 
  /** 
   * 當開端解析元素的開端標簽的時刻,就會觸發這個事宜 
   * */ 
  @Override 
  public void startElement(String uri, String localName, String qName, 
      Attributes attributes) throws SAXException { 
    // TODO Auto-generated method stub 
    super.startElement(uri, localName, qName, attributes); 
  } 
 
  /** 
   * 當讀到文本元素的時刻要觸發這個事宜. 
   * */ 
  @Override 
  public void characters(char[] ch, int start, int length) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.characters(ch, start, length); 
  } 
 
  /** 
   * 當讀到停止標簽的時刻 就會觸發這個事宜 
   * */ 
  @Override 
  public void endElement(String uri, String localName, String qName) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.endElement(uri, localName, qName); 
  } 
 
} 

起首  我們創立一個list  用來保留解析出來的person數據

List<Person> persons; 

然則?在哪裡初始化呢?我們可以在startDocument()外面初始化,由於當開端解析xml文件的聲明的時刻就會觸發這個事宜所以放在這裡比擬適合

/** 
 * 當開端解析xml文件的聲明的時刻就會觸發這個事宜, 可以做一些初始化的任務 
 * */ 
@Override 
public void startDocument() throws SAXException { 
  // TODO Auto-generated method stub 
  super.startDocument(); 
  // 初始化list 
  persons = new ArrayList<Person>(); 
} 

接上去  就要開端解析了  

/** 
   * 當開端解析元素的開端標簽的時刻,就會觸發這個事宜 
   * */ 
  @Override 
  public void startElement(String uri, String localName, String qName, 
      Attributes attributes) throws SAXException { 
    // TODO Auto-generated method stub 
    super.startElement(uri, localName, qName, attributes); 
 
    // 假如讀到是person標簽 開端存儲 
    if (localName.equals("person")) { 
      person = new Person(); 
      person.set_id(attributes.getValue("id")); 
    } 
    curNode = localName; 
  } 

 下面的代碼中  localName表現以後解析到的元素名

//步調 
//1.斷定能否是person元素 
//2.創立新的Person對象 
//3.獲得id 添加到Person對象中 
curNode 用來保留以後的元素名 在characters中會應用到
/** 
   * 當讀到文本元素的時刻要觸發這個事宜. 
   * */ 
  @Override 
  public void characters(char[] ch, int start, int length) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.characters(ch, start, length); 
 
    if (person != null) { 
      //掏出今朝元素對應的值 
      String txt = new String(ch, start, length); 
      //斷定元素能否是name 
      if (curNode.equals("name")) { 
        //將掏出的值添加到person對象 
        person.set_name(txt); 
      } else if (curNode.equals("age")) { 
        person.set_age(txt); 
      } 
    } 
  } 

接上去是引見標簽停止的時刻須要做的工作

/** 
 * 當讀到停止標簽的時刻 就會觸發這個事宜 
 * */ 
@Override 
public void endElement(String uri, String localName, String qName) 
    throws SAXException { 
  // TODO Auto-generated method stub 
  super.endElement(uri, localName, qName); 
 
  // 假如是 而且person不為空,添加到list 
  if (localName.equals("person") && person != null) { 
    persons.add(person); 
    person = null; 
  } 
 
  curNode = ""; 
} 

解析的工作停止了  年夜概流程就是
1.一個元素開端時    會挪用startElement辦法
2.接上去會挪用到characters辦法,可以用來獲得元素的值
3.一個元素停止時    會挪用到endElement辦法
解析停止以後  我們須要寫一個辦法  用來獲得解析後保留的list

public List<Person> ReadXML(InputStream is) { 
 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    try { 
      SAXParser parser = factory.newSAXParser(); 
 
      // 第一種辦法 
      // parser.parse(is, this); 
 
      // 第二種辦法 
      XMLReader reader = parser.getXMLReader(); 
      reader.setContentHandler(this); 
      reader.parse(new InputSource(is)); 
 
    } catch (Exception e) { 
      // TODO: handle exception 
      e.printStackTrace(); 
    } 
 
    return persons; 
  } 

下面的代碼就不說明了   只需將inputStream對象傳入  便可以解析出內容
看完了代碼,我來給出完全的代碼

package com.example.demo.Utils; 
 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 
 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
 
import org.xml.sax.Attributes; 
import org.xml.sax.InputSource; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 
import org.xml.sax.helpers.DefaultHandler; 
 
import com.example.demo.Person; 
 
public class SAX_parserXML extends DefaultHandler { 
 
  List<Person> persons; 
  Person person; 
  // 以後節點 
  String curNode; 
 
  public List<Person> ReadXML(InputStream is) { 
 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    try { 
      SAXParser parser = factory.newSAXParser(); 
 
      // 第一種辦法 
      // parser.parse(is, this); 
 
      // 第二種辦法 
      XMLReader reader = parser.getXMLReader(); 
      reader.setContentHandler(this); 
      reader.parse(new InputSource(is)); 
 
    } catch (Exception e) { 
      // TODO: handle exception 
      e.printStackTrace(); 
    } 
 
    return persons; 
  } 
 
  /** 
   * 當開端解析xml文件的聲明的時刻就會觸發這個事宜, 可以做一些初始化的任務 
   * */ 
  @Override 
  public void startDocument() throws SAXException { 
    // TODO Auto-generated method stub 
    super.startDocument(); 
    // 初始化list 
    persons = new ArrayList<Person>(); 
  } 
 
  /** 
   * 當開端解析元素的開端標簽的時刻,就會觸發這個事宜 
   * */ 
  @Override 
  public void startElement(String uri, String localName, String qName, 
      Attributes attributes) throws SAXException { 
    // TODO Auto-generated method stub 
    super.startElement(uri, localName, qName, attributes); 
 
    // 假如讀到是person標簽 開端存儲 
    if (localName.equals("person")) { 
      person = new Person(); 
      person.set_id(attributes.getValue("id")); 
    } 
    curNode = localName; 
  } 
 
  /** 
   * 當讀到文本元素的時刻要觸發這個事宜. 
   * */ 
  @Override 
  public void characters(char[] ch, int start, int length) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.characters(ch, start, length); 
 
    if (person != null) { 
      // 掏出今朝元素對應的值 
      String txt = new String(ch, start, length); 
      // 斷定元素能否是name 
      if (curNode.equals("name")) { 
        // 將掏出的值添加到person對象 
        person.set_name(txt); 
      } else if (curNode.equals("age")) { 
        person.set_age(txt); 
      } 
    } 
  } 
 
  /** 
   * 當讀到停止標簽的時刻 就會觸發這個事宜 
   * */ 
  @Override 
  public void endElement(String uri, String localName, String qName) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.endElement(uri, localName, qName); 
 
    // 假如是person開頭 而且person不為空,添加到list 
    if (localName.equals("person") && person != null) { 
      persons.add(person); 
      person = null; 
    } 
 
    curNode = ""; 
  } 
 
} 

 寫個辦法挪用下這個類

List<Person> persons = new SAX_parserXML().ReadXML(is); 
      StringBuffer buffer = new StringBuffer(); 
      for (int i = 0; i < persons.size(); i++) { 
        Person person =persons.get(i); 
        buffer.append("id:" + person.get_id() + "  "); 
        buffer.append("name:" + person.get_name() + "  "); 
        buffer.append("age:" + person.get_age() + "\n"); 
      } 
      Toast.makeText(activity, buffer, Toast.LENGTH_LONG).show(); 

 假如你看到上面的界面  解釋解析勝利了~

小結:

DOM(文件對象模子)解析:解析器讀入全部文檔,然後構建一個駐留內存的樹構造,然子女碼便可以依據DOM接口來操作這個樹構造了。 
 
  長處:全部文檔讀入內存,便利操作:支撐修正、刪除和重現分列等多種功效。 
 
  缺陷:將全部文檔讀入內存中,保存了過量的不須要的節點,糟蹋內存和空間。 
 
  應用場所:一旦讀入文檔,還須要屢次對文檔停止操作,而且在硬件資本充分的情形下(內存,CPU)。 
 
為懂得決DOM解析存在的成績,就湧現了SAX解析。其特色為: 
 
  長處:不消完成調入全部文檔,占用資本少。特別在嵌入式情況中,如android,死力推舉應用SAX解析。 
 
  缺陷:不像DOM解析一樣將文檔歷久駐留在內存中,數據不是耐久的。假如事宜事後沒有保留數據,數據就會喪失。 
 
  應用場所:機械有機能限制

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved