Das Datenformat XML
XML steht für Extensible Markup Language, also eine erweiterbare Auszeichnungssprache. XML ist der Standard, wenn es darum geht, strukurierte Daten portabel zu speichern oder zu übertragen.- Ein Element besitzt einen Bezeichner und einen Inhalt
- Ein Element besitzt ein Start-Tag und ein End-Tag. Beide umrahmen spitze Klammern, also Kleiner und Größerzeichen. Das End-Tag besitzt zusätzlich einen Schrägstrich:
- Ein Start-Tag kann auch ein Attribut besitzen.
- Elemente können ineinander verschachtelt werden und können so komplexere Datenstrukturen nachbilden.
- Ein XML-Dokument besitzt genau ein Wurzelelement.
- Alle anderen Elemente können mehrfach auftreten und damit Arrays nachbilden.
<Fuhrpark> <Auto> <Marke>Renault</Marke> <Typ>R4</Typ> <Preis>6798.99</Preis> <Hubraum einheit="ccm">845</Hubraum> </Auto> <Auto> <Marke>Opel</Marke> <Typ>Zafira</Typ> <Preis>8798.99</Preis> <Hubraum einheit="ccm">1598</Hubraum> </Auto> </Fuhrpark>
Parsen und Generieren von XML in Java
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("datei.xml")); // Wir holen das root-Element Node rootNode = document.getDocumentElement(); NodeList nodeList = rootNode.getChildNodes(); // Durchsuchen aller Unterknoten for (int i = 0; i < nodeList.getLength(); i++) { Node nodeChild = nodeList.item(i); // Verarbeite die Knoten hier! }
Von XML zum Objekt: JAXB
JAXB ist eine Bibliothek, die auch von REST verwendet wird, wenn als Datenformat appication/xml angegeben wird. Die Handhabung ist dort extrem einfach. Die Klasse, deren Objekte übertragen werden sollen, wird die Annotation @XmlRootElement vorangestellt.@XmlRootElement public class Person implements Serializable { private static final long serialVersionUID = 1L; private Long id; // ...Eine solche Person wird dann im REST-Server zur Verfügung gestellt. Dabei wird als Rückgabetyp einfach Person angegeben. Die Umwandung in XML erledigt JAXB im Hintergrund.
// ... Innerhalb der REST-Service-Klasse @GET @Path("person/id/{id}") @Produces(MediaType.APPLICATION_XML) public Person getXmlPerson( @PathParam("id") long id) { Person person = dao.getPerson(id); return person; }Der Client muss natürlich auch eine Klasse Person definieren, die sinnvollerweise identisch ist, um aus dem XML-String ein brauchbares Objekt zu machen. Auch der Client gibt @XmlRoot als Annotation an.
Verwendet der Client Jersey, kann er ebenso einfach angeben, dass XML verwendet werden soll und das Thema ist durch. Wird aber beispielsweise HttpUrlConnection direkt verwendet, muss das Client-Programm die Wandlung von XML in ein Objekt selbst durchführen.
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; // ... private Person getPerson(String url, int id) { url += "/api/person/id/" + id; Person person = null; try { // Der XML-String wird geholt (hier nicht näher ausgeführt. String xmlStr = verbindGetXmlString(url); // Setze den Kontext auf eine Person, baue den Ummarshaller JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); StringReader reader = new StringReader(xmlStr); person = (Person) unmarshaller.unmarshal(reader); // Zum Test ausgeben... System.out.println(person.getName()); } catch (IOException e) { e.printStackTrace(); } catch (JAXBException e) { e.printStackTrace(); } return person; } // ...
Im Array
In der Regel werden Personen nicht nur einzeln benötigt, sondern eine ganze Reihe davon. Bei REST ist das kein Problem, Sie geben lediglich an, dass Sie eine Liste meinen:@GET @Path("allpersons") @Produces(MediaType.APPLICATION_XML) public List<Person> getPersonen() {( List<Person> list = dao.getPersonenListe(); return list; }Auf Client-Seite müssen Sie nun eine neue Klasse erstellen, die die übertragene Liste als solche aufnimmt. Der REST-Server wird der automatisch erzeugten Listen-Klasse ein s anhängen. Die Listenklasse für Person heißt also Persons.
import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Persons implements Serializable { private static final long serialVersionUID = 6516481325506402152L; private List<Person> liste = new ArrayList<Person>(); public List<Person> getPerson() { return liste; } public void setPerson(List<Person> liste) { this.liste = liste; } }Das Programm wird nun ein Objekt von Persons entgegen nehmen und über die Methode getPerson an die Liste der Personen gelangen.
private static String getBuchungen(String url, int jahr, int monat) { url += "/api/allpersons/"; List<Person> liste = new ArrayList<Person>(); try { String xmlStr = verbindGetXmlString(url); JAXBContext jaxbContext = JAXBContext.newInstance(Persons.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); StringReader reader = new StringReader(xmlStr); Persons ps = (Persons) unmarshaller.unmarshal(reader); liste = ps.getPerson(); // Zum Test ausgeben for (Person p : liste) { System.out.println(p.getName()); } } catch (IOException e) { e.printStackTrace(); } catch (JAXBException e) { e.printStackTrace(); } return xmlStr;