# XML einlesen



## stefang1989 (18. Mrz 2010)

Hallo, ich hab schon ein bisschen im Forum gesucht, jedoch werde ich aus den Threads nicht wirklich schlau.

Ich muss für mein Programmierpraktikum im 2ten Semester eine XML Datei einlesen, die Informationen über einen Graphen enthält.
Die XML ist mit der GXL erstellt und sieht etwa so aus:

[XML]
<gxl>
    <graph id="id1">
        <node id="id2">
            <attr name="description">
                <string>n1</string>
            </attr>
            <attr name="x">
                <int>0</int>
            </attr>
            <attr name="y">
                <int>0</int>
            </attr>
        </node>
</gxl>
[/XML]

Nun stellt sich mir die Frage, wie ich an die einzelnen Elemente herankomme um meinen Knoten zu erzeugen.

Ich bin bisher so weit:


```
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(is);

NodeList nodes = doc.getElementsByTagName("node");
NodeList edges = doc.getElementsByTagName("edge");
```

Da komme ich jetzt nicht weiter. Ich schaff es nicht, aus den nodes.item(i) bestimmte Werte zu extrahieren und in Variablen zu speichern.

Bin Dankbar für jeden Ratschlag.

Liebe Grüße,
Stefan


----------



## Atze (18. Mrz 2010)

DocumentBuilder: parse(File f) : DocumentBuilderjavax.xml.parsersJava by API

vielleicht hilft dir das weiter


----------



## stefang1989 (18. Mrz 2010)

Tut mir leid :-/ Das hilft mir nicht wirklich weiter.

Ich bin ein ziemlicher Anfänger was Java angeht - sollte ich vielleicht noch sagen.

Ich hab schon versucht es so zu machen :


```
NodeList sections = document.getElementsByTagName("node");
for (int i = 0; i < sections.getLength(); i++) {
    Node knoten = sections.item(i);
    String desc = knoten.getFirstChild().getNextSibling().getTextContent().replace(" ", "").replace("\n", "");
}
```

Damit bekomm ich zwar speziell für meine XMLdatei die Daten. Aber das kanns ja nicht sein.

Gibts denn da nicht irgend ne einfachere Möglichkeit, die man auch als Anfänger verstehen kann?


----------



## Murray (18. Mrz 2010)

Etwas so (nur in den Editor gehackt, daher vermutlich nicht korrekt; das Prinzip dürfte aber klar werden):

```
NodeList sections = document.getElementsByTagName("node");
for (int i = 0; i < sections.getLength(); i++) {
    Element knoten = (Element)(sections.item(i));
    String id = knoten.getAttribute( "id");
    String description = null;
    int x = 0;
    int y = 0;
    NodeList attrs = knoten.getElementsByTagName("attr");
    for (int j = 0; j < attrs.getLength(); j++) {
        Element attr = (Element)(attrs.item( j));
        String name = attr.getAttribute( "name");
        if ( "description".equals( name)) {
           description = ((Element)(attr.getElementsByTagName( "string").item(0))).getTextContent();
        } else if ( "x".equals( name)) {
           x = Integer.parseInt( ((Element)(attr.getElementsByTagName( "int").item(0))).getTextContent());
        } else if ( "y".equals( name)) {
        	 y = Integer.parseInt( ((Element)(attr.getElementsByTagName( "int").item(0))).getTextContent());
        } else {
            throw new IllegalArgumentException( "attr.name=" + name);
        }
    }
}
```


----------



## dzim (18. Mrz 2010)

Gibt es denn zu diesem XML ein Schema? Also kein DTD...

Wenn nein, dann bau dir eins dazu. Eclipse z.B. bringt - entsprechend konfiguriert - einen graphischen Schema-Editor mit. Allerdings kannst du hier auch sicher aus einer Reihe von anderen freien Editoren wählen.

Wenn du dann ein Schema hast, generiere mittels des in Java enthaltenen Programs "xjc" die Mapping-Klassen dazu. Das "buzzword" hier ist JAXB.
Da findest du sicher viele einfache Beispiele im Netz.
Fakt ist, dass du dann nur ein mal das File mit der Quelle angeben musst und kannst danach einfach mittels normaler Java-Methoden über die Daten iterieren, da es intern dann konkrete Objekte, wie zum Beispiel Listen sind.


----------



## Atze (18. Mrz 2010)

stefang1989 hat gesagt.:


> Damit bekomm ich zwar speziell für meine XMLdatei die Daten. Aber das kanns ja nicht sein.



he, das willst du doch, oder? was willst du denn schreiben, nen parser für alle xmls? die gibts doch schon. du brauchst doch die daten für deinen speziellen fall, oder nicht?


----------



## Noctarius (18. Mrz 2010)

Zeigt auf die Signatur 
Einfach die beiden Tagnamen als Handler registrieren und weiterverarbeiten (brauchst nur ein XML-Schema .xsd)


----------



## stefang1989 (19. Mrz 2010)

Guten Abend bzw. Morgen 

Der Ansatz von Murray hat mir sehr geholfen. Danke!

Jetzt kann ich hier vielleicht grade noch die nächste Frage posten:

Habe nun folgenden Code:


