PHP » XML-Ersetzungen

Zweck

Die Klasse xml stellt alle benötigten Funktionen bereit um einzelne Tags in einem XML-Dokument ggf. abhängig von ihren Kind-Elementen und Attributen durch andere Ausgaben zu ersetzen. So lassen sich theoretisch ganze XML-Dokumente in andere Formate konvertieren, aber auch einfach nur ein XML-Dialekt in einen anderen umschreiben. Ich habe die Klasse mit der Intention geschrieben, mir das Erstellen sehr großer XHTML-Dokumente zu vereinfachen, indem die Klasse einige Abkürzungen und Vereinfachungen bereitstellt. Außerdem werden die Templates in meinem Content-Management-System übersichtlicher, da dort kein Programmcode und keine Platzhalter nach frei erfundenem Schema enthalten sind, sondern normale XML-Elemente ersetzt werden, die durch ihre Attribute weitere Optionen spezifizieren können. Zusammengefasst macht die Klasse nach der Integration das Schreiben von normalem XHTML durch ihre Erweiterungen einfacher und übersichtlicher, und am Ende kommt valides, sauberes XHTML1 heraus.

Aufbau und interne Struktur

Die xml-Klasse besitzt folgende Methoden:

public function output($xml, $returntype = "xhtml", $doctype = "xhtml1-strict")
Die Funktion output ist die Wichtigste von allen: man ruft sie auf, übergibt ihr das gesamte XML-Dokument, legt fest, was für ein Inhaltstyp zurückgegeben werden soll (einzig unterstützter ist im Moment «xhtml» — theoretisch ist es aber leicht, die Tags um z. B. einen «plaintext»-Rückgabetyp zu erweitern) und spezifziert den zu verwendenden Doctype, wobei "" für keinen XHTML-Kopf steht, "xhtml1-strict" und "xhtml1-transitional" durch die entsprechenden Doctypes ersetzt werden und alle anderen Werte als kompletter Doctype angesehen werden, d. h. man kann für diesen Parameter z. B. einen HTML4-Doctype verwenden.
public function setDataItem($key, $val)
Setzt ein sog. «DataItem». Die Tags können auf allgemeine Optionen, die in den DataItems spezifziert sind zugreifen.
public function getDataItem($key)
Liest ein DataItem. Vorwiegend in den Klassen der Tags benötigt.
public function setBeforeParseCallback($callback)
Dieser Funktion übergibt man einen Callback, der aufgerufen wird, bevor die parse-Methode XML-Daten verarbeitet. Das ist z. B. nützlich, wenn man in seinen Dokumenten vor dem Parsen Ersetzungen von invaliden Elementen o. Ä. vornehmen will.
public function addReplacement($callback, $key = False)
Dieser Funktion wird eigentlich nur in den Klassen der Tags benötigt: Wenn ein Tag im XML-Dokument vorkommt, die Daten die als Ersatzstring verwendet werden sollen jedoch erst vorliegen, nachdem alle anderen Tags verarbeitet wurden (z. B. bei der Inhaltsübersicht), muss man einen Platzhalter einfügen, der später von einer anderen Funktion ersetzt wird. Den Platzhalter bestimmt die Funktion automatisch, außer man gibt für $key explizit einen Wert an, $callback steht für die Funktion, die am Ende den Platzhalter ersetzt. Sie wird von der output-Funktion aufgerufen und bekommt als einzigen Parameter die Ausgaben der verarbeiteten Tags übergeben.
public function addFunction($callback)
Wenn die Verarbeitung des kompletten XML-Dokuments abgeschlossen ist soll die output-Funktion die als $callback-Parameter übergebene Funktion mit den Ausgaben der verarbeiteten Tags als einzigen Parameter auf das Ergebnis anwenden.
public function setProtocol($key, $val)
$key gibt ein Protokoll an, z. B. «http://», $val gibt einen Ersatzstring an, z. B. «callurl.php?link=%u». Beginnt das Protokoll mit «callback:», ist $val ein Callback dem als Parameter die URL ohne Protokoll übergeben wird.
public function getFreeID()
Gibt bei jedem Aufruf eine andere freie ID zurück. Per "autoid".$this->xml->getFreeID() kann man so im Code eines Tags sich eine freie ID erzeugen.
public static function mask($xml)
Maskiert einen String per htmlspecialchars().
public static function mask_xml($xml)
Alias zur mask-Methode
public function parse($xml, $onlychilds = False)
Parst einen XML-String. XML-Kopfzeile wird, wenn diese fehlt, automatisch hinzugefüt, unter Annahme des Zeichensatzes «iso8859-1». Fehlt weiterhin ein Root-Element, das die Unterlemente enthält, wird dieses ebenfalls automatisch angefügt. Per $onlychilds kann eingestellt werden, ob das Root-Element im Ergebnis ebenfalls enthalten sein soll.
public function parseNode($node, $onlychilds = False , $returncontent = True, $xmlfuncs = True, $attributes = array(), $tags = array())
Parst einen XMLDOM-Node. $onlychilds gibt an, ob das Root-Element in der Ausgabe ebenfalls enthalten sein soll, $xmlfuncs regelt ob die variablen XML-Erweiterungen mit einbezogen werden sollen oder nicht, $attributes ist ein Array, das die Attribute enthält, die ausgelesen werden sollen, die übrigen Attribute werden nur als vollständiger String zurückgegeben, der direkt in einem XML-Element verwendet werden kann. $tags ist ein Array, dass die Namen der Kindelemente enthält, deren Inhalt ohne weitere Verarbeitung aufgezeichnet werden soll. Die Funktion gibt ein Array mit vier Elementen zurück:
"content_string"
Enthält den verarbeiteten Inhalt des Wurzelelements, bzw. wenn $onlychilds = False dann auch die Ausgabe des Wurzelelements selbst.
"attributes_string"
Enthält einen String der Form « id="hehe" style="color:red;"» mit den Attributen, die nicht im Übergabearray $attributes enthalten sind.
"attributes_array"
Enthält ein Array mit den Werten der in $attributes enthaltenen Attribute.
"tags_array"
Enthält ein Array mit den Inhalten der in $tags genannten Tags.
public function attributes($node, $attributes = array())
Eine Kurzform zu parseNode(): return $this->parseNode($node, True, False, True, $attributes); Sie ist dazu gedacht, sich innerhalb der Tags per $this->xml->attributes($this->node, array("attribut1", "attribut2")) die gewünschten Attribute auslesen zu lassen.
public function href($xml, $content, $attributes, $child = False)
Diese Funktion kann von den Tag-Klassen aufgerufen werden, falls sie ein als Link per href-Attribut markierbares Element sind. Es wird dann der fertige XHTML-Code für die übergebenen Daten mit dem eingebauten Link erzeugt. $child regelt, ob das a-Tag hierarchisch weiter innen oder außen als das Element stehen muss (in den meisten Fällen gilt: wenn das Element keinen Inhalt hat, muss das a außen stehen, sonst innen). $attributes ist ein Array mit den Attributen des Elements (bei denen u. A. das href-Attribut vorkommt), $content sind evtl. Kindelemente des Elements, das in $xml genannt ist und, wenn es Kinder haben kann, dort «%s» als Platzhalter angibt.
public function url($url)
Dieser Funktion übergibt man eine URL und sie gibt die gleiche oder eine modifzierte URL zurück, abhängig von den per setProtocol() spezifzierten Protokollen.

