Tech Technology Tech Technology - 2 months ago 7
Android Question

How to parse xml data in ArrayList

I need to parse xml data in android. I have seen this project: here from github which teaches how to parse xml data in listbox. However, I want to get xml data to different strings. Although, I have used pretty much the same code as in the github project but I only get error and the app stops responding.

Code:

public class Main extends Fragment {
android.view.View myview;
EditText number;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myview = inflater.inflate(R.layout.fragment_screen, container, false);
number = (EditText) myview.findViewById(R.id.number);
XmlParser par = new XmlParser();
number.setText(par.getStackSitesFromFile(getActivity().getBaseContext())
.get(0).getLink()); **Error here**
return myview;
}
}


XmlParser.java

public class XmlParser {
static final String KEY_SITE = "rate";

static final String KEY_NAME = "Name";

static final String KEY_LINK = "Rate";

static final String KEY_ABOUT = "Date";

static final String KEY_IMAGE_URL = "Time";



public static List<HandleXML> getStackSitesFromFile(Context ctx) {
// List of StackSites that we will return

List<HandleXML> stackSites;

stackSites = new ArrayList<HandleXML>();

// temp holder for current StackSite while parsing

HandleXML curStackSite = null;

// temp holder for current text value while parsing

String curText = "";
try {

// Get our factory and PullParser

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

XmlPullParser xpp = factory.newPullParser();
// Open up InputStream and Reader of our file.

FileInputStream fis = ctx.openFileInput("/sdcard/rates.xml");

BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
// point the parser to our file.

xpp.setInput(reader);
// get initial eventType

int eventType = xpp.getEventType();
// Loop through pull events until we reach END_DOCUMENT

while (eventType != XmlPullParser.END_DOCUMENT) {

// Get the current tag

String tagname = xpp.getName();
// React to different event types appropriately

switch (eventType) {

case XmlPullParser.START_TAG:

if (tagname.equals("test")) {
curStackSite = new HandleXML();
}
break;
case XmlPullParser.TEXT:
//grab the current text so we can use it in END_TAG event
curText = xpp.getText();
break;
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase("test")) {
stackSites.add(curStackSite);
} else if (tagname.equalsIgnoreCase(KEY_NAME)) {
curStackSite.setName(curText);
} else if (tagname.equals("Rate")) {
curStackSite.setLink(curText);
} else if (tagname.equalsIgnoreCase(KEY_ABOUT)) {
curStackSite.setAbout(curText);
} else if (tagname.equalsIgnoreCase(KEY_IMAGE_URL)) {
curStackSite.setImgUrl(curText);
}
break;
default:
break;
}
eventType = xpp.next();
}
} catch (Exception e) {
e.printStackTrace();
}


// return the populated list.
return stackSites;
}
}


And finally, HandleXml.java

public class HandleXML {
private String name;
private String rate;
private String date;
private String time;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getLink() {
return rate;
}

public void setLink(String rate) {
this.rate = rate;
}

public String getAbout() {
return date;
}

public void setAbout(String date) {
this.date = date;
}

public String getImgUrl() {
return time;
}

public void setImgUrl(String time) {
this.time = time;
}

@Override
public String toString() {
return name + rate;
}
}


Xml File:

<?xml version="1.0" encoding="UTF-8"?>
<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="1" yahoo:created="2016-09-07T05:50:08Z" yahoo:lang="en-US">
<results>
<test>
<Name>EUR/USD</Name>
<Rate>1.1251</Rate>
<Date>9/7/2016</Date>
<Time>0:56am</Time>
</test>
<test>
<Name>EUR/USD</Name>
<Rate>1.1253</Rate>
<Date>9/7/2016</Date>
<Time>0:56am</Time>
</test>
</results>
</query>


The error is in the first fragment of code in:
number.setText(par.getStackSitesFromFile(getActivity().getBaseContext()).get(0).getLink());

Answer

The arraylist returns empty because FileInputStream fis is set to open a file which contains path separator (/) , and it causes

java.lang.IllegalArgumentException: File /sdcard/rates.xml contains a path separator

. You have to use FileInputStream fis = new FileInputStream (new File("/sdcard/rates.xml")); instead. Do not forget to close fis by fis.close();

Final code for XmlParser will be:

public class XmlParser {
static final String KEY_SITE = "rate";

static final String KEY_NAME = "Name";

static final String KEY_LINK = "Rate";

static final String KEY_ABOUT = "Date";

static final String KEY_IMAGE_URL = "Time";

FileInputStream fis;


public static List<HandleXML> getStackSitesFromFile() {
    // List of StackSites that we will return

    List<HandleXML> stackSites;

    stackSites = new ArrayList<HandleXML>();

    // temp holder for current StackSite while parsing

    HandleXML curStackSite = null;

    // temp holder for current text value while parsing

    String curText = "";
    try {

        // Get our factory and PullParser

        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

        XmlPullParser xpp = factory.newPullParser();
        // Open up InputStream and Reader of our file.

        fis =  new FileInputStream(new File("/sdcard/rates.xml"));

        BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
        // point the parser to our file.

        xpp.setInput(reader);
        // get initial eventType

        int eventType = xpp.getEventType();
        // Loop through pull events until we reach END_DOCUMENT

        while (eventType != XmlPullParser.END_DOCUMENT) {

            // Get the current tag

            String tagname = xpp.getName();
            // React to different event types appropriately

            switch (eventType) {

            case XmlPullParser.START_TAG:

                if (tagname.equals("test")) {
                    curStackSite = new HandleXML();
                }
                break;
            case XmlPullParser.TEXT:
                //grab the current text so we can use it in END_TAG event
                curText = xpp.getText();
                break;
            case XmlPullParser.END_TAG:
                if (tagname.equalsIgnoreCase("test")) {
                    stackSites.add(curStackSite);
                } else if (tagname.equalsIgnoreCase(KEY_NAME)) {
                    curStackSite.setName(curText);
                } else if (tagname.equals("Rate")) {
                    curStackSite.setLink(curText);
                } else if (tagname.equalsIgnoreCase(KEY_ABOUT)) {
                    curStackSite.setAbout(curText);
                } else if (tagname.equalsIgnoreCase(KEY_IMAGE_URL)) {
                    curStackSite.setImgUrl(curText);
                }
                break;
            default:
                break;
            }
            eventType = xpp.next();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        fis.close();
    }catch(Exception e){
        Log.i("Problem closing", "Closing fis");
    }


    // return the populated list.
    return stackSites;
}
}

And then set number.setText() like that: number.setText(par.getStackSitesFromFile().get(0).getLink());