最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中使用DOM和SAX解析XML文件的方法示例

 更新時(shí)間:2015年11月09日 08:58:41   作者:圣騎士Wind的博客  
這篇文章主要介紹了Java中使用DOM和SAX解析XML文件的方法示例,通過(guò)實(shí)例文章中最后也給出了一些對(duì)比結(jié)論,需要的朋友可以參考下

dom4j介紹
  dom4j的項(xiàng)目地址:http://sourceforge.net/projects/dom4j/?source=directory

  dom4j是一個(gè)簡(jiǎn)單的開(kāi)源庫(kù),用于處理XML、 XPath和XSLT,它基于Java平臺(tái),使用Java的集合框架,全面集成了DOM,SAX和JAXP。

 

dom4j的使用
  下載了dom4j項(xiàng)目之后,解壓縮,將其jar包(我的當(dāng)前版本叫做dom4j-1.6.1.jar)加入class path下面。

 ?。≒roperties->Java Build Path -> Add External JARs...)。

  之后就可以使用其提供的API進(jìn)行編程。

 

程序?qū)嵗?
  第一個(gè)程序,用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框架學(xué)習(xí) 使用dom4j框架創(chuàng)建xml文檔并輸出保存
 * 
 */
public class Dom4JTest1
{

  public static void main(String[] args) throws Exception
  {
    // 第一種方式:創(chuàng)建文檔,并創(chuàng)建根元素
    // 創(chuàng)建文檔:使用了一個(gè)Helper類(lèi)
    Document document = DocumentHelper.createDocument();

    // 創(chuàng)建根節(jié)點(diǎn)并添加進(jìn)文檔
    Element root = DocumentHelper.createElement("student");
    document.setRootElement(root);

    // 第二種方式:創(chuàng)建文檔并設(shè)置文檔的根元素節(jié)點(diǎn)
    Element root2 = DocumentHelper.createElement("student");
    Document document2 = DocumentHelper.createDocument(root2);

    // 添加屬性
    root2.addAttribute("name", "zhangsan");
    // 添加子節(jié)點(diǎn):add之后就返回這個(gè)元素
    Element helloElement = root2.addElement("hello");
    Element worldElement = root2.addElement("world");

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

    // 輸出
    // 輸出到控制臺(tái)
    XMLWriter xmlWriter = new XMLWriter();
    xmlWriter.write(document);

    // 輸出到文件
    // 格式
    OutputFormat format = new OutputFormat("  ", true);// 設(shè)置縮進(jìn)為4個(gè)空格,并且另起一行為true
    XMLWriter xmlWriter2 = new XMLWriter(
        new FileOutputStream("student.xml"), format);
    xmlWriter2.write(document2);

    // 另一種輸出方式,記得要調(diào)用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/>

  生成的一個(gè)xml文檔:

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

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

 

程序?qū)嵗?
  程序?qū)嵗?,讀入xml文檔并分析,將其內(nèi)容輸出。

  首先,待分析的文檔如下:

<?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框架學(xué)習(xí): 讀取并解析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());

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

    // 獲取名字為指定名稱(chēng)的第一個(gè)子元素
    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();
    // 注意要用完整類(lèi)名
    org.w3c.dom.Document document2 = db.parse(new File("students.xml "));

    DOMReader domReader = new DOMReader();

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

    Element rootElement = document3.getRootElement();

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

  }

}


  代碼運(yùn)行后輸出:

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實(shí)現(xiàn)實(shí)體解析的步驟
//下面使用XMLReader 來(lái)解析
(一)第一步:新建一個(gè)工廠類(lèi)SAXParserFactory,代碼如下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:讓工廠類(lèi)產(chǎn)生一個(gè)SAX的解析類(lèi)SAXParser,代碼如下:
SAXParser parser = factory.newSAXParser();
(三)第三步:從SAXPsrser中得到一個(gè)XMLReader實(shí)例,代碼如下:
XMLReader reader = parser.getXMLReader();
(四)第四步:把自己寫(xiě)的handler注冊(cè)到XMLReader中,一般最重要的就是ContentHandler,代碼如下:
reader.setContentHandler(this);
(五)第五步:將一個(gè)xml文檔或者資源變成一個(gè)java可以處理的InputStream流后,解析正式開(kāi)始,代碼如下:
reader.parse(new InputSource(is));
 
 
//下面使用SAXParser來(lái)解析
(一)第一步:新建一個(gè)工廠類(lèi)SAXParserFactory,代碼如下:
SAXParserFactory factory = SAXParserFactory.newInstance();
(二)第二步:讓工廠類(lèi)產(chǎn)生一個(gè)SAX的解析類(lèi)SAXParser,代碼如下:
SAXParser parser = factory.newSAXParser();
(三)第三步:將一個(gè)xml文檔或者資源變成一個(gè)java可以處理的InputStream流后,解析正式開(kāi)始,代碼如下:
parser.parse(is,this);
估計(jì)大家都看到了ContentHandler ,下面具體的講下
解析開(kāi)始之前,需要向XMLReader/SAXParser 注冊(cè)一個(gè)ContentHandler,也就是相當(dāng)于一個(gè)事件監(jiān)聽(tīng)器,在ContentHandler中定義了很多方法
//設(shè)置一個(gè)可以定位文檔內(nèi)容事件發(fā)生位置的定位器對(duì)象
public void setDocumentLocator(Locator locator)
 