Es wird weiterhin das Interface «xml_widget» spezifiziert, das angibt, wie die Klassen der Tags aufgebaut zu sein haben müssen: sie müssen einen Konstruktor enthalten, dem $node und die xml-Klasse übergeben wird, eine statische dtd-Funktion enthalten, die den Teil der zum Tag gehörenden DTD zurückgibt und eine output-Funktion besitzen, die als einzigen Parameter den Rückgabetyp (z. B. «xhtml») erhält. Die output-Funktion muss dann die Ausgabe des Tags im entsprechenden Format zurückgeben.

Möchte man ein XML-Dokument verarbeiten erzeugt man sich also eine Instanz der xml-Klasse und ruft die output-Methode mit dem XML-Dokument als Parameter auf. Die Klasse prüft dann, was für Klassen existieren, die mit dem Namen «xml_» beginnen, und nimmt den anschließend folgenden Namen als Tag-Bezeichnung. Diese Elemente werden dann von der jeweiligen Klasse verarbeitet. Es werden rekursiv alle XML-Elemente verarbeitet und die «ohne Sonderbehandlung» einfach übernommen, wobei das href-Attribut und das parentattr-Kindelement mit enbezogen wird. Möchte man ein neues Tag spezifizieren muss man nichts weiter tun, als eine neue xml_TAGNAME-Klasse zu erzeugen, die den Ansprüchen des Interfaces xml_widget genügt.

