# XML Knoten mit rekursiver Methode auslesen



## Enigma228 (17. Jul 2009)

Hallo!

Ich möchte einen Personenknoten aus dem Xml-Dokument an eine spezielle rekursive Funktion übergeben, welche true oder false zurückgibt je nachdem ob Treffer vorliegt.
die Suchoptionen werden in Form einer Hashmap übergeben. 
(z.B. Name(Schlüssel) , Wasser und Adresse(Schlüssel), willywasser@web.de)
ich habe das ganze mit loggen lassen und er gibt mir auch einen Treffer an aber er übergibt ihn nicht an die Hauptfunktion.
Wo liegt mein Fehler?

XML-Datei:

```
<?xml version="1.0" encoding="iso-8859-1"?>
<Verzeichnis>
    <Person>
        <Index>1244735513374</Index>
        <Name>Karlsen</Name>
        <Vorname>Bärbel</Vorname>
        <Strasse>Am Karlsberg</Strasse>
        <Nr>17</Nr>
        <Plz>53684</Plz>
        <Ort>Karlsburg</Ort>
        <Msn>
            <Landesvorwahl>0049</Landesvorwahl>
            <Vorwahl>04875</Vorwahl>
            <RufNr>369852</RufNr>
            <Typ>Tel</Typ>
            <Nutzung>privat</Nutzung>
            <Bemerkung>keine</Bemerkung>
        </Msn>
        <Msn>
            <Landesvorwahl>0049</Landesvorwahl>
            <Vorwahl>0176</Vorwahl>
            <RufNr>5248745</RufNr>
            <Typ>Handy</Typ>
            <Nutzung>privat</Nutzung>
            <Bemerkung>keine</Bemerkung>
        </Msn>
    </Person>
    <Person>
        <Index>1244733096384</Index>
        <Name>Wasser</Name>
        <Vorname>Willy</Vorname>
        <Strasse>Wasserstr.</Strasse>
        <Nr>12</Nr>
        <Plz>12534</Plz>
        <Ort>Wasserstadt</Ort>
        <Msn>
            <Landesvorwahl>0049</Landesvorwahl>
            <Vorwahl>03859</Vorwahl>
            <RufNr>24153</RufNr>
            <Typ>Tel</Typ>
            <Nutzung>privat</Nutzung>
            <Bemerkung>keine</Bemerkung>
        </Msn>
        <Mail>
            <Adresse>WillyWasser@web.de</Adresse>
            <Info>keine</Info>
        </Mail>
    </Person>
</Verzeichnis>
```

Hauptfunktion: hier wird die Person an eine durchsuchende rekursive Funktion übergeben und wenn ein Treffer vorliegt, als TreeSet an den Rest des Programms weitergeleitet:

```
// Einträge werden gesucht
	public TreeSet<Person> searchEntry(HashMap<String,String> hm){
		TreeSet<Person> ts = new TreeSet<Person>();
		nl = doc.getElementsByTagName("Person");
		int temp = nl.getLength(); // Anzahl der Personen in XML Datei
		for (int i=0;i<temp;i++){	// gehen jetzt die einzelnen Personen der Nodelist nl durch
			System.out.println(""+i+". Person wird übergeben");
			if(recursiveMethod(nl.item(i), hm, false,0)){
				ts.add(changeNodeToPerson(nl.item(i).getChildNodes()));
				System.out.println("Person wurde zugefügt");
			}
		}
		return ts;
	}
```

Funktion zum Durchsuchen der übergebenen Nodelist einer Person:

```
public boolean recursiveMethod(Node n, HashMap<String,String> hm, boolean treffer, int funktionsaufrufe){
		if (n.hasChildNodes()){
			for(int i=0;i<n.getChildNodes().getLength();i++){
				recursiveMethod(n.getChildNodes().item(i), hm, treffer, funktionsaufrufe+1);
			}
		}else{
			System.out.println(n.getTextContent()+" -> n hat keine Kindknoten");
			for(String a: hm.keySet()){ // Hashmap wird hier durchgegangen
				if(n.getNodeName().equals(a)){
					if(n.getTextContent().equals(hm.get(a))){
						treffer = true;
						System.out.println("treffer");
					}else treffer = false;
				}
			}
		}
		System.out.println("Anzahl: "+funktionsaufrufe);
		return treffer;
}
```


----------



## Murray (19. Jul 2009)

Wenn n Child-Nodes hat, wird zwar die Methode rekursiv aufgerufen; die Return-Werte dieser rekursiven Aufrufen werden aber nicht ausgewertet; stattdessen wird der als Parameter übergebene Wert für _treffer_ zurückgeliefert.


----------



## Enigma228 (19. Jul 2009)

Also eine globale Boolean Variable?


