0

Why the code below works when I parse a StringReader, but not an InputStream from a file located in the internal memory, even though the file has exactly the same data from the String used before (commented in code)? The parser reaches EOF right after the second line. When I use the String, it goes all the way to the end. The variable linha is just to see, during debugging, what line is being parsed and when I use the InputStream approach, the parser reaches EOF in line 2 of the file.

    public boolean read(){
    boolean ret = false;
    try{
        InputStream is =  mContext.openFileInput(fileName);



        if(is!=null) {

            XmlPullParserFactory xmlFactoryObject = XmlPullParserFactory.newInstance();
            XmlPullParser myparser = xmlFactoryObject.newPullParser();
            xmlFactoryObject.setNamespaceAware(true);
            myparser.setInput(is,null); //or myparser.setInput(is,"utf-8");
            int event;
            String name = null;
            boolean sai = false;
            event=myparser.getEventType();
            do{
                linha = myparser.getLineNumber();
               if ((event == XmlPullParser.START_TAG)
                   &&((name=myparser.getName()).equals("list-of-commands")))
                       sai = true;
               else
                    event = myparser.next();
            }while(!sai && event!= XmlPullParser.END_DOCUMENT);
            if((name!=null) && myparser.getAttributeValue(null,"machine").equals(modelName)){
                MachineCommand novoParam = null;
                int itemCount = 0;
                while (event != XmlPullParser.END_DOCUMENT) {
                    linha = myparser.getLineNumber();
                    name = myparser.getName();
                    switch (event) {
                        case XmlPullParser.START_TAG:
                            if (name.equals("param")) {
                                itemCount = 0;
                                int numComando =
                                        Integer.parseInt(myparser.getAttributeValue(null,"num_command"));
                                int numParam =
                                        Integer.parseInt(myparser.getAttributeValue(null,"num_param"));
                                novoParam =
                                        ((MachineCommand) progMenu.getExpandableListAdapter()
                                                .getChild(numComando, numParam))
                                                .deepClone(mContext);
                                novoParam.setNumCommand(numComando);
                                novoParam.setNumParam(numParam);
                            } else if (name.equals("spinner")) {
                                int selected =
                                   Integer.parseInt(myparser.getAttributeValue(null,"selected_pos"));
                                Spinner sp = (Spinner)novoParam.getValueAt(itemCount++);
                                sp.setSelection(selected);
                            } else if (name.equals("EditTextNoKB")) {
                                String text = myparser.nextText();
                                EditTextNoKB et = (EditTextNoKB)novoParam.getValueAt(itemCount++);
                                et.setText(text);
                            }
                            break;
                        case XmlPullParser.END_TAG:
                            if (name.equals("param")) {
                                ((ArrayAdapter<MachineCommand>)(dslvProgList.getAdapter())).add(novoParam);
                            }
                    }
                    event = myparser.next();
                }
                if(dslvProgList.getCount()>0) ret = true;
            }
        }
    }catch(Exception e) {
        e.printStackTrace();
        ret = false;
    }


    return ret;

}

The xml file to be parsed is below:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<list-of-commands machine="1005" version="1.0.0">
  <param num_command="0" num_param="0">Velocidade<EditTextNoKB>6</EditTextNoKB></param>
  <param num_command="0" num_param="2">Sentido<Spinner selected_pos="1">Anti-horário</Spinner></param>
  <param num_command="0" num_param="5">Zerar Contador</param>
  <param num_command="0" num_param="1">Desacelerar<EditTextNoKB>69</EditTextNoKB>voltas</param>
  <param num_command="2" num_param="4">Aguardar Liberar</param>
</list-of-commands>

