XML解析

目錄

定義

XML(extensible Markup Language) ,是一種數據標記語言 & 傳輸格式html

做用

  • 對數據進行標記(結構化數據)
  • 對數據進行存儲
  • 對數據進行傳輸

與html的區別:html用於顯示信息;xml用於存儲&傳輸信息node

XML特色

  • 標籤可進行自定義數組

    XML容許做者定義本身的標籤和文檔結構
  • 自我描述性app

    > **XML文檔實例**
    > 
    > ```
    > <?xml version="1.0" encoding="ISO-8859-1"?>
    >   <!-- XML版本(1.0)和所使用編碼方法-->
    > <note> 
    > <!-- 根元素 -->
    > <to>George</to>
    > <from>John</from>
    > <heading>Reminder</heading>
    > <body>Dont't forget the meeting!</body>
    > <!-- 根元素下的4個子元素-->
    > </note>
    > <!-- 根元素的結尾 -->
    > ```
    > 
    > 僅僅是一個純文本,有文本處理能力的軟件均可以處理xml
  • 可拓展性dom

    在不中斷解析、應用程序的狀況下進行拓展。
  • 可跨平臺數據傳輸ide

    可在不兼容的系統之間進行交換數據,下降了複雜性
  • 數據共享方便性能

    XML以純文本進行存儲,獨立於軟件、硬件和應用程序的數據存儲方式,使得不一樣應用程序、軟件和硬件都能訪問xml的數據

語法

  • 元素要關閉標籤ui

    `< p >this is a bitch <p>`
  • 對大小寫敏感this

    < P >這是錯誤的<p>
    < p >這是正確的 <p>
  • 必需要有根元素(父元素)編碼

    <root>
     <kid>
     </kid>
    </root>
  • 屬性值必須加引號

    <note date="16/08/08">
    </note>
  • 實體引用
實體引用 符號 含義
&lt; < 小於
&gt ; > 大於
&amp; & 和浩
&apos; 單引號
&quot; " 雙引號

元素不能使用&(實體的開始)和<(新元素的開始)

  • 註釋

    `<!-- This is a comment -->`
  • XML的元素、屬性和屬性值

    > 文檔實例
    > 
    > ```
    > <bookstore>
    > <book category="CHILDREN">
    >    <title lang="en"> Harry Potter </title>
    >    <author> JK.Rowling</author>
    > </book>
    > <book category="WEB">
    >    <title lang="en"> woshiPM </title>
    >    <author>Carson_Ho</author>
    > </book>
    > </bookstore>
    > ```
    > 
    > 其中,<bookstore>是根元素;<book>是子元素,也是元素類型之一;而<book>中含有屬性,即category,屬性值是CHILDREN;而元素<author>則擁有文本內容( JK.Rowling)
  • 元素與屬性的差異

    屬性即提供元素額外的信息,但不屬於數據組成部分的信息。
    
    > 範例一
    > 
    > ```
    > <bookstore>
    > <book category="CHILDREN">
    >    <title lang="en"> Harry Potter </title>
    >    <author> JK.Rowling</author>
    > </book>
    > ```
    > 
    > 範例二
    > 
    > ```
    > <bookstore>
    > <book >
    >    <category>CHILDREN<category>
    >    <title lang="en"> Harry Potter </title>
    >    <author> JK.Rowling</author>
    > </book>
    > ```
    > 
    > 範例一和二提供的信息是徹底相同的。

通常狀況下,請使用元素,由於

  1. 屬性沒法描述樹結構(元素能夠)
  2. 屬性不容易拓展(元素能夠)

使用屬性的狀況:用於分配ID索引,用於標識XML元素。

實例

<bookstore>
  <book id = "501">
     <category>CHILDREN<category>
     <title lang="en"> Harry Potter </title>
     <author> JK.Rowling</author>
  </book>
  <book  id = "502">
     <category>CHILDREN<category>
     <title lang="en"> Harry Potter </title>
     <author> JK.Rowling</author>
  </book>