Integration in eigene Projekte

Integration der XML-Klasse

Möchte man die Klasse in ein Dokument integrieren, muss man erst dessen Inhalt nicht direkt an den Browser senden, sondern per Output Buffering für die spätere Verarbeitung aufheben. Am Ende kann man dann die Klasse mit den aufgezeichneten Daten aufrufen. Macht man das in mehreren Dateien, ist es sinnvoll, die Befehle auszulagern und per include() einzubinden. Ein Beispieldokument könnte so aussehen:

<?php
    ob_start
();
?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
<head>
<title>Test</title>
</head>
<body>
<p>test<seperator />bla</p>
</body>
</html>
<?php
    
include("xml.php");
    
$path "xml/";
    
$tags scandir($path);
    foreach(
$tags as $tag)
        if (
$tag[0] != "." && substr($tag, -1) != "~" && !is_dir($path.$tag))
            include(
$path.$tag);
    
$xml = new xml;
    echo 
$xml->output(ob_get_clean());
?>

Hier werden die Tags aus dem Unterverzeichnis «xml» geladen, es wird angenommen dass sich die xml-Klasse im gleichen Verzeichnis wie das Dokument, das sie inkludiert befindet. Es ist abhängig von den Dateien im Unterverzeichnis, wie das XML-Dokument modifziert wird. Das Ergebnis, das an den Browser geschickt wird, sieht bei diesem Code so aus:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de">
<head>
<title>Test</title>
</head>
<body>
<p>test<hr />bla</p>
</body>
</html>

Damit das Beispiel funktioniert muss die «replacement.php»-Erweiterung installiert sein.

Das Eingabe-Dokument muss ein valides XML-Dokument sein, andernfalls beendet die Klasse mit einer Exception! Damit man den Fehler besser nachvollziehen kann, gibt die Klasse weiterhin das Eingabedokument mit Zeilennummern aus.

Tags durch definierte Inhalte ersetzen

<?php
class xml_seperator extends xmlreplacement
{
    public function 
xhtml($attributes)
    {
        return 
"<hr".$attributes." />";
    }
}
?>

Der oben stehende Programmcode der xml_seperator-Klasse gibt, wenn das seperator-Tag im Dokument vorkommt <hr /> aus, wobei alle Attribute des Eingangselements übernommen werden, d. h. <seperator style="width:50%" /> führt zur Ausgabe <hr style="width:50%" />.

So kann man leicht Tags durch andere Ausgaben ersetzen lassen, was z. B. für ein Template-System hilfreich ist, bei dem an der Stelle, an der das Tag <content /> vorkommt der Inhalt eingesetzt werden soll. Per <?php
class xml_content extends xmlreplacement
{
    public function 
xhtml($attributes)
    {
        
$content $this->xml->getDataItem("content");
        
$parse $this->xml->parse($content);
        return 
$parse["content_string"];
    }
}
?>
könnte man sich das Tag durch einen anderen Inhalt ersetzen lassen, den man vor dem Aufruf der output-Funktion der xml-Klasse per <?php
$xml
->setDataItem("content"$lustigerinhalt);
?>
verfügbar machen muss.

Damit das funktioniert, muss die Erweiterung «replacement.php» installiert sein.

parentattr: Attribut dem Elternelement hinzufügen

Manchmal ist es wünschenswert, einem Element als Attribut den Wert eines anderen Elements zuzuweisen. Das geht wie folgt: <input type="submit">
    <parentattr name="value">
        <lang key="send" />
    </parentattr>
</submit>
Das würde einem Submit-Button als Beschriftung den Rückgabewert des lang-Tags zuweisen, das die entsprechende Beschriftung abhängig von der Sprache aus einer Datenbank laden kann.

Das «parentattr»-Element wird von der xml-Klasse selbst unterstützt, man muss keine zusätzliche Erweiterung installieren.

Mehrsprachigkeit

In einem mehrsprachigen Dokument sind zwei Punkte wünschenswert:

  1. Man sollte die Möglichkeit haben, mehrfach verwendete Textabschnitte aus einer Datenbank zu laden, ohne sich dabei um die momentan eingestellte Sprache kümmern zu müssen.
  2. Es sollte möglich sein, einen Textabschnitt nur anzuzeigen, wenn eine bestimmte Sprache eingestellt ist.