```
public N createNode(Node element) {
        Element knoten = (Element) element;
        String id = knoten.getAttribute("id");
        String description = null;
        int x = 0;
        int y = 0;
        NodeList attrs = knoten.getElementsByTagName("attr");
        for (int j = 0; j < attrs.getLength(); j++) {
            Element attr = (Element) (attrs.item(j));
            String name = attr.getAttribute("name");
            if ("description".equals(name)) {
                description = ((Element) (attr.getElementsByTagName("string").item(0))).getTextContent();
            } else if ("x".equals(name)) {
                x = Integer.parseInt(((Element) (attr.getElementsByTagName("int").item(0))).getTextContent());
            } else if ("y".equals(name)) {
                y = Integer.parseInt(((Element) (attr.getElementsByTagName("int").item(0))).getTextContent());
            } else {
                throw new IllegalArgumentException("attr.name=" + name);
            }
        }
        N node = new N(); // Hier soll ein neues Element erzeugt werden.
        node.setId(id);
        return node;
    }
```

An der Stelle mit dem Kommentar soll nun ein neues Object vom Typ N erzeugt werden, das anschliessend zurückgegeben wird. Nun hänge ich fest, wie ich denn ein solches Objekt zur Laufzeit erzeugen kann? Geht das denn so? Oder habe ich da einen Denkfehler drin?

Vielen Dank schonmal - und nochmal an alle die was gepostet haben, besonders Murray  - Ich habs sogar verstanden 

Lg, Stefan


----------



## Noctarius (19. Mrz 2010)

```
knoten.getOwnerDocument().createElement(tagName);
```
Document (Java Platform SE 6)


----------



## Murray (19. Mrz 2010)

stefang1989 hat gesagt.:


> An der Stelle mit dem Kommentar soll nun ein neues Object vom Typ N erzeugt werden, das anschliessend zurückgegeben wird. Nun hänge ich fest, wie ich denn ein solches Objekt zur Laufzeit erzeugen kann? Geht das denn so? Oder habe ich da einen Denkfehler drin?


An der Stelle erzeugst du ja bereits eine neues Objekt vom Typ N und gibst es zurück - was ist also das Problem? Soll das neue N-Objekt neben der ID auch noch die anderen Merkmale des XML-Nodes haben? Dann können man einen passenden Konstruktor spendieren oder - wie bei der ID - entsprechende Setter aufrufen. Vielleicht postests du mal den Code von N.

Oder geht es wirklich darum, beim Parsen des XMLs neue Nodes anzulegen, wie Noctarius das beschrieben hat?


----------



## Noctarius (19. Mrz 2010)

Da sie wieder node als Variablen-Namen gewählt hat bin ich wieder von einem DOM-Node ausgegangen


----------



## Atze (19. Mrz 2010)

wer ist denn "sie"?


----------



## Noctarius (19. Mrz 2010)

Huch er


----------



## stefang1989 (19. Mrz 2010)

Guten Morgen,

An der entsprechenden Stelle soll ein Knoten in einem Graphen erstellt werden, dessen Datenstruktur ich selbst entworfen habe. Jedoch gibt es eben unterschiedliche Typen von Knoten. ( XYNode, XYZNode, ... ) Die alle jeweils unterschiedliche konstruktoren haben. Teil der Aufgabe ist es, eine allgemeingültige Lösung zu implementieren.

Hier mal beispielsweise der Konstruktor von XYNode :

```
/**
     * Erstellt einen neuen Knoten.
     * @param x x-Koordinate
     * @param y y-Koordinate
     * @param description Beschreibung des Knoten
     */
    public XYNode(String description, int x, int y) {
        xkoord = x;
        ykoord = y;
        desc = description;
    }
```

Das ganze sieht so aus:
Ich habe eine GXLSupport.java in der die methoden mit diesem N definiert werden, die XML datei eingelesen wird usw... Weiter habe ich eine XYGXLSupport die von der Klasse GXLSupport<XYNode> erbt. Über diese XYGXLSupport klasse lese ich dann mein File ein in dem XYNodes stehen.
Nun ist die Frage, ob ich in XYGXLSupport eine extra createNode methode überladen muss um einen XYNode zu erzeugen oder ob es möglich ist, der vererbenden Klasse zu sagen, welchen Typen sie erstellen soll ( sollte ja via N klappen ) und welchen Konstruktor sie verwenden soll.

Ist sowas möglich oder bin ich da auf dem falschen Weg?

Danke wiedermal 

Stefan


----------



## Noctarius (19. Mrz 2010)

Dann musst du ja an irgendwas unterscheiden können (z.B. Tagname) welche Instanz erzeugt werden soll. Wenn du alle diese Klassen vom selben Interface bzw der selben Superclass ableitest kannst du per If-ElseIf-Else Konstrukt instanzieren und Daten ausgeben.


----------



## Atze (19. Mrz 2010)

Noctarius hat gesagt.:


> Huch er



hehe, ich dachte du weißt mehr als wir


----------



## Noctarius (19. Mrz 2010)

Atze hat gesagt.:


> hehe, ich dachte du weißt mehr als wir



Das bestimmt *gg* ;-)


----------



## Atze (19. Mrz 2010)

ich rede nicht von dingen wie pornografie  *duck*


----------



## Stefang1989 (20. Mrz 2010)

Hallo,

Hab nun alles hinbekommen.
Das mit dem erstellen des Objects hatte ich nur falsch verstanden.
Habe nämlich eine abtrakte klasse, die hier von meinen Datenstrukturen erbt. Und habe aber zum einlesen und erstellen der knoten eine Typenfeste klasse gegeben.

Somit ist das Thema erledigt und kann geschlossen werden 

Vielen dank nochmals an alle die mir geholfen haben!!

Liebe Grüße,
Stefan


----------

