javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]

nieselfriem

Bekanntes Mitglied
Hallo,

ich will mit einer Methode eine im Web bereitgestellte XML-Datei herunter laden und den Stream gleich als XML wieder einlesen um ihn dann lokal weiter zu verarbeiten. Dazu habe ich folgende Klasse geschrieben

Java:
public class ImportXML {

    private final String USER_AGENT = "mozilla/5.0";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws Exception {
        // TODO code application logic here
        ImportXML http = new ImportXML();
        XmlToSQL xmlsql = new XmlToSQL();
        InputStream in; 
        System.out.println("Testing - Send http Post request");
        in = http.sendPost();
        xmlsql.parseXML(in);
        
    }

    private  InputStream sendPost() throws Exception {
        String username ="georg";
        String password ="werner";
        String userpass = username + ":" + password;
        String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());
        String url = "http://localhost/dbxmlexport/";
        System.out.println("url");
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);
        con.setRequestProperty("Accept-Language", "en-US,en, q=0.5");
        con.setRequestProperty ("Authorization", basicAuth);
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes("");
        wr.flush();
        wr.close();
        int responseCode = con.getResponseCode();
        System.out.println("\nSending POST request tu URL : " + url);
        System.out.println("Response Code: " + responseCode);
        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
       

        //System.out.println(response.toString());
        Path target = Paths.get("c:/tmp/test.xml");
        InputStream is = new ByteArrayInputStream(response.toString().getBytes());
        Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
      
        return con.getInputStream();
    }

}

Nun will ich den Inputstream in der unten stehenden Klasse aufnehmen lassen und gleich weiter verarbeiten, ohne die XML-Datei auf dem Filesystem zwischen zu speichern.

Java:
public class XmlToSQL {

    ArrayList<Countries> cnt = new ArrayList<Countries>();
    private String tag = "";
    private String wert = "";
    private InputStream is;

    public ArrayList parseXML(InputStream isp) {
        this.is = isp;
        
        try {
            XMLInputFactory iF = XMLInputFactory.newInstance();
            
            XMLStreamReader sr = iF.createXMLStreamReader(is);
            
            while(sr.hasNext()) {
                switch (sr.next()) {
                    case XMLStreamConstants.START_ELEMENT:
                        if (!sr.getLocalName().equals("Countries")) {
                            tag = sr.getLocalName().trim();
                        }//if
                        break;
                case XMLStreamConstants.END_ELEMENT:
                        if (sr.getLocalName().equals("Country")) {
                            tag = "endcountry";
                        }
                        wert = "";
                        break;
                 case XMLStreamConstants.CHARACTERS:
                        if (tag.equals("Country") && sr.getText().trim().length() > 0) {
                            wert = "*";
                        }//if
                        else {
                            if (sr.getText().trim().length() > 0) {
                                wert = sr.getText().trim();
                            }
                        }
                        if ((wert.length() > 0 && tag.length() > 0) || (wert.equals("") && tag.endsWith("bewerber"))) {
                            cnt.add(new Countries(tag, wert));
                        }
                        break;
                }
            }
            
        } catch (Exception e) {
            e.printStackTrace();

        }
        return cnt;
    }
}

Doch leider bekomme ich so die Exception,

Code:
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]
Message: Vorzeitiges Dateiende.
	at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:601)
	at importxml.XmlToSQL.parseXML(XmlToSQL.java:31)
	at importxml.ImportXML.main(ImportXML.java:40)

Was muss ich da ändern?

VG niesel
 
Zuletzt bearbeitet:
Die Message zeigt doch eindeutig, dass die Datei zu kurz ist. Du lässt dir auch nirgendwo den Inhalt der Datei ausgeben, um zu kontrollieren, ob da überhaupt was drinsteht. Das ist schon sehr leichtsinnig.
Mögliche Fehlerursachen: also ich kann da nur raten, weil ich mit HttpURLConnections noch nix gemacht habe
- Du öffnest einen OutputStream der connection und schreibst "" rein. K.A. ob damit ev. Inhalte "überschrieben" werden.
- Du verwendest den InputStream der connection als Eingabestrom für einen BufferedReader, mit dem ein StringBuffer gefüllt wird. Es wird solange aus dem InputStream gelesen, bis sein Ende erreicht ist. Am Ende der Methode gibst du wieder con.getInputStream zurück. Ev. fängt der ja nich noch mal von vorne an aus der Connection zu lesen?
- Wie sieht überhaupt die Datei auf "c:/tmp/test.xml" aus? Entgegen deiner Beschreibung wird offenbar doch eine Kopie der Datei auf die Festplatte geschrieben.
 
Das da was drin steht ist sicher, da der Stream die Datei in ein Verzeichnis schreibt. Das wird in der Methode sendPost() mit den Zeilen
Java:
Path target = Paths.get("c:/tmp/test.xml");
        InputStream is = new ByteArrayInputStream(response.toString().getBytes());
        Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
auch ausgeführt. Es ist auche eine Valide XML-Datei. Wenn ich den Umweg über eine Datei gehen, funktioniert das Einlesen der Datei im XMLStreamReader auch, nur wenn ich den Stream direkt ohne Umweg einfügen will nicht.
 
Das da was drin steht ist sicher, da der Stream die Datei in ein Verzeichnis schreibt. Es ist auche eine Valide XML-Datei. Wenn ich den Umweg über eine Datei gehen, funktioniert das Einlesen der Datei im XMLStreamReader auch, nur wenn ich den Stream direkt ohne Umweg einfügen will nicht.
Dann bleibt als Erklärung eigentlich nur noch übrig, daß der InputStream aus dem 2. Aufruf von con.getInputStream() leer ist. Das kannst du leicht überprüfen, indem du den an die parseXML methode übergegebenen InputStream in eine Datei speicherst und deren Inhalt kontrollierst.
Um den Fehler ganz zu umgehen, würde ich auf das mehrmalige Verwenden von con.getInputStream() verzichten, stattdessen den InputStream aus dem erstmaligen Lesen in ein byte Array einlesen und damit dann weiterarbeiten.
Dein aktueller Weg InputStream -> InputStreamReader -> BufferedReader -> StringBuffer -> String -> byte[] -> könnte stark verkürzt werden. So müsste das gehen:
Java:
    public byte[] readData(InputStream inputStream) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[16384];
        int read = 0;
        while ((read = inputStream.read(buf)) != -1) {
            bos.write(buf, 0, read);
        }
        bos.flush();
        return bos.toByteArray();
    }
 

Zurück
Oben