Beides ist mit dem lang-Tag möglich. Zuerst muss man Sprachdaten zur Verfügung stellen, die man vorher aus einer Datenbank laden kann: <?php
$lang 
= array
(
    
"send" => array
    (
        
"de" => "Absenden",
        
"en" => "Submit"
    
),
    
"reset" => array
    (
        
"de" => "Zurücksetzen",
        
"en" => "Reset"
    
)
);
$xml->setDataItem("lang""de");
$xml->setDataItem("lang"$lang);
?>
Anschließend hat man die Möglichkeit, einfach auf diese Daten zuzugreifen: <ul>
    <li>Englisch: <lang key="reset" lang="en" /></li>
    <li>Deutsch: <lang key="reset" lang="de" /></li>
    <li>Momentane Standard-Sprache: <lang key="reset" /></li>
</ul>
Wird über das lang-Attribut die Standardeinstellung nicht explizit überschrieben, wird das DataItem «lang» als Standardsprache verwendet. Das DataItem «lang_var» muss die Keys enthalten, über die auf den jeweiligen Textabschnitt zugegriffen werden kann, jedem Key wird ein Array zugeordnet, welches als Index wiederum die Sprache verwendet und als Wert den Text in der jeweiligen Sprache. Die Daten werden nicht maskiert ausgegeben, d. h. man kann in den Texten auch XML-Tags verwenden. Schreibt man in den Texten «%s» wird das «%s» durch den Wert des Attributs «replace» ersetzt, wenn dieses angegeben ist.

Um einen Text nur einzublenden, wenn die momentan eingestellte Sprache Deutsch ist, könnte man die Attribute des Tags so setzen: <lang if="de">Hallo!</lang><lang if="en">Hello!</lang> So wird «Hallo!» angezeigt, wenn Deutsch als Sprache eingestellt ist-

Damit dieses Tag verfügbar ist, muss die Erweiterung «lang.php» installiert sein.

XHTML2: href-Attribut

Das href-Attribut habe ich von XHTML2 geklaut. Es sagt aus, dass ein Element ein Link ist, ohne ein a-Tag zu verwenden. Dann kann man z. B. sowas schreiben: <ul>
    <li href="http://google.de">Google ist böse!</li>
    <li href="/witze-seite">Viele lustige Witze</li>
    <li href="http://php.net">RTFM</li>
</ul>

Dieses Attribut muss von dem jeweiligen Erweiterungs-Tag unterstützt werden. Für «normale» XHTML-Elemente unterstützt die xml-Klasse das Attribut selbst bereits. Folgende standardmäßig in XHTML1 verfügbaren Tags werden unterstützt:

XHTML2: seperator-Tag

Das seperator-Tag gibt einfach nur ein hr aus, erzeugt also eine Trennlinie. Ich habe den Namen von XHTML2 geklaut und mag es, weil es einen sehr einfachen Programmcode hat. Es ist in der «replacements.php»-Erweiterung enthalten.

XHTML2: section- und h-Tags für bessere Gliederung des Inhalts

XHTML2 kennt section- und h-Tags. Mit ihnen sparrt man sich die Markierung des Überschriften-Levels über eine Nummer, man gibt das Level durch die Verschachtelung der section-Tags an. Ein mit toc="no" gekennzeichnetes h-Tag taucht nicht in der Inhaltsübersicht auf (s. U.). <h>Interessantes Dokument</h>
<section>
    <h>1. Kapitel</h>
    <p>Einleitungstext</p>
    <section>
        <h>Unterüberschrift</h>
        <p>foo</p>
    </section>
</section>
<section>
    <h>2. Kapitel</h>
    <p>bar</p>
</section>

Diese Tags sind über die Erweiterungen «h.php» und «section.php» verteilt.

Automatisches Erzeugen einer Inhaltsübersicht

Um eine Inhaltsübersicht zu erzeugen, wie sie z. B. am Anfang dieser Dokumentation zu sehen ist, kann man einfach ein <toc /> verwenden. Damit das geht muss die «toc.php»-Erweiterung installiert sein. Es werden jedoch nur h-Überschriften in section-Elementen dargestellt, keine normalen h1-, h2-, …-Tags

Titel eines Links automatisch bestimmen, Einfärben bei nicht-existenter Zielseite

