# Java Klasse für gegebenes XML erstellen



## Teradil (31. Okt 2008)

Hallo ihrs,

ich hab hier ein XML-Dokument, dass unter anderem folgenden Schnippsel enthält:


```
<keywords>
	<keyword id="11" src="null">wort1</keyword>
	<keyword id="27" src="null">wort2</keyword>
	<keyword id="32" src="null">wort3</keyword>
</keywords>
```

Ich muss dafür eine Java-Klasse erstellen, die ich durch ein XStream füllen wollte.

Deshalb hab ich erstmal versucht mit XStream eine XML-Datei zu erzeugen, die der dort oben ähnlich sieht.
Dafür habe ich bisher folgendes probiert:


```
public class Keyword {
	String id = "";
	String src = "";
	String keyword;

	public Keyword(String s) {
		keyword = s;
	}
}
```

und 

```
import java.util.ArrayList;

import com.thoughtworks.xstream.XStream;

public class XStest {

	public static void main(String[] args) {

		XStream xstream = new XStream();

		xstream.alias("keyword", Keyword.class);
		xstream.useAttributeFor(Keyword.class, "id");
		xstream.useAttributeFor(Keyword.class, "src");
		
		Keyword k1 = new Keyword("Wort1"));
		
		System.out.println(xstream.toXML(k1));
	}

}
```

Das entstehende XML sieht dann so aus: 

```
<keyword id="" src="">
  <keyword>wort1</keyword>
</keyword>
```

Das extra Tag innerhalb der ersten keyword-Tags würde ich jetzt gerne noch loswerden.  Kennst sich da jemand aus, wie ich das hinbekomme? Oder ist der Ansatz mit der eigenen Keyword-Klasse hier schon ungünstig?


----------



## ralfz (19. Nov 2008)

Hi,

kenne mich damit leider nicht wirklich aus, hatte nur gerade ein ähnliches oder genau das Problem mit JAXB.

Wenn es denn hier ähnlich ist, dann musst du den Wert der nicht als extra <Keyword>wert</Keyword> erscheinen soll, irgendwie direkt als "den" Value für diesen Knoten deklarieren.

Gibt es da irgendeine Methode wie:

```
xstream.useValueFor(Keyword.class, "keyword");
```

???
Gruß
Zirni[/code]


----------



## Murray (19. Nov 2008)

Falls es noch interessiert: es funktiomiert mit einem Konverter:

```
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class XStest {

   public static void main(String[] args) {

      XStream xstream = new XStream();

      xstream.alias("keyword", Keyword.class);
      xstream.registerConverter( new KeywordConverter());
      
      Keyword k1 = new Keyword("Wort1");
      k1.src = "src1";
      k1.id = "id1";
      
      String xml = xstream.toXML(k1);
      
      System.out.println( xml);
      
      Object unmarshalled = xstream.fromXML( xml);

      System.out.println( unmarshalled);

   }

}

class Keyword {
	   String id = "";
	   String src = "";
	   String keyword;

	   public Keyword() {
		   this( null);
	   }
	   
	   public Keyword(String s) {
	      keyword = s;
	   }
	   
	   public String toString() {
		   return super.toString() + "[id=" + src + ",id=" + id + ",keyword=" + keyword + "]";
	   }
	}

class KeywordConverter implements Converter {
	
	
	public boolean canConvert( Class type) {
		return type.equals( Keyword.class);
	}
	
	public void marshal( Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
		 
		Keyword keyword = (Keyword)value;

		writer.addAttribute( "id", keyword.id);
		writer.addAttribute( "src", keyword.src);
		writer.setValue( keyword.keyword);

	}
	
	public Object unmarshal( HierarchicalStreamReader reader, UnmarshallingContext context) {
		
		Keyword keyword = new Keyword();
		
		keyword.src = reader.getAttribute( "src");
		keyword.id = reader.getAttribute( "id");
		keyword.keyword = reader.getValue();

		return keyword;
	}

}
```


----------



## ralfz (19. Nov 2008)

Hi Murray,

also ich hatte mir gestern auch mal etwas das xstream und dessen API angeschaut, da ich es gar nicht kannte.

Ich konnte allerdings nicht glauben, dass man nicht einfach zusätzlich zur Methode "useAttributeFor" auch eine Methode für den Value hat.

Hab noch ne Weile gesucht, dann aber aufgegeben...

Danke für den Post, hatte mich jetzt echt mal interessiert wie das geht...

Gruß
Zirni


----------



## Murray (19. Nov 2008)

Wenn man den ganzen einfachen Fall hat, dass eine Klasse nur einen Member hat, der dann als inner-content im Tag landen soll (also <keyword>der text</keyword>), dann würde es noch etwas einfacher gehen (indem man nur einen SimpleValueConverter implementiert); dabei kann man dann aber keine Attribute mehr setzen. Für das hier geforderte Format geht es aber wohl nicht anders, als mit einem Converter die vollständige Kontrolle über das Marshalling und Unmarshalling zu übernehmen.


----------

