# XML, UTF-8, JDOM und Umlaute



## SpammerSlammer (23. Aug 2009)

Hallo,

ich nutze JDOM, um XML-Code in Dateien zu schreiben. Ich habe als Kodierung UTF-8 angegeben, weil mein Programm auch mit russischen, griechischen, koreanischen, chinesischen und japanischen Texten umgehen können muss. Leider werden deutsche Umlaute dann natürlich wie bei HTML umkodiert (z.B. ü in [noparse]&amp;#252;[/noparse]). Einigen Forenbeiträgen habe ich entnommen, dass es keine Probleme gibt, wenn man den Zeichensatz auf ISO-8859-1 ändert, aber das kommt wegen der anderen Sprachen nicht in Frage.

Meine Frage lautet daher: Wenn UTF-8 doch eigentlich mehr als eine Million Zeichen darstellen kann und in die XML-Dateien selbst irgendwelche kyrillischen oder koreanischen Zeichen eingebaut werden können (d.h. ohne Umkodierung), warum müssen dann einfache deutsche Umlaute umkodiert werden? Ich meine, im Zeichensatz sind sie doch alle drin, genau so wie die kyrillischen oder koreanischen Zeichen?!


----------



## musiKk (23. Aug 2009)

Also ich kenne mich mit JDOM im Speziellen vielleicht nicht aus, aber schon


> Leider werden deutsche Umlaute dann natürlich wie bei HTML umkodiert (z.B. ü in &amp;#252.


kann ich nicht nachvollziehen. Deutsche Umlaute haben keine Sonderstellung im Vergleich zu anderen Zeichen.

Vielleicht kannst Du mal ein kleines Code-Beispiel bringen, in dem das Problem deutlich wird.


----------



## SpammerSlammer (27. Aug 2009)

Sorry wegen der späten Antwort!

OK, das Problem habe ich scheinbar nur, weil ich die Daten aus einer JEditorPane nehme, die mit HTML arbeitet...

Mein Problem: Wenn ich normale Umlaute oder auch fernöstliche Schriftzeichen in eine solche JEditorPane einfüge und dann wieder auslese (z.B. um sie in eine XML-Datei auszugeben), wie kann ich die HTML-kodierten Zeichen dann wieder in UTF-8 zurückkonvertieren?

Hier ein Minimalbeispiel:


```
import java.io.*;
import javax.swing.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;

public class XmlBeispiel {
	
	public XmlBeispiel() {
		String umlaute = "Umlaute: ä, ö, ü, ß";
		
		JEditorPane editorPane = new JEditorPane();
		editorPane.setContentType("text/html");
		editorPane.setText(umlaute);
		String htmlString = editorPane.getText();
		String ohneHtml = htmlString.replaceAll("</?\\w++[^>]*+>", "");
		
		Element root = new Element("root");
		Document document = new Document(root);
		Element element = new Element("element");
		element.setText(ohneHtml);
		root.addContent(element);
		try {
			FileOutputStream outStream = new FileOutputStream("output.xml");
			XMLOutputter outToFile = new XMLOutputter();
			Format format = Format.getPrettyFormat();
			format.setEncoding("utf-8");
			outToFile.setFormat(format);
			outToFile.output(document, outStream);
			outStream.flush();
			outStream.close();
		} catch (IOException e) {
			System.out.println("Cannot save:" + e.getMessage());
		}
	}
	
	public static void main (String[] args) {
		new XmlBeispiel();
	}
}
```

In diesem Beispiel sind die Umlaute in der resultierenden Datei "output.xml" alle HTML-kodiert.

Ich kann mir doch nicht für jedes mögliche Zeichen auf dieser Welt eine regex bauen, um das wieder hinzubiegen?!


----------



## SpammerSlammer (27. Aug 2009)

Na gut, ich habe jetzt ein bisschen hin- und herprobiert und die Lösung selbst gefunden. War eine ziemlich fiese Angelegenheit - ein Wunder, dass ich das so schnell hingekriegt habe... Hier die Details der Lösung für alle Interessierten:

Bisher hatte ich die HTML-Datei mit einem regulären Ausdruck von den HTML-Tags befreit, ohne aber die Sonderzeichen entsprechend zurückzukonvertieren. Was auch schwierig wäre bei mehr als einer Million möglichen Zeichen... Das war also in Zeile 17:
[JAVA=17]String ohneHtml = htmlString.replaceAll("</?\\w++[^>]*+>", "");[/code]

Diese habe ich ausgetauscht gegen den Swing-HTML-Parser. Dieser wird meistens in Kombination mit einem FileReader verwendet, aber ich habe stattdessen einen StringReader eingebaut. Zeile 17 des vorherigen Posts muss also durch folgenden Code ersetzt werden, um alle HTML-Zeichen passend zurückzukonvertieren:

[JAVA=17]
		HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback () {
		    public void handleText(char[] data, int pos) {
		        ohneHtml = String.valueOf(data);
		    }
		};
		Reader reader = new StringReader(htmlString);
		try {
			new ParserDelegator().parse(reader, callback, false);
		} catch (IOException ioe) {
			System.out.println(ioe);
		}
[/code]

Natürlich muss man die entsprechenden Importe einbauen und den String "ohneHtml" als Klassenvariable definieren.

Hier ist zwecks Copy & Paste noch mal der gesamte Code:


```
import java.io.*;
import javax.swing.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.ParserDelegator;

public class XmlBeispiel {
	
	String ohneHtml;
	
	public XmlBeispiel() {
		String umlaute = "Umlaute: ä, ö, ü, ß";
		
		JEditorPane editorPane = new JEditorPane();
		editorPane.setContentType("text/html");
		editorPane.setText(umlaute);
		String htmlString = editorPane.getText();
		
		HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback () {
		    public void handleText(char[] data, int pos) {
		        ohneHtml = String.valueOf(data);
		    }
		};
		Reader reader = new StringReader(htmlString);
		try {
			new ParserDelegator().parse(reader, callback, false);
		} catch (IOException ioe) {
			System.out.println(ioe);
		}
		
		Element root = new Element("root");
		Document document = new Document(root);
		Element element = new Element("element");
		element.setText(ohneHtml);
		root.addContent(element);
		try {
			FileOutputStream outStream = new FileOutputStream("output.xml");
			XMLOutputter outToFile = new XMLOutputter();
			Format format = Format.getPrettyFormat();
			format.setEncoding("utf-8");
			outToFile.setFormat(format);
			outToFile.output(document, outStream);
			outStream.flush();
			outStream.close();
		} catch (IOException e) {
			System.out.println("Cannot save:" + e.getMessage());
		}
	}
	
	public static void main (String[] args) {
		new XmlBeispiel();
	}
}
```

Ich habe es auch mit koreanischen Zeichen getestet. Läuft so weit gut.


----------

