Variablenübergabe von PHP nach XSL

Hier mal nen Beispiel(der Einfachheit halber alles in einem einzigen Skript)
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 :eek:

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();

?>
 
Ohh Sven Mintel & Felix Jacobi danke sehr gut .
Die 1. Variante ist die mit dem String welche ich bereits gekannt.
Habe auf 2. wollte ich verzichten weil ich mit mehreren Scripten die XML auslese.

Ich habe auch schon sehr lange nach einer für mich schöneren Lösung gesucht.

Ich hatte an die Art gedacht wie mann das auch mit der dynamisch erstellten CSS-Datei macht.
CSS:
cssdatei.css.php5
und dann halt den passenden header
PHP:
header('Content-type: text/css');

XSL:
xsldatei.xsl.php5
ginge das auch habs jetzt noch nicht getestet
also wenn es denn dan einen header dieser art gibt :confused:
PHP:
header('Content-type: text/xsl');

Aber das scheint es nicht zu geben laut meiner Intensivrecherge im Netz.
Oder Irre ich mich da.
wollte es dann halt so includieren
PHP:
include('xsldatei.xsl.php5?hm=Home');

Scheine wieder mal mein Wissen unterschätzt zu haben.
Vielleicht geh ich nächste woche mal in die HTW und
hole mir Fachliteratur dazu.

Aber danke für eure intensiven Hilfestellungen. :)
 
Ok zu gehen scheint es jetzt habe eine mischform aus beiden generiert:
Also xml als Datei und die xsl als String leider noch Fehler durchwachsen.
Aber Funktionell ok.

Ging erst nicht weil ich das Hauptmenü-XSL auf php4
und die Untermenü-XSL auf php5 basis eingelesen hatte.

Testweise kann man jetzt also in der Adressleiste folgendes eingeben:
/opmenue.php5?hmu=Hauptmenüpunkt
natürlich einen mit Pfeil also mit Untermenüpunkten.

Hier !


PHP:
$xsl='
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" encoding="UTF-8" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" doctype-system="http://www.w3.org/TR/html4/loose.dtd"/>
<xsl:template match="/">
     <xsl:apply-templates/>
</xsl:template>
<xsl:variable name="varname">'.$hm.'</xsl:variable>
<!--<xsl:variable name="varname">$name</xsl:variable> -->
<xsl:template match="hm">
<xsl:if test="bname/text() = $varname"> 
            <a>
                <xsl:attribute name="href">#</xsl:attribute>              
                <span>
                <xsl:attribute name="id">hmu<xsl:number/></xsl:attribute>
                <xsl:attribute name="style">
                color:#fff;
                padding-left:5px; 
                padding-right:5px; 
                padding-top:3px;
                padding-bottom:2px;
                font-weight:bold;
                font:normal 18px/25px DeliciousBold,sans-serif;
                background-image: url(../dl-flyout/paperstruct.png);
                -moz-border-radius-topright:1ex;
                -moz-border-radius-topleft:1ex;
                -webkit-border-top-right-radius:1ex;
                -webkit-border-top-left-radius:1ex;
                </xsl:attribute>
                <xsl:value-of select="bname"/>
                </span>
            </a><br />
            <xsl:if test="count(um)!=0">
                <xsl:if test="um[position()!=1]">
                    <div>
                    <xsl:attribute name="id">hmu<xsl:number/></xsl:attribute>
                    <xsl:attribute name="style">
                    padding:5px;
                    padding-top:10px;
                    line-height:21px;
                    </xsl:attribute>        
                         <xsl:apply-templates select="um"/>
                    </div>
                </xsl:if>
            </xsl:if>
</xsl:if>     
</xsl:template>
<xsl:template match="um">
    <span>
        <xsl:attribute name="class">um<xsl:number level="multiple" value="count(../preceding-sibling::hm)+1" /></xsl:attribute>
        <!--<xsl:attribute name="style">padding-left:3px; padding-right:3px; margin-right:3px; margin-left:3px; </xsl:attribute>-->
        <xsl:attribute name="style">padding:3px; </xsl:attribute>
            <a>
                <xsl:attribute name="href">http://stephanie-meschke.de.tl/<xsl:value-of select="bname"/>.htm</xsl:attribute>
                <xsl:attribute name="title"><xsl:value-of select="bname"/>.html</xsl:attribute>
                <xsl:value-of select="bname"/>
            </a>
    </span>     
</xsl:template>
</xsl:stylesheet>
';

//XML

/*$xml='
<root>
  <php>menu</php>
  <testvar1/>
  <testvar2/>
</root>
';*/
$xml = 'xml2/opmenue.xml';



//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);

$xml = new DOMDocument;
$xml->load('xml2/opmenue.xml');
//$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($xml);
echo $doc->saveHTML();

?>
 
Ohh
Ich hatte an die Art gedacht wie mann das auch mit der dynamisch erstellten CSS-Datei macht.
CSS:
cssdatei.css.php5
und dann halt den passenden header
PHP:
header('Content-type: text/css');

XSL:
xsldatei.xsl.php5
ginge das auch habs jetzt noch nicht getestet
also wenn es denn dan einen header dieser art gibt :confused:
PHP:
header('Content-type: text/xsl');

Aber das scheint es nicht zu geben laut meiner Intensivrecherge im Netz.
Oder Irre ich mich da.
wollte es dann halt so includieren
PHP:
include('xsldatei.xsl.php5?hm=Home');

Der MIME-Type für XSLT ist Application/xslt+xml

Zu dem "includen":
Das XSLT-Dokument kannst du genau wie das XML-Dokument per load() aus einer Datei laden. Es ist von seiner Natur her XML, weswegen sich auch die Methoden für XML-Dokumente darauf anwenden lassen.
 
Sprich wenn ich das Dokument also wie oben beschrieben erstellen will muss ich.
folgenden Header wie in xml verwenden klingt logisch und ich glaube damit hast du Recht.
PHP:
header ("content-type: text/xml");

Danke für den Denkanstoß.

werde dem mal einen Test unterziehen

MfG Grafixboy
 
Zurück