Skip to content

5. XML und PHP

In diesem Kapitel geben wir eine Einführung in die Verwendung von XML-Dokumenten (eXtensible Markup Language) mit PHP. Dies geschieht im Kontext der im vorigen Kapitel behandelten Steueranwendung.

5.1. XML-Dateien und XSL-Stylesheets

Betrachten wir die folgende Datei XML, die das Ergebnis von Simulationen darstellen könnte:

<?xml version="1.0" encoding="windows-1252"?>
<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>
  <simulation marie="non" enfants="2" salaire="200000" impot="33388"/>
</simulations>

Wenn man dies mit IE 6 anzeigt, erhält man folgendes Ergebnis:

Image

IE6 erkennt, dass es sich um eine Datei XML handelt (dank der Dateiendung .xml), und formatiert sie auf seine eigene Weise. Mit Netscape erhält man eine leere Seite. Betrachtet man jedoch den Quellcode (Ansicht/Quelltext), so findet man tatsächlich die ursprüngliche Datei XML:

Image

Warum zeigt Netscape nichts an? Weil es ein Stylesheet benötigt, das ihm vorschreibt, wie die Datei „XML“ in die Datei „HTML“ umgewandelt werden muss, die es dann anzeigen kann. Nun verfügt IE 6 über ein Standard-Stylesheet, während die Datei XML kein solches enthält, was hier der Fall war.

Es gibt eine Sprache namens XSL (eXtensible StyleSheet Language), mit der sich die Umwandlungen beschreiben lassen, die erforderlich sind, um eine XML-Datei in eine beliebige Textdatei umzuwandeln. XSL ermöglicht die Verwendung zahlreicher Anweisungen und ähnelt stark den Programmiersprachen. Wir werden hier nicht näher darauf eingehen, da dies mehrere Dutzend Seiten in Anspruch nehmen würde. Wir werden lediglich zwei Beispiele für XSL-Stylesheets beschreiben. Das erste ist dasjenige, das die Datei XML simulations.xml in HTML-Code umwandelt. Dieses wird so geändert, dass es auf das Stylesheet verweist, das die Browser verwenden können, um es in das Dokument HTML umzuwandeln, das sie dann anzeigen können:

<?xml version="1.0" encoding="windows-1252"?>
<?xml-stylesheet type="text/xsl" href="simulations.xsl"?>
<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>
  <simulation marie="non" enfants="2" salaire="200000" impot="33388"/>
</simulations>

Die Bestellung XML

<?xml-stylesheet type="text/xsl" href="simulations.xsl"?>

bezeichnet die Datei simulations.xsl als Stylesheet (xml-stylesheet) vom Typ text/xsl c.a.d. Eine Textdatei, die den Code XSL enthält. Dieses Stylesheet wird von Browsern verwendet, um den Text XML in ein Dokument HTML umzuwandeln. Hier ist das Ergebnis, das mit Netscape 7 beim Laden der Datei XML simulations.xml erzielt wird:

Image

Wenn wir uns den Quellcode des Dokuments ansehen (Ansicht/Quelltext), finden wir das ursprüngliche Dokument XML vor und nicht das angezeigte Dokument HTML:

Image

Netscape hat das Stylesheet simulations.xsl verwendet, um das oben genannte Dokument XML in das anzeigbare Dokument HTML umzuwandeln. Nun ist es an der Zeit, uns den Inhalt dieses Stylesheets anzusehen:

<?xml version="1.0" encoding="windows-1252"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" indent="yes"/>

    <xsl:template match="/">
        <html>
          <head>
            <title>Simulations de calculs d'impôts</title>
        </head>
          <body>
            <center>
              <h3>Simulations de calculs d'impôts</h3>
            <hr/>
            <table border="1">
                    <th>marié</th><th>enfants</th><th>salaire</th><th>impôt</th>
                          <xsl:apply-templates select="/simulations/simulation"/>
                        </table>
         </center>
       </body>
     </html>
        </xsl:template>


    <xsl:template match="simulation">
          <tr>
            <td><xsl:value-of select="@marie"/></td>
            <td><xsl:value-of select="@enfants"/></td>
            <td><xsl:value-of select="@salaire"/></td>
            <td><xsl:value-of select="@impot"/></td>
        </tr>
       </xsl:template>
  </xsl:stylesheet>
  • Ein Stylesheet XSL ist eine XML-Datei und folgt daher deren Regeln. Es muss unter anderem „wohlgeformt“ sein, d. h., jeder geöffnete Tag muss geschlossen werden.
  • Die Datei beginnt mit zwei Befehlen XML, die in jedem Stylesheet XSL unter Windows beibehalten werden können:
<?xml version="1.0" encoding="windows-1252"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

Das Attribut encoding="windows-1252" ermöglicht die Verwendung von Zeichen mit Akzenten im Stylesheet.

  • Das Tag <xsl:output method="html" indent="yes"/> weist den Interpreter XSL an, „eingrücktes“ HTML zu erzeugen.
  • Das Tag <xsl:template match="Element"> dient dazu, das Element des XML-Dokuments zu definieren, auf das die Anweisungen angewendet werden sollen, die sich zwischen <xsl:template ...> und </xsl:template> befinden.
    <xsl:template match="/">
................
        </xsl:template>

Im obigen Beispiel bezeichnet das Element „/“ die Wurzel des Dokuments. Das bedeutet, dass, sobald der Anfang des Dokuments XML erreicht wird, die Befehle XSL, die sich zwischen den beiden Tags befinden, ausgeführt werden.

  • Alles, was kein XSL-Tag ist, wird unverändert in den Ausgabestrom übernommen. Die XSL-Tags werden ausgeführt. Einige davon erzeugen ein Ergebnis im Ausgabestrom. Betrachten wir das folgende Beispiel:
    <xsl:template match="/">
        <html>
          <head>
            <title>Simulations de calculs d'impôts</title>
        </head>
          <body>
            <center>
              <h3>Simulations de calculs d'impôts</h3>
            <hr/>
            <table border="1">
                    <th>marié</th><th>enfants</th><th>salaire</th><th>impôt</th>
                          <xsl:apply-templates select="/simulations/simulation"/>
                        </table>
          </center>
        </body>
      </html>
        </xsl:template>

Zur Erinnerung: Das analysierte Dokument XML lautet wie folgt:

