Android - using parsed xml data to update SQLite - android

just a reminder that I'm a noob so maybe my question is fairly stupid...
Anyway I'm using SAX to parse an XML file and I can correctly loop through the items and print their contents to the log. What I'd need though is for this parser to return a multidimensional associative array that I can iterate through and subsequently use to update an SQLite database...
Question(s):
Does such a thing exist in Android? Should I be using some other datatype instead? How is it done?
I'll include some code of the parser (the endElement method does the printing to log, so far it has one element per item but that will change, hence the need for multidimensional):
private boolean in_image = false;
private boolean in_homeimage = false;
StringBuilder sb;
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
for (int i=start; i<start+length; i++) {
sb.append(ch[i]);
}
//super.characters(ch, start, length);
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if( localName.equals("image") && this.in_homeimage ){
this.in_homeimage = false;
Log.i("Extra", "Found homeimage: " + sb);
}
else if( localName.equals("image") ){
this.in_image = false;
Log.i("Extra", "Found image: " + sb);
}
//super.endElement(uri, localName, qName);
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
sb = new StringBuilder();
if( localName.equals("image") && attributes.getValue("name") == "home" )
this.in_homeimage = true;
else if( localName.equals("image") )
this.in_image = true;
//super.startElement(uri, localName, qName, attributes);
}
Thanks in advance

Related

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 SAXParser Leftovers

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);}}};
}

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);
}

featching cat_desc according cat_name from xml

I have to display cat_name in listview and when i click any name it will display it's cat_description. my url is http://mobileecommerce.site247365.com/admin/catdata.xml
I can able to display name in listview.My problem is i parse whole cat_desc but i want particular cat_desc according to cat_name.if any one have an idea for this?
I use
if(currenttag.equals("Cat_Desc"))
sitesList.setCat_Desc(String.valueOf(ch,start,length));
For set cat_desc. but it will set all cat_desc but i want specific cat_desc.
When i fetching cat_desc i use sitelist.getcatdesc().size().It will show me approximately 4500.
If any one having any solution or give me solution for this.
My Handler-
public void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException
{
currenttag=localName;
if(currenttag.equals("NewDataSet")) {
currentElement =true;
sitesList = new SitesList();
}
}
public void endElement(String uri, String localName, String qName)throws SAXException
{
super.endElement(uri, localName, qName);
if(qName.equals("NewDataSet"))
{
currentElement = false;
}
}
public void characters(char[] ch, int start, int length)throws SAXException
{
if(currenttag.equals("Cat_Name"))
sitesList.setCat_Name(String.valueOf(ch,start,length));
else if(currenttag.equals("Cat_Desc"))
sitesList.setCat_Desc(String.valueOf(ch,start,length));
java class--
for (int i = 0; i less than sitesList.getCat_Name().size(); i++)
catNames[i]=sitesList.getCat_Name().get(i);
for(int j=0; j less than sitesList.getCat_Desc().size();j++)
catdesc[j]=sitesList.getCat_Desc().get(j);
Thanks and Regards
Arpit
If I'm understanding you correctly, you can modify this code:
else if(currenttag.equals("Cat_Desc"))
sitesList.setCat_Desc(String.valueOf(ch,start,length));
To this
else if(currenttag.equals("Cat_Desc")){
sitesList.setCat_Desc(String.valueOf(ch,start,length));
if(currentCat.equals("desired_cat"){
specialDescription = String.valueOf(ch,start,length);
Where specialDescription is a field (instance variable) in your SaxParser class.

Android SAX parser not getting full text from between tags

I've created my own DefaultHandler to parse rss feeds and for most feeds it's working fine, however, for ESPN, it is cutting off part of the article url due to the way ESPN formats it's urls. An example of a full article url from ESPN..
http://sports.espn.go.com/nba/news/story?id=5189101&campaign=rss&source=ESPNHeadlines
The problem is for some reason the DefaultHandler characters method is only getting this from the tag that contains the above url.
http://sports.espn.go.com/nba/news/story?id=5189101
As you can see, it's cutting everything off the url from the ampersand escape code and after. How can I get the SAX parser to not cut my string off at this escape code? For ref. here is my characters method..
public void characters(char ch[], int start, int length) {
String chars = (new String(ch).substring(start, start + length));
try {
// If not in item, then title/link refers to feed
if (!inItem) {
if (inTitle)
currentFeed.title = chars;
} else {
if (inLink)
currentArticle.url = new URL(chars);
if (inTitle)
currentArticle.title = chars;
if (inDescription)
currentArticle.description = chars;
if (inPubDate)
currentArticle.pubDate = chars;
if (inEnclosure) {
}
}
} catch (MalformedURLException e) {
Log.e("RSSReader", e.toString());
}
}
Rob W.
As you can see, it's cutting
everything off the url from the
ampersand escape code and after.
From the documentation of the characters() method:
The Parser will call this method to
report each chunk of character data.
SAX parsers may return all contiguous
character data in a single chunk, or
they may split it into several chunks;
however, all of the characters in any
single event must come from the same
external entity so that the Locator
provides useful information.
When I write SAX parsers, I use a StringBuilder to append everything passed to characters():
public void characters (char ch[], int start, int length) {
if (buf!=null) {
for (int i=start; i<start+length; i++) {
buf.append(ch[i]);
}
}
}
Then in endElement(), I take the contents of the StringBuilder and do something with it. That way, if the parser calls characters() several times, I don't miss anything.
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
sb=new StringBuilder();
if(localName.equals("icon"))
{
iconflag=true;
}
}
#Override
public void characters (char ch[], int start, int length) {
if (sb!=null && iconflag == true) {
for (int i=start; i<start+length; i++) {
sb.append(ch[i]);
}
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if(iconflag)
{
info.setIcon(sb.toString().trim());
iconflag=false;
}
}
So I figured it out, the code above is the solution.
I ran into this problem the other day, it turns out the reason for this is the CHaracters method is being called multiple times in case any of these Characters are contained in the Value:
" "
' &apos;
< <
> >
& &
Also be careful about Linebreaks / newlines within the value!!!
If the xml is linewrapped without your controll the characters method wil also be called for each line that is in the statement, plus it will return the linebreak! (which you manually need to strip out in turn).
A sample Handler taking care of all these problems is this one:
DefaultHandler handler = new DefaultHandler() {
private boolean isInANameTag = false;
private String localname;
private StringBuilder elementContent;
#Override
public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
if (qname.equalsIgnoreCase("myfield")) {
isInMyTag = true;
this.localname = localname;
this.elementContent = new StringBuilder();
}
}
public void characters(char[] buffer, int start, int length) {
if (isInMyTag) {
String content = new String(ch, start, length);
if (StringUtils.equals(content.substring(0, 1), "\n")) {
// remove leading newline
elementContent.append(content.substring(1));
} else {
elementContent.append(content);
}
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qname.equalsIgnoreCase("myfield")) {
isInMyTag = false;
// do something with elementContent.toString());
System.out.println(elementContent.toString());
this.localname = "";
}
}
}
I hope this helps.

Categories

Resources