# JDOM und Sonderzeichen < >



## andiner (1. Aug 2008)

Hallo liebe Leidensgenossen, 

ich versuche mit meinem Programm ein Java Modell in eine XML Datei zu schreiben und arbeite dazu mit JDOM. Soweit klappt das auch ganz gut bis auf ein kleines Problem, was mich langsam ganz schön wurmt.
Die Sonderzeichen < und > werden in meinem XML File als gt; und lt; geschrieben. So wird bspw aus den String   

```
<![CDATA[1]]>   =    gt;![CDATA[1]]lt;
```
Das ist sehr Problematisch für mich da ich das XML File für ein Programm aufarbeite was damit nicht viel anfangen kann. 
Ich bin schon so weit dass ich gelesen habe diese kodierung ist wohl HTML und damit wohl auch XML typisch.
Wie schaffe ich es den String in die Datei zu schreiben ohne ihn umzucodieren?

so erzeuge ich den String da er in Tags sein muss

.addContent(new Element("Value").setText("<![CDATA[]]>"));

und so sieht die Erzeugung meines Outputstreams aus


```
try {
   		 FileOutputStream out =  new  FileOutputStream("test.xml");
   		  XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
   		  serializer.output(doc,out);
   		  out.flush();
   		  out.close();
   		}
   	 catch (IOException e) {
   		 
   	 }
```

Kann mir vielleicht jemand helfen


----------



## musiKk (1. Aug 2008)

Dein Encoding in XML Entities verwirrt mich ein wenig, aber ich gehe mal davon aus, dass du & lt; und & gt; meinst.
_edit:_ Da spackt die Forensoftware rum, ich meins natuerlich ohne Leerzeichen... war wohl sicher doch nicht dein Fehler...

Weiterhin habe ich noch nicht mit JDOM gearbeitet, aber es gibt doch ein CDATA-Element, warum nimmst du nicht das?


----------



## andiner (1. Aug 2008)

Hallo
ja genau meine & lt; und & gt; ohne Leerzeichen, habe das & weg gelassen weil es mit der Forensoftware nicht klappt wie du schon sagst, stimmt ist mit Leerzeichen verständlicher.

Mit Cdata kenne ich mich nicht aus, denke hat auch keine XML Formatierung und Hierarchiedie ich sonst brauche, würde das Problem auch lieber mit JDOM lösen  :?


----------



## musiKk (1. Aug 2008)

Jetzt bin ich aber wirklich verwirrt. Oben schreibst du, du arbeitest mit JDOM, unten, du wuerdest das Problem lieber mit JDOM loesen. Oben schreibst du was mit CDATA und unten schreibst du, dass du dich damit nicht gut auskennst.

Was du in ein CDATA packst, kannst du dir fast beliebig aussuchen. Nur ]]> darf im Inhalt nicht so vorkommen. Wenn du etwas mit Sonderzeichen als normalen Text hinzufuegst, dann werden diese natuerlich durch die entsprechenden XML Entities ersetzt, weil es sonst kein valides XML mehr waere.


----------



## andiner (1. Aug 2008)

Ok ich dachte du meinst ich soll das Problem mit CDATA lösen und es wäre Alternative zu JDOM. DAS in den TAG CDATA steht ist reiner Zufall, sollte einfach nur ein String sein  hätte auch anders heißen können.

Aber egal also wie gesagt möchte die Strings < > mit JDOM schreiben ohne dass diese in & lt; und & gt umgewandelt werden.
Gibt es da eine Möglichkeit?


----------



## musiKk (1. Aug 2008)

Nein. Die fuenf Sonderzeichen sind Bestandteil der XML-Syntax und duerfen nur ueber die entsprechende Entitaetenreferenzen eingebunden werden. CDATA ist ein Element, welches das aufhebt, allerdings auch alles andere wie jegliche Struktur auch.


----------



## andiner (2. Aug 2008)

Hm das ist echt witzig dass cdata das aufhebt, nur leider nicht aufgerufen werden kann da es ja mir < anfängt und > endet und so schon vorher transformiert wird bevor es den Inhalt in den [] schützen kann.
Meine damit dass mein Programm das CDATA nicht erkennt da < und > vorher transformiert werden.

.addContent(new Element("Value").setText("<![CDATA[]]>"));


Habe eine Methode gefunden welche die Zeichen wohl schützt escapeText() doch leider ist sie in der kostenpflichtigen Libary com.intellij.openapi.util 

http://www.informit.com/articles/article.aspx?p=31698&seqNum=4
http://www.jetbrains.com/idea/openapi/5.0/com/intellij/openapi/util/JDOMUtil.html#escapeText(java.lang.String)

Wenn man sich die Methode im ersten Bspl ansieht sieht es so aus als ändert sie < und > in eine Zeichenfolge die dann im XML Dokument tatsächlich wieder < und > abbildet...
Wenn ich die nur kennen würde  :bahnhof:


----------



## musiKk (2. Aug 2008)

andiner hat gesagt.:
			
		

> Hm das ist echt witzig dass cdata das aufhebt, nur leider nicht aufgerufen werden kann da es ja mir < anfängt und > endet und so schon vorher transformiert wird bevor es den Inhalt in den [] schützen kann.
> Meine damit dass mein Programm das CDATA nicht erkennt da < und > vorher transformiert werden.


Darum habe ich ja oben das CDATA-Element verlinkt. Das ist jetzt keineswegs beleidigend gemeint, aber von XML verstehst du nicht so sehr viel, oder? Es gibt z. B. von O'Reilly direkt ein Buch ueber Java & XML.


----------



## andiner (2. Aug 2008)

Sagen wir mal so ich verstehe für meine Zwecke genug hab da auch nicht viel mit zu schaffen. Habe jetzt nur das Problem die Sonderzeichen < und > in mittels Jdom ordentlich in das File zu schreiben ohne diese zu konvertieren. Dafür muss ich doch jetzt auch kein Buch lesen, wo das wahrscheinlich nicht ein mal drin steht, wenn ja und du es gelesen hättest, wüsstest du ja wie es geht und könntest es sagen  :roll:


----------



## musiKk (2. Aug 2008)

Naja, darum gehts mir nicht. Es ist einfach so, dass spitze Klammern in XML-Dateien nicht als Text verwendet werden duerfen. Die werden immer wie inzwischen bekannt kodiert. Beim Lesen des XML-Dokumentes werden sie wieder zurueckgesetzt. Ich verstehe halt nicht, was daran nicht in Ordnung ist. JDOM kuemmert sich ja offenbar von alleine drum.


----------



## andiner (3. Aug 2008)

Ok dann erkläre ich es.
Ich erzeuge aus einem allgemein gefassten Simulationsmodel was mit Magic Draw erzeugt wurde und in ein Java Modell übertragen wurde ein Modell für einen bestimmten Simulator. Dieser Simulator nimmt seine Imputdatei XML strukturiert und mit Schlüsselwörtern zwischen den TAGS welche die Sonderzeichen < und > enthalten. Zum erzeugen der Imput Datei des Simulators muss ich die Zeichen also un transformiert in das XML File bringen.
Ich hoffe du glaubst mir jetzt das ich dies benötige und gibst wenn einen konstruktiven Beitrag zum Thema.


----------



## musiKk (3. Aug 2008)

Gut, dann lass ichs. 1. ist von mir alles meines Erachtens wichtige mindestens zwei Mal gesagt und 2. lasse ich mich nicht anscheissen dafuer, dass ich versuche, jemandem zu helfen.


----------



## andiner (3. Aug 2008)

Ok wenn du da so rann gehst dann muss ich mich entschuldigen. Ich finde es immer nur schrecklich wenn Leute in solchen Foren anderen Leuten Ihr Problem nicht abnehmen und so tun, als seien sich die Leute Ihres eigenen Problem nicht bewusst, oder haben gar keine Ahnung und sollen ein Grundlagen Buch lesen, obwohl die Leute das Problem oft selbst nicht lösen könnten.Noch schrecklicher finde ich ein einfachen Link ohne Kommentar zur jeweiligen Dokumentation. 

Das kommt für mich dann immer so besserwisserisch und am Ende nur destruktiv. Und deshalb werden wahrscheinlich auch viele Leute mit hilfsbedürftigen, ernst gemeinten Problemen abgeschreckt in solchen Foren zusammen zu arbeiten.

Wenn du deine Hilfe ernst meinst und mit an einer Lösung interessiert bist dann tut es mir leid. Ich hoffe nur du verstehst dass das eben beschriebene.

Würde mich trotzdem sehr über eine Lösung des Problems freuen. Die einzige Lösung wäre jedoch die Sonderzeichen < > genau so mit Jdom in das Dokument zu bekommen. Umweglösungen wie einlesen und ersetzen danach, bin ich mir auch bewusst, will ich aber umgehen.


----------



## musiKk (3. Aug 2008)

Ok. Ich habe jetzt mal ein XML-Dokument erstellt, welches folgenden Inhalt hat: Ein Root-Element <foo> und als Inhalt den Text ba>r. Den habe ich wie folgt in eine Textdatei geschrieben:

```
DefaultJDOMFactory jdf = new DefaultJDOMFactory();
Element e = new Element("foo");
e.setContent(new Text("ba>r"));
Document doc = jdf.document(e);
Format f = Format.getPrettyFormat();
XMLOutputter xmlo = new XMLOutputter(f);
OutputStream os = new FileOutputStream("test.txt");
xmlo.output(doc, os);
```

Das Resultat ist (halt wieder ohne Leerzeichen nach dem &... doofe Forensoftware...)

```
<?xml version="1.0" encoding="UTF-8"?>
<foo>ba& gt;r</foo>
```

Nun habe ich die Datei wieder eingelesen. Dafuer gibt es natuerlich viele Moeglichkeiten. Z. B.

```
SAXBuilder sb = new SAXBuilder();
Document d = sb.build(new FileInputStream("test.txt"));
```

Wenn ich mir jetzt das Root-Element per

```
System.out.println(d.getRootElement().getContent());
```

steht in der Konsole

```
[[Text: ba>r]]
```

Letzten endes ist das das, was ich die ganze Zeit zugegebenermassen vielleicht nicht zu freundlich rueber gebracht habe. Das XML-Dokument hat verschiedenen Anspruechen zu genuegen, u.a. dass die Sonderzeichen nicht direkt im Text auftauchen, daher werden sie durch die XML Entities ersetzt. Allerdings aendert das nichts am semantischen Inhalt des Dokuments: Da steht sinngemaess weiterhin eine spitze Klammer. Wenn das Dokument wieder geparst wird, dann hat die interne Darstellung wieder die spitze Klammer, weil die XML Entities wieder aufgeloest werden. Wenn dein Programm, welches die XML-Datei als Input hat, das XML-Dokument parst, dann wird es die & gt; usw. wieder durch die spitzen Klammern ersetzen.

Ich muss mir das auch ab und zu bewusst vor Augen halten.


----------



## andiner (3. Aug 2008)

erst mal vielen Dank für deine Mühe,

ich weiß schon was du meinst und du hast auch im gewissen Sinn und bei den meisten Fällen recht. Die Sonderzeichen werden in den meisten Fällen wieder ohne Probleme in das Zeichen < und > geparst. So ja auch wenn ich das Dokument nach seiner Transformation mit den ungeliebten Zeichen & lt; und & gt; in Firefox öffne gibt er mir diese als < und > aus.
Bei deinem Jdom Programm was die Zeichen wieder einholt genauso. Nur leider bei meinem Simulator nicht, wenn er die Zeichen einliest dann gibt es eine Fehlermeldung da er sie nicht transformiert und das Dokument dann für Ihn kein passendes Modell Format ist. Nur brauche ich unbedingt für diesen Simulator das Dokument also muss ich die Transformation umgehen. 

Es gibt auch eine Methode escapeText in der Kostenpflichtigen Libary com.intellij.openapi.util.JDOMUtil. Mit dieser ist es laut aussage einiger Tutorials wohl möglich die Zeichentransfomation zu umgehen. Also muss es eine Möglichkeit geben das hin zu bekommen, ausserdem zeigt das ja, dass mein Problem schon öfter mal aufgetreten ist.

http://www.cafeconleche.org/books/xm...s/ch14s04.html

http://www.jetbrains.com/idea/openap.../JDOMUtil.html


----------



## andiner (3. Aug 2008)

Hallo, da leider niemand eine Lösung für das Problem kennt, habe ich mir eine Klasse geschrieben welche mir die Sonderzeichen abändert. Falls mal noch ein Unglücklicher auf das Problem und diesen Thread stößt hier der Code 


```
import java.io.*;
 
public class Main {
	
	   public static String sb;
	   public static File newFile;
	   

	 public Main() 
	 {
		 try
		 {
		    File oldFile = new File("c:/test.xml");
		    File newFile = new File("c:/test2.xml");
		    newFile.createNewFile();
		    String sb =readFileContent(oldFile);
		    
		    FileWriter writer = new FileWriter(newFile);
		    writer.write(sb);
		    writer.flush();
		    writer.close(); 
		 }
		 catch (IOException e) {
	   		 
	   	 }
	}
	 
	 
	 public static void main(String [] args) {
	   Main mainl = new Main();
		  
	 }
	 
	 public static String readFileContent (File oldFile) {
		    StringBuilder sb = new StringBuilder();
		    try {   
		            FileReader reader = new FileReader(oldFile);
		            int character;
		            while ((character=reader.read()) >-1) 
		            {
		            	// filtern der Sonderzeichen 
		            	if (character == 38)
		            	{   
		            		character=reader.read();
		            		if (character == 108)
		            		{
		            			character=reader.read();
		            			if (character == 116)
		            			{   
		            				character=reader.read();
		            				if (character == 59)
		            				{
		            					character=60;
		            				}
		            				else {   sb.append((char) 38);
		            			             sb.append((char) 108);
		            				         sb.append((char) 116);}
		            			}
		            			else 	{   sb.append((char) 38);
		            			            sb.append((char) 108);}
		            		}
		            		
		            		else if (character == 103)
		            		{   System.out.println("da");
		            			character=reader.read();
		            			if (character == 116)
		            			{   
		            				character=reader.read();
		            				if (character == 59)
		            				{
		            					character=62;
		            				}
		            				else {sb.append((char) 38);
		            				      sb.append((char) 103);
		            				      sb.append((char) 116);}
		            			}
		            			else 	   {sb.append((char) 38);
		            			            sb.append((char) 103);}
		            		}
		            		
		            		else sb.append((char) 38);
		            	}
		            	
		             	
		                sb.append((char) character);
		            }
		            reader.close();
		        } catch(FileNotFoundException fnfe) {
		            fnfe.printStackTrace();
		        } catch (IOException ioe) {
		            ioe.printStackTrace();
		        }
		        return sb.toString();
		    }
	 
	}
```


----------



## SpammerSlammer (26. Sep 2008)

andiner hat gesagt.:
			
		

> Hallo, da leider niemand eine Lösung für das Problem kennt, habe ich mir eine Klasse geschrieben welche mir die Sonderzeichen abändert. Falls mal noch ein Unglücklicher auf das Problem und diesen Thread stößt hier der Code