<?xml version="1.0" encoding="windows-1252"?>
<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>
  <simulation marie="non" enfants="2" salaire="200000" impot="33388"/>
</simulations>

Gleich zu Beginn des analysierten Dokuments XML (match="/") gibt der Interpreter XSL den folgenden Text aus

<html>
          <head>
            <title>Simulations de calculs d'impôts</title>
        </head>
          <body>
            <center>
              <h3>Simulations de calculs d'impôts</h3>
            <hr>
            <table border="1">
                    <th>marié</th><th>enfants</th><th>salaire</th><th>impôt</th>

Es ist zu beachten, dass im Ausgangstext <hr/> stand und nicht <hr>. Im Ausgangstext konnte man nicht <hr> schreiben, da dies zwar ein gültiges HTML-Tag ist, aber ein ungültiges XML-Tag. Wir haben es hier jedoch mit einem XML-Text zu tun, der „wohlgeformt“ sein muss, d. h., dass jedes Tag geschlossen werden muss. Man schreibt also <hr/>, und da man <xsl:output text="html ..."> geschrieben hat, wandelt der Interpreter den Text <hr/> in <hr> um. Hinter diesem Text folgt dann der durch den Befehl XSL erzeugte Text:

      <xsl:apply-templates select="/simulations/simulation"/>

Wir werden später sehen, um welchen Text es sich dabei handelt. Schließlich fügt der Interpreter den Text hinzu:

                    </table>
          </center>
        </body>
      </html>

Der Befehl <xsl:apply-templates select="/simulations/simulation"/> fordert die Ausführung der „Vorlage“ (Template) des Elements /simulations/simulation an. Sie wird jedes Mal ausgeführt, wenn der Interpreter XSL im analysierten Text XML ein Tag <simulation>..</simulations> oder <simulation/> innerhalb eines Tags <simulations>..</simulations> findet. Wenn ein solches Tag gefunden wird, führt der Interpreter die Anweisungen des folgenden Modells aus:

    <xsl:template match="simulation">
          <tr>
            <td><xsl:value-of select="@marie"/></td>
            <td><xsl:value-of select="@enfants"/></td>
            <td><xsl:value-of select="@salaire"/></td>
            <td><xsl:value-of select="@impot"/></td>
        </tr>
       </xsl:template>

Betrachten wir die folgenden Zeilen XML:

<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>

Die Zeile <simulation ..> entspricht der Vorlage der Anweisung XSL <xsl:apply-templates select="/simulations/simulation>". Der Interpreter XSL wird daher versuchen, die Anweisungen, die dieser Vorlage entsprechen, darauf anzuwenden. Er findet die Vorlage <xsl:template match="simulation"> und führt sie aus. Zur Erinnerung: Alles, was kein Befehl XSL ist, wird vom Interpreter XSL unverändert übernommen, während die Befehle XSL durch das Ergebnis ihrer Ausführung ersetzt werden. Die Anweisung XSL <xsl:value-of select="@champ"/> wird somit durch den Wert des Attributs „champ“ des analysierten Knotens (hier ein <simulation>-Knoten) ersetzt. Die Analyse der vorhergehenden Zeile XML führt zu folgendem Ergebnis:

XSL
Ausgabe
<tr><td>
<tr><td>
<xsl:value-of select="@marie"/>
ja
</td><td>
</td><td>
<xsl:value-of select="@enfants"/>
2
</td><td>
</td><td>
<xsl:value-of select="@salaire"/>
200000
</td><td>
</td><td>
<xsl:value-of select="@impot"/>
22504
</td></tr>
</td></tr>

Insgesamt die Zeile XML

<simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>

wird in die Zeile HTML umgewandelt:

<tr><td>oui</td><td>2</td><td>200000</td><td>22504</td></tr>

All diese Erklärungen sind zwar etwas rudimentär, aber dem Leser sollte nun klar sein, dass der folgende Text „XML“:

<?xml version="1.0" encoding="windows-1252"?>
<?xml-stylesheet type="text/xsl" href="simulations.xsl"?>
<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>
  <simulation marie="non" enfants="2" salaire="200000" impot="33388"/>
</simulations>

zusammen mit dem folgenden Stylesheet XSL simulations.xsl:

<?xml version="1.0" encoding="windows-1252"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" indent="yes"/>

    <xsl:template match="/">
        <html>
          <head>
            <title>Simulations de calculs d'impôts</title>
        </head>
          <body>
            <center>
              <h3>Simulations de calculs d'impôts</h3>
            <hr/>
            <table border="1">
                    <th>marié</th><th>enfants</th><th>salaire</th><th>impôt</th>
                          <xsl:apply-templates select="/simulations/simulation"/>
                        </table>
         </center>
       </body>
     </html>
        </xsl:template>


    <xsl:template match="simulation">
          <tr>
            <td><xsl:value-of select="@marie"/></td>
            <td><xsl:value-of select="@enfants"/></td>
            <td><xsl:value-of select="@salaire"/></td>
            <td><xsl:value-of select="@impot"/></td>
        </tr>
       </xsl:template>
  </xsl:stylesheet>

erzeugt den folgenden Text: HTML:

<html>
<head>
<title>Simulations de calculs d'impôts</title>
</head>
<body>
<center>
<h3>Simulations de calculs d'impots</h3>
<hr>
<table border="1">
<th>marié</th><th>enfants</th><th>salaire</th><th>impôt</th>
<tr>
<td>oui</td><td>2</td><td>200000</td><td>22504</td>
</tr>
<tr>
<td>non</td><td>2</td><td>200000</td><td>33388</td>
</tr>
</table>
</center>
</body>
</html>

Die folgende Datei: XML simulations.xml

<?xml version="1.0" encoding="windows-1252"?>
<?xml-stylesheet type="text/xsl" href="simulations.xsl"?>
<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>
  <simulation marie="non" enfants="2" salaire="200000" impot="33388"/>
</simulations>

wird von einem aktuellen Browser (hier Netscape 7) wie folgt angezeigt:

Image

5.2. Steueranwendung: Version 5

5.2.1. Die Dateien XML und die Stylesheets XSL der Steueranwendung