//用于處理文檔解析開(kāi)始事件
public void startDocument()throws SAXException
 
//處理元素開(kāi)始事件,從參數(shù)中可以獲得元素所在名稱(chēng)空間的uri,元素名稱(chēng),屬性類(lèi)表等信息
public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException
 
//處理元素結(jié)束事件,從參數(shù)中可以獲得元素所在名稱(chēng)空間的uri,元素名稱(chēng)等信息
public void endElement(String namespacesURI , String localName , String qName) throws SAXException
 
//處理元素的字符內(nèi)容,從參數(shù)中可以獲得內(nèi)容
public void characters(char[] ch , int start , int length)  throws SAXException
順便介紹下XMLReader中的方法。
//注冊(cè)處理XML文檔解析事件ContentHandler
public void setContentHandler(ContentHandler handler)
 
//開(kāi)始解析一個(gè)XML文檔
public void parse(InputSorce input) throws SAXException

大概的講的差不多了  接下來(lái)開(kāi)始講解解析的步驟
我們還是用上一章的代碼
首先 我們創(chuàng)建一個(gè)Person類(lèi)  用來(lái)存儲(chǔ)用戶(hù)的信息

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; 
  } 
} 

接下來(lái)  我們要實(shí)現(xiàn)一個(gè)ContentHandler 用來(lái)解析XML
實(shí)現(xiàn)一個(gè)ContentHandler 一般需要下面幾個(gè)步驟
1、聲明一個(gè)類(lèi),繼承DefaultHandler。DefaultHandler是一個(gè)基類(lèi),這個(gè)類(lèi)里面簡(jiǎn)單實(shí)現(xiàn)了一個(gè)ContentHandler。我們只需要重寫(xiě)里面的方法即可。
2、重寫(xiě) startDocument() 和 endDocument(),一般將正式解析之前的初始化放到startDocument()里面,收尾的工作放到endDocument()里面。
3、重寫(xiě)startElement(),XML解析器遇到XML里面的tag時(shí)就會(huì)調(diào)用這個(gè)函數(shù)。經(jīng)常在這個(gè)函數(shù)內(nèi)是通過(guò)對(duì)localName的值進(jìn)行判斷而操作一些數(shù)據(jù)。
4、重寫(xiě)characters()方法,這是一個(gè)回調(diào)方法。解析器執(zhí)行完startElement()后,解析節(jié)點(diǎn)的內(nèi)容后就會(huì)執(zhí)行這個(gè)方法,并且參數(shù)ch[]就是節(jié)點(diǎn)的內(nèi)容。
5、重寫(xiě)endElement()方法,這個(gè)方法與startElement()相對(duì)應(yīng),解析完一個(gè)tag節(jié)點(diǎn)后,執(zhí)行這個(gè)方法,解析一個(gè)tag后,調(diào)用這個(gè)處理還原和清除相關(guān)信息
首先   新建一個(gè)類(lèi) 繼承DefaultHandler 并重寫(xiě)以下幾個(gè)方法

public class SAX_parserXML extends DefaultHandler { 
 
