# XML mit foreach SimpleXML auslesen, Kombinationen aus Werten bilden



## NTDY (13. Januar 2008)

Szenario eines XML Dokuments:

In einem Mehrfamilienhaus wohnt ein Mieter Axel. Als Untermieter leben mit ihm Berta und Claudia. 
Da diese in der 1. Etage wohnen, können diese nur Mietprobleme haben, zu den Mietern in der 2. Etage. 
In der zweiten Etage wohnen Andreas, und als Untermieter Bastian. 

Wenn es Ärger zwischen beiden Etagen gibt, dann gibt es diese Möglichkeiten, wer mit wem den Ärger haben kann:

Axel - Andreas
Axel - Bastian
Berta - Andreas 
Berta - Bastian
Claudia - Andreas
Claudia - Bastian

In der 3. Etage wohnt nur Stefan. Unter ihm wohnen Andreas und Bastian. Also ist die Ärger-Kombination:

Andreas - Stefan
Bastian - Stefan

3. und 4. Etage
Stefan - Torsten

Jetzt zur Verwunderung geht es mit der 4. Etage und der 1. Etage des 2 Mehrfamilienhauses weiter:
Mehrfamilienhaus 2 mit Oskar und Petra hat die Kombinationen:

Torsten – Oskar
Torsten – Petra

(Der Grund ist, dass das Problem in einer anderen Disziplin angewandt wird und ich nur abstrahieren wollte.)


```
<xml>
<mehrfamilienhaus id="1">
  <personen>
    <vorname>Axel</vorname>
    <nachname>Armon</nachname>
  </personen>
  <personen>
    <vorname>Berta</vorname>
    <nachname>Becker</nachname>
    <untermieter />
  </personen>
  <personen>
    <vorname>Claudia</vorname>
    <nachname>Chuck</nachname>
    <untermieter />
  </personen>
  <personen>
    <vorname>Andreas</vorname>
    <nachname>A.</nachname>
  </personen>
  <personen>
    <vorname>Bastian</vorname>
    <nachname>B.</nachname>
    <untermieter />
  </personen>
  <personen>
    <vorname>Stefan</vorname>
    <nachname>S.</nachname>
  </personen>
  <personen>
    <vorname>Torsten</vorname>
    <nachname>T.</nachname>
  </personen>
</mehrfamilienhaus>
<mehrfamilienhaus id="2">
  <personen>
    <vorname>Oskar</vorname>
    <nachname>Ombar</nachname>
  </personen>
  <personen>
    <vorname>Petra</vorname>
    <nachname>Peschke</nachname>
    <untermieter />
  </personen>
</mehrfamilienhaus>
</xml>
```

Ich möchte nun mit SimpleXML diese Datei auslesen und die oben erwähnten Kombinationen ausgeben lassen. Problem scheint aber zu sein, dass eine foreach Schleife stupide alle Objekte von XML durchgeht und man nicht im Array mit prev() und next() umherspringen kann, wie ich es mir vorstellen würde. Kennt jemand eine Möglichkeit wie ich die Kombinationen dennoch nach oben gewünschten Beispiel ausgeben lassen kann? Ich habe es schon

```
<?php
echo "<pre>";
$xml=simplexml_load_file("mehrfamilienhaeuser.xml");
foreach($xml->xpath("/xml/mehrfamilienhaus/personen") as $werte){
	echo $werte->vorname." ";
	echo $werte->nachname." ";  
	if(count($werte->xpath('untermieter')) > 0){
		echo "\tist Untermieter von\t$ist_mieter<br />";
	}else{
		echo "<br />";
		$ist_mieter = $werte->vorname." ".$werte->nachname;
	}
}
echo "</pre>";
?>
```

Diese Frage basiert auf dem Problem: In foreach den Arrayzeiger vor- und zurück bewegen
http://www.tutorials.de/forum/php/300974-foreach-den-arrayzeiger-vor-und-zurueck-bewegen.html


----------



## Hillkorn (14. Januar 2008)

Würde auf den ersten blick glatt erstmal behaupten das du den leuten die jeweiligen stockwerke noch hinzufügen solltest dann könntest du auch eher weiterkommen oder nicht?


----------



## kuddeldaddeldu (14. Januar 2008)

Hi,



> Jetzt zur Verwunderung geht es mit der 4. Etage und der 1. Etage des 2 Mehrfamilienhauses weiter:
> Mehrfamilienhaus 2 mit Oskar und Petra hat die Kombinationen:



Und dann? Kannst Du aus den Beispielen mal eindeutige Regeln ableiten? Vielleicht könnte man das Originalproblem besser verstehen...

