簡體   English   中英

使用SAX在Android中解析XML

[英]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 )。 你只需要取消注釋即可。

JAVA CLASSES

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM