# Aus lesen einer XML-Datei ( 1 root, 3 childs)



## darkhawk (22. Sep 2011)

Hi, ich finde leider in Beispielen immer nur XML Dateien die 1 Root und 2 Childs haben, aber leider kein drittes. Leider kenne ich mich mit XML und Java nicht so gut aus.

Anbei habe ich ein Beispiel einer XML Datei die ich einlesen möchte und meinen Quellcode, nur irgendwie bekomme ich nur von "Punkt 1" den X-Wert ausgegeben, danach kommt eine "NullPointerException" und die Schleife bricht ab :/

wäre sehr nett wenn mir da jemand helfen könnte

[XML]<?xml version="1.0" encoding="utf-8"?>
<matrix version="2.0">
	<row number="1">

		<point number="1">
			<x>414.9969</x>
			<y>-708.5396</y>
			<z>-89.1267</z>
		</point>
		<point number="2">
			<x>445.4468</x>
			<y>-261.0712</y>
			<z>-36.6527</z>

		</point>
		<point number="3">
			<x>441.3276</x>
			<y>-138.7316</y>
			<z>-18.4372</z>
		</point>

	</row>
	<row number="2">

		<point number="2">
			<x>424.9969</x>
			<y>-708.5396</y>
			<z>-89.1267</z>
		</point>
		<point number="2">
			<x>455.4468</x>
			<y>-261.0712</y>
			<z>-36.6527</z>

		</point>
		<point number="3">
			<x>451.3276</x>
			<y>-138.7316</y>
			<z>-18.4372</z>
		</point>

	</row>
	<row number="3">

		<point number="1">
			<x>434.9969</x>
			<y>-708.5396</y>
			<z>-89.1267</z>
		</point>
		<point number="2">
			<x>465.4468</x>
			<y>-261.0712</y>
			<z>-36.6527</z>

		</point>
		<point number="3">
			<x>461.3276</x>
			<y>-138.7316</y>
			<z>-18.4372</z>
		</point>

	</row>
</matrix>[/XML]


```
import java.io.File;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class test {
	public static void main(String argv[]) {
		try {
			
			File xmlDatei = new File("C:/Users/admin-32/Desktop/Matrix.xml");
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(xmlDatei);
			doc.createDocumentFragment().normalize();		
			
			NodeList MatrixList = doc.getChildNodes();
			Node Matrix = MatrixList.item(0);
			
			
			NodeList Rows = Matrix.getChildNodes();
			for (int i=1; i<Rows.getLength();i++) {
				Node Row = Rows.item(i);
			
				NodeList Punkte = Row.getChildNodes();
				for (int j=1; j<Punkte.getLength();j++) {
					Node Punkt = Punkte.item(j);
			
					NodeList Koordinaten = Punkt.getChildNodes();
					for (int k=1; k<Koordinaten.getLength();k++) {
						Node Koordinate = Koordinaten.item(k);
						System.out.println(Koordinate.getFirstChild().getNodeValue());
					}
				}
			}
	
			System.out.println("-----------------------");
	

		  } catch (Exception e) { e.printStackTrace();}
	  }

}
```


----------



## nillehammer (22. Sep 2011)

Also bei allen Iterationen mit Index geht es normalerweise bei 0 los und nicht bei 1. Würde mich sehr wundern, wenn es bei NodeList anders wäre. Aus den javadocs ist das zumindest nicht ersichtlich. Probier also mal, Deine Schleifen mit i,j,k=0 los laufen zu lassen.


----------



## darkhawk (22. Sep 2011)

Hi, ich hatte anfangs auch alle bei 0 starten lassen das funktionerte nicht....

habe jetzt mal bischen was per Hand ausprobiert und bin auf dieses merkwürdige Ergebnis gestoßen:
 Die Schleifenvariablen i,j,k dürfen nur ungerade Werte annehmen, also 1,3,5 dann klappt es irgendwie, aber ist das NORMAL ??? Irgendwas muss ich doch hier falsch machen oder Zählt java von alleine irgendwie mit hoch ??


```
for (int i=1; i<Rows.getLength();i++) {
                Node Row = Rows.item(i);
                i++;
                NodeList Punkte = Row.getChildNodes();
                for (int j=1; j<Punkte.getLength();j++) {
                    Node Punkt = Punkte.item(j);
                    j++;
                    NodeList Koordinaten = Punkt.getChildNodes();
                    for (int k=1; k<Koordinaten.getLength();k++) {
                        Node Koordinate = Koordinaten.item(k);
                        System.out.println(Koordinate.getFirstChild().getNodeValue());
                        k++;
                    }
                }
            }
```


----------



## nillehammer (22. Sep 2011)

Hmm, sehr strange. Java zählt eigentlich nix von sich aus hoch. Und auch bei dem index=0 bin ich mir ziemlich sicher. sonst würde diese Zeile ja auch nicht funktionieren:

```
Node Matrix = MatrixList.item(0);
```
Und die Javadoc-Beschreibung macht das auch deutlich, dass der Index bei 0 losgeht. Siehe hier:NodeList#getLength()

