1. 程式人生 > >Andorid中使用Jsoup解析庫解析XML、HTML、Dom節點---第三方庫學習筆記(三)

Andorid中使用Jsoup解析庫解析XML、HTML、Dom節點---第三方庫學習筆記(三)

XML介紹:

XML簡介:

  • XML,可擴充套件標記語言,標準通用標記語言的子集。
  • 一種用於標記電子檔案使其具有結構性的標記語言。
  • 它可以用來標記資料、定義資料型別
  • 是一種允許使用者對自己的標記語言進行定義的源語言。
  • 非常適合全球資訊網傳輸
  • 提供統一方法描述和交換獨立於應用程式或供應商的結構化資料

XML的特點:

  • XML是一種標記語言,很類似HTML
  • XML的設計宗旨是傳輸資料,而非顯示資料
  • XML標籤沒有被預定義,需要自行定義標籤
  • XML被設計為具有自我描述性
  • XML是W3C的推薦標準

    XML與HTML對比:

    1. XML和HTML是為不同目的而設計:
  • XML被設計為傳輸和儲存資料,其焦點是資料的內容

  • HTML被設計用來顯示資料,其焦點是資料的外觀
  • HTML旨在顯示資料,而XML旨在傳輸資料

2.XML僅僅是純文字
有能力處理純文字的軟體都可以處理XML。不過能夠讀懂XML的應用程式可以有針對的處理XML的標籤。標籤的功能性意義依賴於應用程式的特性。

3.XML沒有預定義的標籤
在HTML中使用的標籤(以及HTML的結構)是預定義的。HTML文件只使用在HTML標準中定義過的標籤。

XML的語法規則:

  1. 在XML中,省略關閉標籤是非法的,所有標籤都必須有關閉標籤。
  2. XML標籤對對大小寫敏感
  3. XML必須正確的巢狀
  4. XML文件必須有根元素
  5. XML的屬性值必須加引號
  6. XML中,空格會被保留

元素可以包含其他元素、文字、或者兩者的混合物。元素也可以擁有屬性。

<bookstore>
  <book category="children">
    <title>Harry Potter</title>
    <author>JK.Rowing</author>
    <year>2005</year>
    <price>29.9</price>
  </book>
</bookstore>
<bookstore><book
>
都擁有元素內容,因為他們包含了其他元素。 <author>只有文字內容,因為僅包含文字。 在上例中,只有<book>元素屬性(category="children")

使用JDK自帶的API(Document)解析和生成XML檔案:
需要解析的XML檔案:

<?xml version="1.0" encoding="utf-8"?>
    <languages cat="it">
        <lan id="1">
            <name>Java</name>
            <ide>Eclipse</ide>
        </lan>
        <lan id="2">
            <name>Swift</name>
            <ide>XCode</ide>
        </lan>
        <lan id="3">
            <name>C#</name>
            <ide>Visual Studio</ide>
        </lan>
    </languages>
package com.example.myxmltest;

import java.io.InputStream;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
    private TextView text;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        dealXML();//解析XML檔案