EDIT: As pointed in the comments below, I could state the problem is in the write procedure of the file. Maybe some invalid char? Here is the code used to create the file in the internal memory:

    public boolean write(){
    try {
        FileOutputStream fos = mContext.openFileOutput(fileName, Context.MODE_PRIVATE);


        XmlSerializer serializer = Xml.newSerializer();
        serializer.setOutput(fos, "utf-8");
        serializer.startDocument("utf-8", true);
        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

        serializer.startTag(null, "list-of-commands");
        serializer.attribute(null, "machine", modelName);  //TO DO: Estes dois atributos devem ser
        serializer.attribute(null,"version","1.0.0"); //definidos em arquivo de configuração

        for(int i=0; i<dslvProgList.getCount()-1; i++){
            MachineCommand com = (MachineCommand)dslvProgList.getItemAtPosition(i);
            serializer.startTag(null,"param");
            serializer.attribute(null, "num_command", com.getStringNumCommand());
            serializer.attribute(null,"num_param",com.getStringNumParam());
            serializer.text(com.getName());
            for (int j=0; j<com.getNumOfValues(); j++){
                View v = com.getValueViewAt(j);
                if(v instanceof EditTextNoKB){
                    serializer.startTag(null, "EditTextNoKB");
                    serializer.text(((EditTextNoKB)v).getText().toString());
                    serializer.endTag(null, "EditTextNoKB");
                }
                else if(v instanceof Spinner){
                    serializer.startTag(null, "Spinner");
                    int selectedPos = ((Spinner) v).getSelectedItemPosition();
                    serializer.attribute(null, "selected_pos", String.valueOf(selectedPos));
                    serializer.text(((Spinner) v).getItemAtPosition(selectedPos).toString());
                    serializer.endTag(null, "Spinner");
                }
            }
            serializer.text(com.getUnity());
            serializer.endTag(null, "param");
        }
        serializer.endTag(null, "list-of-commands");
        serializer.endDocument();

        serializer.flush();

        fos.close();
    }catch (Exception e){
        return false;
    }
    return true;
}
  • Which condition is responsible for the early finish when u debug the code? I used XmlPull years ago the last time before I got to know ORM. Now I use the library XStream which rapidly minimized code to parse XML. There are many more ORM libraries out there. – OneWorld Mar 01 '15 at 07:07
  • It reaches END_DOCUMENT condition, even though it is parsing the second line of xml, like the xml is made of only those two lines. Curious thing is that parsing the a String that doesn't happen. I use Xmlpullparser in another code, and there everything works fine. The difference is that in that other code I parse a file from assets, so it is opened using Context.getAssets().open(file); – Eduardo Tavares Mar 01 '15 at 13:27
  • Write yourself debug code to see what's XmlPull Parser input. Like instead of your switch construct, just print the parsers content using getText. See http://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html for the full API. Also try to write the content of the InputStream into a String to see if the stream works. Rephrase your question with your newest findings to attract more users to your question. – OneWorld Mar 01 '15 at 13:49
  • @OneWorld: Curious behavior here. When I tried to put the content of InputStream into a String, it stops at the second line as well. The file in the internal memory, when opened in the notepad, for example, is complete. It was created by my app using XmlSerializer serializer = Xml.newSerializer(); serializer.setOutput(fos, "UTF-8"); serializer.startDocument("UTF-8", true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); to improve readability. Could this be inserting any not recognizable char at the end of the line? – Eduardo Tavares Mar 01 '15 at 14:25
  • Try to learn how others read xml files with this parser. here somebody uses a different input stream in one of the answers: https://www.google.de/url?sa=t&source=web&rct=j&ei=tyXzVJPeDsW3PPXIgOAH&url=http://stackoverflow.com/questions/15698237/xmlpullparser-get-file-from-filesystem&ved=0CBwQFjAA&usg=AFQjCNHFk3QPsGsFBPwAhh-Qa8CIauL7FQ&sig2=yFTHRr2oJJ8caHNSiYjHyg – OneWorld Mar 01 '15 at 14:53
  • Oh, I'm not sure I got your last tip, but just to make clear, if I put the same xml file in my assets folder and open it using InputStream is = mContext.getAssets().open("teste.wprx"); it is parsed all the way to the end. As I pointed out with the tests above, it is not the parser, but the InputStream that comes incomplete when I get a File from the internal memory. Very strange. I'm completely lost as I can't find any reference to this kind of issue... – Eduardo Tavares Mar 01 '15 at 15:30
  • UPDATE: the problem is in the file created by the app. To test it in assets I copied the contents and pasted in a new file in assets. That worked. Then I got this new created file (in assets) and put it in the internal memory. It worked too. So, the original file created by app has some invalid char, I guess, that is corrected when I copy paste the contents of that file. I'll do more tests. – Eduardo Tavares Mar 01 '15 at 15:54
  • Since this is no more an issue of reading the file it's better to delete this question and to open a new question about the invalid created file if you need further help there. – OneWorld Mar 01 '15 at 17:22

1 Answers1

0

Turns out it was just something really stupid. The whole problem was my encoding string: "UTF-8". The right one would be "utf-8" (NO CAPITALS). It was wrong on writing and reading. I'll edit the code to reflect the right one. @OneWorld: Thank you and you are right, the issue is on writing and then reflects on reading. Do you think I should delete this question, or should I leave it here as answered, so other people can benefit of it? As it was a silly mistake, I'm not sure I should keep it. I'm new here, so I ask for your tip on this.