Jump to content

PHP in XSL document


Recommended Posts

I've done a bit of xml and xsl but how would I use php with xml and xsl? Would it be written in the xsl, xml or a separate php document. Eventually I'll be programming with xml so I thought I should start getting into it. Or if you have a tutorial on how to use php with xsl shoot me a link.

Link to post
Share on other sites

It's done in a separate PHP file. For sample codes and instructions on what is required to perform XSLT processing with PHP, look at the 6th answer of the XSLT FAQ.

Link to post
Share on other sites

it's a bit more complicated than I thought...EDIT: Does this mean I can use this to display an xml/xsl document?

<?php/* load the xml file and stylesheet as domdocuments */$xsl = new DomDocument();$xsl->load("articles.xsl");$inputdom = new DomDocument();$inputdom->load("articles.xml");/* create the processor and import the stylesheet */$proc = new XsltProcessor();$xsl = $proc->importStylesheet($xsl);$proc->setParameter(null, "titles", "Titles");/* transform and output the xml document */$newdom = $proc->transformToDoc($inputdom);print $newdom->saveXML();?>

Link to post
Share on other sites

I had a question... since my site is bilingual and I have a field in my xml doc that is named desc_e and desc_f. Is there a way I could detect which language is the current page? I will be including the xml doc in my php page.

Link to post
Share on other sites

Would anyone that's done this before show me the code. I just want to see how it's done and those examples are kinda complex. I want something real simple.

Link to post
Share on other sites

Sorry. I have problems with my ISP so I wasn't able to answer in a while. Even now, I'm not using my home PC and all.What you want is fairly simple once you see it done once (huh) and as with many things in XSLT, there are numerous ways to approach it, all with their advantages and drawbacks. I'll only present to you the approach I believe is best- mixing two of the better methods.In the PHP file, you need to somehow carry the language information from one page to the other and/or negotiate it every time. Ideally, negotiate it the first time, and use a query string (GET) variable from then on. Cookies are also acceptable, but only if you ensure the query string variable will have a priority over it.Once you estabilish the language, you should load the appropriate XML file with the load() function which you can see used in the code sample. If you don't want to have one XML file per language and keep the stuff in one XML file instead, you could only pass a parameter to the stylesheet with the setParameter() function (also used in the example, for no real reason). I do sugguest separated XML files though, as this is more efficient. There's no reason to parse data which won't be used in the end.For getting the common stuff such as navigation for example, you should keep the common data in a separated XML file (or file sets as with the per-page data).What you do from then on depends on how you've made the rest. If in each XML file you have xml:lang attribute at the top, you could use this in XSLT to locate the respective navigation:

<xsl:apply-templates select="document(concat('/common-data/menu_',/*/@xml:lang,'.xml')"/>

If not, you could pass a parameter to the stylesheet, which will be used as part of the document() function's argument, like so:

<xsl:apply-templates select="document(concat('/common-data/menu_',$lang,'.xml')"/>

which will result in the '/common-data/menu_en.xml' if the lang parameter is "en" for english or '/common-data/menu_fr.xml' if the lang parameter is "fr" for french,etc.In PHP, this would result in something like this (can vary a lot, depending on how exactly you want it):

