Einleitung
Dieser Abschnitt befasst sich kurz mit den XML-Dateien, die in den Chroniken von BVN verwendet werden. Es ist möglich, dass die
Informationen für all diejenigen, die über kein XML-Grundwissen verfügen, nicht einfach zu verstehen sind.
Zunächst werden wir uns damit befassen, wie die einzelnen XML-Dateien angeordnet sind, um die Hierarchie und Themen zu kennzeichnen,
die im Verzeichnisbaum stehen. Dann können wir uns dem Namensschema zuwenden, das für die Dateien verwendet wird. Diese zwei
Aspekte sollten uns dann das nötige Grundwissen geben, damit wir auf Wunsch den Namen und den Ort einer Datei herausfinden können,
um im dritten Teil zu erlernen wie die Daten auf der eingenen Webseite darstellbar sind.
Wir werden also die Verzeichnisstruktur durchgehen und den Inhalt jedes XML-Dateityps auflisten. Folgende Themen werden angesprochen:
- Verband (Vereins- und Mannschaftslisten)
- Spielplan
- Rangliste
- RSS Feed (Live Bookmark)
Schliesslich werden auch noch zwei Beispielcodes geliefert, die die abgerufenen Daten mittels HMTL und PHP darstellt.
Die Praxis hat gezeigt, dass das erste Beispiel bei gewissen Servern nicht funktioniert, da das direkte Lesen von Dateien
von anderen Servern nicht erlaubt wird. Das zweite Beispiel besteht daher aus zwei Dateien. Die HTTPRequest Bibliothek
und dem leicht angepassten Script aus Beispiel 1.
- Teil I : DIE XML-DATEIEN
- Teil II : DER INHALT
- Teil III : DIE ANWENDUNG
1. Verzeichnisbaum
Alle XML-Dateien sind unter derselben URL erreichbar:
http://www.bvn.ch/xml/
Eine Datei, die unter „http://www.bvn.ch/xml/ranking/H2L.xml zu finden ist, wird in der folgenden Erklärung nur mit:
"ranking/H2L.xml" angesprochen.
Bei allen Verzeichnissen und Dateien ist auf die Gross- und Kleinschreibung zu achten!
XML - Filetypen
Von diesem URL ausgehend gibt es momentan folgende vier Verzeichnisse:
association - Alle Vereine und der Mannschaften des Verbandes
schedules - Alle Spielpläne der verschiedenen Vereine
ranking - Alle Ranglisten der verschiedenen Ligen
rssFeed - Die Files der RSS Feeds des BVN
2. Schema der Dateinamen
Das Schema der Dateinamen ermöglicht es uns, die genaue Bezeichnung der Dateien zu standardisieren (gemäss
unserer allgemeinen Terminologie der regulären Ausdrücke).
Schrägschrift
Ein Begriff in Italic steht für einen Wert, der hier eingefügt wird.
Zum Beispiel: idClub wird durch den tatsächlichen Kürzel eines Vereins
ersetzt und idLeague wird durch den tatsächlichen Namen der Liga ersetzt. Mit
folgendem Beispiel können wir auch schon die Namen der Files in den Verzeichnissen konkret definieren:
xml/ranking/idLeague.xml
xml/schedule/idClub.xml
Nun ist schon alles bekannt, was es über XML-Dateien zu den Chroniken vom BVN Service zu wissen gibt.
Wir können uns nun also dem Inhalt zuwenden und die Informationen auflisten, die aus jeder Datei gewonnen werden können.
3. Die Bedeutung von XML
Die Bedeutung von XML hier einmal mehr zu erklären, wäre reine Zeitverschwendung, da es schon viele grossartige Erklärungen im Web gibt. Hier sei die Einleitung von Wikipedia zitiert:
Die Extensible Markup Language (engl. für „erweiterbare Auszeichnungs-Sprache“), abgekürzt XML, ist ein Standard zur Erstellung maschinen- und menschenlesbarer Dokumente in Form einer Baumstruktur, der vom World Wide Web Consortium (W3C) definiert wird. XML definiert dabei die Regeln für den Aufbau solcher Dokumente. Für einen konkreten Anwendungsfall ("XML-Anwendung") müssen die Details der jeweiligen Dokumente spezifiziert werden. Dies betrifft insbesondere die Festlegung der Strukturelemente und ihre Anordnung innerhalb des Dokumentenbaums. XML ist damit ein Standard zur Definition von beliebigen, in ihrer Grundstruktur jedoch stark verwandten Auszeichnungssprachen. Eine Sprache zur Definition anderer Sprachen nennt man Metasprache. XML ist eine vereinfachte Teilmenge von SGML.
http://de.wikipedia.org/wiki/Xml
Weiterführende Informationen zu XML können entweder unter obigem Link oder unter
http://www.professionelle-softwareentwicklung-mit-php5.de/erste_auflage/ gefunden werden.
Hier sei einfach noch erwähnt, dass wir bewusst, Attribute so selten wie nötig verwendet haben, um bei der Darstellung ein
möglichst einfaches Abarbeiten mit dem in PHP5 enthaltenen SimpleXML zu ermöglichen. SimpleXML wird daher im Kapitel 8 auch noch
kurz vorgestellt.
4. Übersetzung
Liste der Vereine und deren Teams -- token.xml
<association date='2005-12-26 16:45:59'>
<club>
<idClub>laufen</idClub>
<clubName>BBC Laufen</clubName>
<region>BVN</region>
<homepage>www.bbc-laufen.ch</homepage>
<team>
<idTeam>16</idTeam>
<idLeague>D3L</idLeague>
<category>Senior</category>
<teamName>BBC Laufen</teamName>
<leagueName>Damen 3. Liga</leagueName>
</team>
<team>
<idTeam>74</idTeam>
<idLeague>H4L</idLeague>
<category>Senior</category>
<teamName>BBC Laufen</teamName>
<leagueName>Herren 4. Liga</leagueName>
</team>
</club>
</association>
In der Datei "token.xml" setzt sich der Wurzelknoten "asscociation" aus mehreren "club"-Verzweigungspunkten
zusammen, welche einerseits die Clubinformationen und anderseits wiederum mehrere "team" -Verzweigungspunkte beinhalten, die ihrerseits
die wichtigsten Informationen bezüglich der Teams anzeigen.
Die Datei dient als Nachschlagewerk, so dass wenn wir später das SimpleXML Script konfigurieren wollen, hier einfach die Vereins-,
Mannschafts- oder Liga-Referenz herauslesen können.
5. Spielplan
Spielplanliste der Mannschaften des Vereines idClub -- idClub.xml
<club date='2005-12-26 17:15:23'>
<team idTeam="16">
<match>
<matchNr>2501</matchNr>
<date>20.09.05</date>
<time>19:30</time>
<homeName>BBC Laufen</homeName>
<awayName>BC Boncourt</awayName>
<gymName>Gym Laufen</gymName>
<homeScore>35</homeScore>
<awayScore>68</awayScore>
</match>
<match>
<matchNr>2556</matchNr>
<date>27.09.05</date>
<time>20:15</time>
<homeName>TV Muttenz 2</homeName>
<awayName>BBC Laufen</awayName>
<gymName>Donnerbaum</gymName>
<homeScore>30</homeScore>
<awayScore>48</awayScore>
</match>
</team>
</club>
In der Datei "idClub.xml" setzt sich der Wurzelknoten "club" aus mehreren
"team"-Verzweigungspunkten zusammen, welche einerseits das Attribut "idTeam" und anderseits
wiederum mehrere "match" -Verzweigungspunkte beinhalten, die ihrerseits dann die Informationen über ein Spiel anzeigen.
Die "idTeam"-Attribute der"team"-Verzweigungspunkte geben die Referenz (oder ID) gemäß der "token.xml"
Übersetzung-XMLs an.
6. Rangliste
Rangliste der Mannschaften der Liga idLeague -- idLeague.xml
<league>
<team>
<rank>1</rank>
<name>BC Boncourt</name>
<games>3</games>
<win>3</win>
<lost>0</lost>
<forfait>0</forfait>
<scored>316</scored>
<received>64</received>
<difference>252</difference>
<points>6</points>
<directEncounter>1</directEncounter>
<directEncounterPoints>2</directEncounterPoints>
<directEncounterDifference>33</directEncounterDifference>
</team>
<team>
<rank>2</rank>
<name>BC Münchenstein 2</name>
<games>3</games>
<win>3</win>
<lost>0</lost>
<forfait>0</forfait>
<scored>186</scored>
<received>89</received>
<difference>97</difference>
<points>6</points>
<directEncounter>0</directEncounter>
<directEncounterPoints>0</directEncounterPoints>
<directEncounterDifference>0</directEncounterDifference>
</team>
</league>
In der Datei "idLeague.xml" setzt sich der Wurzelknoten "league" aus mehreren
"team"-Verzweigungspunkten zusammen, welche ihrerseits wiederum mehrere Informationen über die Rangliste
der Liga preisgeben.
7. Voraussetzung
Die hier vorgestellte Variante setzt einen Webserver mit PHP 5 und minimale PHP Kenntnisse voraus.
8. SimpleXML
Für die einfache Verarbeitung von XML-Dokumenten bietet PHP die SimpleXML-Programmierschnittstelle an. Diese baut auf der Idee des
Perl-Paketes XML::Simple auf und bietet einen intuitiven Zugriff auf XML-Daten.
Zu vertiefenden Informationen verweisen wir wieder auf Wikipedia sowie PHP.net, ausserdem empfehlen wir
http://www.professionelle-softwareentwicklung-mit-php5.de/erste_auflage/programming-php.xml.simplexml.html.
Für unseren Zweck reicht es jedoch vollkommen zu wissen, dass die Funktion simplexml_load_file() ein Objekt der Klasse
SimpleXMLElement für die Verarbeitung von XML-Daten erzeugt, die aus einer Datei gelesen werden.
Ein Objekt der Klasse SimpleXMLElement enthält für jedes XML-Kindelement eine Instanzvariable, die den entsprechenden Namen trägt.
Kommt dieses nur einmal vor, so ist der Wert der Instanzvariablen der Wert des Kindelementes. Kommt das Kindelement mehrfach vor,
so enthält die Instanzvariable ein Array von SimpleXMLElement-Objekten für die Kindelemente.
Vor- und Nachteile
- + Einfacher Zugriff auf XML-Element.
- + Geringer Speicherverbrauch, da PHP-Objekte nur bei Bedarf erzeugt werden und das Dokument zu Beginn nur einmal (im Speicher der libxml2-Bibliothek) vorliegt.
- + Schnell.
- - Zugriff auf Attribute eines XML-Elementes umständlich.
- - Kein Standard.
9. Beispiel 1 (mit simplexml_load_file)
<?php
$XMLFilePath = "http://www.bvn.ch/xml/schedule/SC_UNI_BASEL.xml";
function printScheduleData($XMLFilePath, $idTeam) {
if (!(file_exists($XMLFilePath))) {
return FALSE;
}
$club = simplexml_load_file($XMLFilePath);
foreach ($club as $team) {
if ($team['idTeam'] == $idTeam) {
foreach ($team as $match) {
$arSplitDate = explode(".",$match->date);
printf ("<tr>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s:%s</td>\n
</tr>\n",
$match->matchNr,
strftime("%a", mktime(0, 0, 0, $arSplitDate[1], $arSplitDate[0], "20".$arSplitDate[2])),
$match->date,
$match->time,
utf8_decode($match->homeName),
utf8_decode($match->awayName),
utf8_decode($match->gymName),
$match->homeScore, $match->awayScore);
}
}
}
}
?>
<table width='676' border='0' cellpadding='0' cellspacing='0'>
<tr>
<td class='title'>#</td>
<td class='title'>Tag</td>
<td class='title'>Datum</td>
<td class='title'>Zeit</td>
<td class='title'>Heim</td>
<td class='title'>Gast</td>
<td class='title'>Halle</td>
<td class='title'>Resultat</td>
</tr>
<?php
$idTeam = 440;
printScheduleData($XMLFilePath, $idTeam);
?>
</table>
10. Beispiel 2 (mit simplexml_load_string)
<?php include_once("./lib.HTTPRequest.php"); ?>
<?php
// Dateiname z.b. schedule.php
$XMLFilePath = "http://www.bvn.ch/xml/schedule/SC_UNI_BASEL.xml";
function printScheduleData($XMLFilePath, $idTeam) {
$myRequest = new HTTPRequest($XMLFilePath);
$xml_contents = $myRequest->DownloadToString();
$club = simplexml_load_string($xml_contents);
foreach ($club as $team) {
if ($team['idTeam'] == $idTeam) {
foreach ($team as $match) {
$arSplitDate = explode(".",$match->date);
printf ("<tr>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s:%s</td>\n
</tr>\n",
$match->matchNr,
strftime("%a", mktime(0, 0, 0, $arSplitDate[1], $arSplitDate[0], "20".$arSplitDate[2])),
$match->date, $match->time,
utf8_decode($match->homeName),
utf8_decode($match->awayName),
utf8_decode($match->gymName),
$match->homeScore, $match->awayScore);
}
}
}
}
?>
<table width='676' border='0' cellpadding='0' cellspacing='0'>
<tr>
<td class='title'>#</td>
<td class='title'>Tag</td>
<td class='title'>Datum</td>
<td class='title'>Zeit</td>
<td class='title'>Heim</td>
<td class='title'>Gast</td>
<td class='title'>Halle</td>
<td class='title'>Resultat</td>
</tr>
<?php
$idTeam = 440;
printScheduleData($XMLFilePath, $idTeam);
?>
</table>
11. HTTP Request Library (notwendig für Bsp2)
<?php
// Dateiname lib.HTTPRequest.php für Aufruf aus Beispiel 2
class HTTPRequest {
var $_fp; // HTTP socket
var $_url; // full URL
var $_host; // HTTP host
var $_protocol; // protocol (HTTP/HTTPS)
var $_uri; // request URI
var $_port; // port
// scan url
function _scan_url() {
$req = $this->_url;
$pos = strpos($req, '://');
$this->_protocol = strtolower(substr($req, 0, $pos));
$req = substr($req, $pos+3);
$pos = strpos($req, '/');
if($pos === false) {
$pos = strlen($req);
}
$host = substr($req, 0, $pos);
if(strpos($host, ':') !== false) {
list($this->_host, $this->_port) = explode(':', $host);
} else {
$this->_host = $host;
$this->_port = ($this->_protocol == 'https') ? 443 : 80;
}
$this->_uri = substr($req, $pos);
if($this->_uri == '') {
$this->_uri = '/';
}
}
// constructor
function HTTPRequest($url) {
$this->_url = $url;
$this->_scan_url();
}
// download URL to string
function DownloadToString() {
$crlf = "\r\n";
// generate request
$req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
. 'Host: ' . $this->_host . $crlf
. $crlf;
// fetch
$this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '')
. $this->_host, $this->_port);
fwrite($this->_fp, $req);
while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp)) {
$response .= fread($this->_fp, 1024);
}
fclose($this->_fp);
// split header and body
$pos = strpos($response, $crlf . $crlf);
if($pos === false) {
return($response);
}
$header = substr($response, 0, $pos);
$body = substr($response, $pos + 2 * strlen($crlf));
// parse headers
$headers = array();
$lines = explode($crlf, $header);
foreach($lines as $line) {
if(($pos = strpos($line, ':')) !== false) {
$headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
}
}
// redirection?
if(isset($headers['location'])) {
$http = new HTTPRequest($headers['location']);
return($http->DownloadToString($http));
} else {
return($body);
}
}
}
?>
12. Beispiel 3 (für Rangliste)
<?php include_once("./lib.HTTPRequest.php"); ?>
<?php
$XMLFilePath = "http://www.bvn.ch/xml/ranking/H3L.xml";
function printRankingData($XMLFilePath) {
$myRequest = new HTTPRequest($XMLFilePath);
$xml_contents = $myRequest->DownloadToString();
$league = simplexml_load_string($xml_contents);
// evtl hier das Array League noch nach Rank sortieren
foreach ($league as $team) {
printf ("<tr>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
<td>%s</td>\n
</tr>\n",
$team->rank,
utf8_decode($team->name),
$team->games,
$team->win,
$team->lost,
$team->forfait,
$team->scored,
$team->received,
$team->difference,
$team->points,
$team->directEncounter,
$team->directEncounterPoints,
$team->directEncounterDifference
);
}
}
?>
<table width='676' border='0' cellpadding='0' cellspacing='0'>
<tr>
<td class='title' width="30"> </td>
<td class='title' width="400">Mannschaft</td>
<td class='title' width="50">Spiele</td>
<td class='title' width="40">S</td>
<td class='title' width="40">N</td>
<td class='title' width="40">FF</td>
<td class='title' width="50">Erz</td>
<td class='title' width="50">Erh</td>
<td class='title' width="50">KV</td>
<td class='title' width="50">Punkte</td>
<td class='title' width="50">SpDB</td>
<td class='title' width="60">Pt.DB</td>
<td class='title' width="50">KVDB</td>
</tr>
<?php printRankingData($XMLFilePath); ?>
</table>