Kehren wir zu unserem Ausgangspunkt zurück, nämlich der Webanwendung für Steuern, und erinnern wir uns daran, dass wir diese so ändern möchten, dass die Antwort an die Kunden im Format XML statt im Format HTML erfolgt. Diese Antwort „HTML“ wird von einem Stylesheet „XSL“ begleitet, damit die Browser sie anzeigen können. Im vorigen Absatz haben wir Folgendes vorgestellt:

  • die Datei simulations.xml, die den Prototyp einer Antwort XML mit simulierten Steuerberechnungen darstellt
  • die Datei simulations.xsl, die das Stylesheet XSL darstellt, das dieser Antwort XML beigefügt wird

Wir müssen auch den Fall einer Antwort mit Fehlern berücksichtigen. Der Prototyp der Antwort XML ist in diesem Fall die folgende Datei erreurs.xml:

<?xml version="1.0" encoding="windows-1252"?>
<?xml-stylesheet type="text/xsl" href="erreurs.xsl"?>
<erreurs>
    <erreur>erreur 1</erreur>
  <erreur>erreur 2</erreur>
</erreurs>

Das Stylesheet erreurs.xsl, mit dem dieses Dokument XML in einem Browser angezeigt werden kann, sieht wie folgt aus:

<?xml version="1.0" encoding="windows-1252"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" indent="yes"/>

    <xsl:template match="/">
        <html>
          <head>
            <title>Simulations de calculs d'impôts</title>
        </head>
          <body>
            <center>
              <h3>Simulations de calculs d'impôts</h3>
          </center>            
          <hr/>
          Les erreurs suivantes se sont produites :
          <ul>
                  <xsl:apply-templates select="/erreurs/erreur"/>
              </ul>            
        </body>
      </html>
        </xsl:template>

    <xsl:template match="erreur">
          <li><xsl:value-of select="."/></li>
        </xsl:template>
</xsl:stylesheet>    

Dieses Stylesheet führt einen bisher noch nicht vorkommenden Befehl XSL ein: <xsl:value-of select="."/>. Dieser Befehl gibt den Wert des analysierten Knotens aus, in diesem Fall einen Knoten <erreur>texte</erreur>. Der Wert dieses Knotens ist der Text zwischen dem öffnenden und dem schließenden Tag, hier texte.

Der Code erreurs.xml wird durch das Stylesheet erreurs.xsl in das folgende Dokument HTML umgewandelt:

<html>
<head>
<title>Simulations de calculs d'impots</title>
</head>
<body>
<center>
<h3>Simulations de calculs d'impots</h3>
</center>
<hr>
          Les erreurs suivantes se sont produites :
          <ul>
<li>erreur 1</li>
<li>erreur 2</li>
</ul>
</body>
</html>

Die Datei erreurs.xml wird zusammen mit ihrem Stylesheet von einem Browser wie folgt angezeigt:

Image

5.2.2. Die Anwendung „xmlsimulations“

Wir erstellen eine Datei xmlsimulations.html, die wir im Verzeichnis der Anwendung „impots“ ablegen. Die angezeigte Seite sieht wie folgt aus:

Image

Dieses Dokument „HTML“ ist ein statisches Dokument. Sein Code lautet wie folgt:

<html>
    <head>
      <title>impots</title>
    <script language="JavaScript" type="text/javascript">
        function effacer(){
           // Formular zurücksetzen
        with(document.frmImpots){
            optMarie[0].checked=false;
          optMarie[1].checked=true;
          txtEnfants.value="";
          txtSalaire.value="";
          txtImpots.value="";
        }//mit
      }//Löschen

      function calculer(){
           // Überprüfung der Parameter vor dem Absenden an den Server
        with(document.frmImpots){
          //Anzahl der Kinder
          champs=/^\s*(\d+)\s*$/.exec(txtEnfants.value);
          if(champs==null){
            // Das Formular wurde nicht überprüft
            alert("Le nombre d'enfants n'a pas été donné ou est incorrect");
            nbEnfants.focus();
            return;
          }//if
           //Gehalt
          champs=/^\s*(\d+)\s*$/.exec(txtSalaire.value);
          if(champs==null){
            // Das Modell wurde nicht überprüft
            alert("Le salaire n'a pas été donné ou est incorrect");
            salaire.focus();
            return;
          }//wenn
          // Alles in Ordnung – wird gesendet
          submit();
        }//mit
      }//berechnen        
        </script>
  </head>

  <body background="/poly/impots/7/images/standard.jpg">
      <center>
        Calcul d'impôts
        <hr>
      <form name="frmImpots" action="/poly/impots/7/xmlsimulations.php" method="POST">
          <table>
            <tr>
              <td>Etes-vous marié(e)</td>
            <td>
                <input type="radio" name="optMarie" value="oui">oui
              <input type="radio" name="optMarie" value="non" checked>non
            </td>
          </tr>
          <tr>
              <td>Nombre d'enfants</td>
            <td><input type="text" size="3" name="txtEnfants" value=""></td>
          </tr>
          <tr>
              <td>Salaire annuel</td>
            <td><input type="text" size="10" name="txtSalaire" value=""></td>
          </tr>
          <tr></tr>
          <tr>
              <td><input type="button" value="Calculer" onclick="calculer()"></td>
            <td><input type="button" value="Effacer" onclick="effacer()"></td>
          </tr>
        </table>
      </form>
    </center>
 </body>
</html>

Es sei darauf hingewiesen, dass die Daten des Formulars an URL /poly/impots/7/xmlsimulations.php gesendet werden. Der Code der Anwendung xmlsimulations.php ist dem der Anwendung impots.php sehr ähnlich. Der Leser wird gebeten, diesen noch einmal durchzugehen. Zur Erinnerung: Der Eingabecode lautet:

