[英]Parsing XML in Android with SAX
我有一個XML文件,如下所示:
<questions title="(Some question Category)">
<question>
<ask>(Some question)?</ask>
<answer>(Some answer)</answer>
<answer correct="true">(Some correct answer)</answer>
<answer>(Some answer)</answer>
<answer>(Some answer)</answer>
</question>
</questions>
我正在使用SAX來解析文件。 據我所知,所有必需的SAX文件都已正確設置。
然后我有一個處理程序類,我查找了如何編寫稍微不同的XML文件。 我嘗試將其調整為上面的xml,這是我想出的(未完成):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.widget.TextView;
public class QuestionHandler extends DefaultHandler {
//list for imported product data
private ArrayList<TextView> theViews;
//string to track each entry
private String currQuestion = "";
//flags to keep track of XML processing
private boolean isAsk = false;
private boolean isAnswer = false;
//context for user interface
private Context theContext;
//constructor
public QuestionHandler(Context cont) {
super();
theViews = new ArrayList<TextView>();
theContext = cont;
}
//start of the XML document
public void startDocument () { Log.i("QuestionHandler", "Start of XML document"); }
//end of the XML document
public void endDocument () { Log.i("QuestionHandler", "End of XML document"); }
//opening element tag
public void startElement (String uri, String name, String qName, Attributes atts)
{
//find out if the element is a question
if(qName.equals("question"))
{
//set ask and answer tag to false
isAsk = false;
isAnswer = false;
//create View item for question display
TextView questionView = new TextView(theContext);
questionView.setTextColor(Color.rgb(73, 136, 83));
//add the attribute value to the displayed text
String viewText = "Items from " + atts.getValue("name") + ":";
questionView.setText(viewText);
//add the new view to the list
theViews.add(questionView);
}
//or if the element is an asked question
else if(qName.equals("ask"))
isAsk = true;
//or if element is an answer
else if(qName.equals("answer"))
isAnswer = true;
}
//closing element tag
public void endElement (String uri, String name, String qName)
{
if(qName.equals("question"))
{
//create a View item for the asked
TextView askView = new TextView(theContext);
askView.setTextColor(Color.rgb(192, 199, 95));
//display the compiled items
askView.setText(currQuestion);
//add to the list
theViews.add(askView);
//create a View item for the answers
TextView answersView = new TextView(theContext);
answersView.setTextColor(Color.rgb(192, 199, 95));
//display the compiled items
answersView.setText(currQuestion);
//add to the list
theViews.add(answersView);
//reset the variable for future items
currQuestion = "";
}
}
//element content
public void characters (char ch[], int start, int length)
{
//string to store the character content
String currText = "";
//loop through the character array
for (int i=start; i<start+length; i++)
{
switch (ch[i]) {
case '\\':
break;
case '"':
break;
case '\n':
break;
case '\r':
break;
case '\t':
break;
default:
currText += ch[i];
break;
}
}
//prepare for the next item
if(isAsk || isAnswer && currText.length()>0)
currQuestion += currText+"\n";
}
public ArrayList<TextView> getData()
{
//take care of SAX, input and parsing errors
try
{
//set the parsing driver
System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");
//create a parser
SAXParserFactory parseFactory = SAXParserFactory.newInstance();
SAXParser xmlParser = parseFactory.newSAXParser();
//get an XML reader
XMLReader xmlIn = xmlParser.getXMLReader();
//instruct the app to use this object as the handler
xmlIn.setContentHandler(this);
//provide the name and location of the XML file **ALTER THIS FOR YOUR FILE**
URL xmlURL = new URL("http://www.macs.hw.ac.uk/~pjbk/quiz/example.xml");
//open the connection and get an input stream
URLConnection xmlConn = xmlURL.openConnection();
InputStreamReader xmlStream = new InputStreamReader(xmlConn.getInputStream());
//build a buffered reader
BufferedReader xmlBuff = new BufferedReader(xmlStream);
//parse the data
xmlIn.parse(new InputSource(xmlBuff));
}
catch(SAXException se) { Log.e("AndroidTestsActivity",
"SAX Error " + se.getMessage()); }
catch(IOException ie) { Log.e("AndroidTestsActivity",
"Input Error " + ie.getMessage()); }
catch(Exception oe) { Log.e("AndroidTestsActivity",
"Unspecified Error " + oe.getMessage()); }
//return the parsed product list
return theViews;
}
}
最后,我的initialiseQuestions()方法,從另一個工作活動,是將提取的XML數據分配給一個問題類(再次,未完成):
private void initialiseQuestions() {
// TODO Auto-generated method stub
questions = new Vector<Question>(); //Vector containing our questions
try
{
//create an instance of the QuestionHandler class
QuestionHandler handler = new QuestionHandler(getApplicationContext());
//get the string list by calling the public method
ArrayList<TextView> newViews = handler.getData();
//convert to an array
Object[] question = newViews.toArray();
//loop through the items, creating a View item for each
for(int i=0; i<question.length; i++)
{
//add the next question in the list
Question q1 = new Question(question[i]);
q1.addAnswer("Harold Godwin", false);
q1.addAnswer("Edward the Confessor", false);
q1.addAnswer("William the Conqueror", true);
q1.addAnswer("Alfred the Great", false);
questions.add(q1);
//mainLayout.addView((TextView)products[i]);
}
}
catch(Exception pce) { Log.e("AndroidTestsActivity", "PCE "+pce.getMessage()); }
我的主要問題是我真的不明白我在處理程序和initialiseQuestions方法中正在做什么/需要改變什么。 我不知道如何在處理程序中創建字符串(如果你只需要發回一個字符串數組,為什么需要textViews?)我不知道如何在initialiseQuestions中處理數據。 正如您所看到的,initaliseQuestions方法應該使用已解析的XML並使用數據實例化問題對象。
有人能告訴我我需要改變什么嗎?
解析XML確實是一項非常整潔的工作。 有一個非常好的庫Simple XML ,我們可以在Android中輕松使用它。 它是基於注釋的庫,有很好的教程。 最好的是它直接從XML和性能方面返回POJO,這很好。
您需要做的就是為您的XML創建基於注釋的POJO(請參閱網站上的教程)。 使用serializer.read(pojoClassType, xmlStr)
來獲取POJO的對象。
此外,您可以使用Java Generics
概念僅使一個通用方法讀取每個XML文件。 喜歡,
public <T> T parseXML(Class<T> pojoType, String xmlStr){
//your code
}
這就是我使用SAX使它工作的方式。
我為我的調試示例修改了一個XML文件:
<game>
<questions title="History">
<question>
<ask>Who won the Battle of Hastings?</ask>
<answer>Harold Godwinson</answer>
<answer correct="true">William of Normandy</answer>
<answer>Edward the Confessor</answer>
<answer>Harald Hadrada</answer>
</question>
<question>
<ask>French revolution date?</ask>
<answer>January 10th</answer>
<answer correct="true">July 14th</answer>
<answer>September 9th</answer>
<answer>February 20th</answer>
</question>
</questions>
<questions title="Geography">
<question>
<ask>France capital?</ask>
<answer>Montreal</answer>
<answer correct="true">Paris</answer>
<answer>Lyon</answer>
<answer>Barcelona</answer>
</question>
</questions>
</game>
我已按順序放置游戲根標記 ,因為您可以看到,如果您想要多個主題,請使XML有效。
重要提示:我的示例也適用於URL( http://www.macs.hw.ac.uk/~pjbk/quiz/example.xml )。 你只需要取消注釋即可。
Anserw
public class Anserw {
private String content;
private boolean isCorrect;
public Anserw(){}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public boolean isCorrect() {
return isCorrect;
}
public void setCorrect(boolean isCorrect) {
this.isCorrect = isCorrect;
}
}
題
public class Question {
private String ask;
private ArrayList<Anserw> alAnserws;
public Question(){}
public String getAsk() {
return ask;
}
public void setAsk(String ask) {
this.ask = ask;
}
public ArrayList<Anserw> getAlAnserws() {
return alAnserws;
}
public void setAlAnserws(ArrayList<Anserw> alAnserws) {
this.alAnserws = alAnserws;
}
}
QuestionsHandler
public class QuestionsHandler extends DefaultHandler{
private HashMap<String, ArrayList<Question>> hmTitleQuestions;
private String reading;
private String currentTitle;
private Question question;
private ArrayList<Anserw> alAnserws;
private ArrayList<Question> alQuestions;
private Anserw anserw;
public QuestionsHandler(){
hmTitleQuestions = new HashMap<>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(qName.equals("questions")){
currentTitle = attributes.getValue("title");
alQuestions = new ArrayList<>();
}
if(qName.equals("question")){
question = new Question();
}
if(qName.equals("answer")){
anserw = new Anserw();
boolean flag = false;
String correctAttribute = attributes.getValue("correct");
if(correctAttribute != null){
if(correctAttribute.equals("true")){
flag = true;
}
}
anserw.setCorrect(flag);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.equals("questions")){
hmTitleQuestions.put(currentTitle, alQuestions);
}
if(qName.equals("question")){
question.setAlAnserws(alAnserws);
alQuestions.add(question);
}
if(qName.equals("ask")){
question.setAsk(reading);
alAnserws = new ArrayList<>();
}
if(qName.equals("answer")){
anserw.setContent(reading);
alAnserws.add(anserw);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
reading = new String(ch, start, length);
}
public HashMap<String, ArrayList<Question>> getHmTitleQuestions() {
return hmTitleQuestions;
}
}
XMLManager
public final class XMLManager {
public static HashMap<String, ArrayList<Question>> getHmTitleQuestions(){
HashMap<String, ArrayList<Question>> hmTitleQuestions = null;
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
/*
URL url = new URL("http://www.macs.hw.ac.uk/~pjbk/quiz/example.xml");
HttpURLConnection connexion = (HttpURLConnection) url.openConnection();
connexion.connect();
InputSource in = new InputSource(connexion.getInputStream());
*/
QuestionsHandler qHandler = new QuestionsHandler();
/*
* FROM INTERNET XML
*
parser.parse(in, qHandler);
hmTitleQuestions = qHandler.getHmTitleQuestions();
*/
/*
* FROM LOCAL XML TO DEBUG
*/
File file = new File("D:\\Loic_Workspace\\TestGameSAXUrl\\res\\game.xml");
parser.parse(file,qHandler);
hmTitleQuestions = qHandler.getHmTitleQuestions();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return hmTitleQuestions;
}
}
MyMain
public class MyMain {
/**
* @param args
*/
public static void main(String[] args) {
for(String s : XMLManager.getHmTitleQuestions().keySet()){
ArrayList<Question> alQuestions = XMLManager.getHmTitleQuestions().get(s);
ArrayList<Anserw> alAnserws = null;
System.out.println(s);
for(Question q:alQuestions){
System.out.println(q.getAsk());
alAnserws = q.getAlAnserws();
for(Anserw a:alAnserws){
System.out.println("Content anserw : "+a.getContent()+"/"+a.isCorrect());
}
}
}
}
}
History
Who won the Battle of Hastings?
Content anserw : Harold Godwinson/false
Content anserw : William of Normandy/true
Content anserw : Edward the Confessor/false
Content anserw : Harald Hadrada/false
French revolution date?
Content anserw : January 10th/false
Content anserw : July 14th/true
Content anserw : September 9th/false
Content anserw : February 20th/false
Geography
France capital?
Content anserw : Montreal/false
Content anserw : Paris/true
Content anserw : Lyon/false
Content anserw : Barcelona/false
希望能幫助到你 ;-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.