XML 文件解析 | Java Debug 筆記

本文正在參加「Java主題月 - Java Debug筆記活動」,詳情查看<活動連接>java

在實際工做中,對 XML 文件的操做是很是常見的,在此將對 XML 文件的解析展開討論,與你們分享一下,但願之後工做中遇到可以快速上手。node

XML解析

xml 文件中因爲更多的是描述信息的內容,因此在獲得一個xml文檔以後應該利用程序按照裏面元素的定義名稱取出對應的內容,這一過程就稱爲xml解析。markdown

解析xml文件的4種方式:app

  1. DOM         
  2. SAX
  3. JDOM    
  4. DOM4J

文檔對象模型(DOM)

  • DOM ---對象化的 XML數據接口

它定義了XML文檔的邏輯結構,給出了一種訪問和處理XML文檔的方法。利用DOM,程序開發人員能夠動態地建立文檔,遍歷文檔結構,添加、修改、刪除文檔內容,改變文檔的顯示方式等等。框架

  • DOM

DOM 這個層次的結構是一棵根據 XML 文檔生成的節點樹。在這棵節點樹中,有一個根節點--Document節點,全部其餘的節點都是根節點的後代節點。節點樹生成以後,就能夠經過 DOM 接口訪問、修改、添加、刪除、建立樹中的節點和內容。dom

讀入xml:函數

DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
// 獲取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析xml文檔
Document doc = builder.parse(new File("src\\dom.xml"));
Element root = builder.getDocumentElement();//得到根元素
寫回xml:
TransformerFactory tfactory=TransformerFactory.newInstance();
Transformer tformer = tfactory.newTransformer();
tformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream("src\\dom1.xml")));

獲得文檔模型的根元素
Element root = doc.getDocumentElement();  
元素Element的函數:
String getTagName()   -獲得標籤的名字 String getAttribute(「unit」) -獲得元素的unit屬性值 節點Node的函數: NodeList  getChildNodes()   - 獲得子節點的集合 Node getFirstChild()         - 獲得第一個子節點 Node getLastChild()        - 獲得最後一個子節點 節點Node的函數: Node getNextSibling() - 獲得下一個兄弟節點 Node getPreviousSibling()   - 獲得前一個兄弟結點 Node getParentNode()     - 獲得父節點 NamedNodeMap getAttributes()  - 獲得全部的屬性集合 String getNodeName()         - 獲得當前節點的名字 String getNodeValue()   - 獲得當前節點的值 NodeList的函數 int getLength()    -獲得集合長度 Node item(int index)  - 獲得集合中的一個元素 寫XML文檔函數 DocumentBuilder 的函數: Document doc = builder.newDocument(); -新建一個模型
Document 的函數:
Element createElement(String name) – 創建一個元素 Text createTextNode(String data)-建立一個文本節點 Node的函數: Node appendChild(Node child)  - 添加一個子節點 Element 的函數: void setAttribute(String name, String value)  - 設置元素的一個屬性和屬性值 複製代碼

簡單應用程序接口(SAX)

SAX 是一種事件驅動的接口,它的基本原理是由接口的用戶提供符合定義的處理器,XML 分析時遇到特定的事件,就去調用處理器中特定事件的處理函數。post

捕獲和響應各個事件:ui

  • startDocument( ) endDocument( ) 事件是在文檔的起始處和結束處被激發的
  • startElement( ) endElement( ) 事件是在遇到起始標記和結束標記時被激發的
  • characters( ) 事件是在遇到字符數據時被激發的

使用 SAX 解析 XML 文檔的步驟以下:編碼

(1)建立 SAXParserFactory 的實例

(2)建立 SAXParser 的實例

(3)建立 SAXParserHandler

(4)使用 parse() 方法解析 XML 文檔

SAXParserFactory spfactory = SAXParserFactory.newInstance();
// 生成SAX解析對象
SAXParser parser = spfactory.newSAXParser();
// 指定XML文件,進行XML解析
 parser.parse(new File("src\\dom.xml"), new SaxReader());
複製代碼

Jdom

JDOM 使用標準的 Java 編碼模式,用以來彌補 DOMSAX 在實際應用當中的不足之處。

這些不足之處主要在於 SAX 沒有文檔修改、隨機訪問以及輸出的功能,而對於 DOM 來講,在使用時來用起來不太方便。

JDOM 中,XML 元素就是 Element 的實例,XML 屬性就是 Attribute 的實例,XML 文檔自己就是 Document 的實例。

由於 JDOM 對象就是像 DocumentElementAttribute 這些類的直接實例,所以建立一個新 JDOM 對象就如在 Java 語言中使用 new 操做符同樣容易。而不使用複雜的工廠化模式,使對象操做更爲方便。

Document類操做:

Element root=new Element("GREETING");
Document doc=new Document(root);
root.setText("HelloJDOM!");
複製代碼

Attribute 類操做:

Attribute rootAttri = new Attribute("comment","introduce myself");//建立名爲 commnet,值爲 introduce myself 的屬性。
rootElement.setAttribute(rootAttri);//將剛建立的屬性添加到根元素。
複製代碼

