So I've got to parse ugly files that contain nested tags like
<p>blah<strong>lah</strong>blah</p>
The nested tags are defined and I don't care about them. But they make XmlPullParser fail:
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(some_reader);
while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (XmlPullParser.START_TAG == event) {
String tag = parser.getName();
if (tag != null) {
tag = tag.toLowerCase();
} else {
continue;
}
if ("p".equals(tag)) {
String text = parser.nextText();
// and here we go
// org.xmlpull.v1.XmlPullParserException: expected: /p read: strong
}
}
}
Question: any chance I could get away w/o preprocessing the file stripping all the unnecessary tags or using a third-party library?
EDIT:
Updated the snippet to actually make sense.
So I've got rid of XMLPullParser and switched to SAXParser. Besides, it performs better.
package com.xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
public class FeedHandler extends DefaultHandler {
StringBuilder sb = null;
String ret = "";
boolean bStore = false;
int howMany = 0;
FeedHandler() { }
String getResults()
{
return "XML parsed data.\nThere are [" + howMany + "] status updates\n\n" + ret;
}
#Override
public void startDocument() throws SAXException
{
// initialize "list"
}
#Override
public void endDocument() throws SAXException
{
}
#Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
try {
if (localName.equals("status"))
{
this.sb = new StringBuilder("");
bStore = true;
}
if (localName.equals("user"))
{
bStore = false;
}
if (localName.equals("text"))
{
this.sb = new StringBuilder("");
}
if (localName.equals("created_at"))
{
this.sb = new StringBuilder("");
}
} catch (Exception e)
{
Log.d("error in startElement", e.getStackTrace().toString());
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException
{
if (bStore)
{
if (localName.equals("created_at"))
{
ret += "Date: " + sb.toString() + "\n";
sb = new StringBuilder("");
return;
}
if (localName.equals("user"))
{
bStore = true;
}
if (localName.equals("text"))
{
ret += "Post: " + sb.toString() + "\n\n";
sb = new StringBuilder("");
return;
}
}
if (localName.equals("status"))
{
howMany++;
bStore = false;
}
}
#Override
public void characters(char ch[], int start, int length)
{
if (bStore)
{
String theString = new String(ch, start, length);
this.sb.append(theString);
}
}
}
and this my xmlActivity class that extend Activity
InputSource is = new InputSource(getResources().openRawResource(R.raw.my));
System.out.println("running xml file..... ");
// create the factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// create a parser
SAXParser parser = factory.newSAXParser();
// create the reader (scanner)
XMLReader xmlreader = parser.getXMLReader();
// instantiate our handler
FeedHandler fh = new FeedHandler();
// assign our handler
xmlreader.setContentHandler(fh);
// perform the synchronous parse
xmlreader.parse(is);
// should be done... let's display our results
tvData.setText(fh.getResults());
Related
I am creating the recovery of text using XML from a URL. I get the text. But I have a problem.
When the text of an item of the XML is large, in the TextView not shows all text of the XML.
What can be the error?
ACTIVITY
class tareaAsyncHorariosTarifas extends AsyncTask<Void, Void, Void> {
XmlReader helper;
#Override
protected Void doInBackground(Void... params) {
helper = new XmlReader(color);
helper.get();
return null;
}
#Override
protected void onPostExecute(Void result) {
StringBuilder builder = new StringBuilder();
for (HorariosTarifasObj post : helper.posts) {
builder.append(post.getHorarios());
}
if(builder.toString().equals("")) {
horario2.setText("-");
} else {
horario2.setText(Html.fromHtml(builder.toString()));
}
builder = new StringBuilder();
for (HorariosTarifasObj post : helper.posts) {
builder.append(post.getTarifas());
}
if(builder.toString().equals("")) {
tarifa2.setText("-");
} else {
tarifa2.setText(Html.fromHtml(builder.toString()));
}
}
}
XML READER
public XmlReader(String color) {
this.color = color;
}
public void get() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
reader.setContentHandler(this);
InputStream inputStream = new URL(URL + color + ".xml").openStream();
reader.parse(new InputSource(inputStream));
} catch (Exception e) {
}
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currTag = true;
currTagVal = "";
if (localName.equals("color")) {
post = new HorariosTarifasObj();
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
currTag = false;
if(localName.equalsIgnoreCase("horarios")) {
post.setHorarios(currTagVal);
} else if(localName.equalsIgnoreCase("tarifas")) {
post.setTarifas(currTagVal);
} else if (localName.equalsIgnoreCase("color")) {
posts.add(post);
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (currTag) {
currTagVal = currTagVal + new String(ch, start, length);
currTag = false;
}
}
In internet I got a code to download the text of an XML from a URL. The works ok. My problem is that I have to download many XML simultaneously.
I can to improve my code to make downloading faster? thanks
XMLParser
public XmlReader(String monumento) {
this.monumento = monumento;
}
public void get() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
reader.setContentHandler(this);
InputStream inputStream = new URL(URL + monumento + ".xml").openStream();
reader.parse(new InputSource(inputStream));
} catch (Exception e) {
}
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currTag = true;
currTagVal = "";
if (localName.equals("monumento")) {
post = new HorariosTarifasObj();
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
currTag = false;
if(localName.equalsIgnoreCase("horarios")) {
post.setHorarios(currTagVal);
} else if(localName.equalsIgnoreCase("tarifas")) {
post.setTarifas(currTagVal);
} else if (localName.equalsIgnoreCase("monumento")) {
posts.add(post);
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (currTag) {
currTagVal = currTagVal + new String(ch, start, length);
currTag = false;
}
}
ACTIVITY.java
class tareaAsyncHorariosTarifas extends AsyncTask<Void, Void, Void> {
XmlReader helper;
#Override
protected Void doInBackground(Void... params) {
helper = new XmlReader(monumento);
helper.get();
return null;
}
#Override
protected void onPostExecute(Void result) {
StringBuilder builder = new StringBuilder();
for (HorariosTarifasObj post : helper.posts) {
builder.append(post.getHorarios());
}
if(builder.toString().equals("")) {
horario2.setText("-");
} else {
horario2.setText(Html.fromHtml(builder.toString()));
}
builder = new StringBuilder();
for (HorariosTarifasObj post : helper.posts) {
builder.append(post.getTarifas());
}
if(builder.toString().equals("")) {
tarifa2.setText("-");
} else {
tarifa2.setText(Html.fromHtml(builder.toString()));
}
}
}
How can I show XML tag values on basis of particular condition using local XML parsing.
E.g. I have this XML file stored in assets folder,
<language>
<languagename>English</languagename>
<contact>EContact</contact>
<update>EUpdate</update>
</language>
<language>
<languagename>Hebrew</languagename>
<contact>HContact</contact>
<update>HUpdate</update>
</language>
I have two buttons, when I click English I want to show data Regarding English and when I click Hebrew , I want to show only Hebrew. Please provide help.
Thanks
This is the XML parser Function it takes the XML as String.
public class XMLParser {
public static void parser(String s) {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MyXMLhandler h = new MyXMLhandler();
xr.setContentHandler(h);
// Log.e("string", s);
xr.parse(new InputSource(new StringReader(s)));
} catch (ParserConfigurationException e) {
Log.e("ParserError", e.getMessage());
} catch (SAXException e) {
Log.e("SAXError", e.getMessage());
} catch (IOException e) {
Log.e("IOError", e.getMessage());
}
}
}
Use this handler class to extract the information that u need:
public class MyXMLhandler extends DefaultHandler {
private boolean language = false;
private boolean languagename = false;
private boolean contact = false;
private boolean update = false;
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (localName.equalsIgnoreCase("language")) {
language = true;
} else if (localName.equalsIgnoreCase("languagename")) {
languagename = true;
} else if (localName.equalsIgnoreCase("contact")) {
contact = true;
} else if (localName.equalsIgnoreCase("update")) {
update = true;
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equalsIgnoreCase("language")) {
language = false;
} else if (localName.equalsIgnoreCase("languagename")) {
languagename = false;
} else if (localName.equalsIgnoreCase("contact")) {
contact = false;
} else if (localName.equalsIgnoreCase("update")) {
update = false;
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (language == true) {
String s = new String(ch, start, length);
Log.w("Language", s);
}
if (languagename == true) {
String s = new String(ch, start, length);
Log.w("Languagename", s);
}
if (contact == true) {
String s = new String(ch, start, length);
Log.w("contact", s);
}
if (update == true) {
String s = new String(ch, start, length);
Log.w("update", s);
}
}
}
Use this function above and modify it to solve ur problem
I have developed simple webservice base math app in which I use the XML base service and use sax parser to parse the webservice response.
I already parse the XML base webservice using sax parser but my problem is when I parse this not get the whole data of the particular tag. For this my code is below.
private List < Object > callWebService() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
final List < Object > list = new ArrayList < Object > ();
DefaultHandler handler = new DefaultHandler() {
boolean language = false;
boolean langid = false;
boolean langname = false;
boolean icon = false;
public void startDocument() throws SAXException {
list.clear();
}
public void endDocument() throws SAXException {}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("language")) {
language = true;
objLanguage = new Language();
return;
}
if (qName.equalsIgnoreCase("langid")) {
langid = true;
return;
}
if (qName.equalsIgnoreCase("langname")) {
langname = true;
return;
}
if (qName.equalsIgnoreCase("icon")) {
icon = true;
return;
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("langid")) {
langid = false;
return;
}
if (qName.equalsIgnoreCase("langname")) {
langname = false;
return;
}
if (qName.equalsIgnoreCase("icon")) {
icon = false;
return;
}
if (qName.equalsIgnoreCase("language")) {
if (langid == false && langname == false && icon == false) {
language = false;
list.add(objLanguage);
return;
}
}
}
public void characters(char ch[], int start, int length) throws SAXException {
String theString = new String(ch, start, length);
if (langid == true) {
objLanguage.setLangId(theString);
} else if (langname == true) {
objLanguage.setLangName(theString);
} else if (icon == true) {
objLanguage.setIconImage(genHelper.convertIconImageInByteBuffer(theString));
}
}
};
parser.parse("http://mathevaluate.com/webservice/langlist.php", handler);
return list;
} catch (Exception ex) {
System.out.println("ERROR : " + ex.toString());
return null;
}
}
Problem is language Name Tag which contain very big string of data like
<langname>this is the part where i can`t get the whole string of the tag so post this question</langname>
When I parse this it can`t get the proper string value of this tag how can I get this?
If you special characters such as apostrophes and others in your response the data will break at that particular point. You can read here for more SAX parser: Ignoring special characters
I have a XML file in assets folder.
I am parsing it in my Activity and displaying it.
In XML file I has a data with < symbol, I use < at < symbol.
But, the symbol is not displying and text after the symbol only i am getting.
ex "hi < hello"
parsing result will be only hello
parsing code
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
SecondHandler shandler = new SecondHandler();
xr.setContentHandler(shandler);
InputStream in = this.getAssets().open(fileName);
xr.parse(new InputSource(in));
itemlist = shandler.getParsedData();
} catch (Exception e) {
System.out.println("Error : " + e);
}
Map<String, String> item = (Map<String, String>) list.get(5);
String qus = item.get("question");
String ans = item.get("answer");
}
xml file..
..........
<dict>
<question>hello</question>
<answer>I am < 5 you</answer>
</dict>
......
handler code.
public class SecondHandler extends DefaultHandler {
private String tagName;
#SuppressWarnings("rawtypes")
private ArrayList<Map> dataSet;
private Map<String, String> dictionary;
#SuppressWarnings("rawtypes")
public ArrayList<Map> getParsedData() {
return dataSet;
}
#Override
public void startDocument() throws SAXException {
}
#Override
public void endDocument() throws SAXException {
// Nothing to do
}
#SuppressWarnings("rawtypes")
#Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
tagName = localName;
if (localName.equals("array")) {
this.dataSet = new ArrayList<Map>();
} else if (localName.equals("dict")) {
dictionary = new HashMap<String, String>();
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (localName.equals("array")) {
} else if (localName.equals("dict")) {
dataSet.add(dictionary);
}
}
#Override
public void characters(char ch[], int start, int length) {
String string = new String(ch, start, length);
string = string.replaceAll(" ", "");
string = string.replaceAll("\n", "");
string = string.replaceAll("\t", "");
if (string.length() > 0 && string != null) {
dictionary.put(tagName, new String(ch, start, length));
// System.out.println("Dictionary : " + dictionary);
}
}
}
How to solve this problem
Thanks in advance...!
A SAX parser can supply character data to the ContentHandler in as many calls of the characters() method as it chooses. Your characters() method is putting each of the substrings in the same hashtable entry, overwriting any previous substrings; you need to concatenate them.
may be you directly use "<" in xml file write ,
So use Value-->String class
==>string name="temperature_lt" value is= Temperature & l t;(Note here ignore space)
and extractin xml file
==>android:text="#string/temperature_lt"
try it,