Im Übrigen hat Hillkorn recht. Wenn Du jetzt plötzlich Mehrfamilienhäuser hast, muss das aus der XML-Struktur auch hervorgehen. D.h. "mehrfamilienhaus" hat "etagen" als Unterelemente, das wiederum "personen" als Unterelemente hat. Wozu ist eigentlich dieses leere Tag Untermieter da? Das hat doch auf Deine Kombinationsregeln gar keinen Einfluss. Würde man außerdem auch eher als Attribut realisieren (<person type="hauptmieter"> und <person type="untermieter">...

prev() und next() werden Dich auf keinen Fall weiterbringen. Warum arbeitest Du jetzt wieder mit einer simplen Schleife? Ich habe Dir in Deinem ersten Thread dazu doch schon gezeigt, wie Du mehrere Schleifen sinnvoll unter Verwendung von $key => $value schachteln kannst.

LG


----------



## NTDY (14. Januar 2008)

Also. Das Problem stammt aus der Musik und es handelt sich um die Spezifikation von MusicXML. In der Musik gibt es Noten oder Akkorde. Wenn ich einen Akkord in MusicXML abbilden will, dann nehme ich die unterste Note (der mieter) und stapele die Noten die zum Akkord gehören übereinander (die untermieter). In MusicXML bekommen alle Noten, die über der untersten liegen, das leere Element <chord/>

Das MusicXML Beispiel (gekürzt)

```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.0 Partwise//EN"
                                "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise>
  <!--=========================================================-->
  <part id="P1">
    <measure number="1">
      <note>
        <pitch>
          <step>C</step>
        </pitch>
      </note>
      <note>
        <chord/>
        <pitch>
          <step>F</step>
        </pitch>
      </note>
      <note>
        <chord/>
        <pitch>
          <step>A</step>
        </pitch>
      </note>
      <note>
        <pitch>
          <step>A</step>
        </pitch>
      </note>
      <note>
        <chord/>
        <pitch>
          <step>C</step>
        </pitch>
      </note>
      <note>
        <pitch>
          <step>F</step>
        </pitch>
      </note>
      <note>
        <pitch>
          <step>E</step>
        </pitch>
      </note>
    </measure>
    <!--=======================================================-->
    <measure number="2">
      <note>
        <pitch>
          <step>B</step>
        </pitch>
      </note>
      <note>
        <chord/>
        <pitch>
          <step>D</step>
        </pitch>
      </note>
      <note>
        <rest/>
      </note>
      <note>
        <rest/>
      </note>
    </measure>
  </part>
  <!--=========================================================-->
</score-partwise>
```

In Notendarstellung:

```
-------O---|----F
         O |    E
-----------|-O--D
    O      |    C
-----------|-O--H
 O  O      |    A
-----------|----G
 O         |    F
-----------|----E
-O-
```

Kombinationen:

1. Akkord zum 2. Akkord (Intervall) von Measure 1
C - A
C - C
F - A
F - C
A - A
A - C

2. Akkord (Intervall) zur 3. Note
A - F
C - F

3. Note zur 4. Note
F - E

4. Note zum 1. Akkord (Intervall) von Measure 2
E - D
E - H

Für die Musik würde dies bedeuten, dass ich theoretisch vom 1. Akkord zum 2. Akkord (Intervall) 6 Bewegungskombinationen einer Melodie bilden kann. Da eine Melodie nach einem Takt nicht aufhört, gibt es natürlich auch Kombinationen von der letzten Note / dem letzten Akkord zur neuen Note / neuen Akkord in measure(2)



> Warum arbeitest Du jetzt wieder mit einer simplen Schleife? Ich habe Dir in Deinem ersten Thread dazu doch schon gezeigt, wie Du mehrere Schleifen sinnvoll unter Verwendung von $key => $value schachteln kannst.



Die Schleifen arbeiten ja nur immer nur für einen Tag. Aber wenn ich tagübergreifend arbeite, dann funktioniert es nicht mehr. Bsp. letzte <note> in measure(1) und erster Akkord in measure(2)


----------



## kuddeldaddeldu (14. Januar 2008)

Hi,

siehst Du, das versteht man besser, als wenn sich Mieter der 4. Etage mit Mietern der 1. Etage des Nachbarhauses kloppen sollen. Da Du die XML-Struktur nicht ändern kannst, würde ich das Ganze auch nicht direkt verarbeiten, sondern in eine Array-Struktur packen, die sich besser verarbeiten lässt. Weil, die Takte, und was jetzt Grundton ist und was nicht, kann Dir da doch herzlich egal sein, oder? Und dann kannst Du einfach mein Array-Beispiel verwenden.

LG


----------