Ansonsten ist mir nur ein unnötiges Statement in Deinem Code aufgefallen. Ersetze Zeile 17

```
doc.createDocumentFragment().normalize();
```
durch das hier:

```
doc.normalizeDocument();
```

Ach ja, und Variablennamen (row, punkt, koordinate) bitte klein geschrieben. Aber das ist nur eine Stilfrage und hilft dir bei Deinem Problem nicht weiter...


----------



## nillehammer (22. Sep 2011)

Ahh ok, jetzt hab ich das mit dem Index gerafft. Das Attribut des jeweiligen Elements (number) ist wahrscheinlich das erste Child. Danach kommen erst die Child-*Elemente*. Deswegen war es schon richtig, den Index bei 1 loslaufen zu lassen. Das könnte auch der Grund sein, warum die Iteration insgesamt nicht funktioniert. Vielleicht hat er noch andere Nodes in der NodeList als die, die Du denkst. Lass Dir mal das Ergebnis von getLength() ausgeben, wenn das größer als der erwartete Wert ist, hast du noch andere Sachen in der NodeList.


----------



## darkhawk (22. Sep 2011)

Danke... werde das mit den Variablennamen mir mal angewöhnen. 

Habe jetzt auch meine Zeile 17 durch das ersetzt

```
doc.normalizeDocument();
```


Die Länge ist jeweils 7 das könnte irgendwie stimmen mit dem ersten CHild "number". Dann darf da ja keiner was an den Attributen ändern, sonst passen meine Schleifen ja garnicht. Kann ich das irgendwie umgehen, dass der die Attribute "number" und vlt andere die noch hinzukommen könnten nicht mitzählt?


----------



## nillehammer (23. Sep 2011)

Da gibt es viele Möglichkeiten. Du könntest so wie jetzt durch alle children iterieren, aber nur die children auswerten, die Elemente sind. Das bedeutet die wenigsten Änderungen an Deinem Code. Ist aber unsicher, wenn jemand unerwartete Elemente einfügt. Das sähe dann so aus:

```
//... Code wie bisher ...//
// Hier der veränderte Code //
for (int i=1; i<Rows.getLength();i++) {
                Node Row = Rows.item(i);
                 // Wenn child kein Element, dann abbrechen und mit nächstem child weiter machen.
                if (Node.ELEMENT_NODE!= Row.getNodeType(){
                  continue;
                }
                NodeList Punkte = Row.getChildNodes();
                for (int j=0; j<Punkte.getLength();j++) {
                    Node Punkt = Punkte.item(j);
                    // Wenn child kein Element, dann abbrechen und mit nächstem child weiter machen.
                    if (Node.ELEMENT_NODE!= Punkt.getNodeType(){
                      continue;
                    }
                    NodeList Koordinaten = Punkt.getChildNodes();
                    for (int k=0; k<Koordinaten.getLength();k++) {
                        Node Koordinate = Koordinaten.item(k);
                        // Wenn child kein Element, dann abbrechen und mit nächstem child weiter machen.
                        if (Node.ELEMENT_NODE!= Koordinate.getNodeType(){
                          continue;
                        }
                        System.out.println(Koordinate.getFirstChild().getNodeValue());
                    }
                }
            }
    
            System.out.println("-----------------------");
    
 
          } catch (Exception e) { e.printStackTrace();}
```
Eine andere Möglichkeit wäre, mit Element statt mit Node zu arbeiten. Das ist noch etwas sicherer. Jetzt können auch unerwartete Elemente nichts kaputt machen. Fehlende natürlich schon. Das sähe dann so aus:

```
// Wir wissen, dass MatrixList.item(0) ein Element zurück liefert. Deswegen können wir casten.
          Element Matrix = (Element) MatrixList.item(0);
            
            // So kriegen wir nur Elemente mit Tag-Namen "row" alles andere bleibt draußen.
            NodeList Rows = Matrix.getElementsByTagName("row");
            for (int i=0; i<Rows.getLength();i++) {
                // Rows enthält nur Element, wir können gefahrlos casten.
                Element Row = (Element) Rows.item(i);
            
                NodeList Punkte = Row.Matrix.getElementsByTagName("point");
                for (int j=0; j<Punkte.getLength();j++) {
                    Element Punkt = (Element) Punkte.item(j);
                    Node x = Punkt.getElementsByTagName("x").item(0);
                    Node y = Punkt.getElementsByTagName("y").item(0);
                    Node z = Punkt.getElementsByTagName("z").item(0);
                    System.out.println(x.getFirstChild());
                    System.out.println(y.getFirstChild());
                    System.out.println(z.getFirstChild());
                }
            }
    
            System.out.println("-----------------------");
    
 
          } catch (Exception e) { e.printStackTrace();}
      }
```
Eine letzte Möglichkeit wäre die Nutzung von XPATH.


----------



## darkhawk (5. Okt 2011)

Danke )

letzteres mir den Elementen klingt sehr gut. Es dürfen eh nur weitere Punkte mit allen Koordinaten hinzugefügt werden und es werden auch immer alle Koordinaten gebraucht. 

ich danke dir


----------

