I've implemented a SAXparser in my application which has worked fine previously but i'm having problems with a new XML document.
This is my parser
public List<Article> getLatestArticles(String feedUrl) {
URL url = null;
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
url = new URL(feedUrl);
xr.setContentHandler(this);
xr.parse(new InputSource(url.openStream()));
} catch (IOException e) {
Log.e("RSS Handler IO", e.getMessage() + " >> " + e.toString());
} catch (SAXException e) {
Log.e("RSS Handler SAX", e.toString());
} catch (ParserConfigurationException e) {
Log.e("RSS Handler Parser Config", e.toString());
}
catch (java.lang.IllegalArgumentException e){
Log.e("RSS Handler lang", e.getMessage() + " >> " + e.toString());
}
return articleList;
}
The parser starts off ok but then i get a java.lang.IllegalArgumentException error. I believe this may be due to an element with no value in my xml feed, it looks like this <Description/>.
Any suggestion on how to fix this would be much appreciated.
If </Description> is a self closing tag (i.e. it has not opening <Description> tag and no text value) then this syntax is perfectly correct.
It is hard to tell exactly what is causing the error without seeing the callback methods (e.g. startElement method) but there is one major gottcha that you can check
The SAX parse method throws an illegalArguementException if the InputStream is null. It might be worth checking the value coming into the SAX parser.
You can use the following code to check the input stream for nulls.
InputStreamReader reader = new InputStreamReader(url.openStream());
if (!reader.ready()) {
System.out.println("error");
}
The connection could close before all the data downloads.
Try using a BufferedInputStream and see if that helps:
BufferedInputStream _url_ = new BufferedInputStream(new URL(feedUrl).openStream());
...
BufferedReader isr = new BufferedReader(new InputStreamReader(_url_));
InputSource is = new InputSource(isr);
xr.parse(is);
<Description/> is the xml construction issue for SAXParser. have a look into the structure.
Ideally it should be </Description> as a closing tag.
For self-closing tags SAXParser will assume it as a closing tag.
So instead of startElement you will get a call from endElement.
Related
I am Using following two methods for parsing my Xml Data:
private static XMLReader prepareSAX() throws ParserConfigurationException,
SAXException {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
return sp.getXMLReader();
}
public static void LectorSAX(XMLReader xr, String url) {
try {
InputSource is = new InputSource(url);
is.setEncoding("UTF-8");
xr.parse(is);
} catch (SAXException e) {
System.err.println("Error de sax LectorSAX.java: " + e);
e.printStackTrace();
} catch (IOException e) {
System.err.println("Error de io LectorSAX.java: " + e);
e.printStackTrace();
}
}
Now My Xml Data Is as following:
<Product>
<Product_ID>22434</Product_ID>
<Chinese_Name>三Q 逆齡速效霜</Chinese_Name>
<English_Name>Q10 QUICK GEL MOIST & WHITENING</English_Name>
<Image_Path>http://www.abc.com/prodImage/dtl/13011015,38,8.jpg</Image_Path>
<Original_Price>880</Original_Price>
<Discounted_Price>0</Discounted_Price>
<Product_Detail><![CDATA[<html><body>三Q 逆齡速效霜</br>Q10 QUICK GEL MOIST & WHITENING<br><br></body></html>]]></Product_Detail>
</Product>
I am Getting Following Exeption:
01-29 04:14:10.637: W/System.err(1665): Error de sax LectorSAX.java: org.apache.harmony.xml.ExpatParser$ParseException: At line 185, column 36: unknown encoding
01-29 04:14:10.758: W/System.err(1665): at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:515)
01-29 04:14:10.758: W/System.err(1665): at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:474)
01-29 04:14:10.758: W/System.err(1665): at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:321)
01-29 04:14:10.818: W/System.err(1665): at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:294)
01-29 04:14:10.818: W/System.err(1665): at com.dhc.xmlparsing.XMLParser.LectorSAX(XMLParser.java:79)
My 185th line is English_Name Tag.
so where i am doing Wrong,please help me out.
Finally got a solution,it was problem with encoding "&"(special character) by saxParser so i have replace "&" with &. now its working perfectly, code is shown below:
response = response.replaceAll("&", "&");
InputSource inputSource = new InputSource();
inputSource.setEncoding("UTF-8");
Log.i("TAG", "response" + response);
inputSource.setCharacterStream(new StringReader(response));
xr.parse(inputSource);
I am also facing same problem in my code, i tried below solution. It worked for me.
InputSource inputSource = new InputSource();
inputSource.setEncoding("ISO-8859-1");
inputSource.setCharacterStream(new StringReader(response));
xr.parse(inputSource);
I want to parse the URL of a weather API in my sample Android app, but it arises an exception while parsing the url.
If I comment the last statement of the try block:
xr.parse(new InputSource(url.openStream()));
then my program runs successfully. Please revise my code where I parse my URL.
try {
URL url;
String queryString ="http://free.worldweatheronline.com/feed/weather.ashx?q=34.01,71.54&format=xml&num_of_days=5&key=ccad66928f081759132201";
url = new URL(queryString.replace(" ", "%20"));
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
WeatherHandler myWeatherHandler = new WeatherHandler();
xr.setContentHandler(myWeatherHandler);
xr.parse(new InputSource(url.openStream()));
Log.d(TAG, "it's all right");
} catch (Exception e) {
System.out.println(e);
Log.d(TAG, "it's Wrong");
}
Here is the Screen shot of the log cat when the exception occurs.
Are you sure the line:
new InputSource(url.openStream());
from
xr.parse(new InputSource(url.openStream()));
is returning something? If you have to connect to the Internet, don't forget to add the permissions to the manifest. And you should also test if you actually get something from that url before trying to parse.
At least that's my interpretation from your Log and Exception.
I need to parse the XML data returned from accessing a REST-based service to display only one single tag. For example, parse the XML data shown below to display firstname tag and value John only.
<company>
<staff>
<firstname>John</firstname>
<lastname>Doe</lastname>
</staff>
</company>
I am struggling to figure out how to interface with the SAX parsing code once XML data is returned by RESTClient. I tried different approaches after learning from different example codes but still cannot figure it out partly because they do not have the same exact purpose. So please kindly teach me how to call/pass the data to the parsing code and what to return from the parsing code, whether the parsing code should be in a separate class, etc. I am basically clueless without some guidance. Relevant RESTClient code is presented below. Thanks!
public class RESTClient {
public static String callRESTService(String url) {
String result = null;
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet(url);
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
InputStream instream = entity.getContent();
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp;
try (
sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
DefaultHandler handler = new DefaultHandler();
xr.setContentHandler(handler);
InputSource is = new InputSource(instream);
xr.parse(is);
//what should/can be returned here from the parsing code:
//String, InputSource, InputStream?. Convert data type?
}
catch (SAXException e)
{
e.printStackTrace();
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
)
http://as400samplecode.blogspot.com/2011/11/android-parse-xml-file-example-using.html
You have to extend DefaultHandler and make your own XML handler where you will parse your xml.
You can see the example of extending Defaulthandler in above link.
I insist that you should keep your parser code in separate file . Since RestClient is only responsible for sending and receiving of data from remote location . This is would also provide u lose coupling between the two components .
what to return from the parsing code Output of processor depends on your needs. (Personally i am returning List of HashMap)
I suggest that you return a POJO here.
I'm having some trouble reading two BBC feeds on my Android app, they both seem to time out. This is especially strange because all other feeds work fine using the exact same system. I guess if someone could test them in their Eclipse it might help me determine if my work's firewall/proxy is restricting access to this specific website.
The feeds are http://newsrss.bbc.co.uk/weather/forecast/2159/Next3DaysRSS.xml and http://feeds.bbci.co.uk/news/england/kent/rss.xml.
I have other feeds being read with work fine e.g. http://www.kent.ac.uk/news/rss.html
The other strange thing is the chap next to me working on an iPhone under the same network restrictions is not having a problem.
Any help would be greatly appreciated!
For info here is the code I've been using to pull in feeds:
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
// proxy settings
String proxyHost = android.net.Proxy.getDefaultHost();
int proxyPort = android.net.Proxy.getDefaultPort();
if(proxyPort != -1){
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost(proxyHost,proxyPort));
}
URL url = null;
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
url = new URL(feedUrl);
URLConnection conn = url.openConnection();
// setting these timeouts ensures the client does not deadlock indefinitely
// when the server has problems.
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);
xr.setContentHandler(this);
/* This is where it lurches indefinitely VVV */
xr.parse(new InputSource(url.openStream()));
} catch (IOException e) {
Log.e("RSS Handler IO", e.getMessage() + " >> " + e.toString());
} catch (SAXException e) {
Log.e("RSS Handler SAX", e.toString());
} catch (ParserConfigurationException e) {
Log.e("RSS Handler Parser Config", e.toString());
}
I'm going to guess you're having the same problem as this question. Does it work if you take out the proxy settings? If that's the problem, I'd suggest writing the response stream to memory before feeding it to your XMLReader.
the following code is for xml parsing.
try
{
HttpEntity entity = response.getEntity();
final InputStream in = entity.getContent();
final SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
final XmlHandler handler = new XmlHandler();
Reader reader = new InputStreamReader(in, "UTF-8");
InputSource is = new InputSource(reader);
is.setEncoding("UTF-8");
parser.parse(is, handler);
//TODO: get the data from your handler
}
catch (final Exception e)
{
Log.e("ParseError", "Error parsing xml", e);
}
over here where do i pass the url.
also the response object in the line
response.getEntity() is an object of HttpResponse()?
thank you in advance.
The code you show is the processing after the url connection has been opened, and the result has been obtained. At this point there is no more url to pass.
response is the HttpResponse.
I think you can do something like this:
Url url = new URL("http:// [and so on]");
XMLReader xmlReader = parser.getXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource(url.openStream()));