[Android]Android XML解析

[Android]Android XML解析

Android除了可以與SQLite作連線外,其實也可透過XML解析的方式,

使Android可以與電腦資料庫進行連線,這篇文章主要是說明Android該如何解析XML,

並且主要不是說明程式碼用途,而是說明該怎樣修改道自己可以使用的情況!!

而使用的範圍當然不止僅限於與資料庫連線,使用的用途可以相當多元的。

首先我們必須要有一個XML格式,而如果是要連線資料庫,那就是在資料庫伺服器中建立一網頁伺服器,

而將資料庫查詢結果透過XML方式來呈現,至於網頁撰寫方式在這邊就不贅述。

 

下列為一XML檔,後續程式將會以該檔案為範例撰寫。

切記,如果是要以"檔案"方式存取XML,而不是網頁伺服器存取時,

必須將XML檔放至src資料夾底下。

檔案名稱:AllLocation.xml


<AllLocation>
	<Location>
		<Name>A</Name>
		<Upper_left_x>120.123</Upper_left_x>
		<Upper_left_y>22.123</Upper_left_y>
		<Lower_left>121.123</Lower_left>
		<Upper_right>23.123</Upper_right>
	</Location>
	<Location>
		<Name>B</Name>
		<Upper_left_x>120.321</Upper_left_x>
		<Upper_left_y>22.321</Upper_left_y>
		<Lower_left>119.321</Lower_left>
		<Upper_right>21.321</Upper_right>
	</Location>
</AllLocation>

格式內容可以依照個人需求來修改,後續也會說明其他可修改或對應的地方,

其中我使用的標籤會影響以下的程式碼,如有自行定義的要更正。

 

接下來是說明該如何宣告用來接收解析後結果的變數名稱,

檔案名稱:Locate.java


package coordinate.location;

public class Locate {
	public String Name;	//以下變數名稱,建議與XML定義的標籤名稱相同
	public String Upper_left_x;
	public String Upper_left_y;
	public String Lower_left;
	public String Upper_right;
	
	public Locate(){}
	
	public Locate(String Name, String Upper_left_x,String Upper_left_y, String Lower_left, String Upper_right)
	{
		this.Name=Name;
		this.Upper_left_x=Upper_left_x;
		this.Upper_left_y=Upper_left_y;
		this.Lower_left=Lower_left;
		this.Upper_right=Upper_right;
	}
	//以下宣告為兩兩一組,個別宣告變數存取或讀取時使用
	//宣告要使用Name內容時使用,建議getName <<其中的文字與變數名稱相同較好管理
	public String getName() {
		return Name;
	}
	//宣告要存取Name內容時使用,建議setName <<其中的文字與變數名稱相同較好管理
	public void setName(String Name) {
		this.Name = Name;
	}
	public String getUpper_left_x() {
		return Upper_left_x;
	}

	public void setUpper_left_x(String Upper_left_x) {
		this.Upper_left_x = Upper_left_x;
	}
	public String getUpper_left_y() {
		return Upper_left_y;
	}

	public void setUpper_left_y(String Upper_left_y) {
		this.Upper_left_y = Upper_left_y;
	}
	public String getLower_left() {
		return Lower_left;
	}

	public void setLower_left(String Lower_left) {
		this.Lower_left = Lower_left;
	}
	public String getUpper_right() {
		return Upper_right;
	}

	public void setUpper_right(String Upper_right) {
		this.Upper_right = Upper_right;
	}
}

以上內容如果有自行定義的名稱,其實透過搜尋就可以簡單發現需修改哪邊,

因為變數名稱我都與XML定義的標籤同名,所以相對較好修改,對後續使用也方便。

 

設定完後,我們該設定一個說明文件,用來告知解析器我們標籤中的文字與我們宣告的變數,

畢竟只是我們自己知道名稱是相同,而解析器還是得告知他該如何對應,並且將值放入變數中。

 

檔案名稱:SAXContentHandler.java


package coordinate.location;

import java.util.ArrayList;
import java.util.List;

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

public class SAXContentHandler extends DefaultHandler {
	private List<Locate> Locate_List;//修改為自己定義的一個陣列大小,通常除List字眼外,我會與下方變數同名稱
	private Locate Locate;//修改為自己訂一個名稱,我整個專案都會統一名稱
	private String preTag; //固定不需修改
	
	//getLBSs()名稱可自行定義,但下個檔案中會用到,所以需要注意要對應
	public List<Locate> getLBSs() {
		return Locate_List;
	}

	/**
	 * 接收文件的開始
	 */
	@Override
	public void startDocument() throws SAXException {
		Locate_List = new ArrayList<Locate>();//這邊就是與上面宣告的第一個相同
	}