//        createXML();//建立XML檔案
    }

    /**
     * 建立XML檔案
     */
    private void createXML() {
        try {
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document document = builder.newDocument();
        //建立根節點元素
        Element root = document.createElement("Languages");
        //為根節點元素設定屬性值
        root.setAttribute("cat", "it");

        //第一個子節點
        //建立子節點元素,併為子節點元素設定屬性值
        Element lan1 = document.createElement("lan");
        lan1.setAttribute("id", "1");
        //建立子節點的子節點元素,併為其設定內容屬性值
        Element name1 = document.createElement("name");
        name1.setTextContent("Java");
        Element ide1 = document.createElement("ide");
        ide1.setTextContent("Eclipse");
        //將這些內容節點新增到子節點中作為子節點的子節點
        lan1.appendChild(name1);
        lan1.appendChild(ide1);

        //第二個子節點
        //建立子節點元素,併為子節點元素設定屬性值
        Element lan2 = document.createElement("lan");
        lan2.setAttribute("id", "2");
        //建立子節點的子節點元素,併為其設定內容屬性值
        Element name2 = document.createElement("name");
        name2.setTextContent("Swift");
        Element ide2 = document.createElement("ide");
        ide2.setTextContent("XCode");
        //將這些內容節點新增到子節點中作為子節點的子節點
        lan2.appendChild(name2);
        lan2.appendChild(ide2);

        //第三個子節點
        //建立子節點元素,併為子節點元素設定屬性值
        Element lan3 = document.createElement("lan");
        lan3.setAttribute("id", "3");
        //建立子節點的子節點元素,併為其設定內容屬性值
        Element name3 = document.createElement("name");
        name3.setTextContent("C#");
        Element ide3 = document.createElement("ide");
        ide3.setTextContent("Visual studio");
        //將這些內容節點新增到子節點中作為子節點的子節點
        lan3.appendChild(name3);
        lan3.appendChild(ide3);

        //將子節點新增到根節點中作為根節點的子節點
        root.appendChild(lan1);
        root.appendChild(lan2);
        root.appendChild(lan3);
        //新增根節點元素
        document.appendChild(root);

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty("encoding", "utf-8");
        StringWriter sw = new StringWriter();
        transformer.transform(new DOMSource(document), new StreamResult(sw));
        text.setText(sw.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 用JDK自帶的API(Document)解析XML檔案
     */
    private void dealXML() {
        try {
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            InputStream inputStream = getAssets().open("languages.xml");
            Document document = builder.parse(inputStream);
            //當前的element代表根節點中所有內容
            Element element = document.getDocumentElement();
            NodeList nodeList = element.getElementsByTagName("lan");
            for (int i = 0; i < nodeList.getLength(); i++) {
                Element lan = (Element) nodeList.item(i);
                text.append(lan.getAttribute("id")+"\n");
                text.append(lan.getElementsByTagName("name").item(0).getTextContent()+"\n");
                text.append(lan.getElementsByTagName("ide").item(0).getTextContent()+"\n");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initView() {
        text = (TextView) findViewById(R.id.text);
    }
}

HTML、XML等Dom節點類解析庫的使用:

Jsoup簡介:
jsoup是一款Java的HTML解析器,可直接解析某個URL地址、HTML文字內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於JQuery的操作方法來取出和操作資料。

Jsoup特點:

  • HTML、XML、自定義DOM格式文字解析
  • 可操作HTML元素、屬性、文字
  • 適用於採集解析網站HTML
  • DOM解析功能非常強大

Jsoup基本用法:

  1. 分析Html或Dom文字的結點標籤結構
  2. 尋找你要解析的那個內容部分所在的結點標記
  3. 呼叫Jsoup API解析結點內容

程式碼演示:

  1. 使用Jsoup載入Html資料
  2. 使用Jsoup解析並提取HTML元素
  3. 使用Jsoup修改資料
  4. 使用Jsoup HTML文件清理
package com.test.Jsoup;

import java.io.File;
import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Whitelist;
import org.jsoup.select.Elements;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;

import com.example.myxmltest.R;

/**
 * Jsoup的四個功能的基本使用方法
 * @author Administrator
 *
 */
public class JsoupTest extends Activity {
    private String html = "<html><head><title>Jsoup的用法</title></head><body><p><a href='http://baidu.com'>這裡是Jsoup專案的相關文章</a></p></body></html>";
    private String url = "http://baidu.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*
         * 1.使用 Jsoup 載入 Html 資料功能
         * 資料內容可以是:html文字、url、本地html
         */

        //1.html文字
        Document doc = Jsoup.parse(html);
        //可以獲取到html中<title>的值
        doc.title();

        //2.url
        try {
            //通過GET方式請求
            Document doc2 = Jsoup.connect(url).get();
            //通過POST方法請求
//          Document doc2 = Jsoup.connect(url).data("key","value").timeout(3000).post();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //3.本地html
        //獲取本地html檔案
        File file = new File(Environment.getExternalStorageDirectory()+"/index.html");
        //parse()方法引數解釋:1.html檔案  2.html的編碼格式(本地html檔案是什麼編碼就寫什麼編碼)  3.當本地html檔案中的圖片或者連結採用的是相對路徑時,就可以通過指定的baseUri替換路徑的字首。eg:.../baidu.png-->http://baidu.com/baidu.png
        try {
            Document doc3 = Jsoup.parse(file, "utf-8", "http://baidu.com");
        } catch (IOException e) {
            e.printStackTrace();
        }

        /*
         * 2.使用 Jsoup 解析並提取 HTML元素功能
         */
        Elements eles = doc.getElementsByTag("a");//將a標籤的列表儲存成元素集合
        for (Element link : eles) {
            //獲取a標籤中href的屬性值
            String linkHref = link.attr("href");
            //獲取a標籤中的文字值
            String text = link.text();
        }
        //檢索元素功能
        //檢索html檔案中的a標籤並且就有href屬性的a標籤列表儲存成元素集合
        Elements elements = doc.select("a[href]");
        //檢索html檔案中有img標籤的.png格式的圖片
        Elements elements2 = doc.select("img[src$=.png]");
        //檢索出元素名為className的div標籤的元素
        Element element3 = doc.select("div.className").first();

        /*
         * 3.使用 Jsoup 修改資料屬性功能
         */
        //對元素名為className的div標籤新增屬性,屬性名為key,屬性值為value
        doc.select("div.className").attr("key","value");
        //為元素名為className的div標籤新增屬性類,新增的屬性為:class="myclass"
        doc.select("div.className").addClass("myclass");
        //移除img標籤的onClick屬性
        doc.select("img").removeAttr("onClick");

        /*
         * 4.使用 Jsoup HTML 文件清理功能
         */
        String htmls = "";//不安全的一個html程式碼
        String safe = Jsoup.clean(htmls, Whitelist.basic());//用基本的白名單將不安全的html程式碼轉換為安全的html

    }
}

使用Jsoup來實現複雜的Html列表解析:

實現效果:
使用 Jsoup 實現對某網站新聞列表的採集解析

package com.test.jsoupdemo;

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.example.myxmltest.R;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

/**
 * 使用Jsoup解析HtmL新聞列表
 */
public class JsoupDemo extends Activity {
    private String url = "http://mobile.csdn.net/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {

            @Override
            public void run() {
                parseHtml();
            }
        }).start();;
    }
    //使用Jsoup解析html新聞列表
    private void parseHtml() {
        try {
            Document doc = Jsoup.connect(url).get();
            //將所有的新聞列表儲存為元素的集合
            Elements elements = doc.select("div.unit");
            for (Element element : elements) {
                //獲取每一條新聞的標題<h1>標籤中的文字內容,因為每條新聞中只有一個h1,所以可以通過getElementsByTag("h1")獲取到
                String title = element.getElementsByTag("h1").first().text();
                //獲取每條新聞標題中的<h1>標籤中的超連結
                String href = element.getElementsByTag("h1").first().getElementsByTag("a").first().attr("href");
                //獲取每條新聞的新聞內容<dd>標籤中的文字內容
//              String content = element.getElementsByTag("dd").first().text();
                Log.i("tag", title);
                Log.i("tag", href);
//              Log.i("tag", content);

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


}

原網頁截圖:
這裡寫圖片描述

對應的網頁原始碼截圖:
這裡寫圖片描述

根據上圖可以看出每條新聞的相同點:每條新聞的內容都是在<div class="unit">標籤中。

這裡寫圖片描述
通過上圖可以發現每條新聞中只有一個<h1>標籤。

執行結果截圖:
這裡寫圖片描述