TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
Advertisement
Associates
Associates
techtuts Darkmindz
CSS Tutorials Tutorialsphere.com - Free Online Tutorials
Boston PHP SurfnLearn
Reply
 
LinkBack (1) Thread Tools Search this Thread Display Modes
Old 11-30-2007, 08:43 PM   1 links from elsewhere to this Post. Click to view. #1 (permalink)
The Frequenter
Advanced Programmer Top Contributor Good Samaritan 
 
Join Date: Oct 2007
Location: Manchester, UK
Posts: 469
Thanks: 26
sketchMedia is on a distinguished road
Default Generating XML/XSL from a Mysql DB with PHP's DOM functions (part Two) XSLT

Hello again,

This is the second part to my PHP XML/XSLT tutorial.

In this tutorial i will be going through a very simple XSL using the XML data produced from part one.

I just going to briefly go over the point to all this, because, many people (including myself) learn things a lot quicker if the technology has a point, or to put it in better words the technology isn't described as a long list of mumbo jumbo and there is a clear cut point to answer the question 'why would i need that?'.

Ok, we already know that XML is a standard for creating markup languages which describe the structure of data, and it comes in very handy, for example Ajax uses xml to transfer data between server and client, through xmlhttprequest. Most of us already know this, but what a few may not know (including myself until a few months ago) is that you can apply a style sheet to XML and produce HTML from it, the style sheets are called XSL or eXtensible Stylesheet Language.

There are 3 main ways of doing this:
the first way is to add a XSL style sheet to an XML file then let the browser do the 'transformation' in other words render the xml data according to the XSL style, much like css. Although this method works, it wont however work on non XSLT aware browsers.

The second way of doing it is by using javascript to do the transformation, but, once again, browser incompatibilities limit the success of this method.

So then how do we do it?, well the third way is to use PHP(or any other server side script like php or asp will do the trick) to do the transformation, then generate the HTML so that any browser can see it properly, this is the method that i will be showing you in this tutorial.

Ok, first off we need an XSL file, i've got one pre made, ill paste it in then go over it.

xml Code:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method='html'/>

<xsl:param name="title">Car List Generated by PHP/XML/XSTL</xsl:param>

<xsl:template match="/">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <title><xsl:value-of select="$title"/></title>
        <style type="text/css">
            <![CDATA[
            <!--
              caption { font-weight: bold; }
              th {
              background: #A2A2A2;
              color: #fff;
              font-family: arial;
              font-weight: normal;
              font-size: 12px;
              }
              tr {
                font-family: arial;
                color: #000;
                font-size: 12px;
                background: #7D90A1;
              }
            -->

            ]]>
        </style>
    </head>
    <body>
        <div class="center" style="width: 300px; margin: 0 auto">
        <table border="0" style="width: 300px">
            <caption><xsl:value-of select="$title"/></caption>
            <thead>
                <tr>
                    <th>Car Name</th>
                    <th>BHP</th>
                    <th>Year Released</th>
                </tr>
            </thead>
            <tbody>
            <xsl:for-each select="carlist/car">
            <tr>
                <td><xsl:value-of select="name"/></td>
                <td><xsl:value-of select="bhp"/></td>
                <td><xsl:value-of select="year_released"/></td>
            </tr>
            </xsl:for-each>
            </tbody>
        </table>
        </div>
    </body>
    </html>
    </xsl:template>   
    </xsl:stylesheet>
Ok, alot of code to get through here so i better get started :)

Because XSL is still XML we must start it as we would an XML file:
xml Code:
<?xml version='1.0'?>
The next line is an XMLns (XML Name Space) declaration, this is so that we can get access to the XSLT elements, attributes and features through the namespace 'xsl', the url just represents an URL that contains the list of elements, attributes and features that we can now use.

xml Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
Next we need to define what output form our XSL will take:
xml Code:
<xsl:output method='html/>
We will be outputting to HTML so i have selected HTML, but according to W3schools this is the following accepted values:
xml Code:
method="xml|html|text|name"
Its important to note that Netscape 6 only supports xml and html in the output method.

Next we define a parameter, this will contain our final output title:
xml Code:
<xsl:param name="title">Car List Generated by PHP/XML/XSTL</xsl:param>
Dont worry if you dont understand that, it will become clear soon :)

Next we start our template:
xml Code:
<xsl:template match="/">
This is where a bit of xPath knowledge comes in, the match attribute is used to associate a template with an XML element. The value of the match attribute is an XPath expression (i.e. match="/" defines the whole document, because "/" in xPath is used to select the root node) so we are starting a template for the whole document.
Again if that still makes no sense, it will become clear eventually :)