  /** 
   * 當(dāng)開(kāi)始解析xml文件的聲明的時(shí)候就會(huì)觸發(fā)這個(gè)事件, 可以做一些初始化的工作 
   * */ 
  @Override 
  public void startDocument() throws SAXException { 
    // TODO Auto-generated method stub 
    super.startDocument(); 
     
  } 
 
  /** 
   * 當(dāng)開(kāi)始解析元素的開(kāi)始標(biāo)簽的時(shí)候,就會(huì)觸發(fā)這個(gè)事件 
   * */ 
  @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); 
  } 
 
  /** 
   * 當(dāng)讀到文本元素的時(shí)候要觸發(fā)這個(gè)事件. 
   * */ 
  @Override 
  public void characters(char[] ch, int start, int length) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.characters(ch, start, length); 
  } 
 
  /** 
   * 當(dāng)讀到結(jié)束標(biāo)簽的時(shí)候 就會(huì)觸發(fā)這個(gè)事件 
   * */ 
  @Override 
  public void endElement(String uri, String localName, String qName) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.endElement(uri, localName, qName); 
  } 
 
} 

首先  我們創(chuàng)建一個(gè)list  用來(lái)保存解析出來(lái)的person數(shù)據(jù)

List<Person> persons; 

但是?在哪里初始化呢?我們可以在startDocument()里面初始化,因?yàn)楫?dāng)開(kāi)始解析xml文件的聲明的時(shí)候就會(huì)觸發(fā)這個(gè)事件所以放在這里比較合適

/** 
 * 當(dāng)開(kāi)始解析xml文件的聲明的時(shí)候就會(huì)觸發(fā)這個(gè)事件, 可以做一些初始化的工作 
 * */ 
@Override 
public void startDocument() throws SAXException { 
  // TODO Auto-generated method stub 
  super.startDocument(); 
  // 初始化list 
  persons = new ArrayList<Person>(); 
} 

接下來(lái)  就要開(kāi)始解析了  

/** 
   * 當(dāng)開(kāi)始解析元素的開(kāi)始標(biāo)簽的時(shí)候,就會(huì)觸發(fā)這個(gè)事件 
   * */ 
  @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標(biāo)簽 開(kāi)始存儲(chǔ) 
    if (localName.equals("person")) { 
      person = new Person(); 
      person.set_id(attributes.getValue("id")); 
    } 
    curNode = localName; 
  } 

 上面的代碼中  localName表示當(dāng)前解析到的元素名

//步驟 
//1.判斷是否是person元素 
//2.創(chuàng)建新的Person對(duì)象 
//3.獲取id 添加到Person對(duì)象中 
curNode 用來(lái)保存當(dāng)前的元素名 在characters中會(huì)使用到
/** 
   * 當(dāng)讀到文本元素的時(shí)候要觸發(fā)這個(gè)事件. 
   * */ 
  @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) { 
      //取出目前元素對(duì)應(yīng)的值 
      String txt = new String(ch, start, length); 
      //判斷元素是否是name 
      if (curNode.equals("name")) { 
        //將取出的值添加到person對(duì)象 
        person.set_name(txt); 
      } else if (curNode.equals("age")) { 
        person.set_age(txt); 
      } 
    } 
  } 

接下來(lái)是介紹標(biāo)簽結(jié)束的時(shí)候需要做的事情

/** 
 * 當(dāng)讀到結(jié)束標(biāo)簽的時(shí)候 就會(huì)觸發(fā)這個(gè)事件 
 * */ 
@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 = ""; 
} 

