SaxParser on Android: Unexpected End Of Document Exception
Asked Answered
V

3

11

I'm getting a "SAXParseException: Unexpected end of document" error when trying to parse an xml document on android.

The document in question is from the google weather api, but it seems to throw the same error regardless of the xml file in question (as long as the xml is valid) so I suspect it's a problem with my approach, rather than the xml.

This is being done as a learning exercise, so I've probably (hopefully) overlooked something obvious =)

I've run the xml through an online validator, and it comes back as being well formed. (Can't tell me if it's valid as I don't have a DTD, but I dont think I need the DTD to parse the xml).

This is the code that I'm using to try and parse the file:

private void refreshForecast() 
        URL url;
        try {       
                url = new URL( "http://192.168.1.66:8000/google4.xml");

                URLConnection connection = url.openConnection();
                HttpURLConnection httpConnection = (HttpURLConnection)connection; 
                int responseCode = httpConnection.getResponseCode(); 

                if (responseCode == HttpURLConnection.HTTP_OK) { 
                        InputStream in = httpConnection.getInputStream();        
                        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                        DocumentBuilder db = dbf.newDocumentBuilder();

                        // falls over here parsing the xml.
                        Document dom = db.parse(in);    
                }
        } catch (ManyExceptions e) {
        .... 
} 

A cutdown version of the xml that produces the error is:

<?xml version="1.0"?>
<xml_api_reply version="1">
      <weather>
            <forecast_information>
                    <city>Hamilton</city>
            </forecast_information>
      </weather>
</xml_api_reply>

The stacktrace is:

11-20 06:17:24.416: WARN/System.err(406): org.xml.sax.SAXParseException: Unexpected end of document
11-20 06:17:24.416: WARN/System.err(406):     at org.apache.harmony.xml.parsers.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:131)
11-20 06:17:24.416: WARN/System.err(406):     at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:110)
11-20 06:17:24.426: WARN/System.err(406):     at com.dave.nzweather.WeatherApp.refreshForecast(WeatherApp.java:159)
11-20 06:17:24.426: WARN/System.err(406):     at com.dave.nzweather.WeatherApp.onCreate(WeatherApp.java:100)
11-20 06:17:24.426: WARN/System.err(406):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
11-20 06:17:24.438: WARN/System.err(406):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
11-20 06:17:24.438: WARN/System.err(406):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
11-20 06:17:24.446: WARN/System.err(406):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
11-20 06:17:24.446: WARN/System.err(406):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
11-20 06:17:24.456: WARN/System.err(406):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-20 06:17:24.456: WARN/System.err(406):     at android.os.Looper.loop(Looper.java:123)
11-20 06:17:24.456: WARN/System.err(406):     at android.app.ActivityThread.main(ActivityThread.java:4627)
11-20 06:17:24.466: WARN/System.err(406):     at java.lang.reflect.Method.invokeNative(Native Method)
11-20 06:17:24.466: WARN/System.err(406):     at java.lang.reflect.Method.invoke(Method.java:521)
11-20 06:17:24.466: WARN/System.err(406):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-20 06:17:24.476: WARN/System.err(406):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-20 06:17:24.476: WARN/System.err(406):     at dalvik.system.NativeStart.main(Native Method)
11-20 06:17:24.486: WARN/ROGER(406): org.xml.sax.SAXParseException: Unexpected end of document

In the interest of brevity, I've not included the original xml, but it's just the standard weather xml from googles feed.

I've also tried a few completely different xml files, (including the sample from http://www.ibm.com/developerworks/xml/library/x-android/) and they all give the same error. (They also all validate as well formed when I run them through an online xml validator).

This makes me think that it's not a problem with the xml, but rather with how I'm trying to feed it into the parser.

Cheers

Dave Smylie