	/**
	 * 接收字元資料的通知
	 */
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		try {
			String data = new String(ch, start, length);//不需修改
			//這邊的意思是,當解析到XML中有Name時,就將該標籤的內容存入setName中
			if ("Name".equals(preTag)) {	
				Locate.setName(data);
			}
			if ("Upper_left_x".equals(preTag)) {
				Locate.setUpper_left_x(data);
			}
			if ("Upper_left_y".equals(preTag)) {
				Locate.setUpper_left_y(data);
			}
			if ("Lower_left".equals(preTag)) {
				Locate.setLower_left(data);
			}
			if ("Upper_right".equals(preTag)) {
				Locate.setUpper_right(data);
			}
		} catch (Exception ee) {

		}
	}

	/**
	 * 接收元素開始的通知
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		 //這邊的意思是,當解析到XML中的Location標籤時,為一筆資料開始
		if ("Location".equals(localName)) {
			Locate = new Locate();
		}
		preTag = localName;
	}

	/**
	 * 接收元素結尾的通知
	 */
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		//這邊的意思是,當解析到XML中的Location標籤時,為一筆資料結束
		if ("Location".equals(localName) && Locate != null) {	
			Locate_List.add(Locate);
			Locate = null;
		}
		preTag = null;
	}
}

上面程式碼中,期時會發現許多重複的字,如果要修改為自己定義的名稱或標籤,

很簡單,用搜尋慢慢取代就好。

 

接下來,就是要如何將XML丟進去解析器解析了,

檔案名稱:SAXParseXML.java


package coordinate.location;

import java.io.InputStream;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SAXParseXML {//這的檔案基本上只需要修改下方 List<Locate>,改為自己定義的,如上述檔案中的內容
	public static List<Locate> readXML(InputStream inStream) throws Exception {
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser saxParse = factory.newSAXParser();

		SAXContentHandler handler = new SAXContentHandler();
		saxParse.parse(inStream, handler);
		inStream.close();
		//下方getLBSs()如有自行定義,可修改為上個檔案所修改的名稱
		return handler.getLBSs();
	}
}

 

最後,就是Activity程式碼中該如何將所想要的XML丟進去,並且取值出來。

檔案名稱:LocationActivity.java


package coordinate.location;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
//這邊宣告就略過,太站畫面了,撰寫中只需按下Ctrl+Shift+O就會自動帶入了

public class LocationActivity extends Activity {
	/** Called when the activity is first created. */
	Locate Locate;//名稱為先前自行定義的名稱
	List<Locate> Locate_List;
	String Name, Upper_left_x, Upper_left_y, Lower_left, Upper_right,Name_ID = "A";

	public void onCreate(Bundle savedInstanceState) {
		this.requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Locate_List = getXMLData();	//將XML丟入解析器進行解析
		ShowXMLData();		//顯示解析後結果

	}

	private List<Locate> getXMLData() {
		List<Locate> Locate_List = new ArrayList<Locate>();//如有修改為其他名稱需要注意的地方!!
		try {
			//以下為"XML是一個檔案時"將XML丟入解析器的寫法
			InputStream inStream = LocationActivity.class.getClassLoader()
					.getResourceAsStream("AllLocation.xml");
			//以下為"XML來源是網頁伺服器時"將XML丟入解析器的寫法
			URL xmlurl = new URL("http://xxx.xxx.xxx.xxx/xml.aspx?ID=x"); 	//網址依照自己的伺服器名稱,ID只是參考用變數名稱
			InputStream inStream = xmlurl.openStream();

			//將上方所選擇之XML丟入解析器
			Locate_List = SAXParseXML.readXML(inStream);
		} catch (Exception ee) {
		}
		return Locate_List;	//如有自行定義必須要修改的地方!!
	}

	private void ShowXMLData() {
		//在解析完成後的內容會以陣列方式丟入Locate_List中,並且比數為第0筆開始
		//下方為從第0筆開始存取到最後一筆的範例,並且其中的if是當Name的值為為上方宣告的Name_ID相同時,就存取該筆資料
		for (int i = 0; i < Locate_List.size(); i++) {
			if (Locate_List.get(i).Name.equals(Name_ID)) {
				Name = Locate_List.get(i).Name;
				Upper_left_x = Locate_List.get(i).Upper_left_x;
				Upper_left_y = Locate_List.get(i).Upper_left_y;
				Lower_left = Locate_List.get(i).Lower_left;
				Upper_right = Locate_List.get(i).Upper_right;
			}
		}
	}
}

上面的程式碼中,大多的變數我都統一,因為這樣才方便管理以及修改,

並且如是初學者要使用該XML解析器,也可以很方便的修改幾個地方就可使用。

 

以上有錯字深感抱歉....