----------



## Enigma228 (22. Jul 2009)

habe eine globale Boolean Variable  (b_treffer) eingebaut. soweit ok, aber..
da eine Person ja mehrere MSNs haben kann, kann es vorkommen das das richtige Ergebnis im der ersten MSN da ist und in der 2. MSN aber die globale Boolean Variable wieder negiert wird weil ja dort die Rufnummer nicht mehr stimmt und somit ist die Person wieder kein Treffer obwohl er es sein sollte..


Daraufhin habe ich den gefundenen Treffer aus der Hashmap entfernt und bekomme leider dann eine 
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
	at java.util.HashMap$KeyIterator.next(Unknown Source)
	at doc.DomParser.recursiveMethod(DomParser.java:146) usw.


Der Fehler tritt nachdem die Hashmap komplett leer sein sollte..
er macht den Fehler also erst wenn der zweite von zwei Schlüsseln aus der Liste genommen wurde..
kurzer Auszug aus den Sysout-Ergebnissen:
...
Hat n Kindknoten?
n hat Kindknoten!
Prüfe mit hilfe der Hashmap den TextContent und Nodename
Derzeit gesuchter Schlüssel ist: Name
Ist n ein Elementknoten?
n ist ein Elementknoten!
Ist Textcontent: Karlsen = Wert der Hashmap Karlsen
Wert der Hashmap stimmt überein mit Textcontent
B_treffer ist true
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
	at java.util.HashMap$KeyIterator.next(Unknown Source)
	at doc.DomParser.recursiveMethod(DomParser.java:146) usw.


Was kann ich noch tun?


```
// Einträge werden gesucht
	public TreeSet<Person> searchEntry(HashMap<String,String> hm){
		TreeSet<Person> ts = new TreeSet<Person>();
		 
		b_treffer = false;
		nl = doc.getElementsByTagName("Person");
		HashMap<String,String> hm2 = new HashMap<String, String>(hm);
		int temp = nl.getLength(); // Anzahl der Personen in XML Datei
		for (int i=0;i<temp;i++){	// gehen jetzt die einzelnen Personen der Nodelist nl durch
			System.out.println(""+i+". Person wird übergeben");
			hm2 = new HashMap<String, String>(hm);
			recursiveMethod(nl.item(i), hm2, 0);
			System.out.println("Funktion komplett durch : b_treffer ist "+b_treffer);
			if(b_treffer){
				ts.add(changeNodeToPerson(nl.item(i).getChildNodes()));
				System.out.println("Person wurde zugefügt");
				b_treffer = false;
			}
		}
		return ts;
	}
	
	// Übergebener Personenknoten wird rekursiv durchsucht
	public void recursiveMethod(Node n, HashMap<String,String> hm2, int funktionsaufrufe){
		System.out.println("Name des Knotens: "+n.getNodeName());
		System.out.println("Hat n Kindknoten?");
		if (n.hasChildNodes()){
			System.out.println("n hat Kindknoten!");
			System.out.println("Prüfe mit hilfe der Hashmap den TextContent und Nodename");
			for (String a:hm2.keySet()){
				System.out.println("Derzeit gesuchter Schlüssel ist: "+ a);
				System.out.println("Ist n ein Elementknoten?");
				if(n.getNodeType() == Node.ELEMENT_NODE){
					System.out.println("n ist ein Elementknoten!");
					System.out.println("Ist Textcontent: "+n.getTextContent()+" = Wert der Hashmap "+hm2.get(a));
					if(n.getNodeName().equals(a)){
						if(n.getTextContent().equals(hm2.get(a))){
							System.out.println("Wert der Hashmap stimmt überein mit Textcontent");
							b_treffer = true;
							hm2.remove(a); // getroffenes Element wird aus Hashmap entfernt
							System.out.println("B_treffer ist "+b_treffer);
							if(hm2.isEmpty()){
								break;
							}
						}else {
							System.out.println("Keine Übereinstimmung Wert der Hashmap mit Textcontent");
							System.out.println("Abbruch der Hashmapabfrage");
							b_treffer = false;
							break;
						}
					}
					
				}
			}
			System.out.println("Kindknoten wird rekursiv neu aufgerufen");
			for(int i=0;i<n.getChildNodes().getLength();i++){
				System.out.println("Name des Knotens mit Kindknoten vor der rek. Übergabe: "
						+n.getChildNodes().item(i).getNodeName());
				if(n.getChildNodes().item(i).getNodeType()== Node.ELEMENT_NODE){
					recursiveMethod(n.getChildNodes().item(i), hm2, funktionsaufrufe+1);
				}
				
			}
		}
		System.out.println("Anzahl: "+funktionsaufrufe);
	}
```


----------

