XML einlesen

  • Themenstarter Themenstarter stefang1989
  • Beginndatum Beginndatum
S

stefang1989

Gast
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:

Java:
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
 
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 :

Java:
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?
 
Etwas so (nur in den Editor gehackt, daher vermutlich nicht korrekt; das Prinzip dürfte aber klar werden):
Java:
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);
        }
    }
}
 
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.
 
Zeigt auf die Signatur 😀
Einfach die beiden Tagnamen als Handler registrieren und weiterverarbeiten (brauchst nur ein XML-Schema .xsd)
 
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:

Java:
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
 
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?
 
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 :
Java:
/**
     * 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
 
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.
 
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
 

Zurück
Oben