if (ereg('en|fr',$_GET['lang'])) { //If the GET variable for the language specifies english or french$lang = $_GET['lang']; //Pass the corresponding value}else {$lang = 'en'; //Default value for the lang variable}$inputdom->load("article_" . $lang . ".xml"); //Load the XML file with the negotiated language$proc->setParameter(null, "lang", $lang); //Optional if you have xml:lang in the XML. Pass a parameter to the XSLT stylesheet with the negotiated language as a value

Link to post
Share on other sites

I'll only be using this xml for my website gallery. So there will be very little information in the xml file. Just a couple sites. I would prefer having everything in 1 file since it would make updating easier for me. boen_robot: Could you paste the php code to load an xml and xsl doc? I tried last night but it didn't quite work out.

Link to post
Share on other sites
boen_robot: Could you paste the php code to load an xml and xsl doc? I tried last night but it didn't quite work out.
Have you followed the installation instructions as written? Also, do you have PHP4 or PHP5? If it's 4, this won't work and you'll need this instead:
<?php$xsltFile = "test.xsl";$xmlFile = "test.xml";//Load the XSLT processor$engine = xslt_create();//You need to pass each parameter-value pair in the following array as associative array$args = array();//Execute the transformation$output = xslt_process($engine, $xmlFile, $xsltFile, NULL, NULL, $args);//Show the transformation in the browserprint $output;xslt_free($engine);?>

Link to post
Share on other sites

What do you mean by //You need to pass each parameter-value pair in the following array as associative array?

Link to post
Share on other sites

IF you need to pass parameters to the XSLT, you need to pass them in the form of an associative array, like this:

$args = array('lang'=>'en','another-parameter-name'=>'another-parameter-value');

Passing parameters to the stylesheet means you're changing that value and the stylesheet can then act accordingly, as with the language, where the appropriate file would be queried with document().

Link to post
Share on other sites

So for testing purposes I don't need to put anything right? It should simply display whatever I put in my xml and xsl files? When I view my php page, the page stops where the xml should appear. The files are in the same folder, file names are correct. I'm not sure what could be wrong. I'm not sure of the php version installed.

Link to post
Share on other sites
So for testing purposes I don't need to put anything right? It should simply display whatever I put in my xml and xsl files? When I view my php page, the page stops where the xml should appear. The files are in the same folder, file names are correct. I'm not sure what could be wrong. I'm not sure of the php version installed.
Right. You don't need anything.check the installed version with phpinfo(). Also look for a table above which there should be "xsl". Simply CTRL+F for "libxslt" (for PHP5) or "Salbotron" (for PHP4). If you don't find either, then XSLT processing support is simply disabled at your host and they'll have to enable it (or allow you to enable it yourself with dl()).
Link to post
Share on other sites
So I guess I got PHP5.
And you're saying
<?php/* load the xml file and stylesheet as domdocuments */$xsl = new DomDocument();$xsl->load("articles.xsl");$inputdom = new DomDocument();$inputdom->load("articles.xml");/* create the processor and import the stylesheet */$proc = new XsltProcessor();$xsl = $proc->importStylesheet($xsl);/* transform and output the xml document */$newdom = $proc->transformToDoc($inputdom);print $newdom->saveXML();?>

(replace the file names of course)doesn't work? How about this one:

<?php$xml = new DomDocument;$xml->load('test.xml');$xsl = new DomDocument;$xsl->load('test.xsl');$xslt = new Xsltprocessor;$xslt->importStylesheet($xsl);$transformation = $xslt->transformToXml($xml);echo $transformation;?>

(replace the file names again)Try this at the constructor line too:

$xslt = new XSLTProcessor();

I'm just not sure if class constructors are case sencetive, and the last one is how it's shown in PHP's manual.The libxslt version seems old. I'm guessing you have PHP 5.1.*. I've never really used XSLT successfully on it. In PHP 5.2.* however I've never had problems.

Link to post
Share on other sites

Damn... I have:

XSL enabled libxslt Version 1.1.17 libxslt compiled against libxml Version 2.6.26 EXSLT enabled libexslt Version 0.8.13
And
PHP Version 5.2.1RC5-dev
(the exact version is at the top of the phpinfo page)and it seems to work. I wonder why on earth is not working on this version. If you're running on your computer, consider upgrading to 5.2, but if we're talking "the host"... I'm thinking of executing the XSLT processor as a binary file, but that's a lot harder to set up, and if you're not sure that the system() function is enabled, it might not work. Not to mention it varies depending on the OS of the server.Ah, wait. I forgot. Are you sure the XML and XSLT file are well formed and won't produce an error otherwise? Try to execute the transformation on the client side with a processing instruction in the XML (just for the test) like so (just below the XML prolog, before the root element):
<?xml-stylesheet type="text/xsl" href="test.xsl"?>

(replace test.xsl of course)If that results in an error in the browser, then the problem is not with PHP to begin with. It's the XML and/or XSLT file(s) that need fixing.

Link to post
Share on other sites

So the server doesn't have 5.2 and it seems like they won't upgrade for a while... So what are my options at this point for xml? Should I just forget it for now?

Link to post
Share on other sites

Read the last paragraph again. Check the XML and XSLT files. The only possible issues now are wrong paths or non well-formed XML/XSLT document(s).Actually, try this:

<?php//The file paths.$xsltFile = 'test.xsl';$xmlFile = 'test.xml';//Verify the file paths. I haven't tested this, so try without it if you're sure the paths ARE correct.if (!file_exists($xmlFile)) {die('No XML file at "' . $xmlFile . '". Verify the file exists and check for spelling mistakes');}if (!file_exists($xsltFile)) {die('No XSLT file at "' . $xsltFile . '". Verify the file exists and check for spelling mistakes');}//Prepare the XML file$xml = new DomDocument;if (!$xml->load($xmlFile)) {die('XML file at "' . $xmlFile . '" is not well-formed');}//Prepare the XSLT file$xsl = new DomDocument;if (!$xsl->load($xsltFile)) {die('XSLT file at "' . $xsltFile . '" is not well-formed');}//Load the XSLT processor$xslt = new Xsltprocessor;$xslt->importStylesheet($xsl);//Execute the transformationif (!$transformation = $xslt->transformToXml($xml)) {die('Error during transformation of "' . $xmlFile . '" with  "' . $xsltFile . '" as stylesheet. Possibly an endless loop or illegal XSLT construct.');}//Show the transformation in the browser. Just before this phase is the right time to check the output if needed.echo $transformation;?>

It has error handlers everywhere, so you should be able to understand where the truth lies (I remember Skemcin using this pun...heh).

Link to post
Share on other sites

Whoa?!?! You didn't got ANY of the error messages in the file?!?! Now this is just getting ridiculous!Desparate measures... start the PHP with

<?phpdie("If you don't see even this message, PHP is not executed to begin with");

And really, if you can't see even this error message, something is totally wrong with the way you're using PHP. Perhaps I've made a typo somewhere. Comment the rest of the code, and leave only those two lines (and the closing "?>" of course) standing. If even THAT doesn't return the message above, the issue is not even in the scope of this PHP file and the problem is elswhere. Perhaps if you're including this file into another, the problem could be in the other one.

Link to post
Share on other sites

I see the error message. I use php on all of the pages of my site so php should be fine also...XML:

<?xml version="1.0" encoding="iso-8859-1" ?><?xml-stylesheet type="text/xsl" href="gallery.xsl"?><gallery>	<website>		<title>Deep Coding</title>		<desc_e>This is a short description of DC.</desc_e>		<desc_f>Ceci est une courte description de DC</desc_f>		<smallthumb>/images/websites/newdeepcoding_small.jpg</smallthumb>		<largethumb>/images/websites/newdeepcoding_large.jpg</largethumb>	</website></gallery>

XSL:

<?xml version="1.0" encoding="iso-8859-1" ?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/">	<html>	<body>	<ul>	<xsl:for-each select="/gallery/website">	<li><a href="<xsl:value-of select="largethumb"/>" rel="lightbox" title="<xsl:value-of select="title"/> - <xsl:value-of select="desc_e"/>" ><img src="<xsl:value-of select="smallthumb"/>" alt="<xsl:value-of select="title"/>" /></a></li>	</xsl:for-each>	</ul>	</body>	</html></xsl:template></xsl:stylesheet>

I've tested these 2 files by themselves before and the xsl doc outputted exactly what I wanted so they should be fine.

Link to post
Share on other sites

Well, I saved those two with names of "gallery.xml" and "gallery.xsl" respectively, tested them in the browser (they really worked), saved the following PHP in the same folder as them:

<?php//Prepare the variables. This is especially usefull if you only want to rename their name in the URL while keeping their functionality$xsltFile = 'gallery.xsl';$xmlFile = 'gallery.xml';//Verify the file paths. I haven't tested this, so try without it if you're sure the paths ARE correct.if (!file_exists($xmlFile)) {die('No XML file at "' . $xmlFile . '". Verify the file exists and check for spelling mistakes');}if (!file_exists($xsltFile)) {die('No XSLT file at "' . $xsltFile . '". Verify the file exists and check for spelling mistakes');}//Prepare the XML file$xml = new DomDocument;if (!$xml->load($xmlFile)) {die('XML file "' . $xmlFile . '" is not well-formed or the path to it is wrong');}//Prepare the XSLT file$xsl = new DomDocument;if (!$xsl->load($xsltFile)) {die('XSLT file "' . $xsltFile . '" is not well-formed or the path to it is wrong');}//Load the XSLT processor$xslt = new Xsltprocessor;$xslt->importStylesheet($xsl);//Execute the transformationif (!$transformation = $xslt->transformToXml($xml)) {die('Error during transformation of "' . $xmlFile . '" with  "' . $xsltFile . '" as stylesheet. Possibly an endless loop or illegal XSLT construct.');}//Show the transformation in the browser. Just before this phase is the right time to check the output if needed.echo $transformation;?>

And I ran the PHP file. It all worked with no errors and the following output (code):

<html><body>	<ul>		<li><a href="/images/websites/newdeepcoding_large.jpg" rel="lightbox" title="Deep Coding - This is a short description of DC." ><img src="/images/websites/newdeepcoding_small.jpg" alt="Deep Coding" /></a></li>		</ul>	</body></html>

Rendered as:

<ul> <li><a href="/images/websites/newdeepcoding_large.jpg" rel="lightbox" title="Deep Coding - This is a short description of DC." ><img src="/images/websites/newdeepcoding_small.jpg" alt="Deep Coding" /></a></li> </ul>

But here's something interesting. I disabled the XSL extension and when I ran the PHP file I did got a blank screen. I added

ini_set('display_errors','On');

which of course yeld the following output:

Fatal error: Class 'Xsltprocessor' not found in X:\XXXX\XXXX.php on line 27

(file path "X"-ed intentionally)Try giving the above ini_set() a try. Also add:

ini_set('error_reporting',1);

To ensure all errors will be displayed. Who knows... perhaps the presence of the XSL extension in phpinfo() doesn't really ensure it's availability.There's no way around it. The above two lines placed on top MUST ensure some REAL error information. If that doesn't work, I don't know what will.Last, but not least. You are checking this PHP file "as is" right? You're not including it in something or anything?

Link to post
Share on other sites

I added ini_set('display_errors','On'); and I got 2 errors:

Warning: domdocument() expects at least 1 parameter, 0 given in /test.php on line 21Fatal error: Call to undefined function: load() in /test.php on line 22
Line 21: $xml = new DomDocument;Line 22: if (!$xml->load($xmlFile)) {

The php code was copied from what you gave me earlier and I didn't alter anything except for the filenames.

Link to post
Share on other sites

FINALLY! Mystery solved. It seems PHP 5.2 has some additional DOM features, which PHP 5.1 doesn't, which however are not descibed in the manual. Here's a possible workaround:

$xml = new DomDocument('1.0');if (!$xml->loadXML(file_get_contents($xmlFile))) {

And of course the equivalent at the XSLT file:

$xsl = new DomDocument('1.0');if (!$xsl->loadXML(file_get_contents($xsltFile))) {

I believe that should work now. Keep the error messages turned on just in case.

Link to post
Share on other sites
Warning: domdocument(): Start tag expected, '<' not found in /test.php on line 21Fatal error: Call to undefined function: loadxml() in /test.php on line 22
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...