Ich habe das gleiche Problem. Leider hat Deine Lösung bei mir nicht problemlos funktioniert, d.h. Teile der Tags wurden gelöscht und Attribute durch "null" ersetzt. Kann mir nicht erklären warum. Ich habe nun so lange an Deiner Klasse gebastelt, bis sie auch für meinen Zweck funktionierte. Falls es jemanden interessiert, hier ist der Code:


```
import java.io.*;

public class Sonderzeichen {
   
    String xmlInhalt;  

    public Sonderzeichen( String datei ) {
        xmlInhalt = this.DateiLaden( datei );
        xmlInhalt = xmlInhalt.replaceAll("\u0026\u006c\u0074\u003b", "\u003c");
        xmlInhalt = xmlInhalt.replaceAll("\u0026\u0067\u0074\u003b", "\u003e");
        DateiSpeichern( xmlInhalt, datei );
    }
   
    public String DateiLaden( String dateiname ) {
        String inhalt = new String("");
        try {
            BufferedReader Eingabe = new BufferedReader(new FileReader(dateiname));
            String zeile = Eingabe.readLine();
            while (zeile != null) {
                inhalt = inhalt + zeile + "\n";
                zeile = Eingabe.readLine();
            }
        Eingabe.close();
        }
        catch (IOException e) {
            System.out.println("Error while reading the file " + dateiname);
        }
        System.out.println("File " + dateiname + " has been successfully opened");
        return inhalt;
    }
    
    public void DateiSpeichern( String zeichenkette, String filename ) {
    	try {
            BufferedWriter Ausgabe = new BufferedWriter(new FileWriter(filename));
            Ausgabe.write(zeichenkette);
            Ausgabe.close();
        }
        catch (IOException e) {
            System.out.println("Error while saving the manipulated text to " + filename);
        }
        System.out.println("Manipulated text has been saved to " + filename);
    }
}
```

Das ganze kann in einer anderen Klasse ganz normal nach dem JDOM-Export drangehängt werden:


```
Sonderzeichen umwandeln = new Sonderzeichen( dateiname );
```

Immer noch keine wirklich saubere Lösung, zumal eine Leerzeile an die modifizierte Datei gehängt wird. Aber besser als nix.


----------



## SpammerSlammer (10. Dez 2008)

Noch ein Nachtrag:

Wenn die Dateien ein paar hundert Kilobyte groß sind, kann das ganze schon mal locker ~ 15 Sekunden dauern.

Daher habe ich das ganze noch mal modifiziert und StringBuffer statt normalen Strings in der Schleife eingesetzt:


```
import java.io.*;

public class dnaReformatXml {
   
    String xmlInhalt;  

    public dnaReformatXml( String datei ) {
        xmlInhalt = this.DateiLaden( datei );
        xmlInhalt = xmlInhalt.replaceAll("\u0026\u006c\u0074\u003b", "\u003c");
        xmlInhalt = xmlInhalt.replaceAll("\u0026\u0067\u0074\u003b", "\u003e");
        DateiSpeichern( xmlInhalt, datei );
    }
   
    public String DateiLaden( String dateiname ) {
        StringBuffer inhalt = new StringBuffer("");
        try {
            BufferedReader eingabe = new BufferedReader(new FileReader(dateiname));
            String zeile = eingabe.readLine();
            while ( zeile != null ) {
                inhalt.append( zeile );
                inhalt.append( "\n" );
                zeile = eingabe.readLine();
            }
        eingabe.close();
        }
        catch (IOException e) {
            System.out.println("Error while reading the file " + dateiname);
        }
        return inhalt.toString();
    }
    
    public void DateiSpeichern( String zeichenkette, String filename ) {
    	try {
            BufferedWriter ausgabe = new BufferedWriter(new FileWriter(filename));
            ausgabe.write(zeichenkette);
            ausgabe.close();
        }
        catch (IOException e) {
            System.out.println("Error while saving the manipulated text to " + filename);
        }
    }
}
```


----------