Vins answered 21/11, 2010 at 18:4 Comment(2)
Have you tried reading in the complete file first? I remember having an issue like that long time ago, maybe that helps.Montenegro
I'm assuming so - I'm dumping out the retrieved file via android.util.log and it's showing the complete file in there. However, Im running that inputstream into a stringbuffer, so it's possible that the log is getting a completely finished stream, where as parse() is getting an incomplete stream.... I'll see if I can convert it to a stringbuffer and parse that...Vins
P
3

Looking at your code it seems that you are trying to fetch the file off a computer on your network. Have you tried to open that URL in a browser to check if it is really sending the XML file?

Alternatively you can also check with Wireshark what answer your phone gets. My guess is that you simply don't get the XML document back but a 404 error page.

Purse answered 21/11, 2010 at 19:14 Comment(4)
I originally thought that network issues might be the problem, so i'm now retrieving it of a local webserver. I can see the request complete okay in the server log and I dump out the contents of the retrieved xml file to eclipse via android.util.log so I'm pretty sure it's receiving the file okay. . .Vins
@Dave Smylie: What was the problem?Purse
i'm still not sure - i suspect the input stream i was passing into parse() wasn't completely retrieving the document. (Even though when I converted the input stream to a string and dumped it in the log it would show the complete document - so possibly the input stream wasnt flushing.... anyway, as soon as I just passed parse() a uri instead and let it fetch the document the issue went away.Vins
I am having the exact same problem. I added tracing for the SAXParseException and using SAXParseException.getColumnNumber to see if there was an offending character. It in fact returns -1, indicating that inputstream is not terminating properly. (Which is obviously consistent with the error message). I would like to know how to terminate a stream "properly" for the sax parser.Sprayberry
V
4

Solved (sort of)...

I saw sax.parser could also take in a uri directly (instead of the input stream).

As soon as I tried that, it parsed okay, and the code was a whole lot shorter =)

Thanks for the help.

  String weatherFeed = "http://192.168.1.66:8000/google.xml";
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  DocumentBuilder db = dbf.newDocumentBuilder();
  Document dom = db.parse(weatherFeed);
Vins answered 22/11, 2010 at 18:54 Comment(0)
P
3

Looking at your code it seems that you are trying to fetch the file off a computer on your network. Have you tried to open that URL in a browser to check if it is really sending the XML file?

Alternatively you can also check with Wireshark what answer your phone gets. My guess is that you simply don't get the XML document back but a 404 error page.

Purse answered 21/11, 2010 at 19:14 Comment(4)
I originally thought that network issues might be the problem, so i'm now retrieving it of a local webserver. I can see the request complete okay in the server log and I dump out the contents of the retrieved xml file to eclipse via android.util.log so I'm pretty sure it's receiving the file okay. . .Vins
@Dave Smylie: What was the problem?Purse
i'm still not sure - i suspect the input stream i was passing into parse() wasn't completely retrieving the document. (Even though when I converted the input stream to a string and dumped it in the log it would show the complete document - so possibly the input stream wasnt flushing.... anyway, as soon as I just passed parse() a uri instead and let it fetch the document the issue went away.Vins
I am having the exact same problem. I added tracing for the SAXParseException and using SAXParseException.getColumnNumber to see if there was an offending character. It in fact returns -1, indicating that inputstream is not terminating properly. (Which is obviously consistent with the error message). I would like to know how to terminate a stream "properly" for the sax parser.Sprayberry
S
3

Your problem may have been caused by an encoding issue.

Try creating your inputStream via a ByteArrayInputStream with UTF-8 encoding like below and see if that works. This, (below), is what I had to use when I had a String of XML, but it may still be an issue via the inputestream you are using.

String sData = "..Your XML in here..";
DocumentBuilder db = dbf.newDocumentBuilder(); 
InputStream is = new ByteArrayInputStream(sData.getBytes("UTF-8"));
Document doc = db.parse(is);

This assumes that your XML is has UTF-8 encoding specified like this

<?xml version="1.0" encoding="UTF-8" ?>

Otherwise you should make sure your encoding defined in your InputStream is the same as that defined in your XML.

Sprayberry answered 26/4, 2011 at 7:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.