<hyperlink page="home" /> Dieser Code soll einen Link zur Startseite erzeugen und automatisch deren Seitentitel einlesen. Existiert keine «home»-Seite wird dem Link eine «error404»-Klasse zugewiesen, damit er per CSS anders formatiert werden kann (z. B. rot-Färben von Links wie in gängigen Wiki-Systemen). Damit das geht muss eine Funktion spezifiziert werden, die ermittelt, ob eine Seite existiert und eine, die den Seitentitel bestimmt: <?php
$seiten 
= array
(
    
"home" => "Startseite",
    
"witze-seite" => "Lustige Witze"
);

function 
title($page)
{
    global 
$seiten;
    if (!isset(
$seiten[$page]))
        return 
"Kein Titel.";
    return 
$seiten[$page];
}

function 
exists($page)
{
    global 
$seiten;
    return isset(
$seiten[$page]);
}

$xml->setDataItem("hyperlink_exists""exists"));
$xml->setDataItem("hyperlink_title""title"));
?>
Das page-Attribut ist für die Verlinkung zu einer internen Seite gedacht. Verwendet man mod_rewrite und möchte z. B. vor jedem Seitenpfad ein «/inhalt/» in die URL einfügen, kann man das so machen: <?php
$xml
->setDataItem("hyperlink_url""/inhalt/%s");
?>
Man kann den Titel eines Links natürlich auch nicht-automatisch bestimmen lassen: <hyperlink page="witze-seite">Anderer lustiger Seitentitel</hyperlink> Möchte man auf eine externe Seite verlinken, geht das so: <hyperlink extern="http://google.de">Google</hyperlink> hat ein Monopol! Über das anchor-Attribut kann man einen Anker festlegen, wie mit «home#anker» — schreibt man das jedoch ins page-Attribut rein, müsste die title- und exists-Funktion das erst wegfiltern, außerdem ist ein extra Attribut schöner. <hyperlink anchor="kapitel3">Drittes Kapitel</hyperlink> Das blank-Attribut legt fest, ob die Zielseite in einem neuen Fenster geöffnet werden soll. Damit das geht, muss erstens ein Transitional-Doctype gesetzt werden, und zweitens muss dies explizit im PHP-Code erlaubt werden: <?php
$xml
->setDataItem("hyperlink_blank"True);
?>
Dies gibt die Möglichkeit, für eine komplette Internetseite das Öffnen neuer Seiten auf einmal zu konfigurieren, da ich z. B. für kommerzielle Seiten in der Regel neue Fenster öffne, für meine eigenen hingegen nicht. Mit dieser Einstellung kann ich das Öffnen neuer Seiten dann für meine gesamte Internetseite an- oder ausschalten. Setzt man blank="force" wird diese Einstellung umgangen und es wird aufjedenfall immer ein neues Fenster geöffnet.

Wird ein Link im neuen Fenster geöffnet erhält er zusätzlich die Klasse «blank». Wird er per extern-Attribut erzeugt, ist er auch Mitglied der «extern»-Klasse. So kann man Links abhängig von ihren Eigenschaften auch schon mit CSS2 formatieren.

Die Erweiterung befindet sich in der Datei «hyperlink.php».

Automatisches Erzeugen von Thumbnails und Bildunterschriften

Dieses Tag kann Bilder ausgeben, Bildunterschriften drunter setzen und die Bilder automatisch resizen, d. h. serverseitig Thumbnails erzeugen. Folgende Attribute:

path
Der Pfad zum Bild. Dieser Pfad muss den lokalen Pfad angeben, nicht den, über den der Browser auf das Bild zugreift!
text
Bildbeschreibung. Wird für das alt- und title-Attribut verwendet, ggf. für die Bildunterschrift. Wird eine Bildunterschrift angezeigt wird alt="" gesetzt, damit im Textbrowser nicht alles doppelt dasteht.
width
Bildbreite. Optional wenn weder Floating noch Resizing verwendet wird. Als Einheit muss «px» mit dazu geschrieben werden.
height
Bildhöhe. Optional wenn weder Floating noch Resizing verwendet wird. Als Einheit muss «px» mit dazu geschrieben werden.
resize
Wenn dieses Attribut gesetzt ist, wird ein Thumbnail vom Bild mit width und height als Maximalgröße erstellt. Man kann diesem Attribut entweder «scale» oder «stretch» zuweisen, abhängig davon, ob korrekte Größenverhältnisse gewahrt bleiben sollen oder nicht.
float
Dieser Wert kann «left» oder «right» sein und stellt das Umfließen mit Text ein.
signature
Setzt man signature="signature" wird eine Bildunterschrift angezeigt
sigstyle
Wenn die Bildunterschrift eingeschaltet ist wird das Bild mit einem zusätzlichen div-Tag umgeben, dass auch noch ein p-Element für die Bildbeschreibung enthält. Das sigstyle-Attribut weist dem div-Tag ein style-Attribut zu.

