# XML aus einer URL im Internet lesen (JDOM)



## Belushi (15. Jul 2012)

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:

```
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:

```
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...


----------



## nillehammer (16. Jul 2012)

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: 
	
	
	
	





```
[B]&oe=utf-8[/B]
```


----------



## Belushi (16. Jul 2012)

Der zweite Vorschlag hat direkt funktioniert, danke


```
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?


----------



## nillehammer (16. Jul 2012)

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.

```
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:


----------



## nillehammer (16. Jul 2012)

> 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 
	
	
	
	





```
org.jdom2.input.SAXBuilder
```
 hat noch mehr _build()_-Methoden, um ein 
	
	
	
	





```
org.jdom2.Document
```
 zu erzeugen. Unter anderem auch eine, der ein Reader als Parameter übergeben werden kann.

```
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);
		}
	}
```


----------