Ok now i can start some html to start buiding up our template:
xml Code:
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <title><xsl:value-of select="$title"/></title>
you can see that i have normal html tags <head>/<meta>/<title> then im back into an xsl tag:
xml Code:
<xsl:value-of select="$title"/>
Remember our parameter?, well that one little tag grabs the data from it.
Parameters allow us to have values that we can access from anywhere within the XSL file, the way we access them is by using the value-of method, normally this is used to get values of XML element by using an xPath statement like 'car/name' but because we prefixed the name with '$' it knows that it is a parameter and not an XML element we want.
So basically that produces the HTML code:
html Code:
<title>Car List Generated by PHP/XML/XSTL</title>
Next we are back into HTML again (tags aren't prefixed with xsl, so the xsl parser will just ignore them and present them to the browser 'as is', a bit like the way php ignores any html outside of the <?php ?> tags.

Here we start a 'style' tag and give it some CSS:
xml Code:
<style type="text/css">
            <![CDATA[
            <!--
              caption { font-weight: bold; }
              th {
              background: #A2A2A2;
              color: #fff;
              font-family: arial;
              font-weight: normal;
              font-size: 12px;
              }
              tr {
                font-family: arial;
                color: #000;
                font-size: 12px;
                background: #7D90A1;
              }
            -->

            ]]>
        </style>
Notice the use of the <![CDATA[ ... ]]> tags, this basically tells the parser to ignore anything between them, this is because the parser will try to interpret the css and produce errors, for example the '<' character may appear in javascript, but if left without <![[CDATA ]]> tags wrapping it, it will be misinterpreted by the parser as being a start of a new element, so you must either replace '<' with its entity reference '&lt;' or use <![CDATA[]]> to wrap around the code, thus making the parser ignore them.
There are other characters that will be wrongly interpreted, they are:

< less than
> greater than
& ampersand
' apostrophe
" quotation mark

In the case of javascript and indeed CSS we cannot replace the characters for there entity references because it will break the script, so we must wrap the code in the CDATA.

Phew that was a long winded explanation of something relatively simple .

Anyway onwards we must plod, we have much to cover.

I'm going to skip most of the HTML because it should be self explanatory.
The next xsl tag we come across is:
xml Code:
<xsl:value-of select="$title"/>
which does exactly the same as it did previously for the title tag
xml Code:
<xsl:for-each select="carlist/car">
            <tr>
                <td><xsl:value-of select="name"/></td>
                <td><xsl:value-of select="bhp"/></td>
                <td><xsl:value-of select="year_released"/></td>
            </tr>
            </xsl:for-each>
   
    </xsl:template>
    </xsl:stylesheet>
Ok heres just a very quick html table row, but notice the for-each statement, that is going to loop through every 'car' node then fill the td's with the relevant data for each row, we know its looping through 'car' s because of the xPath expression in the select attribute 'carlist/car/'.
Then we end the 'for-each', then the template (match="/") and then end the stylesheet.


Ok, so thats our XSL roughly described, ON WITH THE PHP!!!

The first thing we do is to create a new XsltProcessor object, this will allow us to process the xsl and perform our 'transformation':
PHP Code:
$xsltProcessor = new XsltProcessor(); 
Next we have to load the xsl document we just created then import it so that we can process it:
PHP Code:
  // create a DOM document and load the XSL stylesheet
  
$xsl = new DomDocument;
  
$xsl->load('car.xsl');
  
  
// import the XSL styelsheet into the XSLT process
  
$xsltProcessor->importStylesheet($xsl); 
Here we create a new DOMdocument object, load the xsl and then we pass it into the importStylesheet() method of XsltProcessor().

Next we need to load our XML file:
PHP Code:
  // create a DOM document and load the XML
  
$xmlDoc = new DomDocument;
  
$xmlDoc->load('cars.xml'); 
Then we invoke the transformation, I've wrapped it in a try - catch to catch errors:
PHP Code:

try
{
    
$html $xsltProcessor->transformToXML($xmlDoc);
    echo 
$html;
}
catch(
Exception $pEx)
{
    echo 
$pEx->getMessage();

That (hopefully) will display the complete page (I've attached a working example)

Hopefully that has shown the usefulness and power of using these technology's. The main point of this script is to separate presentation layer from the logic layer so that any one of these layers can be modified without affecting the other, and I personally prefer this method from the templating systems out there for php, with this you have more flexibility with the XSL file, I haven't even gone over half of the capabilities of XML

You could also save the HTML file instead of echoing it out like so:
.
PHP Code:
try
{
    
$fh fopen('cars.html','w+');
    
fwrite($fh$xsltProcessor->transformToXML($xmlDoc));
    
fclose($fh);
}
catch(
Exception $pEx)
{
    echo 
$pEx->getMessage();

We can also set parameters (like the title) dynamicaly using php:

PHP Code:
$xsltProcessor->setParameter('''title''new value for title'); 
And there is so much more.
Like for example we want alternating row background colors, the way that i can think of, is to have 2 classes 'r0' and 'r1', and then call this in the xsl:
xml Code:
<tr class="r{position() mod 2}">
the 'position()' call is yet again some more xPath magic! Basicaly it returns the index position of the node that is currently being processed, so the first one will be 1, second 2 and so on, then we call 'mod' on that value, which is 'modulus' (division remainder) and then divide by 2, so basically if you have never seen mod before in programming, it finds to see if there is a remainder from the division and returns 1 and 0 depending on if the number divided without leaving a remainder, so basically its to see if the number is odd or even, then we put the result next to the text for the class name using the {}, so to cut a long story short its gonna produce: r1, r0, r1, r0 etc..
There is an example of this in the attachment.

Anyway i hope i have explained everything and got my facts right, and i hope you guys find it useful, XML/XSLT and xPath are all powerful tools and i think we will see more and more of this kind of stuff in the future.
Attached Files
File Type: rar PHP_DOM_XSLT.rar (2.6 KB, 199 views)
__________________

Last edited by sketchMedia : 12-08-2007 at 01:05 PM. Reason: added geshi highlighting to xml
sketchMedia is offline  
Reply With Quote
The Following 4 Users Say Thank You to sketchMedia For This Useful Post:
Gurnk (12-08-2007), ibndawood (12-12-2007), Karl (12-05-2007), Wildhoney (12-01-2007)
Old 12-01-2007, 12:23 AM   #2 (permalink)
The Frequenter
Advanced Programmer Top Contributor Good Samaritan 
 
Join Date: Oct 2007
Location: Manchester, UK
Posts: 469
Thanks: 26
sketchMedia is on a distinguished road
Default

I just wanna add another little xsl tag that is useful, <xsl:sort />

xml Code:
<xsl:sort
  select = string-expression
  lang = { nmtoken }
  data-type = { "text" | "number" | qname-but-not-ncname }
  order = { "ascending" | "descending" }
  case-order = { "upper-first" | "lower-first" } />
can be used in the example script like this:


xml Code:
<xsl:for-each select="carlist/car">
            <xsl:sort select = "bhp" data-type = "number" order = "descending" />

            <tr class="r{position() mod 2}">
                <td ><xsl:value-of select="name"/></td>
                <td><xsl:value-of select="bhp"/></td>
                <td><xsl:value-of select="year_released"/></td>
            </tr>
            </xsl:for-each>
__________________

Last edited by sketchMedia : 12-08-2007 at 01:01 PM. Reason: added highlighting
sketchMedia is offline  
Reply With Quote
Old 12-05-2007, 04:07 PM   #3 (permalink)
The Reckoner
Advanced Programmer Top Contributor 
 
Karl's Avatar
 
Join Date: Sep 2007
Posts: 436
Thanks: 22
Karl is on a distinguished road
Default

Wow, I remember touching on this stuff about a year or so ago, but then I heard it couldn't be used with IE and just forgot all about it. I'm going to have to do some learning because that stuff looks amazing. Why aren't more people using this technique?
__________________
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Karl is offline  
Reply With Quote
Old 12-05-2007, 05:12 PM   #4 (permalink)
Moderateur
RegEx Guru PHP Guru Top Contributor Advanced Programmer 
 
Salathe's Avatar
 
Join Date: Apr 2007
Posts: 710
Thanks: 2
Salathe is on a distinguished road
Default

Quote:
Originally Posted by Karl View Post
Wow, I remember touching on this stuff about a year or so ago, but then I heard it couldn't be used with IE and just forgot all about it. I'm going to have to do some learning because that stuff looks amazing. Why aren't more people using this technique?
With PHP, all of the transformation is going on server-side with the resulting output being whatever you like, including perfectly normal XHTML.

Transforming documents like this does result in a fair hit on the server (at least, it did a while back when I was experimenting). Couple that with yet another layer of abstraction and it's not ideal of every situation. But it's up to you to decide when it would be good to use these techniques and when it wouldn't.
__________________
Salathe is offline  
Reply With Quote
Old 12-05-2007, 06:46 PM   #5 (permalink)
The Reckoner
Advanced Programmer Top Contributor 
 
Karl's Avatar
 
Join Date: Sep 2007
Posts: 436
Thanks: 22
Karl is on a distinguished road
Default

Quote:
Originally Posted by Salathe View Post
With PHP, all of the transformation is going on server-side with the resulting output being whatever you like, including perfectly normal XHTML.
Yeh, I meant at the time, I thought it was useless as I didn't realise I could use PHP to get the job done

Quote:
Originally Posted by Salathe View Post
Transforming documents like this does result in a fair hit on the server (at least, it did a while back when I was experimenting).
We'll have to get some test data so we can see how this technique performs. Well, I say we... *looks at sketch*
__________________
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Karl is offline  
Reply With Quote
Old 12-08-2007, 12:26 PM   #6 (permalink)
The Frequenter
Advanced Programmer Top Contributor Good Samaritan 
 
Join Date: Oct 2007
Location: Manchester, UK
Posts: 469
Thanks: 26
sketchMedia is on a distinguished road
Default

hey guys,
sorry i havnt posted in a while, work is taking up all my free time atm :(

Yea i thought the same Karl, when i first looked at it i was using the browser to do the transformation, it was a cool idea but I too just brushed it aside as being IE unfriendly, but then i found the PHP XSLT functions, i am certainly gonna use it more in the future, i think its real use is probably gonna be more like a page cache or something because (i havnt tested speeds) but im guessing it takes up more server power than normal php/html to create 'on the fly' so to speak.

I do kinda agree with Salathe about the extra layer of abstraction, but that said, it does make it very easy to maintain in my opinion, you have another layer of functionality and lets be honest it does separate php from html, something that some people consider to be the holy grail.

Quote:
We'll have to get some test data so we can see how this technique performs. Well, I say we... *looks at sketch*
hehe, when i get some spare time i certainly will, its a very powerful technique and i think it deserves a proper test.


Anyway im glad you guys found it useful
__________________
sketchMedia is offline  
Reply With Quote
Old 08-19-2008, 08:45 PM   #7 (permalink)
The Wanderer
 
frosty's Avatar
 
Join Date: Aug 2008
Location: texas
Posts: 13
Thanks: 3
frosty is on a distinguished road
Default

Found this to be quite informative...
One question though what if I, oh lets say, have lots and lots of tags to be delt with…

Like


Code:
<RetRequest>
	<Login>
		<uName></uName>
		<uId></uId>
	</Login>
	<InfoBlock>
		<Bits>
			<bitOne></bitOne>
			<bitTwo></bitTwo>
		</Bits>
		<Bits>
			<bitOne></bitOne>
			<bitTwo></bitTwo>
		</Bits>
		<Bits>
			<bitOne></bitOne>
			<bitTwo></bitTwo>
		</Bits>
		<Bits>
			<bitOne></bitOne>
			<bitTwo></bitTwo>
		</Bits>
		<Bits>
			<bitOne></bitOne>
			<bitTwo></bitTwo>
		</Bits>
	</InfoBlock>
	<LastBlock>
		<MoreBits>
			<mBits>
				<mBitOne></mBitOne>
				<mBitTwo></mBitTwo>
			</mBits>
			<mBits>
				<mBitOne></mBitOne>
				<mBitTwo></mBitTwo>
			</mBits>
			<mBits>
				<mBitOne></mBitOne>
				<mBitTwo></mBitTwo>
			</mBits>
		</MoreBits>
	</LastBlock>
</RetRequest>

But on the order of 50 or so parent tags 100's of child tags, pulling information form 20 tables in 2 db's...

(Its the current problem that I am having...getting all the stored variables, and generating the xml string. Can do it just fine storing in session but can not get it to work out of the bd...)
frosty is offline  
Reply With Quote
Old 08-20-2008, 01:02 AM   #8 (permalink)
The Wanderer
 
tripy's Avatar
 
Join Date: Apr 2008
Posts: 7
Thanks: 0
tripy is on a distinguished road
Default

Quote:
With PHP, all of the transformation is going on server-side with the resulting output being whatever you like, including perfectly normal XHTML.
Not necessarily...
Almost every modern browsers support native xml+xsl transformation.

I've wrote, use, and released a set of 2 classes, that allow an easy output of xml, to select what I call a "rendering set" (imagine a version for ipod/pda and another "rich media") and to determine if the client should receive a server-transformed html file, or if xml+xsl can be sent directly.

You can see it in action on Quixml::Quick Xml and Xsl for PHP.
Try to look at the pages source from firefox or safari....

And an example is in the class documentation for the ClXml class => Docs For Class clXml (you loose the navigation by going directly to this page.)
tripy is offline  
Reply With Quote
Reply


LinkBacks (?)
LinkBack to this Thread: http://www.talkphp.com/xml-xslt-xpath-xquery/1561-generating-xml-mysql-db-phps-dom-functions-part-two.html
Posted By For Type Date
Javascript AJAX Generating XML/XSL from a MySQL DB with PHPs DOM Functions (Part Two) Tutorial This thread Refback 12-30-2007 06:12 AM

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 12:47 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0