Android: обработчик возвращает синтаксический анализ пустой строки с помощью SAX Parser - PullRequest
0 голосов
/ 25 августа 2011

Я пытался использовать синтаксический анализатор SAX на Android для отображения некоторого xml, который является результатом запроса к БД.

Я получаю правильный ответ из БД, но когда я хочу проанализировать xml и вывести содержимое в текстовое представление, ExampleHandler (ParsedExampleDataSet) возвращает Object с пустой строкой. Я пытался выяснить, где проблема, но она ускользает от меня.

Пока я знаю, что данные правильно анализируются в методе символов, мне удалось распечатать содержимое в файл журнала, но я не могу вернуть строку в этот момент.

Я уверен, что более опытные программисты могли бы исправить это очень легко:

Мой XML-файл довольно простой, <body> blablablah </body>.

Вот файлы:

 package com.ignacio.BilingualSTT;

 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import android.util.Log;
 import org.apache.http.HttpResponse;
 import org.apache.http.NameValuePair;  
 import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.ByteArrayBuffer;
 import org.xml.sax.InputSource;
 import org.xml.sax.XMLReader;
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.TextView;
 import android.widget.Toast;

public class PostAndGet extends Activity {

    private static String Utterance = null;
    TextView Title;
    TextView Content;
    private static final String TAG = "TextToSpeechDemo";
    String text;

    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.en_results);
            Title = (TextView)findViewById(R.id.A1_title);
            Content= (TextView) findViewById(R.id.A1_content);
            text = "";

            Bundle b = this.getIntent().getExtras();
            if (b !=null){
                    Utterance = b.getString("query");
            }
            postData(Utterance);
    }

    /**
 * Handle the action of the Back button
 */

public void sendback(View v)
{
    Intent Sendback=new Intent(this, EnglishRecognizer.class);
            startActivity(Sendback);
}

/**
 * Start HTTP Post call
 */

public void postData(String Utterance){
            // Create a new HttpClient and Post Header
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("http://hcc.cs.clemson.edu/~ignm/ignacio/Android_QueryResults.php");  

            try {
                    // Add data to the HTTP Request data has to be named query since the PHP page in the server is expecting that name to run the query on the DB
                    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);  
                    nameValuePairs.add(new BasicNameValuePair("query", Utterance));
                    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

                    // Execute HTTP Post Request and retrieve answer from PHP side.
                    HttpResponse response = httpclient.execute(httppost);
                    InputStream is = response.getEntity().getContent();
                    BufferedInputStream bis = new BufferedInputStream(is);
                    ByteArrayBuffer baf = new ByteArrayBuffer(20);
                    int current = 0;

                    while((current = bis.read()) != -1){
                            baf.append((byte)current);
                    }  

                    // Convert the Bytes read to a String and display it in the Title Container
                    text = new String(baf.toByteArray());
                    Title.setText(text);

                    //Send Text to
                    parseXML (text);


            } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    Toast.makeText(this, "Error in the connection", Toast.LENGTH_SHORT).show();
            } catch (IOException e) {
                    // TODO Auto-generated catch block
                    Toast.makeText(this,"IO Exception error", Toast.LENGTH_SHORT).show();
            }
    }


public void parseXML (String text){

    String AnswerExt = text;

    try {
            /* Create a URL we want to load some xml-data from. */
            URL url = new URL("http://hcc.cs.clemson.edu/~ignm/ignacio/"+AnswerExt.toString());

            Log.i(TAG, url.toString());

            /* Get a SAXParser from the SAXPArserFactory. */
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();

            /* Get the XMLReader of the SAXParser we created. */
            XMLReader xr = sp.getXMLReader();
            /* Create a new ContentHandler and apply it to the XML-Reader*/
            ExampleHandler myExampleHandler = new ExampleHandler();
            xr.setContentHandler(myExampleHandler);

            /* Parse the xml-data from our URL. */
            xr.parse(new InputSource(url.openStream()));
            /* Parsing has finished. */

            /* Our ExampleHandler now provides the parsed data to us. */
            ParsedExampleDataSet parsedExampleDataSet = myExampleHandler.getParsedData();


            /* Set the result to be displayed in our GUI. */
            Content.setText(parsedExampleDataSet.getExtractedString());


    } catch (Exception e) {
             /* Display any Error to the GUI. */
             Content.setText("Error: " + e.getMessage());
             Log.e(TAG, "QueryError", e);
    }
}
}

Пример обработчика, модифицированный для анализа моего xml.

 package com.ignacio.BilingualSTT;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler; 
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;

public class ExampleHandler extends DefaultHandler{

    // ===========================================================
    // Fields
    // ===========================================================

    private boolean bodytag = false;
    private static final String TAG = "TextToSpeechDemo";

    public ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();
    public String myReturnString = null;

    // ===========================================================
    // Getter & Setter
    // ===========================================================

    public ParsedExampleDataSet getParsedData() {  
            return this.myParsedExampleDataSet;
    }

    // ===========================================================
    // Methods
    // ===========================================================
    @Override
    public void startDocument() throws SAXException {
            this.myParsedExampleDataSet = new ParsedExampleDataSet();
    }

    @Override
    public void endDocument() throws SAXException {
            // Nothing to do
    }

    /** Gets be called on opening tags like:
     * <tag>
     * Can provide attribute(s), when xml was like:
     * <tag attribute="attributeValue">*/
    @Override
    public void startElement(String namespaceURI, String localName,
                    String qName, Attributes atts) throws SAXException {
            if (localName.equals("body")) {
                    this.bodytag = true;
            }
    }

    /** Gets be called on closing tags like:
     * </tag> */
    @Override
    public void endElement(String namespaceURI, String localName, String qName)
                    throws SAXException {
            if (localName.equals("body")) {
                    this.bodytag = false;
            }
    }

    /** Gets be called on the following structure:
     * <tag>characters</tag> */
    @Override
public void characters(char ch[], int start, int length) {
            if(this.bodytag){
            myParsedExampleDataSet.setExtractedString(new String(ch, start, length));
            //String Temp = myParsedExampleDataSet.getExtractedString();
            //Log.i(TAG, Temp);      
    }
    }

 }

ParsedExampleDataSet:

 package com.ignacio.BilingualSTT;

  public class ParsedExampleDataSet {
    private String extractedString = "No content yet";

    public String getExtractedString() {
            return extractedString;
    }
    public void setExtractedString(String extractedString) {
            this.extractedString = extractedString;
    }      
    public String toString(){
            return this.extractedString;
    }
 }

Спасибо большое !!!

1 Ответ

0 голосов
/ 25 августа 2011

Метод characters может вызываться несколько раз во время нахождения внутри тега, особенно если значение элемента содержит пробелы.

Вы можете увидеть, что это происходит в этом вызове Logcat по нескольким строкам.напечатано.

Из документации :

Этот анализатор вызовет этот метод, чтобы сообщить о каждом фрагменте символьных данных.Синтаксические анализаторы SAX могут возвращать все смежные символьные данные в одном фрагменте или могут разбивать их на несколько фрагментов;однако все символы в любом отдельном событии должны исходить из одной и той же внешней сущности, чтобы локатор предоставлял полезную информацию.

Вместо того, чтобы использовать setExtractedString, вы должны добавить к строящейся строке,возможно используя StringBuilder.

См. принятый ответ здесь .

...