<?php
     // bearbeitet das Steuerformular

     // Bibliotheken
  include "ImpotsDSN.php";

   // Sitzung starten
  session_start();

   // Anwendungskonfiguration
  ini_set("register_globals","off");
  ini_set("display_errors","off");
  $formulaireImpots="impots_form.php";
  $erreursImpots="impots_erreurs.php";
  $bdImpots=array(dsn=>"mysql-dbimpots",user=>admimpots,pwd=>mdpimpots,
      table=>impots,limites=>limites,coeffR=>coeffR,coeffN=>coeffN);

     // die Sitzungsparameter werden abgerufen
  $session=$_SESSION["session"];
   // Ist die Sitzung gültig?
  if(! isset($session) || ! isset($session[objImpots]) || ! isset($session[simulations])){
       // Eine neue Sitzung wird gestartet
    $session=array(objImpots=>new ImpotsDSN($bdImpots),simulations=>array());
    // Sind Fehler aufgetreten?
    if(count($session[objImpots]->erreurs)!=0){
      $requête=array(erreurs=>$session[objImpots]->erreurs);
         // Fehlerseite anzeigen
        include $erreursImpots;
       // Ende
      $session=array();
      terminerSession($session);
    }//if
  }//if

  // Die Parameter des laufenden Austauschs werden abgerufen
  $requête[marié]=$_POST["optMarie"];
  $requête[enfants]=$_POST["txtEnfants"];
  $requête[salaire]=$_POST["txtSalaire"];

   // Sind alle Parameter vorhanden?
  if(! isset($requête[marié]) || ! isset($requête[enfants]) || ! isset($requête[salaire])){
       // Anzeige eines leeren Formulars
    $requête=array(chkoui=>"",chknon=>"checked",enfants=>"",salaire=>"",impots=>"",
            erreurs=>array(),simulations=>array());    
    include $formulaireImpots;
     // Ende
    terminerSession($session);
  }//if

   // Parameterprüfung
  $requête=vérifier($requête);

   // Gibt es Fehler?
  if(count($requête[erreurs])!=0){
       // Formular anzeigen
    include "$formulaireImpots";
     // Ende
    terminerSession($session);
  }//if

   // Berechnung der zu zahlenden Steuer
  $requête[impots]=$session[objImpots]->calculer(array(marié=>$requête[marié],
        enfants=>$requête[enfants],salaire=>$requête[salaire]));

   // eine weitere Simulation
  $session[simulations][]=array($requête[marié],$requête[enfants],$requête[salaire],$requête[impots]);
  $requête[simulations]=$session[simulations];

   // Formularanzeige
  include "$formulaireImpots";

   // Ende
  terminerSession($session);
...

Die Seiten HTML wurden über die Include-Zeilen „...“ angezeigt. Hier soll XML und nicht HTML generiert werden. Es genügt, zwei neue Anwendungen impots_erreurs.php und impots_simulations.php zu schreiben, damit diese XML anstelle von HTML generieren. Der Rest der Anwendung bleibt unverändert. Der Code sieht dann wie folgt aus:

<?php
     // bearbeitet das Steuerformular

     // Bibliotheken
  include "ImpotsDSN.php";

   // Sitzung starten
  session_start();

   // Anwendungskonfiguration
  ini_set("register_globals","off");
  ini_set("display_errors","off");
  $formulaireImpots="xmlsimulations.html";
  $erreursImpots="impots_erreurs.php";
  $simulationsImpots="impots_simulations.php";
  $bdImpots=array(dsn=>"mysql-dbimpots",user=>admimpots,pwd=>mdpimpots,
      table=>impots,limites=>limites,coeffR=>coeffR,coeffN=>coeffN);

     // die Sitzungsparameter werden abgerufen
  $session=$_SESSION["session"];
   // Ist die Sitzung gültig?
  if(! isset($session) || ! isset($session[objImpots]) || ! isset($session[simulations])){
       // Eine neue Sitzung wird gestartet
    $session=array(objImpots=>new ImpotsDSN($bdImpots),simulations=>array());
    // Sind Fehler aufgetreten?
    if(count($session[objImpots]->erreurs)!=0){
      $requête=array(erreurs=>$session[objImpots]->erreurs);
         // Anzeige der Fehlerseite im Format XML
          header("Content-type: text/xml");      
        include $erreursImpots;
       // Ende
      $session=array();
      terminerSession($session);
    }//if
  }//if

   // Die Parameter des laufenden Austauschs werden abgerufen
  $requête[marié]=$_POST["optMarie"];
  $requête[enfants]=$_POST["txtEnfants"];
  $requête[salaire]=$_POST["txtSalaire"];

   // Sind alle Parameter vorhanden?
  if(! isset($requête[marié]) || ! isset($requête[enfants]) || ! isset($requête[salaire])){
       // Anzeige eines leeren Formulars
    include $formulaireImpots;
     // Ende
    terminerSession($session);
  }//if

   // Parameterprüfung
  $requête=vérifier($requête);

   // Gibt es Fehler?
  if(count($requête[erreurs])!=0){
       // Anzeige der Fehler im Format XML
      header("Content-type: text/xml");    
    include "$erreursImpots";
     // Ende
    terminerSession($session);
  }//if

   // Berechnung der zu zahlenden Steuer
  $requête[impots]=$session[objImpots]->calculer(array(marié=>$requête[marié],
        enfants=>$requête[enfants],salaire=>$requête[salaire]));

   // eine weitere Simulation
  $session[simulations][]=array($requête[marié],$requête[enfants],$requête[salaire],$requête[impots]);
  $requête[simulations]=$session[simulations];

   // Anzeige der Simulationen im Format XML
  header("Content-type: text/xml");
  include "$simulationsImpots";

   // Ende
  terminerSession($session);

Wir haben zuvor die beiden Arten von Antworten, die bereitgestellt werden müssen, sowie die dazugehörigen Stylesheets vorgestellt und untersucht. Der Code der Anwendung lautet wie folgt:

<?php
     // Erzeugt den Code XML für die Simulationsseite der Anwendung „Steuern“

   // einige Konstanten
  $xslSimulations="simulations.xsl";

   // Kopfzeilen XML
  echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
  echo "<?xml-stylesheet type=\"text/xsl\" href=\"$xslSimulations\" ?>\n";    
  // die Simulationen
  echo "<simulations>\n";
  for ($i=0;$i<count($requête[simulations]);$i++){
      // Simulation $i
    echo "<simulation marie=\"".$requête[simulations][$i][0]."\" ".
                "enfants=\"".$requête[simulations][$i][1]."\" ".
          "salaire=\"".$requête[simulations][$i][2]."\" ".
          "impot=\"".$requête[simulations][$i][3]."\" />\n";
  }//für
  echo "</simulations>\n";
?>

Mit diesem Code lässt sich ausgehend vom Wörterbuch $requête ein Code XML generieren, der dem folgenden ähnelt:


<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="simulations.xsl" ?>
<simulations>
<simulation marie="non" enfants="3" salaire="200000" impot="22504" />
<simulation marie="oui" enfants="3" salaire="200000" impot="16400" />
<simulation marie="oui" enfants="2" salaire="200000" impot="22504" />
</simulations>

Das Stylesheet simulations.xsl wandelt diesen Code XML in den Code HTML um.

Der Anwendungscode impots_erreurs.php lautet wie folgt:

<?php
     // erzeugt den Code XML der Fehlerseite der Anwendung „impots“

   // einige Konstanten
  $xslErreurs="erreurs.xsl";

   // Kopfzeilen XML
  echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
  echo "<?xml-stylesheet type=\"text/xsl\" href=\"$xslErreurs\" ?>\n";
   // die Fehler
  echo "<erreurs>\n";
  for ($i=0;$i<count($requête[erreurs]);$i++){
      // Fehler $i
    echo "<erreur>".$requête[erreurs][$i]."</erreur>";
  }//for
  echo "</erreurs>\n";
?>

Mit diesem Code lässt sich ausgehend vom Wörterbuch $requête ein Code XML generieren, der dem folgenden ähnelt:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="erreurs.xsl" ?>
<erreurs>
<erreur>Impossible d'ouvrir la base DSN [mysql-dbimpots] (S1000)</erreur>
</erreurs>

Das Stylesheet erreurs.xsl wandelt diesen Code XML in den Code HTML um.

Sehen wir uns ein erstes Beispiel an:

Image

Der SGBD MySQL wird nicht aufgerufen. Man erhält dann folgende Antwort:

Image

Betrachtet man den vom Browser empfangenen Quellcode, so ergibt sich Folgendes:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="erreurs.xsl" ?>
<erreurs>
<erreur>Impossible d'ouvrir la base DSN [mysql-dbimpots] (S1000)</erreur>
</erreurs>

Nun starten wir den Befehl SGBD MySQL und führen nacheinander verschiedene Simulationen durch. Wir erhalten folgende Antwort:

Image

Der vom Browser empfangene Code lautet wie folgt:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="simulations.xsl" ?>
<simulations>
<simulation marie="oui" enfants="2" salaire="200000" impot="22504" />
<simulation marie="non" enfants="2" salaire="200000" impot="33388" />
<simulation marie="non" enfants="3" salaire="200000" impot="22504" />
<simulation marie="oui" enfants="3" salaire="200000" impot="16400" />
</simulations>

Es ist zu beachten, dass unsere neue Anwendung einfacher zu warten ist als die vorherige. Ein Teil der Arbeit wurde auf die Stylesheets XSL verlagert. Der Vorteil dieser neuen Aufgabenteilung besteht darin, dass die Entwicklung der Stylesheets unabhängig von der der Anwendung erfolgt, sobald das Format XML für die Antworten festgelegt wurde.

5.3. Analyse eines XML-Dokuments in PHP

Die nächste Version unserer Steueranwendung wird ein programmierter Client der vorherigen Anwendung xmlsimulations sein. Unser Client wird also XML-Code erhalten, den er analysieren muss, um die für ihn relevanten Informationen zu extrahieren. Wir werden hier eine Pause bei unseren verschiedenen Versionen einlegen und lernen, wie man ein Dokument vom Format XML in das Format PHP analysieren kann. Dazu verwenden wir das folgende Beispiel:


dos>e:\php43\php.exe xmlParser.php
syntaxe : xmlParser.php fichierXML

Die Anwendung xmlParser.php akzeptiert einen Parameter: den URI (Uniform Resource Identifier) des zu analysierenden Dokuments XML. In unserem Beispiel ist dieser URI einfach der Name einer Datei XML, die sich im Verzeichnis der Anwendung xmlParser.php befindet. Betrachten wir zwei Ausführungsbeispiele. Im ersten Beispiel ist die analysierte Datei „XML“ die folgende Datei „erreurs.xml“:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="erreurs.xsl"?>
<erreurs>
    <erreur>erreur 1</erreur>
  <erreur>erreur 2</erreur>
</erreurs>

Die Analyse liefert folgende Ergebnisse:


dos>e:\php43\php.exe xmlParser.php erreurs.xml
ERREURS
 ERREUR
  [erreur 1]
 /ERREUR
 ERREUR
  [erreur 2]
 /ERREUR
/ERREURS

Wir hatten noch nicht beschrieben, was die Anwendung xmlParser.php macht, aber hier sieht man, dass sie die Struktur des analysierten Dokuments XML anzeigt. Das zweite Beispiel analysiert die folgende Datei: XML simulations.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="simulations.xsl"?>
<simulations>
  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>
  <simulation marie="non" enfants="2" salaire="200000" impot="33388"/>
</simulations>

Die Analyse liefert folgende Ergebnisse:


dos>e:\php43\php.exe xmlParser.php simulations.xml
SIMULATIONS
 SIMULATION,(MARIE,oui) (ENFANTS,2) (SALAIRE,200000) (IMPOT,22504)
 /SIMULATION
 SIMULATION,(MARIE,non) (ENFANTS,2) (SALAIRE,200000) (IMPOT,33388)
 /SIMULATION
/SIMULATIONS

Die Anwendung xmlParser.php enthält alles, was wir in unserer Steueranwendung benötigen, da sie in der Lage war, sowohl Fehler als auch Simulationen zu erkennen, die der Webserver senden könnte. Sehen wir uns den Code an:

<?php
   // Syntax $0 fichierXML
   // zeigt die Struktur und den Inhalt der Datei an fichierXML

   // Aufrufprüfung
  if(count($argv)!=2){
       // Fehlermeldung
    fwrite(STDERR,"syntaxe : $argv[0] fichierXML\n");
     // Ende
    exit(1);
  }//if

   // Initialisierungen
  $file=$argv[1];       // die XML-Datei
  $depth=0;               // Einarückungsstufe = Tiefe in der Baumstruktur

   // das Programm

   // Es wird ein Objekt zur XML-Textanalyse erstellt
  $xml_parser=xml_parser_create();

   // Es wird angegeben, welche Funktionen am Anfang und am Ende eines Tags ausgeführt werden sollen
  xml_set_element_handler($xml_parser,"startElement","endElement");

   // Es wird angegeben, welche Funktion beim Auftreten von Daten ausgeführt werden soll
  xml_set_character_data_handler($xml_parser,"afficheData");

  // Öffnen der XML-Datei im Lesemodus
  if (! ($fp=@fopen($file,"r"))){
    fwrite(STDERR,"impossible d'ouvrir le fichier xml $file\n");
    exit(2);
  }//if
   // Auswertung der XML-Datei in Blöcken von 4096 Byte
  while($data=fread($fp,4096)){
    // Analyse der eingelesenen Daten
    if (! xml_parse($xml_parser,$data,feof($fp))){
      // Es ist ein Fehler aufgetreten
      fprintf(STDERR,"erreur XML : %s à la ligne %d\n",
        xml_error_string(xml_get_error_code($xml_parser)),
        xml_get_current_line_number($xml_parser));
       // Ende
      exit(3);
    }//if
  }//while
  // Die Datei wurde durchsucht
   // Die vom XML-Parser belegten Ressourcen werden freigegeben
  xml_parser_free($xml_parser);
   // Ende
  exit(0);

    // -----------------------------------------------------------  
   // Funktion, die beim Auftreten eines Start-Tags aufgerufen wird
  function startElement($parser,$name,$attributs){
    global $depth;
     // eine Folge von Leerzeichen (Einrückung)
    for($i=0;$i<$depth;$i++){
      print " ";
    }//for
     // Attribute
    $précisions="";
    while(list($attrib,$valeur)=each($attributs)){
      $précisions.="($attrib,$valeur) ";
    }
     // Der Name des Tags und eventuelle Attribute werden angezeigt
    if($précisions)
      print "$name,$précisions\n";
    else print "$name\n";
     // eine weitere Ebene in der Baumstruktur
    $depth++;
  }//startElement

    // -----------------------------------------------------------  
   // die Funktion, die beim Auftreten eines End-Tags aufgerufen wird
  function endElement($parser,$name){
     // End-Tag
     // Einrückungsebene
    global $depth;
    $depth--;
    // eine Folge von Leerzeichen (Einrückung)
    for($i=0;$i<$depth;$i++){
      echo " ";
    }//for
     // den Tag-Namen
    echo "/$name\n";
  }//endElement

    // -----------------------------------------------------------  
   // die Funktion zur Datenanzeige
  function afficheData($parser,$data){
     // Einarbeitungsstufe
    global $depth;
     // Die Daten werden angezeigt
    $data=trim($data);
    if($data!=""){
       // eine Reihe von Leerzeichen (Einrückung)
      for($i=0;$i<$depth;$i++){
        echo " ";
      }//for
      echo "[$data]\n";
    }//if
  }//afficheData
?>

Betrachten wir den Code, der sich auf XML bezieht. Um ein Dokument mit der Bezeichnung XML zu analysieren, benötigt unsere Anwendung einen Code-Parser für XML, der üblicherweise als „Parser“ bezeichnet wird.

<?php
...
   // wird ein XML-Textanalyseobjekt erstellt
  $xml_parser=xml_parser_create();

Wenn der Parser das Dokument XML analysiert, löst er Ereignisse aus wie: Ich habe den Anfang des Dokuments gefunden, den Anfang eines Tags, ein Tag-Attribut, den Inhalt eines Tags, das Ende eines Tags, das Ende des Dokuments, … Er übermittelt diese Ereignisse an Methoden, die man ihm zuweisen muss:

<?php
...
   // man gibt an, welche Funktionen am Anfang und am Ende eines Tags ausgeführt werden sollen
  xml_set_element_handler($xml_parser,"startElement","endElement");
   // Es wird angegeben, welche Funktion beim Auftreten von Daten ausgeführt werden soll
  xml_set_character_data_handler($xml_parser,"afficheData");
Vom
Parser
Verarbeitungsmethode
début d'un élément :<balise>
Funktion startElement($parser, $name, $attributs)
$parser: der Parser des Dokuments
$name: Name des analysierten Elements. Wenn das gefundene Element <simulations> ist, lautet name="simulations".
$attributs: Liste der Attribute des Tags in der Form (ATTRIBUT,Wert), wobei ATTRIBUT der Name des Tags in Großbuchstaben ist.
valeur d'un élément :
<balise>valeur</balise>
function afficheData($parser, $data)
$parser: der Parser des Dokuments
$data: die Daten des Tags
fin d'un élément : </balise> ou <balise .../>
function endElement($parser, $name)
Die Parameter entsprechen denen der Methode startElement.

Mit der Funktion startElement lassen sich die Attribute des Elements mithilfe des Parameters $attributs abrufen. Dabei handelt es sich um ein Wörterbuch der Attribute des Tags. Wenn wir also das folgende Tag haben:

  <simulation marie="oui" enfants="2" salaire="200000" impot="22504"/>

dann sieht das Wörterbuch $attributs wie folgt aus: array(marie=>ja,kinder=>2,gehalt=>200000,steuer=>22504)

Sobald der Parser und die oben genannten Methoden definiert sind, erfolgt die Analyse eines Dokuments über die Funktion xml_parse:

<?php
...
   // Auswertung der XML-Datei in Blöcken von 4096 Byte
  while($data=fread($fp,4096)){
    // Analyse der gelesenen Daten
    if (! xml_parse($xml_parser,$data,feof($fp))){
...
    }//if
  }//while
analyse d'un
document $doc
function xml_parse($parser, $doc, $fin)
Der Parser $parser analysiert das Dokument $doc. $doc kann ein Ausschnitt aus einem größeren Dokument sein. Der Parameter $fin gibt an, ob es sich um den letzten Teil handelt (true) oder nicht (false). Bei der Analyse des Dokuments $doc werden die durch xml_set_element_handler definierten Funktionen bei jedem Beginn und Ende eines Tags aufgerufen. Die durch xml_set_character_data_handler definierte Funktion wird jedes Mal aufgerufen, wenn der Inhalt eines Tags abgerufen wurde.

Bei der Analyse des Dokuments XML können Fehler auftreten, insbesondere wenn das Dokument XML „fehlerhaft formatiert“ ist, beispielsweise wenn schließende Tags fehlen. In diesem Fall gibt die Funktion xml_parse einen Wert zurück, der als „falsch“ ausgewertet wird:

<?php
...
    if (! xml_parse($xml_parser,$data,feof($fp))){
      // Es ist ein Fehler aufgetreten
      fprintf(STDERR,"erreur XML : %s à la ligne %d\n",
        xml_error_string(xml_get_error_code($xml_parser)),
        xml_get_current_line_number($xml_parser));
      // Ende
      exit(3);
    }//if
gestion d'erreurs
function xml_get_error_code($parser)
gibt den Code des zuletzt aufgetretenen Fehlers zurück
--
function xml_error_string($code)
gibt die Fehlermeldung zurück, die dem als Parameter übergebenen Code zugeordnet ist
--
function xml_get_current_line($parser)
gibt die Zeilennummer des Dokuments XML zurück, das gerade vom Parser analysiert wird

Nachdem das Dokument analysiert wurde, werden die dem Parser zugewiesenen Ressourcen freigegeben:

<?php
...
   // Die vom XML-Parser belegten Ressourcen werden freigegeben
  xml_parser_free($xml_parser);
libération des
ressources attribuées
au parseur $parser
function xml_free($parser)

Nachdem dies nun erläutert wurde, ist das vorstehende Programm zusammen mit den Ausführungsbeispielen selbsterklärend.

5.4. Steueranwendung: Version 6

Wir verfügen nun über alle Elemente, um einen Client für unseren Steuerdienst zu programmieren, der XML ausgibt. Wir greifen auf Version 4 unserer Anwendung zurück, um den Client zu erstellen, und behalten Version 5 für den Server bei. In dieser Client-Server-Anwendung:

  • wird die Simulation der Steuerberechnung von der Anwendung xmlsimulations.php durchgeführt. Die Antwort des Servers liegt daher im Format XML vor, wie wir es bereits in Version 5 gesehen haben.
  • ist der Client kein Browser mehr, sondern ein eigenständiger PHP-Client. Seine Konsolenoberfläche entspricht der von Version 4.

Der Leser sei gebeten, den Code der Anwendung cltImpots.php noch einmal durchzulesen, bei der es sich um den programmierten Client der Version 4 handelte. Dieser erhielt vom Server ein Dokument mit dem Namen $document. Dieses war zuvor ein Dokument mit dem Namen HTML. Nun handelt es sich um ein Dokument XML. Das Dokument HTML $document wurde von der folgenden Funktion analysiert:

<?php
...
  function getInfos($document){
       // $document: Dokument HTML
     // Es wird entweder die Fehlerliste gesucht
     // oder die Simulationstabelle

     // Aufbereitung des Ergebnisses
    $impots[erreurs]=array();
    $impots[simulations]=array();

........
    return $impots;
    }//getInfos

Die Funktion nahm das Dokument HTML $document entgegen, analysierte es und gab ein Wörterbuch $impots mit zwei Attributen zurück:

  1. Fehler: ein Fehlerarray
  2. Simulationen: ein Array von Simulationen, wobei jede Simulation selbst ein Array mit vier Elementen ist (Ehepartner, Kinder, Gehalt, Steuern).

Die Anwendung cltImpots.php heißt nun cltXmlSimulations.php. Nur der Teil, der das vom Server empfangene Dokument verarbeitet, muss geändert werden, um der Tatsache Rechnung zu tragen, dass es sich nun um ein XML-Dokument handelt. Die Funktion getInfos sieht dann wie folgt aus:

<?php
...
// --------------------------------------------------------------
  function getInfos($document){
       // $document: Dokument XML
     // gesucht wird entweder die Fehlerliste
     // oder die Simulationstabelle

    global $impots,$balises;

     // Aufbereitung des Ergebnisses
    $impots[erreurs]=array();
    $impots[simulations]=array();
     // Laufende Tags
    $balises=array();

     // Es wird ein XML-Textanalyseobjekt erstellt
    $xml_parser=xml_parser_create();
     // Es wird angegeben, welche Funktionen am Anfang und am Ende des Tags ausgeführt werden sollen
    xml_set_element_handler($xml_parser,"startElement","endElement");
     // Festlegung der Funktion, die beim Auftreten von Daten ausgeführt werden soll
    xml_set_character_data_handler($xml_parser,"getData");
    // Es wird eine Analyse von $document durchgeführt
    xml_parse($xml_parser,$document);
     // Die vom XML-Parser belegten Ressourcen werden freigegeben
    xml_parser_free($xml_parser);
     // Ende
    return $impots;
  }//getInfos

    // -----------------------------------------------------------  
  // Funktion, die beim Auftreten eines Start-Tags aufgerufen wird
  function startElement($parser,$name,$attributs){
    global $impots,$balise,$balises,$contenu;

     // Der Name des Tags und sein Inhalt werden notiert
    $balise=strtolower($name);
    $contenu="";
     // wird zum Tag-Stapel hinzugefügt
    array_push($balises,$balise);    
    // Handelt es sich um eine Simulation?
    if($balise=="simulation"){   
         // Die Attribute der Simulation werden notiert
      $impots[simulations][]=array($attributs[MARIE],$attributs[ENFANTS],$attributs[SALAIRE],$attributs[IMPOT]);
    }//if
  }//startElement

    // -----------------------------------------------------------  
   // Die Funktion, die beim Auftreten eines End-Tags aufgerufen wird
  function endElement($parser,$name){
       // Das aktuelle Tag wird abgerufen
    global $impots,$balises,$contenu;
    $balise=array_pop($balises);
    // Handelt es sich um ein Fehler-Tag?
    if($balise=="erreur"){
         // Ein weiterer Fehler
      $impots[erreurs][]=trim($contenu);
    }//if
  }//endElement

    // -----------------------------------------------------------  
   // Die Funktion zur Verarbeitung des Inhalts eines Tags
  function getData($parser,$data){
      // globale Daten
    global $balise,$contenu;
     // Handelt es sich um ein Fehler-Tag?
    if($balise=="erreur"){
         // wird zum Inhalt des aktuellen Tags addiert
      $contenu.=$data;
    }//if
  }//getData

Anmerkungen:

  • Die Funktion getInfos($document) erstellt zunächst einen Parser, konfiguriert diesen anschließend und startet schließlich die Analyse des Dokuments $document:
