Android SAXParser Leftovers - android

I have an Android app that parses XML using SAXParser. Everything goes ok, excepting some texts that get duplicated and trimmed. For example: "Just do it, even if you do not know how!" becomes " not know how!"
This is the DefaultHandler code. 10x!
DefaultHandler handler = new DefaultHandler()
{
Praise praise;
String elementValue = null;
Boolean elementOn = false;
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
if (localName.equals("praise"))
{
praise = new Praise();
elementOn = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException
{
// elementOn = false;
if (localName.equals("PRAISE_TEXT"))
{
praise.setPraiseText(elementValue);
}
if (localName.equals("MOOD"))
{
praise.setMood(elementValue);
}
if (localName.equals("RATING"))
{
praise.setRating(Integer.valueOf(elementValue));
}
if (localName.equals("praise"))
{
elementOn = false;
if (update)
{
if (database.getPraiseByText(praise.getPraiseText(), db) == null)
{
database.addPraise(db, praise.getPraiseText(), praise.getMood(),
Integer.valueOf(praise.getRating()));
}
}
else
database.addPraise(db, praise.getPraiseText(), praise.getMood(),
Integer.valueOf(praise.getRating()));
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException
{
// StringBuffer b = new StringBuffer();
if (elementOn)
{
elementValue = new String(ch, start, length);}}};

In SaxParsing, you do not have guarantee that characters will be called only once!
For this, you should concatenate all the characters you receive withing the same element
This is a just your code with a small modification. You should use StringBuilder instead of using String (:
DefaultHandler handler = new DefaultHandler()
{
Praise praise;
String elementValue = null;
Boolean elementOn = false;
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
elementValue = new String();
if (localName.equals("praise"))
{
praise = new Praise();
elementOn = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException
{
if (localName.equals("PRAISE_TEXT"))
{
praise.setPraiseText(elementValue);
}
if (localName.equals("MOOD"))
{
praise.setMood(elementValue);
}
if (localName.equals("RATING"))
{
praise.setRating(Integer.valueOf(elementValue));
}
if (localName.equals("praise"))
{
elementOn = false;
if (update)
{
if (database.getPraiseByText(praise.getPraiseText(), db) == null)
{
database.addPraise(db, praise.getPraiseText(), praise.getMood(),
Integer.valueOf(praise.getRating()));
}
}
else
database.addPraise(db, praise.getPraiseText(), praise.getMood(),
Integer.valueOf(praise.getRating()));
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException
{
// StringBuffer b = new StringBuffer();
if (elementOn)
{
elementValue = elementValue + new String(ch, start, length);
}
}
};

This problem often comes in SaxParsing. The Actual problem is it breaks the String by "/n" & only last part of String is available for us.
Now come to the solution, Take different booleans for tags(containing problems or for all).
In startElement method make relevent boolean true.
if (localName.equals("PRAISE_TEXT"))
{
isPrase= true'
praise.setPraiseText(elementValue);
}
in endElemet method make relevent boolean false.
if (localName.equals("PRAISE_TEXT"))
{
isPrase= false;
praise.setPraiseText(elementValue);
}
in characters method check for boolean like this:
if(isPrase)
{
elementValue = new String(ch, start, length);}}};
}

Related

How to parse xml having multiple child and in that child there is data?

Here is my xml,
<root>
<child>
<Lunchmenu>
<id>2</id>
<lunch_date>2013-10-24</lunch_date>
<break_name>Lunch</break_name>
<class_id/>
<school_id>1</school_id>
<batch_id/>
</Lunchmenu>
<Eatable>
<id>2</id>
<eatable_name>Apples</eatable_name>
</Eatable>
</child>
<child>
<Lunchmenu>
<id>2</id>
<lunch_date>2013-10-24</lunch_date>
<break_name>Lunch</break_name>
<class_id/>
<school_id>1</school_id>
<batch_id/>
</Lunchmenu>
<Eatable>
<id>3</id>
<eatable_name>Orange</eatable_name>
</Eatable>
</child>
I need to know that, is there any way to parse above xml's child as there are again two separate tags like Lunchmenu and eatable.
I am using sax parser to parse this xml.
I know how to parse single child tag having data and again its iteration, but here I am confused how to do it?
please suggest any solution if anyone knows How to parse it??
thank you
and my parser class is :
SchoolParser.java
public class SchoolParser extends DefaultHandler {
private List<School> schoolListData ;
private boolean isSuccess;
private School school;
StringBuilder tempData;
#Override
public void startDocument() throws SAXException {
super.startDocument();
Log.e("StudentListParser","startDocument");
schoolListData = new ArrayList<School>();
}
public List<School> getSchoolListData(){
return schoolListData;
}
#Override
public void startElement(String uri, String localName, String qName,
org.xml.sax.Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (localName.equals("School")) {
school = new School();
Log.e("SchoolParser", "-----START----");
}
tempData = new StringBuilder();
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
tempData.append(new String(ch, start, length));
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
if(localName.equals("School")){
schoolListData.add(school);
Log.d("localName",localName);
}
else if (localName.equals("id")) {
Log.e("id", localName);
school.id = Integer.parseInt(tempData.toString());
} else if (localName.equals("school_name")) {
school.schoolName = tempData.toString();
Log.e("name", localName);
} else if (localName.equals("logo")) {
school.logo = tempData.toString().getBytes();
Log.e("logo", localName);
}else if (localName.equals("phone")) {
school.phn_no = tempData.toString();
Log.e("phn no", localName);
}
else if (localName.equals("School")) {
Log.e("SchoolParser", "----END---");
}
// int size = buffer.length();
// buffer.delete(0, size);
// Log.i("buffer is empty", ""+buffer.toString());
}
#Override
public void endDocument() throws SAXException {
super.endDocument();
isSuccess = false;
Log.e("StudentListParser", "endDocument");
}
}
May be you can use serialize logic to parse xml to direct java class object.
You can use below class..
package com.lib.android.util;
import java.io.InputStream;
import org.apache.log4j.Logger;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import com.lib.android.util.logger.PLogger;
public class XmlParser
{
private static Logger log = new PLogger(XmlParser.class).getLogger();
public static Object Parse(Class<? extends Object> parseInto, InputStream is)
{
Serializer serializer = new Persister();
try
{
Object obj = serializer.read(parseInto, is);
return obj;
} catch (Exception e)
{
log.error(e.getMessage());
}
return null;
}
}
Hope it will help you..

New to SAX Parser so need this BASIC

if we do this in SAX Parser:
public class SAXXMLHandler extends DefaultHandler {
private List<Employee> employees;
private String tempVal;
private Employee tempEmp;
public SAXXMLHandler() {
employees = new ArrayList<Employee>();
}
public List<Employee> getEmployees() {
return employees;
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// reset
tempVal = "";
if (qName.equalsIgnoreCase("employee")) {
// create a new instance of employee
tempEmp = new Employee();
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("employee")) {
// add it to the list
employees.add(tempEmp);
} else if (qName.equalsIgnoreCase("id")) {
tempEmp.setId(Integer.parseInt(tempVal));
} else if (qName.equalsIgnoreCase("name")) {
tempEmp.setName(tempVal);
} else if (qName.equalsIgnoreCase("department")) {
tempEmp.setDepartment(tempVal);
} else if (qName.equalsIgnoreCase("type")) {
tempEmp.setType(tempVal);
} else if (qName.equalsIgnoreCase("email")) {
tempEmp.setEmail(tempVal);
}
}
}
for this :
<employee>
<id>2163</id>
<name>Kumar</name>
<department>Development</department>
<type>Permanent</type>
<email>kumar#tot.com</email>
</employee>
What we will do in SAX Parser for this :
<MyResource>
<Item>First</Item>
<Item>Second</Item>
</MyResource>
I am a newbie to SAX Parser.
Previously i had problems with DOM and PullParser for the same XML.
Isn't there any parser built for parsing this simple XML.
To parse an entry named MyResource that contains multiple entry of Item you can do something like that :
At first, initialize your variables inside the startDocument method to allow the reuse of your Handler :
private List<MyResource> resources;
private MyResource currentResource;
private StringBuilder stringBuilder;
public void startDocument() throws SAXException {
map = null;
employees = new ArrayList<Employee>();
stringBuilder = new StringBuilder();
}
Detect inside of startElement when a MyResource is starting. The tag name will usually be stored inside the qName argument.
When a MyResource is starting, you may want to create an instance of MyResource as a temporary variable. You will feed it until its end tag is reached.
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("MyResource".equals(qName)) {
currentResource = new MyResource();
}
stringBuilder.setLength(0); // Reset the string builder
}
The characters method is required to read the content of each tag.
Use StringBuilder to read characters. SAX may call more than once the characters method for each tag :
public void characters(char[] ch, int start, int length) throws SAXException {
stringBuilder.append(ch, start, length);
}
Inside the endElement, create a new Item each time the closed tag is named item AND a MyResource is being created (i.e. you have an instance of MyResource somewhere).
When the closed tag is MyResource, add it to a list of results and clean the temporary variable.
public void endElement(String uri, String localName, String qName) throws SAXException {
if("MyResource".equals(qName)) {
resources.add(currentResource);
currentResource = null;
} else if(currentResource != null && "Item".equals(qName)) {
currentResource.addItem(new Item(stringBuilder.toString()));
}
}
I am assuming that you have a List of Item inside MyResource.
Don't forget to add a method to retrieve the resources after the parse :
List<MyResources> getResources() {
return resources;
}

Android: How to parse same tags in SAX Parser?

I am trying to parse and get values from web service. The problem is that Web service has same element name tags which are creating problem to parse as I want to get their value but they are of same name So is difficult for me to mention them as localname.
<countryBean>
<id>236</id>
<name>United State</name>
</countryBean>
<secutiryQuestion1>
<id>2</id>
<question>What was your dream job as a child?</question>
</secutiryQuestion1>
<secutiryQuestion2>
<id>4</id>
<question>What is the name, breed, and color of your pet?</question>
</secutiryQuestion2>
<stateBean>
<country>236</country>
<id>5</id>
<name>California</name>
</stateBean>
<statusBean>
<id>1</id>
<name>Active</name>
</statusBean>
I want to get value of ID tag and other adjacent tag like name,question in different variables. and Here are 5 Id tags.
My class code is like
public class XmlParser extends DefaultHandler {
public RestfullResponse tempResponse = null;
String currentValue = null;
int ServiceType =0;
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(localName.equalsIgnoreCase("countryBean")){
tempResponse=new RestfullResponse();
}
}
/* (non-Javadoc)
* #see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(ServiceType == 1)
{
if(localName.equalsIgnoreCase("id")){
tempResponse.setCountryId(currentValue);
}
if(localName.equalsIgnoreCase("name")){
tempResponse.setCountryName(currentValue);
}
if(localName.equalsIgnoreCase("id")){
tempResponse.setStateId(currentValue);
}
if(localName.equalsIgnoreCase("question")){
tempResponse.setstateBean(currentValue);
}
if(localName.equalsIgnoreCase("Id")){
tempResponse.setStatusId(currentValue);
}
if(localName.equalsIgnoreCase("requestSuccess")){
tempResponse.setStatus(currentValue);
}
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
currentValue = new String(ch, start, length);
}
public RestfullResponse getResponse(){
return tempResponse;
}
}
please Help to store them in
String CountryName= "";
String CountryId = "";
String Statename = "";
String StateId ="";
String Status = "";
String StatusId = "";
String Username ="";
String SecurityQuestion = "";
String SecurityQuestionId = "";
Add boolean variable isCountryBean;
boolean isCountryBean = false , isSecurityQuestion1 = false;
And in startElement(....) write:
if(localName.equalsIgnoreCase("countryBean")){
isCountryBean = true;
// other stuff
} else if (localName.equalsIgnoreCase("secutiryQuestion1")){
isSecurityQuestion1 = true;
isCountryBean = false;
}
And in endElement(...) check:
if(localName.equalsIgnoreCase("id")){
if(isCountryBean){
tempResponse.setCountryId(currentValue);
}
}
if(localName.equalsIgnoreCase("name")){
if(isCountryBean){
isCountryBean = false;
tempResponse.setCountryName(currentValue);
}
}
Do it for other most outward tags. Hope it will help you.
You need to maintain the stack of root nodes.
Take a variable of type String root and maintain a stack of root element.
Inside startElement method:
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException,
IllegalArgumentException
{
// call to abstract method
onStartElement(namespaceURI, localName, qName, atts);
// Keep the trace of the root nodes
if (root.length() > 0)
{
root= root.concat(",");
}
root= root.concat(localName);
}
Inside endElement method:
public void endElement(String namespaceURI, String localName, String qName) throws SAXException
{
// remove the end element from stack of root elements
int index = root.lastIndexOf(',');
if (index > 0)
{
root= root.substring(0, index);
}
onEndElement(namespaceURI, localName, qName);
}

parsing huge length string using sax parser in android

I parsing the xml using sax parser in android. My xml structure is as given below
<customerlist>
<Customer>
<customerId>2</customerId>
<customerFname>prabhu</customerFname>
<customerLname>kumar</customerLname>
<customerImage>
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABHNCSVQICAgIfAhkiAAACJ9JREFUaIHtmllsXFcZx3/n3Due8XgcO3a8xG72tGkTknRJG7qAaEtbhFjVJUpBoBahgkoRUCFe+lCJvkAKCGgFPJQK0VKWqIhShMhL0mahLU1ImjZp0ziZLN5dezxje5Z7z/l4uDOOl9mcOskLf+vTle79fM63nPM/53xn4P+4tFDzrDffkEoKpQxTgAZcoCYvzpT3FxKWwHAD5PLiT3k/DW6JRjQQAupuuadx/VWbYk9b5dcg+uJkQlnR4uaOvjn28J7ticPAOOARODVdtUQTYaDu+7/86GONLfqbvvUiF9DcknB1KJMYtL/a9shrTxA4kWNGFkploAaoa1+t7mxfWhcRqTgULwiUUpG+02N3Aj8jyEBupk4xBxRBBmLJVEqiEznEWgBEBI8MYVVbdHYpFEZ8tNIUT65CrAEFSjmAxZcsIRUp3p7WJFNZAWJAOi/+VJ1SE9IBQmKsgwGsAgth3cCVTZ9FRIFViBXESjC9rCKTG+MjLfcRdRZjJ7+d0/P8LEsab6YxshxjfMK6gU9f/hS+tfk+ZogBMdYhmI8FEpmGcpO4xs8pba1grQCWzcsfYVH0ckbHexkcP8K1nV+jNbaWfad+zliml8+seYpoaCEnh3ZzZfMXuKzhBg50P8v69nuJ1SzmpSPfwPiGnJ+jM7aZtW1fpCW6FusJ6Nk50Br8nNIEQ7posEtlQEGet0QQEayxdMQ2se/U06xsvh3P5NjQvpUzI6+zsul2Wus3MjT+PuO5IXybZVnjzYxMxLFiibhNdCf307HgBqI1bcTcdm5c+m26R/fjKBfBTvYzU+wMm+bkQDaXYiKTJJ1JIlaTM0lWNt7GFc2fIuZ2MJB6l8M9L+JZD7GKkx/sYTDVRSY7Qcab4N8nf01qYpDB1HFOD7+OlhqyuVE8P4OIomvwFTw/O9nHTJnIJMnmUlNtqnoIAbChfQurlrVjjUcs0kEy3cuZ0TdYuehWbln5XerDHVy/5AHaF1xNrdPA+sX3oHFRQHPdajYv/TqezXJ151Y2dNzLW90vsDC6irHcAErB1mtfIKQj3Ljs4fyknhFdreia6AO2lbSxOFVAB7B4//7/Prdx4/o1xsxaPy4KHMfh0KHD71133TVfBnqBQWZQaYVtgS3/+aKgvA1lh5CIYG0wwS4Fqum7rANwjoUuBarpt6wDxhistVh76YZSpflXMQNQXSQuFSo6MJ8ZUCqgcpHq2gv0y6MsC8135K21ZPzROf1PJRsqnq4KGZgP8UyavfEfEeyvyusqpfA8j1gs1lBfXx8qZd9FYyGlVDAklINCTbYpMzbSBb2xsTF6enro7e11CQJddDyVdcDzvEkm+jBwdASXEFkzhuenGcmcIqwXUBdqQQDfpid1tdb09PTQ399PLBYD8H3fh/PZC31YKDQoxenRvZxK7KQ79QYT3iBnj76GVmE6Y5tYsfBWVjTeBiiEYPgMDw+jdTC6RUSLSCEDc3PAGDO5GpeHENJhjPWx+eKBq2s53P8HDvb/jpxJnXMIhZGg2BBPvMqpxKvs1j/m+sUPcVXr3QiGbDaL67po5VQsrMxLicRVYU6Pvs64N4RWLq6KcHp0L/vOPEnWT+a70QggYvnY0sf4xLLHQRSCxjMT7DmzjUQ6jkITCoXIeR4D40cZzZ4t60LFvZAxpuJqaMjQFt3Ie8Mv0538D2GnnmMf/A1HR2EWCSjiiVfQSiOBRygctGj+dHgLd699nivWrObZXQ8yMjSGzjSXXQzmiYUEUKxv2UJbbCMvHrkfV0colf/4yE5AcHRtEADxcHSEj1/2KCKGZKYbZ1GcsFXE3z47lslk/HxjVRe2gHNrQDU0Kgi+8Xl34K84EsEzaRQurqqZRZWaoMzkmzSOruWOFU8iWPbEn2DCJNiybjvt4evRzYdo6bRTq3KzDKm4Ele7BigU49l+TgzvxEiOdS1baa1bh7FZRJghFovhsvqbuXPVTzmZ2MWO44+SNuNoQhzqf57rFj+Eby3KmTS8qCFV0Wg164BCEx/dTSrTS0hHyPnjGONN61aweGaCNYs+x7qWeznY91v+dex7CIImPKn7Tt+fqXWaaIqspts/CGVONRVZqFS1YFb1QIRUti8oWukQx4b+zgcTx0DVBPyOwVERNrR9hVUL72Lv6SeJJ3ZPDi+Z8uc6Ed4Z3M6G9vtR0wM/tzlQWAOqywBY6wexUoKTj6iIh+NEuabtAcJuI28NPMc7A39BowKdok1rcjZFOpvgjhXb+AX3lex33krlglAXaseK5AesYMSjvqaTu1b9BKVcdp18fJLrJR/bUgKaQ/3PYWRaJXFuK7Hv+3M4EwtLGm6irqaF8dwgrdH13LLsB5wc3sk/3v0WILiqNp+VakKiSOdG2Bn/YVmted2N1jmtLG/4JNFQE50LNrMz/jgj6RPU6DrO75JHIbOvBKZh3uaAo2tAFJs7v8OLR7/E/t5ncHAIqeh5b8eV5AvEZTAvu1GlHPpShzibfI0lDTfSWreOROZEsJW4wKiYganPYtBoDvT8hsMDf8TVtRwZ2s7nr3iGjDdCd/JNlDp/nhCBCgkoz0KFCVye/2Eo/T5KhYLmxOFg3++5uu1BLFJkFZ6DWCoWB0s5MOl3ZQcMa1u25HsEJYoTwzs4PrKDluhVGJMtzZXVyjmbqt4LCQTF1cIZtbTAkoabWNl0B6IEFLhOLceH/8nGtq+indC5s9QcRcFU8prTXsgAmQMHDox0dXUlfd/XgBKRElyoEFnO290vTWtirPllrGyma3gHag40KiBoRCtsZlxGgAxFrliDnou/a8rLJmA50AhECO6qLgY8AqMTQBx4ExgGkvlv04wthhhQB7QCC4B6gpvL2bcQFwYGyAIpAqMHCO6Jx6nynrgQgWGCq80kgfEX+mcGBVgCJwpXqxlmRL6AUhnQBAa7U54X43cSBRROYD6BI4XnLFL9H0iaJNCEw0eHAAAAAElFTkSuQmCC
</customerImage>
</Customer>
</customerlist>
I am able to get customerId, customerFname, customrLname, but for customerImage I am not getting complete string I am only getting part of the string i.e (iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABHNCSVQICAgIfAhkiAAACJ9JREFUaIHtmllsXFcZx3/n3Due8XgcO3a8xG72tGkTknRJG7qAaEtbhFjVJUpBoBahgkoRUCFe+lCJvkAKCGgFPJQK0VKWqIhShMhL0mahLU1ImjZp0ziZLN5dezxje5Z7z/l4uDOOl9mcOskLf+vTle79fM63nPM/53xn4P+4tFDzrDffkEoKpQxTgAZcoCYvzpT3FxKWwHAD5PLiT3k/DW6JRjQQAupuuadx/VWbYk9b5dcg+uJkQlnR4uaOvjn28J7ticPAOOARODVdtUQTYaDu+7/86GONLfqbvvUiF9DcknB1KJMYtL/a9shrTxA4kWNGFkploAaoa1+t7mxfWhcRqTgULwiUUpG+02N3Aj8jyEBupk4xBxRBBmLJVEqiEznEWgBEBI8MYVVbdHYpFEZ8tNIUT65CrAEFSjmAxZcsIRUp3p7WJFNZAWJAOi/+VJ1SE9IBQmKsgwGsAgth3cCVTZ9FRIFViBXESjC9rCKTG+MjLfcRdRZjJ7+d0/P8LEsab6YxshxjfMK6gU9f/hS+tfk+ZogBMdYhmI8FEpmGcpO4xs8pba1grQCWzcsfYVH0ckbHexkcP8K1nV+jNbaWfad+zliml8+seYpoaCEnh3ZzZfMXuKzhBg50P8v69nuJ1SzmpSPfwPiGnJ+jM7aZtW1fpCW6FusJ6Nk50Br8nNIEQ7posEtlQEGet0QQEayxdMQ2se/U06xsvh3P5NjQvpUzI6+zsul2Wus3MjT+PuO5IXybZVnjzYxMxLFiibhNdCf307HgBqI1bcTcdm5c+m26R/fjKBfBTvYzU+wMm+bkQDaXYiKTJJ1JIlaTM0lWNt7GFc2fIuZ2MJB6l8M9L+JZD7GKkx/sYTDVRSY7Qcab4N8nf01qYpDB1HFOD7+OlhqyuVE8P4OIomvwFTw/O9nHTJnIJMnmUlNtqnoIAbChfQurlrVj
)
My xmlHandler code is below
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
import com.bvbi.invoicing.client.android.customer.model.CustomerPojoInList;
public class CustomerListParser extends DefaultHandler {
Boolean currentElement = false;
String tempValue = null;
CustomerPojoInList customer = null;
public static ArrayList<CustomerPojoInList> customers = null;
#Override
public void startDocument() throws SAXException {
customers = new ArrayList<CustomerPojoInList>();
}
/** Called when tag starts ( ex:- <name>AndroidPeople</name>
* -- <name> )*/
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentElement = true;
if (localName.equals("Customer"))
{
/** Start */
customer = new CustomerPojoInList();
}
}
/** Called when tag closing */
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
currentElement = false;
String currentValue = tempValue;
tempValue = "";
/** set value */
if (localName.equalsIgnoreCase("customerId"))
customer.setCustomerId(currentValue.toString());
else if (localName.equalsIgnoreCase("customerFname"))
customer.setCustomerFname(currentValue.toString());
else if (localName.equalsIgnoreCase("customerLname"))
customer.setCustomerLname(currentValue.toString());
else if (localName.equalsIgnoreCase("customerImage"))
{
Log.d("prabhu","Customer image in parser......"+currentValue);
customer.setCustomerImage(currentValue.toString());
}
else if (localName.equalsIgnoreCase("Customer"))
customers.add(customer);
}
/** Called to get tag characters */
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (currentElement) {
tempValue = new String(ch,start, length);
if(tempValue.equals(null))
tempValue = "";
currentElement = false;
}
}
#Override
public void endDocument() throws SAXException {
}
}
Please help me to fix the issue.
In sax parser, characters() method parses only maximum of 1024 characters each time. So we need to append the strings until all the characters are parsed.
I changed the above code as follows
public void characters(char[] ch, int start, int length)
throws SAXException
{
Log.d("prabhu","Customer image length in parser......"+length);
if (currentElement ) {
tempValue = new String(ch,start, length);
if(tempValue.equals(null))
tempValue = "";
}
tempValue = tempValue+new String(ch,start, length);
}
The output you posted is exactly 1024 characters. This looks like a certain buffer size. How do you get this output? Maybe check that method and / or your CustomerPojoInList.
I very much believe, that there is some buffer involved that has a maximum of 1024 characters...
Good luck!
first time post. Updated answer with something that might help others. I hope it is not too specific to my particular problem. I am parsing an RSS feed that I create myself with a really long description but the other tags you are interested in, i.e. feed title, date and URL are always short. The description contains information about social events. Within the description, I use tags that I later parse to give me information about the event such as event date (different from RSS pubDate), (Location), (ticketDetails), (Phone), etc, you get the idea.
A good way to handle this is with a slight modification of the answer in this post. I added tags to the description for (Event) and (EndEvent) and I keep appending to my String Builder until I get "(EndEvent)". That way i know i have the full string. It might not work for your situation if you dont control the feed unless you know there is always a certain string at the end of your RSS description.
Posting in case this (cough, hack) helps anyone. Code is as follows:
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
strBuilder = new StringBuilder();
if ("item".equals(qName)) {
currentItem = new RssItem();
} else if ("title".equals(qName)) {
parsingTitle = true;
} else if ("link".equals(qName)) {
parsingLink = true;
}
else if ("pubDate".equals(qName)) {
parsingDate = true;
}
else if ("description".equals(qName)) {
strBuilder = new StringBuilder(); //reset the strBuilder variable to null
parsingDescription = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
String descriptionTester = strBuilder.toString();
if ("item".equals(qName)) {
rssItems.add(currentItem);
currentItem = null;
} else if ("title".equals(qName)) {
parsingTitle = false;
} else if ("link".equals(qName)) {
parsingLink = false;
}
else if ("pubDate".equals(qName)) {
parsingDate = false;
}
//else
// currentItem.setDescription(descriptionTester);
else if ("description".equals(qName) && descriptionTester.contains("(EndEvent)")) {
parsingDescription = false;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (strBuilder != null) {
for (int i=start; i<start+length; i++) {
strBuilder.append(ch[i]);
}
}
if (parsingTitle) {
if (currentItem != null)
currentItem.setTitle(new String(ch, start, length));
parsingTitle = false;
}
else if (parsingLink) {
if (currentItem != null) {
currentItem.setLink(new String(ch, start, length));
parsingLink = false;
}
}
else if (parsingDate) {
if (currentItem != null) {
currentItem.setDate(new String(ch, start, length));
parsingDate = false;
}
}
else if (parsingDescription) {
if (currentItem != null && strBuilder.toString().contains("(EndEvent)" )) {
String descriptionTester = strBuilder.toString();
currentItem.setDescription(descriptionTester);
parsingDescription = false;
}
}
}
As I said, hope that helps someone as I was stumped on this for a while!

selecting specific xml tags with SAX parser

I'm designing an App for android and I need to parse an XML file, I've been told SAX parsers are better for mobile devices to I've been trying to use it but I've gotten stuck. Here is the XML code:
<current_conditions>
<condition data="Clear"/>
<temp_f data="50"/>
<temp_c data="10"/>
<humidity data="Humidity: 76%"/>
<icon data="/ig/images/weather/sunny.gif"/>
<wind_condition data="Wind: NE at 14 mph"/>
</current_conditions>
<forecast_conditions>
<day_of_week data="Tue"/> ****
<low data="43"/>
<high data="64"/> ****
<icon data="/ig/images/weather/mostly_sunny.gif"/>
<condition data="Mostly Sunny"/>
</forecast_conditions>
<forecast_conditions>
<day_of_week data="Wed"/>
<low data="43"/>
<high data="64"/>
<icon data="/ig/images/weather/sunny.gif"/>
<condition data="Clear"/>
</forecast_conditions>
I am trying to get values of only the two tags with * by the side but it returns the values at the end of the document instead. How do I solve this problem as I only want certain values in the XML. Here is my code:
public class ExampleHandler extends DefaultHandler {
private boolean in_in_current_conditions = false;
private boolean in_in_forecast_conditions = false;
private ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();
public ParsedExampleDataSet getParsedData() {
return this.myParsedExampleDataSet;
}
#Override
public void startDocument() throws SAXException {
this.myParsedExampleDataSet = new ParsedExampleDataSet();
}
#Override
public void endDocument() throws SAXException {
}
#Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException
{
if (localName.equals("forecast_information"))
{
this.in_forecast_information = true;
}
else if (localName.equals("current_conditions"))
{
this.in_in_current_conditions = true;
}
else if (localName.equals("forecast_conditions"))
{
this.in_in_forecast_conditions = true;
}
else if (localName.equals("high")) {
if (this.in_in_forecast_conditions)
{
String attrValue = atts.getValue("data");
myParsedExampleDataSet.setCurrtempValue(attrValue);
}
} else if (localName.equals("day_of_week")) {
if (this.in_in_forecast_conditions) {
String attrValue1 = atts.getValue("data");
myParsedExampleDataSet.setLowValue(attrValue1);
}
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (localName.equals("forecast_information")) {
this.in_forecast_information = false;
} else if (localName.equals("current_conditions")) {
this.in_in_current_conditions = false;
} else if (localName.equals("forecast_conditions")) {
this.in_in_forecast_conditions = false;
}
}
#Override
public void characters(char ch[], int start, int length) {
}
}
If I were you then I would just use the Simple XML framework to do the XML parsing work for you. It would not be too difficult then to just create a few objects that could tease this data out of the XML.
P.S. I use the Simple project for all my XML so I even wrote a blog post explaining how to use it in Android projects: you can read it here.
To get those two values you would do something like this:
public class ExampleHandler extends DefaultHandler {
private static final String FORECAST_CONDITION = "forecast_condition";
private boolean day_of_week_dataWanted = false;
private boolean high_dataWanted = false;
private ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();
public ParsedExampleDataSet getParsedData() {
return this.myParsedExampleDataSet;
}
public ExampleHandler() {
this.myParsedExampleDataSet = new ParsedExampleDataSet();
}
#Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
if(FORECAST_CONDITION.equals(localName)){
if("day_of_week".equals(localName)){
day_of_week_dataWanted = true;
}
if("high".equals(localName)){
high_dataWanted = true;
}
}
}
#Override
public void characters(char ch[], int start, int length) {
if(day_of_week_dataWanted){
myParsedExampleDataSet.setLowValue(new String(ch, start, length));
day_of_week_dataWanted = false;
}
if(high_dataWanted){
myParsedExampleDataSet.setCurrtempValue(new String(ch, start, length));
high_dataWanted = false;
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
}
}
But there are more graceful solutions you could look at, hopefully this gives you a hint.
I've sorted this by using populating the values in Arrays and when I want to display them I simple use their position in the array to call them

Categories

Resources