Sven Mintel
Mitglied
Hier mal nen Beispiel(der Einfachheit halber alles in einem einzigen Skript)
Der Wermutstropfen an setParameter():
bei der Verwendung der PHP-Funktionen kann man flexibel arbeiten, also 1 Template für beliebig viele Funktionen benutzen, den Funktionsnamen bezieht man z.B. einfach aus dem Inhalt des dafür vorgesehenen Knotens(im Beispiel <php/>). Auch die Übergabe von Parametern an die PHP-Funktionen ist problemlos möglich.
Bei den Variablen geht das leider nicht so flexibel....ein Zugriff auf Variablen, deren Namen man im Vorraus nicht kennt, ist in XSL nicht möglich(hab zumindest keine Möglichkeit gefunden, und ich hab seeeeehr lange gesucht).
Das schränkt natürlich die Benutzbarkeit ein, weil man für jede Variable ein Template erstellen muss(sofern man sie so benutzt, wie ich in dem Beispiel)
Aber für bestimmte Anwendungen lassen sich diese Variablen gut nutzen.
Angenommen man hat eine mehrsprachige Seite, PHP setzt im XSL eine Variable für die benötigte Sprache.
Dann wäre es bspw. möglich, entsprechend der Variable eine Sprachdatei per document() zu laden oder aber wenn man eine einzige Datei für alle Sprachen hat einen bestimmten Knoten anhand der Variable auszuwählen.
Solltest du jetzt aber doch sehr viel mit diesen Parametern arbeiten wollen, gibt es auch da eine Möglichkeit.
Anstatt mit setParameter() zu Arbeiten, "infiziere" die Sache per XML mit den Variablen
Wie das bspw. geht:
Über ein Nodeset, welches diese Variablen enthält.
Dieses Nodeset holst du im XSL aus einer PHP-Funktion ab, und speicherst es im XSL als Variable.
Jetzt hast du flexiblen Zugriff, denn du kannst aus dieser einzigen gespeicherten Variable beliebige Kindknoten per XPATH abrufen, welche dann die Variablen(Parameter) enthalten.
Zum Testen:
PHP:
<?php
//Stylesheet
$xsl='
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl"
exclude-result-prefixes="php">
<!-- Basis-Template -->
<xsl:template match="/">
<body><xsl:apply-templates/></body>
</xsl:template>
<!-- Template für PHP-Funktionen -->
<xsl:template match="php">
<xsl:for-each select="php:function(string(.))">
<xsl:apply-templates />
</xsl:for-each>
</xsl:template>
<!-- Template für Variablen, für jede benötigte muss ein eigenes angelegt werden -->
<xsl:template match="testvar1">
<p><xsl:value-of select="$testvar1"/></p>
</xsl:template>
<xsl:template match="testvar2">
<p><xsl:value-of select="$testvar2"/></p>
</xsl:template>
<!-- Template für HTML-Elemente, die kennt XML ja sonst nicht -->
<xsl:template match="code|html|title|style|label|script|a|abbr|acronym|address|b|big|body|head|blockquote|cite|dfn|div|em|h1|h2|h3|h4|h5|h6|i|kbd|p|pre|q|quote|samp|textarea|span|small|strike|strong|sub|sup|tt|button|fieldset|form|label|legend|option|optgroup|select|caption|col|colgroup|table|tbody|td|tfoot|th|thead|tr|dl|dd|dt|ol|ul|li|var">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
';
//XML
$xml='
<root>
<php>menu</php>
<testvar1/>
<testvar2/>
</root>
';
//Beispielfunktion, wird über <php>menu</php> aufgerufen
function menu()
{
$menu=new DOMDocument();
$menu->loadXML('<ol><li>Dies</li><li>könnte</li><li>ein</li><li>Menü</li><li>sein</li></ol>');
return $menu;
}
$xsldoc=new DOMDocument();
$xsldoc->loadXML($xsl);
$xmldoc=new DOMDocument();
$xmldoc->loadXML($xml);
$xp = new XsltProcessor();
//PHP-Funktionen verfügbar machen
$xp->registerPHPFunctions();
$xp->importStylesheet($xsldoc);
//Variablen(Parameter) setzen
$xp->setParameter('', array('testvar1'=>'Test-Variable','testvar2'=>'noch eine Test-Variable'));
$doc = $xp->transformToDoc($xmldoc);
echo $doc->saveHTML();
?>
Der Wermutstropfen an setParameter():
bei der Verwendung der PHP-Funktionen kann man flexibel arbeiten, also 1 Template für beliebig viele Funktionen benutzen, den Funktionsnamen bezieht man z.B. einfach aus dem Inhalt des dafür vorgesehenen Knotens(im Beispiel <php/>). Auch die Übergabe von Parametern an die PHP-Funktionen ist problemlos möglich.
Bei den Variablen geht das leider nicht so flexibel....ein Zugriff auf Variablen, deren Namen man im Vorraus nicht kennt, ist in XSL nicht möglich(hab zumindest keine Möglichkeit gefunden, und ich hab seeeeehr lange gesucht).
Das schränkt natürlich die Benutzbarkeit ein, weil man für jede Variable ein Template erstellen muss(sofern man sie so benutzt, wie ich in dem Beispiel)
Aber für bestimmte Anwendungen lassen sich diese Variablen gut nutzen.
Angenommen man hat eine mehrsprachige Seite, PHP setzt im XSL eine Variable für die benötigte Sprache.
Dann wäre es bspw. möglich, entsprechend der Variable eine Sprachdatei per document() zu laden oder aber wenn man eine einzige Datei für alle Sprachen hat einen bestimmten Knoten anhand der Variable auszuwählen.
Solltest du jetzt aber doch sehr viel mit diesen Parametern arbeiten wollen, gibt es auch da eine Möglichkeit.
Anstatt mit setParameter() zu Arbeiten, "infiziere" die Sache per XML mit den Variablen
Wie das bspw. geht:
Über ein Nodeset, welches diese Variablen enthält.
Dieses Nodeset holst du im XSL aus einer PHP-Funktion ab, und speicherst es im XSL als Variable.
Jetzt hast du flexiblen Zugriff, denn du kannst aus dieser einzigen gespeicherten Variable beliebige Kindknoten per XPATH abrufen, welche dann die Variablen(Parameter) enthalten.
Zum Testen:
PHP:
<?php
//Stylesheet
$xsl='
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl"
exclude-result-prefixes="php">
<xsl:variable name="parameters" select="php:function(\'parameters\')"/>
<!-- Basis-Template -->
<xsl:template match="/">
<body><xsl:apply-templates/></body>
</xsl:template>
<!-- Template für PHP-Funktionen -->
<xsl:template match="php">
<xsl:for-each select="php:function(string(.))">
<xsl:apply-templates />
</xsl:for-each>
</xsl:template>
<!-- Template für Variablen, diesmal ist die Sache viel flexibler,
die Variablen werden aus einem Nodeset abgerufen -->
<xsl:template match="variable">
<xsl:variable name="parameter"><xsl:value-of select="."/></xsl:variable>
<p><xsl:value-of select="$parameters/variables/*[name()=$parameter]"/></p>
</xsl:template>
<!-- Template für HTML-Elemente, die kennt XML ja sonst nicht -->
<xsl:template match="code|html|title|style|label|script|a|abbr|acronym|address|b|big|body|head|blockquote|cite|dfn|div|em|h1|h2|h3|h4|h5|h6|i|kbd|p|pre|q|quote|samp|textarea|span|small|strike|strong|sub|sup|tt|button|fieldset|form|label|legend|option|optgroup|select|caption|col|colgroup|table|tbody|td|tfoot|th|thead|tr|dl|dd|dt|ol|ul|li|var">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
';
//XML
$xml='
<root>
<php>menu</php>
<variable>testvar1</variable>
<variable>testvar2</variable>
<variable>testvar3</variable>
<variable>testvar4</variable>
<variable>testvar5</variable>
</root>
';
//Beispielfunktion, wird über <php>menu</php> aufgerufen
function menu()
{
$menu=new DOMDocument();
$menu->loadXML('<ol><li>Dies</li><li>könnte</li><li>ein</li><li>Menü</li><li>sein</li></ol>');
return $menu;
}
//Funktion welche das Nodeset mit den Variablen liefert
function parameters()
{
$vars=new DOMDocument();
$vars->loadXML('<variables>
<testvar1>Test-Variable#1</testvar1>
<testvar2>Test-Variable#2</testvar2>
<testvar3>Test-Variable#3</testvar3>
<testvar4>Test-Variable#4</testvar4>
<testvar5>Test-Variable#5</testvar5>
</variables>');
return $vars;
}
$xsldoc=new DOMDocument();
$xsldoc->loadXML($xsl);
$xmldoc=new DOMDocument();
$xmldoc->loadXML($xml);
$xp = new XsltProcessor();
//PHP-Funktionen verfügbar machen
$xp->registerPHPFunctions();
$xp->importStylesheet($xsldoc);
$doc = $xp->transformToDoc($xmldoc);
echo $doc->saveHTML();
?>