1. 程式人生 > >java中解析xml檔案的五種常見方法:DOM4J,dom,pull,SAX,Jdom

java中解析xml檔案的五種常見方法:DOM4J,dom,pull,SAX,Jdom

package com.zhidi.dom4jtest;


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


import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;


import com.imooc.entity.Book;


public class DOM4JTest {
private static ArrayList<Book> bookList = new ArrayList<Book>();
/**
* @param args
*/
public static void main(String[] args) {
// 解析books.xml檔案
// 建立SAXReader的物件reader
SAXReader reader = new SAXReader();
try {
// 通過reader物件的read方法載入books.xml檔案,獲取docuemnt物件。
Document document = reader.read(new File("src/res/books.xml"));
// 通過document物件獲取根節點bookstore
Element bookStore = document.getRootElement();
// 通過element物件的elementIterator方法獲取迭代器
Iterator it = bookStore.elementIterator();
// 遍歷迭代器,獲取根節點中的資訊(書籍)
while (it.hasNext()) {
System.out.println("=====開始遍歷某一本書=====");
Element book = (Element) it.next();
// 獲取book的屬性名以及 屬性值
List<Attribute> bookAttrs = book.attributes();
for (Attribute attr : bookAttrs) {
System.out.println("屬性名:" + attr.getName() + "--屬性值:"
+ attr.getValue());
}
Iterator itt = book.elementIterator();
while (itt.hasNext()) {
Element bookChild = (Element) itt.next();
System.out.println("節點名:" + bookChild.getName() + "--節點值:" + bookChild.getStringValue());
}
System.out.println("=====結束遍歷某一本書=====");
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}


}

以上DOM4J方法解析Xml檔案,其解析過程就是將其內容解析出來,供程式設計師閱讀,xml檔案的內容多是配置資訊。

DOM4J需要引入加油包,用多種方法讀取其中的內容。

package com.zhidi.test;


import java.io.IOException;


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


import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/*DOM解析,是Java自有的,從體驗上看,較為陌生,需要例項化多種類,程式碼量相對適中
 * 
 */
public class BookeDemo {


public static void main(String[] args) {
//建立一個DocumentBuilderFactory的物件
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
//建立一個DocumentBuilder的物件
try {
DocumentBuilder db=dbf.newDocumentBuilder();
Document document=db.parse("books.xml");

NodeList list=document.getElementsByTagName("book");
System.out.println(list.getLength());
for (int i = 0; i <list.getLength() ; i++) {
Node node=list.item(i);

NamedNodeMap nnm=node.getAttributes();
System.out.println("屬性的個數"+nnm.getLength());
for (int j = 0; j < nnm.getLength(); j++) {
Node nd =nnm.item(j);
System.out.println("屬性名:"+nd.getNodeName());
System.out.println("屬性值:"+nd.getNodeValue());
}
NodeList nl=node.getChildNodes();

for (int k= 0; k < nl.getLength(); k++) {
if(nl.item(k).getNodeType()==Node.ELEMENT_NODE){
//此處判斷不清楚原因
System.out.println(nl.item(k).getNodeName());
System.out.println(nl.item(k).getFirstChild().getNodeValue());
}

}
}

} catch (ParserConfigurationException | SAXException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//建立DocumentBuilder物件

//通過DocumentBuilder物件的parser方法載入books.xml檔案到當前專案下

//獲取所有book節點的集合

//通過nodelist的getLength()方法可以獲取bookList的長度


//遍歷每一個book節點

//通過 item(i)方法 獲取一個book節點,nodelist的索引值從0開始

//獲取book節點的所有屬性集合
//遍歷book的屬性

//通過item(index)方法獲取book節點的某一個屬性

//獲取屬性名

//獲取屬性值

}
////前提:已經知道book節點有且只能有1個id屬性
////將book節點進行強制型別轉換,轉換成Element型別
//
////通過getAttribute("id")方法獲取屬性值
//
//解析book節點的子節點

//遍歷childNodes獲取每個節點的節點名和節點值



//區分出text型別的node以及element型別的node

//獲取了element型別節點的節點名


//獲取了element型別節點的節點值

}
以上Dom方法解析方法,不需要加油包,需要需要java自帶的方法,

package com.pullxml;


import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;


import static org.xmlpull.v1.XmlPullParser.*;


import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;


/**
 * //1.建立解析器工廠類物件
 * @author Administrator
 *2.建立解析器物件;
 *3.位解析器指定待解析的資源
 *4.開始解析

*解析xml是基於事件的
* 1.文件開始:START_DOCUMENT
* 2.標記開始:START_TAG
* 3.標記結束:END_TAG
* 4.文件結束:END_DOCUMENT
*/
 /*此程式用pull方法解析XML檔案,優點是多用switch方法,陌生的方法較少,容易理解;能夠對特定的標記名和標記值進行操作。
  * 缺點是程式量較大,效率較低。
  * 此方法適合於對於XML文件進行修改,對特定標識進行查詢的情況下。
  * 也需要匯入加油包
  */
public class PullXmlDemo {


public static void main(String[] args) throws XmlPullParserException, IOException {

XmlPullParserFactory xpf= XmlPullParserFactory.newInstance();

XmlPullParser xpp=xpf.newPullParser();

xpp.setInput(new FileReader("books.xml"));

int event=xpp.getEventType();

while(event!=END_DOCUMENT){
switch(event){
case START_DOCUMENT:
System.out.println("檔案開始解析");
break;
case START_TAG:
String s1=xpp.getName();
System.out.println("標記開始"+s1);

switch(s1){
case "id":
String s2=xpp.nextText();
System.out.println("id="+s2);
break;
case "name":
String name=xpp.nextText();
System.out.println("書名:"+name);
break;
case "author":
String author=xpp.nextText();
System.out.println("作者"+author);
break;
case "year":
String year=xpp.nextText();
System.out.println("出版年份:"+year);
break;
case "price":
String price=xpp.nextText();
System.out.println("價格:"+price);
break;
case "language":
String language=xpp.nextText();
System.out.println("語言:"+language);
break;
case "book":
int count=xpp.getAttributeCount();
if(count>0){

for (int i = 0; i < count; i++) {
String st1=xpp.getAttributeName(i);
String st2=xpp.getAttributeValue(i);
switch(st1){
case "id":
System.out.println("id="+st2);
break;
case "name":
System.out.println("書名:"+st2);
break;
case "author":
System.out.println("作者"+st2);
break;
case "year":
System.out.println("出版年份:"+st2);
break;
case "price":
System.out.println("價格:"+st2);
break;
case "language":
System.out.println("語言:"+st2);
break;
}
}
}
break;
}
case END_TAG:
String st=xpp.getName();
System.out.println("標記結束"+st);
break;


}

event=xpp.next();
}


}


}
以上pull解析xml檔案的範例,其優點已寫到程式中


package com.zhidi.jdomtest;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;


import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;


import com.imooc.entity.Book;




public class JDOMTest {
private static ArrayList<Book> booksList = new ArrayList<Book>();
/**
* @param args
*/
public static void main(String[] args) {
// 進行對books.xml檔案的JDOM解析
// 準備工作
// 1.建立一個SAXBuilder的物件
SAXBuilder saxBuilder = new SAXBuilder();
InputStream in;
try {
// 2.建立一個輸入流,將xml檔案載入到輸入流中
in = new FileInputStream("src/res/books.xml");
InputStreamReader isr = new InputStreamReader(in, "UTF-8");
// 3.通過saxBuilder的build方法,將輸入流載入到saxBuilder中
Document document = saxBuilder.build(isr);
// 4.通過document物件獲取xml檔案的根節點
Element rootElement = document.getRootElement();
// 5.獲取根節點下的子節點的List集合
List<Element> bookList = rootElement.getChildren();
// 繼續進行解析
for (Element book : bookList) {
Book bookEntity = new Book();
System.out.println("======開始解析第" + (bookList.indexOf(book) + 1)
+ "書======");
// 解析book的屬性集合
List<Attribute> attrList = book.getAttributes();
// //知道節點下屬性名稱時,獲取節點值
// book.getAttributeValue("id");
// 遍歷attrList(針對不清楚book節點下屬性的名字及數量)
for (Attribute attr : attrList) {
// 獲取屬性名
String attrName = attr.getName();
// 獲取屬性值
String attrValue = attr.getValue();
System.out.println("屬性名:" + attrName + "----屬性值:"
+ attrValue);
if (attrName.equals("id")) {
bookEntity.setId(attrValue);
}
}
// 對book節點的子節點的節點名以及節點值的遍歷
List<Element> bookChilds = book.getChildren();
for (Element child : bookChilds) {
System.out.println("節點名:" + child.getName() + "----節點值:"
+ child.getValue());
if (child.getName().equals("name")) {
bookEntity.setName(child.getValue());
}
else if (child.getName().equals("author")) {
bookEntity.setAuthor(child.getValue());
}
else if (child.getName().equals("year")) {
bookEntity.setYear(child.getValue());
}
else if (child.getName().equals("price")) {
bookEntity.setPrice(child.getValue());
}
else if (child.getName().equals("language")) {
bookEntity.setLanguage(child.getValue());
}
}
System.out.println("======結束解析第" + (bookList.indexOf(book) + 1)
+ "書======");
booksList.add(bookEntity);
bookEntity = null;
System.out.println(booksList.size());
System.out.println(booksList.get(0).getId());
System.out.println(booksList.get(0).getName());

}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


}
以上是Jdom解析xml檔案的範例,優點是用已學過集合等知識來解析檔案,連續性好,容易理解。

package com.zhidi.handler;


import java.util.ArrayList;


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


import com.imooc.entity.Book;




public class SAXParserHandler extends DefaultHandler {
String value = null;
Book book = null;
private ArrayList<Book> bookList = new ArrayList<Book>();
public ArrayList<Book> getBookList() {
return bookList;
}


int bookIndex = 0;
/**
* 用來標識解析開始
*/
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
System.out.println("SAX解析開始");
}

/**
* 用來標識解析結束
*/
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
System.out.println("SAX解析結束");
}

/**
* 解析xml元素
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//呼叫DefaultHandler類的startElement方法
super.startElement(uri, localName, qName, attributes);
if (qName.equals("book")) {
bookIndex++;
//建立一個book物件
book = new Book();
//開始解析book元素的屬性
System.out.println("======================開始遍歷某一本書的內容=================");
////已知book元素下屬性的名稱,根據屬性名稱獲取屬性值
//String value = attributes.getValue("id");
//System.out.println("book的屬性值是:" + value);
//不知道book元素下屬性的名稱以及個數,如何獲取屬性名以及屬性值
int num = attributes.getLength();
for(int i = 0; i < num; i++){
System.out.print("book元素的第" + (i + 1) +  "個屬性名是:"
+ attributes.getQName(i));
System.out.println("---屬性值是:" + attributes.getValue(i));
if (attributes.getQName(i).equals("id")) {
book.setId(attributes.getValue(i));
}
}
}
else if (!qName.equals("name") && !qName.equals("bookstore")) {
System.out.print("節點名是:" + qName + "---");
}
}

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//呼叫DefaultHandler類的endElement方法
super.endElement(uri, localName, qName);
//判斷是否針對一本書已經遍歷結束
if (qName.equals("book")) {
bookList.add(book);
book = null;
System.out.println("======================結束遍歷某一本書的內容=================");
}
else if (qName.equals("name")) {
book.setName(value);
}
else if (qName.equals("author")) {
book.setAuthor(value);
}
else if (qName.equals("year")) {
book.setYear(value);
}
else if (qName.equals("price")) {
book.setPrice(value);
}
else if (qName.equals("language")) {
book.setLanguage(value);
}
}


@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
value = new String(ch, start, length);
if (!value.trim().equals("")) {
System.out.println("節點值是:" + value);
}
}
}
以上是SAX方法解析xml檔案,其中方法承接以前學到的知識,具有連續性。容易理解