XML文件解析

作者:xcbeyond
瘋狂源自夢想,技術成就輝煌!微信公眾號:《程序猿技術大咖》號主,專注后端開發多年,擁有豐富的研發經驗,樂于技術輸出、分享,現階段從事微服務架構項目的研發工作,涉及架構設計、技術選型、業務研發等工作。對于Java、微服務、數據庫、Docker有深入了解,并有大量的調優經驗。

XML解析:
    在xml文件中由于更多的是描述信息的內容,所以在得到一個xml文檔之后應該利用程序按照里面元素的定義名稱取出對應的內容,這一過程就稱為xml解析。

解析xml文件的4種方式:
1.DOM         
2.SAX
3.JDOM    
4.DOM4J

文檔對象模型(DOM)

DOM---對象化的XML數據接口
 它定義了XML文檔的邏輯結構,給出了一種訪問和處理XML文檔的方法。利用DOM,程序開發人員可以動態地創建文檔,遍歷文檔結構,添加、修改、刪除文檔內容,改變文檔的顯示方式等等。

DOM樹
  DOM這個層次的結構是一棵根據XML文檔生成的節點樹。在這棵節點樹中,有一個根節點--Document節點,所有其他的節點都是根節點的后代節點。節點樹生成之后,就可以通過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分析時遇到特定的事件,就去調用處理器中特定事件的處理函數。

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

使用 SAX 解析 XML 文檔的步驟如下:
創建 SAXParserFactory 的實例
創建 SAXParser 的實例
創建 SAXParserHandler 類
使用 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 編碼模式,用以來彌補DOM及SAX在實際應用當中的不足之處。
這些不足之處主要在于SAX沒有文檔修改、隨機訪問以及輸出的功能,而對于DOM來說,在使用時來用起來不太方便。
在 JDOM 中,XML 元素就是 Element 的實例,XML 屬性就是 Attribute 的實例,XML 文檔本身就是 Document 的實例。
因為 JDOM 對象就是像 Document、Element 和 Attribute 這些類的直接實例,因此創建一個新 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.dom的jar包
1.實例化一個合適的解析器對象
SAXBuilder builder = new SAXBuilder();
2.構建一個文檔對象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是一個Java的XML API,類似于jdom,用來讀寫XML文件的。它應用于Java平臺,采用了Java集合框架并完全支持DOM,SAX和JAXP。

1.讀取并解析XML文檔:
讀寫XML文檔主要依賴于org.dom4j.io包,其中提供DOMReader和SAXReader兩類不同方式,而調用方式是一樣的。這就是依靠接口的好處。 // 從文件讀取XML,輸入文件名,返回XML文檔
public Document read(String fileName) throws MalformedURLException, DocumentException {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(fileName));
return document;
}
2、取得Root節點
  public Element getRootElement(Document doc){
return doc.getRootElement();
}

3、遍歷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....
       }
  }
 }
獲取節點數量,包含自身。 這個方法所遍歷出來的對象是多種的,node,namespace,text等類型的。 if(element instanceof Element) 條件 element.nodeCount()==1 表示當前元素是子元素

4. 創建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;
}
5字符串與XML的轉換
有時候經常要用到字符串轉換為XML或反之
// XML轉字符串
Document document = ...;
String text = document.asXML();
// 字符串轉XML
String text = <name>James</name>   
Document document = DocumentHelper.parseText(text);
6文件輸出
一個簡單的輸出方法是將一個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();
}