<bookstore>

上述屬性(id)僅用於標識不一樣的便籤,並非數據的組成部分

  • XML元素命名規則

    1. 不能以數字或標點符號開頭
    2. 不能包含空格
    3. 不能以xml開頭
  • CDATA
    不被解析器解析的文本數據,全部xml文檔都會被解析器解析(cdata區段除外)
    <![CDATA["傳輸的文本 "]]>
  • PCDATA
    被解析的字符數據

XML樹結構

XML文檔中的元素會造成一種樹結構,從根部開始,而後拓展到每一個樹葉(節點),下面將以實例說明XML的樹結構。

  • 假設一個XML文件以下

    <?xml version ="1.0" encoding="UTF-8"?>
    <簡歷>
       <基本資料>
       <求職意向>
       <自我評價>
       <其餘信息>
       <聯繫方式>
       <個人做品>
    </簡歷>
  • 其樹結構以下

  • XML節點解釋

    XML文件是由節點構成的。它的第一個節點爲「根節點」。一個XML文件必須有且只能有一個根節點,其餘節點都必須是它的子節點。

this 表明整個XML文件,它的根節點就是 this.firstChild 。 this.firstChild.childNodes 則返回由根節點的全部子節點組成的節點數組。

  每一個子節點又能夠有本身的子節點。節點編號由0開始,根節點的第一個子節點爲 this.firstChild.childNodes[0],它的子節點數組就是this.firstChild.childNodes[0].childNodes 。

根節點第一個子節點的第二個子節點 this.firstChild.childNodes[0].childNodes[1],它返回的是一個XML對象(Object) 。這裏須要特別注意,節點標籤之間的數據自己也視爲一個節點 this.firstChild.childNodes[0].childNodes[1].firstChild ,而不是一個值。

咱們解析XML的最終目的固然就是得到數據的值:

this.firstChild.childNodes[0].childNodes[1].firstChild.nodeValue 。

請注意區分:節點名稱(<性別></性別>)和之間的文本內容(男)能夠看成是節點,也能夠看成是一個值

節點:
名稱:this.firstChild.childNodes[0].childNodes[1]
文本內容:this.firstChild.childNodes[0].childNodes[1].firstChild

值:
名稱:this.firstChild.childNodes[0].childNodes[1].nodeValue
(節點名稱有時也是咱們須要的數據)
文本內容:this.firstChild.childNodes[0].childNodes[1].nodeName

在瞭解完XML以後,是時候來學下如何進行XML的解析了

XML解析

解析XML,即從XML中提取有用的信息

解析方式

基於文檔驅動方式

  • 主流方式:DOM方式
  • 簡介:XML DOM(XML Document Object Model),XML文件對象模型,定義了訪問操做xml文檔元素的方法和接口
  • 工做原理: DOM是基於樹形結構的的節點的文檔驅動方法。使用DOM對XML文件進行操做時,首先解析器讀入整個XML文檔到內存中,而後解析所有文件,並將文件分爲獨立的元素、屬性等,以樹結構的形式在內存中對XML文件進行表示,開發人員經過使用DOM API遍歷XML樹,根據須要修改文檔或檢索所需數據