Element 類操做:

Element root=doc.getRootElement();//得到根元素element
List allChildren=root.getChildren();//得到全部子元素的一個list
List namedChildren=root.getChildren("name");//得到指定名稱子元素的list
Element child=root.getChild(「name」);//得到指定名稱的第一個子元素
allChildren.remove(3);//刪除第四個子元素
allChildren.removeAll(root.getChildren("jack"));//刪除叫「jack」的子元素
root.removeChildren("jack");//便捷寫法
allChildren.add(new Element("jane"));//加入
root.addContent(new Element(「jane」));//便捷寫法
Element nameElement = new Element("name");//建立 name 元素
nameElement.addContent("kingwong");//將kingwong做爲content添加到name元素
rootElement.addContent(nameElement);//將name元素做爲content添加到根元素 getAttributeValue("name") 返回指定屬性名字的值。若是沒有該屬性則返回null,有該屬性可是值爲空,則返回空字符串。
getChildText("childname") 返回指定子節點的內容文本值。  
root.getChild("book").getChild("name").getText();
root.getChild("book").getChild("name").setText("dsgdghdgasg");
複製代碼

解析xml:

使用 Jdom 解析 xml 要導入 org.domjar

  1. 實例化一個合適的解析器對象
SAXBuilder builder = new SAXBuilder();
複製代碼
  1. 構建一個文檔對象doc
Document doc = builder.build(new File("src\\dom.xml"));
複製代碼

XML 文檔輸出:

XMLOutputter outputter=new XMLOutputter();
outputter.output(doc,new FileOutputStream("src\\dom.xml"));
複製代碼

Dom4j

Dom4j 是一個 JavaXML API,相似於 jdom,用來讀寫 XML 文件的。它應用於 Java 平臺,採用了 Java 集合框架並徹底支持DOMSAXJAXP

  1. 讀取並解析 XML 文檔:

讀寫 XML 文檔主要依賴於 org.dom4j.io 包,其中提供 DOMReaderSAXReader 兩類不一樣方式,而調用方式是同樣的。這就是依靠接口的好處。

// 從文件讀取XML,輸入文件名,返回XML文檔
public Document read(String fileName) throws MalformedURLException, DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(fileName));
return document;
}
複製代碼
  1. 取得 Root 節點
public Element getRootElement(Document doc){
     return doc.getRootElement();
}
複製代碼
  1. 遍歷 XML
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
    // 枚舉全部子節點
    Element element = (Element) i.next();
}
for ( Iterator i = root.elementIterator(foo); i.hasNext();) {
    // 枚舉名稱爲foo的節點
    Element foo = (Element) i.next();
}

// 枚舉屬性
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
    Attribute attribute = (Attribute) i.next();
}
複製代碼

遞歸也能夠採用 Iterator 做爲枚舉手段,但文檔中提供了另外的作法

public void treeWalk() {
         treeWalk(getRootElement());
 }
 public void treeWalk(Element element) {
       for (int i = 0, size = element.nodeCount(); i < size; i++) {
           Node node = element.node(i);
          if (node instanceof Element) {
              treeWalk((Element) node);
         }   else { // do something....
       }
  }
 }
複製代碼

獲取節點數量,包含自身。 這個方法所遍歷出來的對象是多種的,nodenamespacetext 等類型的。 if(element instanceof Element) 條件 element.nodeCount()==1 表示當前元素是子元素

  1. 建立XML
public Document createDocument() {
 Document document = DocumentHelper.createDocument();
 Element root = document.addElement(root);
 Element author1 =root.addElement(author).addAttribute(name, James)
  .addAttribute(location, UK).addText(James Strachan);
 Element author2 =root.addElement(author).addAttribute(name, Bob)
  .addAttribute(location, US).addText(Bob McWhirter);
 return document;
}
複製代碼
  1. 字符串與XML的轉換

有時候常常要用到字符串轉換爲XML或反之.

// XML轉字符串
Document document = ...;
String text = document.asXML();
// 字符串轉XML
String text = <name>James</name>   
Document document = DocumentHelper.parseText(text);
複製代碼
  1. 文件輸出

一個簡單的輸出方法是將一個Document或任何的Node經過write方法輸出。

FileWriter out = new FileWriter( foo.xml );
document.write(out);
// 美化輸出或縮進格式,能夠用XMLWriter類 
public void write(Document document) throws IOException {
// 讀取文件
FileWriter fileWriter = new FileWriter("src\\dom2.xml");
//OutputFormat xmlFormat = OutputFormat.createPrettyPrint();// 縮減型格式
OutputFormat xmlFormat =OutputFormat.createCompactFormat();//緊湊型格式
//format.setTrimText(false);//設置text中是否要刪除其中多餘的空格
xmlFormat.setEncoding("gb2312");// 設置編碼
// 建立寫文件方法
XMLWriter xmlWriter = new XMLWriter(fileWriter, xmlFormat);
// 寫入文件
xmlWriter.write(document);
// 關閉
xmlWriter.close();
}
複製代碼