Unterscheidet sich die URL, die der Browser aufrufen soll vom lokalen Pfad, kann diese wie folgt eingestellt werden: <?php
$xml
->setDataItem("image_remote""/%s");
?>
Statt «%s» kann man auch «%u» verwenden, welches für den per urlencode() kodierten Pfad steht. Den Pfad, in dem die Thumbnails gespeichert werden stellt man so ein: <?php
$xml
->setDataItem("image_prefix""cache/thumbnail_");
?>
Es wird automatisch gecached. Beispiel: <image path="lustigesbild.jpg" href="lustigesbild.jpg" text="Sehr witziges Bild" signature="signature" width="100px" height="200px" float="right" resize="scale" />
<!-- Angezeigt wird ein max. 100x200 Pixel großes Thumbnail mit der Bildunterschrift "Sehr witziges Bild", es wird links von Text umflossen und auf Klick erscheint das große Bild (href!). -->

Diese Erweiterung findet sich in der Datei «image.php».

Damit dieses Tag funktioniert muss meine image-Klasse installiert und per include() eingebunden werden!

Integration von TinyMCE und Edit area

Möchte man Edit area oder TinyMCE in seine Website integrieren, geht das mit diesen beiden Tags sehr einfach. Einfach ins form-Tag sowas einfügen: <wysiwyg name="html" value="abc" /> <jstextarea name="code" value="abc" /> Der nötige Javascript-Code wird automatisch eingebunden. Damit das geht muss man jedoch die Dateien von TinyMCE oder Edit area in ein Verzeichnis schieben und den Klassen verraten, wo dieses denn liegt: <?php
$xml
->setProtocol("tinymce://""/resources/javascript/tiny_mce/%s");
$xml->setProtocol("editarea://""/resources/javascript/edit_area/%s");
?>
Die Tags werden durch normale textarea-Tags ersetzt, es wird ihnen eine eindeutige ID zugewiesen und das jeweilige Javascript eingebunden.

Die Erweiterungen befinden sich in den Dateien «jstextarea.php».und «wysiwyg.php»

Variableninhalte einbinden und Daten formatieren

