XML aus einer URL im Internet lesen (JDOM)

Belushi

Mitglied
Hallo zusammen,

ich möchte einige Daten aus link entnehmen. Im Forum habe ich mit JDOM ein interessanten Lösungsvorschlag gefunden: link. Das wollte ich mal ausprobieren. Wenn ich die XML-Datei lokal (im gespeicherten Zustand im Dateisystem) auslese funktionierts, über eine URL erhalte ich diese Exception:
Java:
com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Ungültiges Byte 2 von 4-Byte-UTF-8-Sequenz.
	at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:687)
	at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:473)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1750)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanLiteral(XMLEntityScanner.java:1071)
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanAttributeValue(XMLScanner.java:935)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanAttribute(XMLNSDocumentScannerImpl.java:436)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:253)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2715)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
	at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
	at org.jdom2.input.sax.SAXBuilderEngine.build(SAXBuilderEngine.java:217)
	at org.jdom2.input.sax.SAXBuilderEngine.build(SAXBuilderEngine.java:277)
	at org.jdom2.input.SAXBuilder.build(SAXBuilder.java:1141)
	at reader.Reader.main(Reader.java:24)

Das ist mein Java Code:
Java:
package reader;

import java.io.IOException;
import java.net.URL;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

public class Reader {


	public static void main(String[] args) {

		try {
			
			URL url = new URL("http://www.google.com/ig/api?weather=berlin&hl=de");
			Document document = null;
			SAXBuilder builder = new SAXBuilder();

				try {
					document = builder.build(url);
//					document = builder.build(new File("/home/spree/Arbeitsfläche/wetter.xml"));
				} catch (JDOMException e) {
					System.out.println("Fehler");
					e.printStackTrace();
				}

				
		Element root = document.getRootElement();
		System.out.println(root.getName());

		List<Element> list = root.getChildren();
		Element el=root.getChild("weather");
		
		List <Element> el2=el.getChildren();
		
		for (Element a : el2) {
			System.out.println(a);
		}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

Danke im Voraus...
 
Zuletzt bearbeitet:
Das Encoding des XML-Responses der google weather api ist abhängig von der angeforderten Sprache (bei Dir "de"). Es ist leider nicht UTF-8, sondern irgendwas ISO-... (in Westeuropa wird häufig ISO 8859-1 verwendet.) Für das Problem gibt es zwei Lösungsalternativen

Entweder: Nutze das richtige Encoding
Leider gibt google das verwendete Encoding nicht im xml-Prolog an, sodass es nicht so leicht rauszufinden ist. Du musst Dir den Response-Header anschauen. Dort ist das encoding definiert. Benutze dafür entweder ein Firefox-Plugin, Wireshark o.ä.

Oder: Fordere explizit UTF-8 an
Was wohl auch geht, ist das Encoding explizit anzufordern. Hänge dazu folgenden Query-Parameter an die URL an:
Code:
[B]&oe=utf-8[/B]
 
Zuletzt bearbeitet von einem Moderator:
Der zweite Vorschlag hat direkt funktioniert, danke

Java:
 url = new URL("http://www.google.com/ig/api?weather=berlin&hl=de&oe=utf-8");

Zum ersten Vorschlag:
das Encoding habe ich durch das Abspeichern des XMLs und anschließendem Öffnen mit einem Texteditor abgelesen. Im Prolog des XML-Dokuments steht folgende Deklaration:

[XML]<?xml version="1.0" encoding="UTF-8"?>
<xml_api_reply version="1"><weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0"><forecast_information><city data="Berlin, Berlin"/><postal_code data="berlin"/><latitude_e6 data=""
.....[/XML]

Es ist also UTF-8 Kodiert und nicht ISO-8859-1. Weshalb es dennoch nicht funktioniert hat, ist mir eigentlich immer noch ein Rätsel. Hätte das Dokument eine andere Kodierung, was hätte ich eigentlich tun müssen. Wie passe ich meinen Code an unterschiedliche Kodierungen an?
 
Belushi hat gesagt.:
Es ist also UTF-8 Kodiert und nicht ISO-8859-1. Weshalb es dennoch nicht funktioniert hat, ist mir eigentlich immer noch ein Rätsel.
Hast Recht, ich habe gerade das XML nochmal abgerufen (den ursprünglichen Link ohne utf-8-Parameter) und mir den Response-Header angeschaut. Da steht tasächlich UTF-8 drinnen.
Code:
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
Content-Type: text/xml; charset=UTF-8
...
Würde fast sagen, dass goolge da einen Fehler gemacht hat :reflect:
 
Hätte das Dokument eine andere Kodierung, was hätte ich eigentlich tun müssen. Wie passe ich meinen Code an unterschiedliche Kodierungen an?
Der
Code:
org.jdom2.input.SAXBuilder
hat noch mehr build()-Methoden, um ein
Code:
org.jdom2.Document
zu erzeugen. Unter anderem auch eine, der ein Reader als Parameter übergeben werden kann.
Java:
	public static void main(final String[] args ) throws Throwable {

		final URL weatherUrl = new URL(
				"http://www.google.com/ig/api?weather=berlin&hl=de");

		/*
		 * Mit HttpURLConnection kann man viel http-spezifischen Kram machen.
		 * Z.B. HTTP-Response -Code, -Headers -ErrorStream etc. benutzen.
		 * (Machen wir hier aber nicht)
		 */
		final HttpURLConnection weatherConnection = (HttpURLConnection) weatherUrl
				.openConnection();

		/* 
		 * Hier wird einem InputStreamReader ein CharacterSet übergeben.
		 * Der BufferedReader kann als Parameter für
		 * org.jdom2.input.SAXBuilder.build(...) als Parameter verwendet werden.
		 */
		final BufferedReader weatherReader = new BufferedReader(
				new InputStreamReader(weatherConnection.getInputStream(), "ISO-8859-1"));

		String line = null;
		while ((line = weatherReader.readLine()) != null) {

			System.out.println(line);
		}
	}
 

Neue Themen


Zurück
Oben