I'm trying to Parse an XML file into a List, however it is only getting the last entry in the XML file. I have a sample below
<?xml version="1.0"?>
<stops>
<stop>
<number>stop_code</number>
<lat>stop_lat</lat>
<lon>stop_lon</lon>
<name>stop_name</name>
</stop>
<stop>
<number>112112</number>
<lat> 51.060931</lat>
<lon>-114.065158</lon>
<name>"CRESCENT HEIGHTS HIGH SCHOOL"</name>
</stop>
<stop>
<number>2110</number>
<lat> 51.082803</lat>
<lon>-114.214888</lon>
<name>"EB CAN OLYMPIC RD#OLYMPIC CE ENTR"</name>
</stop>
.....
<stop>
<number>9988</number>
<lat> 51.047388</lat>
<lon>-114.067770</lon>
<name>"NB 2 ST#6 AV SW"</name>
</stop>
<stop>
<number>9998</number>
<lat> 50.997509</lat>
<lon>-114.013415</lon>
<name>"19 St # 62 Ave SE nb ns"</name>
</stop>
And my pull parser is
ublic class PullParser {
public static final String STOP_NAME = "name";
public static final String STOP_LAT = "lat";
public static final String STOP_LON = "lon";
public static final String NUMBER = "number";
private Stops currentStop = null;
private String currentTag= null;
List<Stops> stops = new ArrayList<Stops>();
public List<Stops> parseXML (Context context) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
InputStream stream = context.getResources().openRawResource(R.raw.stops_xml);
xpp.setInput(stream,null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
handleStartTag(xpp.getName());
} else if (eventType == XmlPullParser.END_TAG) {
currentTag = null;
} else if (eventType == XmlPullParser.TEXT) {
handleText(xpp.getText());
}
eventType = xpp.next();
}
} catch (Resources.NotFoundException e) {
Log.d(MainActivity.TAG, e.getMessage());
} catch (XmlPullParserException e) {
Log.d(MainActivity.TAG, e.getMessage());
} catch (IOException e) {
Log.d(MainActivity.TAG, e.getMessage());
}
return stops;
}
private void handleText(String text) {
String xmlText = text;
if (currentStop != null && currentTag != null) {
if (currentTag.equals(STOP_NAME)) {
currentStop.setName(xmlText);
}
else if (currentTag.equals(STOP_LAT)) {
currentStop.setLat(xmlText);
}
else if (currentTag.equals(STOP_LON)) {
currentStop.setLon(xmlText);
}
else if (currentTag.equals(NUMBER)) {
currentStop.setNumber(xmlText);
}
}
}
private void handleStartTag(String name) {
if (name.equals("stop")) {
currentStop = new Stops();
stops.add(currentStop);
}
else {
currentTag = name;
}
}
}
When I run this it only returns a stop number of 9998 for all 5882 entries (That is the correct number of entries in the file). Any thing obvious that I'm missing?
MyXmlPullParser objMyXmlPullParser = new MyXmlPullParser(context);
List<Map<String , String>> list = objMyXmlPullParser.readXml("Xml respose put here", "Table");
public class MyXmlPullParser
{
Context _context ;
public MyXmlPullParser(Context _context)
{
this._context = _context ;
}
public List<Map<String , String>> readXml(String XmlString , String ParentTag)
{
Map<String , String > map = new HashMap<String, String>();
List<Map<String , String >> list = new ArrayList<Map<String , String >>();
try
{
String Tag = "" ;
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader (XmlString));
int eventType = xpp.getEventType();
while (true)
{
if(eventType == XmlPullParser.START_TAG)
{
Tag = xpp.getName();
}
else if(eventType == XmlPullParser.END_TAG)
{
Tag = "" ;
if(xpp.getName().equals(ParentTag))
{
list.add(map);
map = new HashMap<String, String>();
}
}
else if(eventType == XmlPullParser.TEXT)
{
String text = xpp.getText();
if(!Tag.equals("") && !Tag.equals(ParentTag))
{
map.put(Tag, text);
}
}
else if(eventType == XmlPullParser.END_DOCUMENT)
{
System.out.println("End document");
break ;
}
eventType = xpp.next();
}
}
catch (XmlPullParserException e)
{
Log.e("xml reader" , "error in parsing xml");
return null ;
}
catch (IOException e)
{
Log.e("xml reader" , "error in IO in xml");
return null ;
}
return list ;
}
Hope it may helps you
Related
i want to parse xml data in spinner, i already make a getter and setter for the data, here is xml data that i get from URL,
<response>
<result>
<foods>
<food>
<id>01</id>
<name>Pizza</name>
<price>20</price>
</food>
</foods>
</result>
</response>
how to parse list of XML data in spinner?
First of all, create a POJO class for food:
public class Food {
public String id, name, price;
}
private void parseXML(String urlResponse) {
XmlPullParserFactory parserFactory;
try {
parserFactory = XmlPullParserFactory.newInstance();
XmlPullParser parser = parserFactory.newPullParser();
InputStream is = new ByteArrayInputStream(urlResponse.getBytes());
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(is, null);
processParsing(parser);
} catch (XmlPullParserException e) {
} catch (IOException e) {
}
}
private void processParsing(XmlPullParser parser) throws IOException, XmlPullParserException{
ArrayList<Food> foods = new ArrayList<>();
int eventType = parser.getEventType();
Food currentFood = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
String eltName = null;
switch (eventType) {
case XmlPullParser.START_TAG:
eltName = parser.getName();
if ("food".equals(eltName)) {
currentFood = new Food();
foods.add(currentFood);
} else if (currentFood != null) {
if ("name".equals(eltName)) {
currentFood.name = parser.nextText();
} else if ("id".equals(eltName)) {
currentFood.id = parser.nextText();
} else if ("price".equals(eltName)) {
currentFood.price = parser.nextText();
}
}
break;
}
eventType = parser.next();
}
printFoods(foods);
}
I'm trying to parse XML from URL and not getting any data, when I debug I see that I'm stuck in the while() loop. The variable i came up to 160 before I gave up. I don't get why I'm stuck in the while loop and not getting into any of the if statements in the loop.
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
public Task()
{
}
#Override
protected Void doInBackground(Void... params) {
makeTask();
return null;
}
public Task(String title){
mTitle = title;
}
private List<Task> makeTask(){
int i = 0;
tasks = new ArrayList<>();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream stream = url.openStream();
xpp.setInput(stream, null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
}
else if (eventType == XmlPullParser.END_DOCUMENT) {
}
else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("Task")) {
tasks.add(new Task(xpp.nextText()));
Log.d("Task: ", xpp.nextText());
}
else if (eventType == XmlPullParser.END_TAG) {
}
else if (eventType == XmlPullParser.TEXT) {
}
eventType = xpp.next();
}
i++;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return tasks;
}
Edit:
This is the new while() loop and working thanks to #imsiso
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.nextText()));
}
eventType = xpp.next();
}
else
eventType = xpp.next();
The line below in the code List<Task> tasks = task.getTasks(); is giving error:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
I'm think that I'm getting that error because I'm not waiting for the AsyncTask to finish and don't know how I should do that.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*Removed irrelevant code here*/
Task task = new Task();
new Task().execute();
List<Task> tasks = task.getTasks();
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
return view;
}
Here's an example TaskLoader and Callback for Loader.
private LoaderManager.LoaderCallbacks<List<TaskModel>> mLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<TaskModel>>()
{
#Override
public Loader<List<TaskModel>> onCreateLoader(int id, Bundle args)
{
return new TaskLoader(getContext());
}
#Override
public void onLoadFinished(Loader<List<TaskModel>> loader, List<TaskModel> data)
{
mTaskRV.setAdapter(new TaskAdapter(data));
}
#Override
public void onLoaderReset(Loader<List<TaskModel>> loader)
{
//
}
};
And the TaskLoader.
private static class TaskLoader extends AsyncTaskLoader<List<TaskModel>>
{
private static final String TAG = TaskLoader.class.getSimpleName();
private List<TaskModel> mData = null;
public TaskLoader(Context context)
{
super(context);
}
#Override
protected void onStartLoading()
{
super.onStartLoading();
if(mData != null){
deliverResult(mData);
}
if(takeContentChanged() || mData == null){
forceLoad();
}
}
#Override
public void deliverResult(List<TaskModel> data)
{
mData = data;
super.deliverResult(data);
}
#Override
public List<TaskModel> loadInBackground()
{
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream in = null;
try{
in = url.openStream();
xpp.setInput(in, "UTF-8");
return parseTasks(xpp);
}
finally{
if(in != null){
in.close();
}
}
}
catch(MalformedURLException e){
Log.e(TAG, "loadInBackground", e);
}
catch(XmlPullParserException e){
Log.e(TAG, "loadInBackground", e);
}
catch(IOException e){
Log.e(TAG, "loadInBackground", e);
}
return null;
}
private List<TaskModel> parseTasks(XmlPullParser xpp)
throws XmlPullParserException, IOException
{
ArrayList<TaskModel> tasks = new ArrayList<>();
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
if(xpp.getName().equalsIgnoreCase("description")){
tasks.add(new TaskModel(xpp.nextText()));
}
}
eventType = xpp.next();
}
return tasks;
}
}
You should provide a listener to the async task that will be triggered when the doInBackground() completes. For instance:
public interface TaskListener{
public void onTaskDone(List<Task> results);
}
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
private TaskListener mListener;
public Task(TaskListener listener)
{
this.mListener = listener;
}
protected Void doInBackground(Void... params) {
.... xml parsing...
if (mListener != null){
mListener.onTaskDone(tasks);
}
}
}
and when you create the task:
Task task = new Task(this);
letting the class implementing the TaskListener interface.
In this method you provide the task's result to the adapter.
public void onTaskDone(final List<Task> tasks){
runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
}
});
}
First let's use this for while which is more clear. And using get text should be better cause it can avoid jumping over a tag or such in other cases.
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.getText()));
}
}
eventType = xpp.next();
}
And a out that error in List<Task> tasks = task.getTasks(); This should help https://stackoverflow.com/a/218510/2226796
Also I didn't get this part :
Task task = new Task();
new Task().execute();
org.xmlpull.v1.XmlPullParserException: read end tag key with no tags open (position:END_TAG #1:7 in java.io.InputStreamReader#83d457b)
Android 6.0 (API 23)
What's wrong in xml? Or what else could be the reason of that exception?
If i'm not mistaken #1:7 is row 1 and symbol 7 in this row (or may be reverse line 7). But i didn't find what's wrong in this xml.
Thank you very much!
<plist version="1.0">
<dict>
<key>Golfs</key>
<array>
<dict>
<key>GLF_COD</key>
<string>0661</string>
<key>GLF_LIB</key>
<string>AA SAINT OMER GOLF CLUB</string>
<key>GLF_ADR_1</key>
<string>Chemin des Bois</string>
<key>GLF_ADR_2</key>
<string/>
<key>GLF_CPO</key>
<string>62380</string>
<key>GLF_DIS</key>
<string>ACQUIN WESTBECOURT</string>
public class ClubCategoriesInflater extends XMLInflater<List<ClubCategory>> {
#Override
protected void onInflate(List<ClubCategory> clubCategories, InputStream stream) {
int START_NUMBER = 2;
int arrayTagNumber = 0;
ClubCategory clubCategory = null;
XmlPullParser parser = getParser();
if (parser!=null){
String startTag = null;
String lastKey = null;
try {
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_TAG) {
startTag = parser.getName();
if ("array".equals(startTag)){
arrayTagNumber++;
}
if ("dict".equals(startTag)){
clubCategory = new ClubCategory();
}
} else if(eventType == XmlPullParser.END_TAG) {
startTag = null;
if (arrayTagNumber==START_NUMBER){
if ("dict".equals((parser.getName()))){
clubCategories.add(clubCategory);
}
if ("array".equals((parser.getName()))){
return;
}
}
} else if(arrayTagNumber==START_NUMBER && startTag!=null && eventType == XmlPullParser.TEXT) {
if (key.equals(startTag)){
lastKey = parser.getText();
}else if (string.equals(startTag)){
if ("id".equals(lastKey)){
clubCategory.id = Integer.valueOf(parser.getText());
}
else if ("name".equals(lastKey)){
clubCategory.name = parser.getText();
}
}
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Link to that xml
https://esplic-ws1.ffgolf.org/iphone/get_golfs_plist.php?av=1.2&sv=6.0&sn=Android%20OS&su=c19f0b9cc0a3c911&sl=en&sm=Nexus+7
I have used Ksoap2 to connect to this .NET web service and i get a xml response when i enter the users id. I only want to see two tags callTitle and callDescription. I don't need the rest and want to see in text not surround with xml code. can some one please help? I can't find tutorial online.
public class AndroidWebService extends Activity {
/** Called when the activity is first created. */
private static String SOAP_ACTION = "http://tempuri.org/GetHelpDeskCalls";
private static String NAMESPACE = "http://tempuri.org/";
private static String METHOD_NAME = "GetHelpDeskCalls";
static final String URL = "https:/192.2344.123:8080/Service1.asmx";
Button getData;
EditText userID;
TextView data;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.helpdesk);
getData = (Button) findViewById(R.id.button1);
userID = (EditText) findViewById(R.id.txtFar);
data = (TextView) findViewById(R.id.textView1);
Thread nT = new Thread() {
#Override
public void run() {
getData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SoapObject request = new SoapObject(NAMESPACE,
METHOD_NAME);
request.addProperty("userID", userID.getText()
.toString());
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
envelope.dotNet = true;
HttpTransportSE androidHttpTransport = new HttpTransportSE(
URL);
try {
androidHttpTransport.debug = true;
androidHttpTransport.call(SOAP_ACTION, envelope);
final String results = androidHttpTransport.responseDump
.toString();
runOnUiThread(new Runnable() {
public void run() {
data.setText(results.toString());
}
});
} catch (Exception e) {
data.setText("Error" + e);
}
}
});
}
};
nT.start();
}
}
you should parse your XML with the help of xml pull parser
Following code will guide you for doing so
MyXmlPullParser objMyXmlPullParser = new MyXmlPullParser(context);
List<Map<String , String>> list = objMyXmlPullParser.readXml("Xml respose put here", "Table");
public class MyXmlPullParser
{
Context _context ;
public MyXmlPullParser(Context _context)
{
this._context = _context ;
}
public List<Map<String , String>> readXml(String XmlString , String ParentTag)
{
Map<String , String > map = new HashMap<String, String>();
List<Map<String , String >> list = new ArrayList<Map<String , String >>();
try
{
String Tag = "" ;
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader (XmlString));
int eventType = xpp.getEventType();
while (true)
{
if(eventType == XmlPullParser.START_TAG)
{
Tag = xpp.getName();
}
else if(eventType == XmlPullParser.END_TAG)
{
Tag = "" ;
if(xpp.getName().equals(ParentTag))
{
list.add(map);
map = new HashMap<String, String>();
}
}
else if(eventType == XmlPullParser.TEXT)
{
String text = xpp.getText();
if(!Tag.equals("") && !Tag.equals(ParentTag))
{
map.put(Tag, text);
}
}
else if(eventType == XmlPullParser.END_DOCUMENT)
{
System.out.println("End document");
break ;
}
eventType = xpp.next();
}
}
catch (XmlPullParserException e)
{
Log.e("xml reader" , "error in parsing xml");
return null ;
}
catch (IOException e)
{
Log.e("xml reader" , "error in IO in xml");
return null ;
}
return list ;
}
Hope it may helps you
Is there a standard xml parser in android, where i can put any standard link for the RSS and it will give me the result? i found an example but i must specify the path for the items.
Some thing like this link
http://www.rssboard.org/files/sample-rss-2.xml
try {
URL conn = new URL("http://www.rssboard.org/files/sample-rss-2.xml");
XmlParserHelper helper = new XmlParserHelper(conn.openStream(), "rss");
final String TITLES = "language";
XmlParseObject object = helper.createObject(TITLES, "//channel//item//title");
object.setParseAttributes();
object.setParseContent();
Map<String, List<XmlObject>> results = helper.parse();
List<XmlObject> titlesList = results.get(TITLES);
for (XmlObject title : titlesList) {
Log.d("Guid:", title.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
public class XmlParserHelper
{
protected String mRootName = "";
protected InputStream mXmlStream = null;
protected List<XmlParseObject> mParseList = new ArrayList<XmlParseObject>();
/**
* Initialize xml helper with file stream
* #param xmlStream input xml stream
*/
public XmlParserHelper(InputStream xmlStream, String rootName)
{
this.mXmlStream = xmlStream;
this.mRootName = rootName;
}
/**
* Point parse all attributes for XPath
* #param objectName key for attributes list in response
* #param XPath path to tag
*/
public void createAttributesObject(String objectName, String XPath)
{
XmlParseObject currentObject = new XmlParseObject(objectName, XPath);
currentObject.setParseAttributes();
mParseList.add(currentObject);
}
public void createContentObject(String objectName, String XPath)
{
XmlParseObject currentObject = new XmlParseObject(objectName, XPath);
currentObject.setParseContent();
mParseList.add(currentObject);
}
public XmlParseObject createObject(String objectName, String XPath)
{
XmlParseObject currentObject = new XmlParseObject(objectName, XPath);
mParseList.add(currentObject);
return currentObject;
}
public Map<String, List<XmlObject>> parse() throws Exception
{
if (mRootName.equals(""))
{
throw new Exception("Root tag must be defined");
}
RootElement root = new RootElement(mRootName);
for (XmlParseObject parselable : mParseList)
{
parselable.configurateListenersForRoot(root);
}
try {
Xml.parse(mXmlStream, Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
Map<String, List<XmlObject>> result = new HashMap<String, List<XmlObject>>();
for (XmlParseObject parselable : mParseList)
{
result.put(parselable.getName(), parselable.getResults());
}
return result;
}
}
URL url = new URL("http://www.rssboard.org/files/sample-rss-2.xml");
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(url.openConnection().getInputStream(), "UTF_8");
//xpp.setInput(getInputStream(url), "UTF-8");
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, etc..
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("item")) {
insideItem = true;
} else if (xpp.getName().equalsIgnoreCase("title")) {
if (insideItem)
headlines.add(xpp.nextText()); //extract the headline
} else if (xpp.getName().equalsIgnoreCase("link")) {
if (insideItem)
links.add(xpp.nextText()); //extract the link of article
}
}else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
insideItem=false;
}
eventType = xpp.next(); //move to next element
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Modify the above according to your needs. I have used a XmlPullParser.