<?php
...
     // Es wird ein XML-Textanalyseobjekt erstellt
    $xml_parser=xml_parser_create();
     // Es wird angegeben, welche Funktionen am Anfang und am Ende des Tags ausgeführt werden sollen
    xml_set_element_handler($xml_parser,"startElement","endElement");
     // Es wird angegeben, welche Funktion beim Auftreten von Daten ausgeführt werden soll
    xml_set_character_data_handler($xml_parser,"getData");
    // Es wird die Analyse von $document durchgeführt
    xml_parse($xml_parser,$document);
  • Nach Abschluss der Analyse werden die dem Parser zugewiesenen Ressourcen freigegeben und das Wörterbuch $impots zurückgegeben.
<?php
...
     // Die vom XML-Parser belegten Ressourcen werden freigegeben
    xml_parser_free($xml_parser);
     // Ende
    return $impots;
  • Die Funktion startElement($parser,$name,$attributs) wird bei jedem Beginn eines Tags aufgerufen. Sie
    • Erfasst das Tag $name in einer Tag-Tabelle $balises. Diese Tabelle wird wie ein Stapel verwaltet: Beim Auftreffen auf das Tag-Endesymbol wird das zuletzt in $balises gestapelte Tag vom Stapel entfernt. Das aktuelle Tag wird ebenfalls in $balise vermerkt. Im Wörterbuch $attributs befinden sich die Attribute des gefundenen Tags, wobei diese Attribute in Großbuchstaben geschrieben sind.
    • speichert die Attribute im globalen Wörterbuch $impots[simulations], wenn es sich um ein Simulations-Tag handelt.
  • die Funktion getData($parser,$data), wenn der Inhalt $data eines Tags abgerufen wurde. Hier wurde eine Vorsichtsmaßnahme getroffen. In bestimmten API, insbesondere in Java, zur Verarbeitung von XML-Dokumenten, wird darauf hingewiesen, dass diese Funktion wiederholt aufgerufen werden kann, c.a.d. dass man den Inhalt eines Tags nicht unbedingt in einem einzigen Durchgang erhält. Hier weist die Dokumentation PHP nicht auf diese Einschränkung hin. Vorsichtshalber wird der erhaltene Wert $data in einer globalen Variablen $contenu gesammelt. Erst beim Auftreten des Tag-Endesymbols geht man davon aus, den gesamten Inhalt des Tags erhalten zu haben. Das einzige Tag, das von dieser Verarbeitung betroffen ist, ist das Tag <erreur>.
  • Die Funktion endElement($parser,$name) wird bei jedem Tag-Ende aufgerufen. Sie wird hier verwendet, um den Namen des aktuellen Tags zu ändern, indem das letzte Tag aus dem Tag-Stapel entfernt wird, und um den Inhalt des Tags <erreur>, das mit dem Array $impots[erreurs] endet, hinzuzufügen.

Hier sind einige Ausführungsbeispiele, zunächst mit einem SGBD, das nicht gestartet wurde:

dos>e:\php43\php.exe cltXmlSimulations.php http://localhost/poly/impots/8/xmlsimulations.php ja 2 200000
Jeton de session=[e8c29ea12f79e4771960068d161229fd]
Les erreurs suivantes se sont produites :
Impossible d'ouvrir la base DSN [mysql-dbimpots] (S1000)

Anschließend mit dem gestarteten SGBD:


dos>e:\php43\php.exe cltXmlSimulations.php http://localhost/poly/impots/8/xmlsimulations.php ja 3 200000
Jeton de session=[69a54d79db10b70ed0a2d55d5026ac8b]
Simulations :
[oui,3,200000,16400]

dos >e:\php43\php.exe cltXmlSimulations.php http://localhost/poly/impots/8/xmlsimulations.php ja 2 200000 69a54d79db10b70ed0a2d55d5026ac8b
Jeton de session=[69a54d79db10b70ed0a2d55d5026ac8b]
Simulations :
[oui,3,200000,16400]
[oui,2,200000,22504]

dos >e:\php43\php.exe cltXmlSimulations.php http://localhost/poly/impots/8/xmlsimulations.php nein 2 200000 69a54d79db10b70ed0a2d55d5026ac8b
Jeton de session=[69a54d79db10b70ed0a2d55d5026ac8b]
Simulations :
[oui,3,200000,16400]
[oui,2,200000,22504]
[non,2,200000,33388]

5.5. Fazit

Dank der Antwort XML lässt sich die Steueranwendung nun sowohl für ihren Entwickler als auch für die Entwickler der Client-Anwendungen einfacher verwalten.

  • Die Entwicklung der Serveranwendung kann nun zwei Personengruppen anvertraut werden: dem PHP-Entwickler des Servlets und dem Grafikdesigner, der das Erscheinungsbild der Browser-Antwort in den Browsern gestaltet. Letzterer muss lediglich die Struktur der Serverantwort XML kennen, um die dazugehörigen Stylesheets zu erstellen. Zur Erinnerung: Diese sind Gegenstand separater XSL-Dateien, die unabhängig von der Anwendung PHP sind. Der Grafikdesigner kann daher unabhängig vom Entwickler arbeiten.
  • Auch die Entwickler der Client-Anwendungen müssen lediglich die Struktur der Serverantwort XML kennen. Änderungen, die der Grafikdesigner an den Stylesheets vornimmt, haben keinerlei Auswirkungen auf diese Antwort XML, die stets unverändert bleibt. Das ist ein enormer Vorteil.
  • Wie kann der Entwickler seine Anwendung PHP weiterentwickeln, ohne alles kaputt zu machen? Zunächst einmal kann er seine Anwendung ganz nach Belieben gestalten, solange sich seine Antwort XML nicht ändert. Er kann auch die Antwort XML weiterentwickeln, solange er die von seinen Clients erwarteten Elemente <Fehler> und <Simulation> beibehält. So kann er dieser Antwort neue Tags hinzufügen. Der Grafikdesigner wird diese in seinen Stylesheets berücksichtigen, und die Browser können die neuen Versionen der Antwort erhalten. Die programmierten Clients hingegen werden weiterhin mit dem alten Modell arbeiten, wobei die neuen Tags einfach ignoriert werden. Damit dies möglich ist, müssen die gesuchten Tags in der Analyse XML der Serverantwort eindeutig identifiziert werden. Genau das wurde in unserem Client XML der Steueranwendung umgesetzt, wo in den Prozeduren ausdrücklich festgelegt wurde, dass die Tags <erreur> und <simulation> verarbeitet werden. Dadurch werden die anderen Tags ignoriert.