<date format="d.m.Y" /> gibt das aktuelle Datum aus. Man kann das Tag auch einen Wert enthalten lassen, dieser muss als Unix-Timestamp formatiert sein. Ich verwende diese Konstruktion in meinem Templates, um das Datum der letzten Aktualisierung auszugeben: <date format="d.m.Y"><option type="content" name="lastchange" /></date> Das option-Tag gibt den Wert einer vorher gespeicherten Variable aus. Man kann wie folgt Daten zur Verfügung stellen: <?php
$xml
->setDataItem("option"  , array
(
    
"get" => $_GET,
    
"post" => $_POST,
    
"content" => array("lastchange" => date("U")
));
?>
So kann man unmittelbar Werte von Get- oder Post-Parametern ausgeben oder auf beliebige anderen Variablen zugreifen. Standardmäßig werden die Ausgaben maskiert, setzt man html="html" werden in den Variablen vorkommende Sonderzeichen nicht maskiert. (Bitte nur mit sicheren Werten machen, andernfalls wird man gegen Cross-Site-Scripting-Attacken anfällig.) Setzt man urlencode="urlencode" wird die Ausgabe vorher per urlencode() verarbeitet.

Die Tags sind unabhängig voneinander und befinden sich in den Erweiterungen «date.php» und «option.php».

Abhängig von Variableninhalten andere Elemente anzeigen

Man kann nicht nur mit dem option-Tag Variableninhalte ausgeben, sondern auch mit dem if-Tag andere Elemente abhängig von dem Inhalt der Variablen anzeigen oder ausblenden. <if type="get" name="showthis" equal="yes">Hehe, ich werde nur angezeigt wenn man mich mit "?showthis=yes" aufruft.</if> Statt dem equal-Attribut kann man auch das unequal-Attribut verwenden.

Das if-Tag befindet sich in der «if.php»-Erweiterung.

Protokolle definieren

Häufig benötigt man Pfade, die sich öfters mal ändern, oder möchte bestimmte Daten von einer Funktion oder Datenbank beziehen. Dafür hab ich mir sowas ausgedacht: Per <?php
$xml
->setProtocol("res://""/resources/%s");
?>
spezifiziert man das Protokoll «res://», das eine Abkürzung für den Pfad «/resources/» darstellt. Damit missbraucht man zwar etwas den Sinn von solchen Protokollangaben, aber der Client bekommt davon ja nix mit, sondern nur sauberes XHTML ausgeliefert, mit korrekten Protokollangaben ;) Man kann auch angeben, dass erst eine Callback-Funktion die eigentlichen Daten bestimmt: <?php
function protocol_file($url)
{
    if (!
file_exists($url))
        return 
"#";
    return 
file_get_contents("dateien/".basename($url));
}

$xml->setProtocol("callback:file://""protocol_file");
?>

Mit solchen Tags muss man sehr aufpassen. Sollte jemand fremdes z. B. über ein kaputtes Gästebuch XML-Code einschleußen können, bedeutet das gleichzeitig, dass er dann beliebige Dateien auslesen könnte!

Diese Funktion wird von der xml-Klasse selbst unterstützt, es werden keine zusätzlichen Erweiterungen benötigt.

Erweiterungen

Download

Die Klasse selbst: Quellcode anzeigen | Herunterladen

Die Erweiterungen der Klasse sollten in einem Unterverzeichnis, z. B. mit dem Namen «xml» gespeichert werden.

xml_date.php
Quellcode anzeigen | Herunterladen
xml_h.php
Quellcode anzeigen | Herunterladen
xml_hyperlink.php
Quellcode anzeigen | Herunterladen
xml_if.php
Quellcode anzeigen | Herunterladen
xml_image.php
Quellcode anzeigen | Herunterladen
xml_jstextarea.php
Quellcode anzeigen | Herunterladen
xml_lang.php
Quellcode anzeigen | Herunterladen
xml_option.php
Quellcode anzeigen | Herunterladen
xml_replacement.php
Quellcode anzeigen | Herunterladen
xml_section.php
Quellcode anzeigen | Herunterladen
xml_toc.php
Quellcode anzeigen | Herunterladen
xml_wysiwyg.php
Quellcode anzeigen | Herunterladen

Schreiben eigener Erweiterungen

Wenn man eigene Erweiterungen entwickeln möchte, ist es sinnvoll, erstmal auf Basis einer anderen, einfachen Erweiterung anzufangen (z. B. option). Dazu kopiert man sich eine Datei im Verzeichnis mit den Tags, ändert den Namen der Klasse auf «xml_TAGNAME» ab. Anschließend muss man die Werte benötigter Attribute auslesen lassen, ggf. die Ausgaben der Kindelemente einlesen und sinnvolle Ausgaben an die xml-Klasse zurückgeben. Es ist sinnvoll, den Programmcode dabei in einen allgemeinen Teil und einen ausgabespezifischen Teil zu gliedern, d. h. das Verarbeiten der Parameter und Bestimmen des Inhalts in der jeweiligen output-Funkton zu erledigen, die Ausgaben für den Ausgabetyp «xhtml» hingegen in der xhtml-Funktion zusammenzubauen. Wer Fragen hat, darf gerne fragen ;)

Implementierte, aber noch nicht veröffentlichte Features

Vor der Veröffentlichung sollte der Programmcode noch einmal durchgegangen und auf Kompatibilität mit dem bereits veröffentlichtem Code geprüft werden. Wer Interesse an den folgenden Features hat, kann mich benachrichtigen, und ich werde mich um baldige Veröffentlichung kümmern.

Zukünftig geplante Features

Validieren mit DTDs

Das Validieren des Eingangsdokuments mit einer DTD ist vorgesehen, jedoch nicht fertig implementiert. Um die Aufgabe zu erfüllen müsste man eine Ausgangs-DTD, wie z. B. die von XHTML1, mit den Eigenschaften der zusätzlich «erfundenen» Tags und Attributen ergänzen. Dazu muss erst die dtd-Funktion jeder Tag-Klasse mit Inhalt gefüllt werden und dann eine Funktion implementiert werden, die die fertige DTD aus der Eingangs-DTD und der DTD aller erweiterten Elemente konstruiert. Wer daran Interesse hat, darf mir gerne schreiben.

Neue Tags

© 2009 Julian von Mendel (http://derjulian.net) | Datum: 19.04.2024