解析的事情結(jié)束了  大概流程就是
1.一個(gè)元素開(kāi)始時(shí)    會(huì)調(diào)用startElement方法
2.接下來(lái)會(huì)調(diào)用到characters方法,可以用來(lái)獲取元素的值
3.一個(gè)元素結(jié)束時(shí)    會(huì)調(diào)用到endElement方法
解析結(jié)束之后  我們需要寫(xiě)一個(gè)方法  用來(lái)獲取解析后保存的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對(duì)象傳入  就可以解析出內(nèi)容
看完了代碼,我來(lái)給出完整的代碼

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; 
  // 當(dāng)前節(jié)點(diǎn) 
  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; 
  } 
 
  /** 
   * 當(dāng)開(kāi)始解析xml文件的聲明的時(shí)候就會(huì)觸發(fā)這個(gè)事件, 可以做一些初始化的工作 
   * */ 
  @Override 
  public void startDocument() throws SAXException { 
    // TODO Auto-generated method stub 
    super.startDocument(); 
    // 初始化list 
    persons = new ArrayList<Person>(); 
  } 
 
  /** 
   * 當(dāng)開(kāi)始解析元素的開(kāi)始標(biāo)簽的時(shí)候,就會(huì)觸發(fā)這個(gè)事件 
   * */ 
  @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標(biāo)簽 開(kāi)始存儲(chǔ) 
    if (localName.equals("person")) { 
      person = new Person(); 
      person.set_id(attributes.getValue("id")); 
    } 
    curNode = localName; 
  } 
 
  /** 
   * 當(dāng)讀到文本元素的時(shí)候要觸發(fā)這個(gè)事件. 
   * */ 
  @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) { 
      // 取出目前元素對(duì)應(yīng)的值 
      String txt = new String(ch, start, length); 
      // 判斷元素是否是name 
      if (curNode.equals("name")) { 
        // 將取出的值添加到person對(duì)象 
        person.set_name(txt); 
      } else if (curNode.equals("age")) { 
        person.set_age(txt); 
      } 
    } 
  } 
 
  /** 
   * 當(dāng)讀到結(jié)束標(biāo)簽的時(shí)候 就會(huì)觸發(fā)這個(gè)事件 
   * */ 
  @Override 
  public void endElement(String uri, String localName, String qName) 
      throws SAXException { 
    // TODO Auto-generated method stub 
    super.endElement(uri, localName, qName); 
 
    // 如果是person結(jié)尾 并且person不為空,添加到list 
    if (localName.equals("person") && person != null) { 
      persons.add(person); 
      person = null; 
    } 
 
    curNode = ""; 
  } 
 
} 

 寫(xiě)個(gè)方法調(diào)用下這個(gè)類(lèi)

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(); 

 如果你看到下面的界面  說(shuō)明解析成功了~

201511985306423.png (332×102)

小結(jié):

DOM(文件對(duì)象模型)解析:解析器讀入整個(gè)文檔,然后構(gòu)建一個(gè)駐留內(nèi)存的樹(shù)結(jié)構(gòu),然后代碼就可以根據(jù)DOM接口來(lái)操作這個(gè)樹(shù)結(jié)構(gòu)了。 
 
  優(yōu)點(diǎn):整個(gè)文檔讀入內(nèi)存,方便操作:支持修改、刪除和重現(xiàn)排列等多種功能。 
 
  缺點(diǎn):將整個(gè)文檔讀入內(nèi)存中,保留了過(guò)多的不需要的節(jié)點(diǎn),浪費(fèi)內(nèi)存和空間。 
 
  使用場(chǎng)合:一旦讀入文檔,還需要多次對(duì)文檔進(jìn)行操作,并且在硬件資源充足的情況下(內(nèi)存,CPU)。 
 
為了解決DOM解析存在的問(wèn)題,就出現(xiàn)了SAX解析。其特點(diǎn)為: 
 
  優(yōu)點(diǎn):不用實(shí)現(xiàn)調(diào)入整個(gè)文檔,占用資源少。尤其在嵌入式環(huán)境中,如android,極力推薦使用SAX解析。 
 
  缺點(diǎn):不像DOM解析一樣將文檔長(zhǎng)期駐留在內(nèi)存中,數(shù)據(jù)不是持久的。如果事件過(guò)后沒(méi)有保存數(shù)據(jù),數(shù)據(jù)就會(huì)丟失。 
 
  使用場(chǎng)合:機(jī)器有性能限制

相關(guān)文章

最新評(píng)論

玉环县| 沅陵县| 桦甸市| 拉萨市| 舟曲县| 宜春市| 玉树县| 巨鹿县| 赤峰市| 浦城县| 正阳县| 河池市| 灌阳县| 那坡县| 北碚区| 色达县| 九寨沟县| 荃湾区| 礼泉县| 德钦县| 博罗县| 兴山县| 京山县| 五台县| 金平| 桑日县| 巢湖市| 通榆县| 旬阳县| 蒙山县| 香河县| 错那县| 四子王旗| 新平| 武隆县| 延寿县| 拜城县| 南阳市| 普兰店市| 澎湖县| 信阳市|