DOM解析
  • 假設須要解析的XML文檔以下(subject.xml)

    <?xml version ="1.0" encoding="UTF-8"?>`
    <code>
    <language id="1">
      <name>Java</name>
      <usage>Android</usage>
    </language>
    <language id="2">
      <name>Swift#</name>
      <usage>iOS</usage>
    </language>
    <language id="3">
      <name>Html5</name>
     <usage>Web</usage>
    </language>
    </code>
  • 核心代碼

    public static List<subject> getSubjectList(InputStream stream)
     { tv = (TextView)findViewById(R.id.tv);
          try {
              //打開xml文件到輸入流
              InputStream stream = getAssets().open("subject.xml");
              //獲得 DocumentBuilderFactory 對象
              DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
              //獲得DocumentBuilder對象
              DocumentBuilder builder = builderFactory.newDocumentBuilder();
              //創建Document存放整個xml的Document對象數據
              Document document = builder.parse(stream);
              //獲得 XML數據的"根節點" 
              Element element = document.getDocumentElement();
              //獲取根節點的全部language的節點
              NodeList list = element.getElementsByTagName("language");
               //遍歷全部節點
              for (int i= 0;i<=list.getLength();i++){
              //獲取lan的全部子元素
                  Element language = (Element) list.item(i);
              //獲取language的屬性(這裏即爲id)並顯示
                  tv.append(lan.getAttribute("id")+"\n");
            //獲取language的子元素 name 並顯示                       tv.append(sub.getElementsByTagName("name").item(0).getTextContent()+"\n");
           //獲取language的子元素usage 並顯示                    tv.append(sub.getElementsByTagName("usage").item(0).getTextContent()+"\n");
              }

總結Dom解析的步驟

一、調用 DocumentBuilderFactory.newInstance() 方法獲得 DOM 解析器工廠類實例。
二、調用解析器工廠實例類的 newDocumentBuilder() 方法獲得 DOM 解析器對象
三、調用 DOM 解析器對象的 parse() 方法解析 XML 文檔獲得表明整個文檔的 Document 對象。

基於事件驅動

  • 主流方式:SAX、PULL方式
  • 解析方式:可直接根據須要讀取所需的JSON數據,不須要像DOM方法把文檔先入到內存中
PULL解析
  • 工做原理:PULL的解析方式與SAX解析相似,都是基於事件的模式。
    PULL提供了開始元素和結束元素。當某個元素開始時,咱們能夠調用parser.nextText從XML文檔中提取全部字符數據,與SAX不一樣的是,在PULL解析過程當中觸發相應的事件調用方法返回的是數字,且咱們須要本身獲取產生的事件而後作相應的操做,而不像SAX那樣由處理器觸發一種事件的方法從而執行代碼。當解釋到一個文檔結束時,自動生成EndDocument事件。
  • 核心代碼

    public class MainActivity extends Activity {
      private EditText et;
      private Button myButton;
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
           myButton = (Button) this.findViewById(R.id.btn01);
          et = (EditText) this.findViewById(R.id.edittext01);
          myButton.setOnClickListener(new OnClickListener() {
          //可變字符序列,比StringBuffer塊
              StringBuilder sb = new StringBuilder("");
              Resources res = getResources();
              XmlResourceParser xrp = res.getXml(R.xml.subject);
              @Override
              public void onClick(View v) {
                  int counter = 0;
                  try {
    
                      // 判斷是否到了文件的結尾
                      while (xrp.getEventType() != XmlPullParser.END_DOCUMENT) {
                          //文件的內容的起始標籤開始,這裏的起始標籤是subject.xml文件裏面<subjects>標籤下面的第一個標籤
                          int eventType=xrp.getEventType();
                          switch (eventType) {
                              case XmlPullParser.START_DOCUMENT:
                                  break;
                              case  XmlPullParser.START_TAG:
                                  String tagname = xrp.getName();
                                  if (tagname.endsWith("language")) {
                                      counter++;
                                      sb.append("這是第" + counter + "種語言"+"\n");
                                      //能夠調用XmlPullParser的getAttributte()方法來獲取屬性的值
                                      sb.append("語言id是:"+xrp.getAttributeValue(0)+"\n");
                                  }
                                  else if(tagname.equals("name")){
                                      //能夠調用XmlPullParser的nextText()方法來獲取節點的值
                                      sb.append("語言名稱是:"+xrp.nextText()+"\n");
                                  }
                                  else if(tagname.equals("teacher")){
                                      sb.append("用途是:"+xrp.nextText()+"\n");
                                  }
                                  break;
                              case XmlPullParser.END_TAG:
                                  break;
                              case XmlPullParser.TEXT:
                                  break;
                          }
                          //解析下一個事件
                          xrp.next();
                      }
                      //StringBuilder要調用toString()方法並顯示
                      et.setText(sb.toString());
                  } catch (XmlPullParserException e) {
    
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          });
      }

SAX解析

  • 工做原理:基於事件驅動,在讀取XML文檔內容時,事件源順序地對文檔進行掃描,當掃描到文檔的開始與結束(Document)標籤、節點元素的開始與結束(Element)標籤時,直接調用對應的方法,並將狀態信息以參數的形式傳遞到方法中,而後咱們能夠依據狀態信息來執行相關的自定義操做。

一樣是採用事件驅動進行解析,但相比pull解析方法,採用SAX方式進行XML解析可能會較爲複雜,這裏就不做實例展現,有興趣的童鞋們能夠本身去嘗試下,畢竟實踐出真知

DOM、SAX、PULL三類方式對比

DOM方式

  • 原理:基於文檔驅動,是先把dom所有文件讀入到內存中,構建一個主流內存的樹結構,而後使用DOM的API遍歷全部數據,調用API檢索想要的數據和操做數據。

    因此,DOM方式的優缺點是:
  • 特色:

    **優勢**:整個文檔樹存在內存中,可對XML文檔進行操做:刪除、修改等等;可屢次訪問已解析的文檔;因爲在內存中以樹形結構存放,所以檢索和更新效率會更高。;
    **缺點**:解析 XML 文件時會將整個 XML 文件的內容解析成樹型結構存放在內存中並建立新對象,比較消耗時間和內存;
  • 使用情境

    對於像手機這樣的移動設備來說,內存是很是有限的,在XML文檔比較小、須要對解析文檔進行必定的操做且一旦解析了文檔須要屢次訪問這些數據的狀況下能夠考慮使用DOM方式,由於其檢索和解析效率較高

SAX方式

  • 原理:基於事件驅動,在讀取XML文檔內容時,事件源順序地對文檔進行掃描,當掃描到文檔的開始與結束(Document)標籤、節點元素的開始與結束(Element)標籤時,直接調用對應的方法,並將狀態信息以參數的形式傳遞到方法中,而後咱們能夠依據狀態信息來執行相關的自定義操做。
  • 特色:

    **優勢**:解析效率高、佔存少、靈活性高
    **缺點**:解析方法複雜(API接口複雜),代碼量大;可拓展性差:沒法對 XML 樹內容結構進行任何修改
  • 使用情境

    適用於須要處理大型 XML 文檔、性能要求較高、不須要對解析文檔進行修改且不須要對解析文檔屢次訪問的場合

PULL方式

  • 原理:PULL的解析方式與SAX解析相似,都是基於事件的模式。

    PULL提供了開始元素和結束元素。當某個元素開始時,咱們能夠調用parser.nextText從XML文檔中提取全部字符數據,與SAX不一樣的是,在PULL解析過程當中觸發相應的事件調用方法返回的是數字,且咱們須要本身獲取產生的事件而後作相應的操做,而不像SAX那樣由處理器觸發一種事件的方法從而執行代碼。當解釋到一個文檔結束時,自動生成EndDocument事件。
  • 特色:

    **優勢**:SAX的優勢PULL都有,並且解析方法比SAX更加簡單
    **缺點**:可拓展性差:沒法對 XML 樹內容結構進行任何修改
  • 使用情境

    適用於須要處理大型 XML 文檔、性能要求較高、不須要對解析文檔進行修改且不須要對解析文檔屢次訪問的場合

一樣的使用情景,在SAX和PULL解析方法中,更加推薦PULL方法

總結

本文對現今主流的數據傳輸格式XML進行了簡單的介紹,但願你們實踐出真知哦!

相關文章
相關標籤/搜索