|
XML / XSL with PHP and how XSLT |
|
|
|
|
Thursday, 10 July 2008 |
Introduction: This article assumes that you already know XML / XSL and you have some knowledge of PHP. It is not necessary to master both languages, some knowledge enough. In this article, only the PHP code will be explained. If you do not understand the code used XSL, please refer to the excellent tutorials that already exist. You can discover how to use XML / XSL with PHP to dynamically generate pages or to generate dynamic content offline. The utility to generate dynamic content offline will be explained in conclusion. You will discover how XSLT PHP during a simple project detailing the completion of a course. You find at the end of a page annex containing among other references to using PHP functions used. Presentation: XML coupled with XSL stylesheets is very convenient to organize and publish data. Take, for example, the publication of a course. We can divide it into sections, then into parts. It would be very interesting to dissociate the course content of its display. In this way, it could change the appearance of the course, etc. ... without having to redo all pages. That is unfortunately the case in the use of HTML pages or traditional PHP. It may also address the numbering of pages. Insert a party or a chapter requires the gap in the numbering of the chapters. Besides, we would be able to provide this course presented in various displays. A display using a page per game for the Internet publication, a page containing all the courses to allow his impression ... Of course it would be extremely painful having to copy and paste to create each of these parties. In addition, the modification of a part of the course entails an obligation to pass these changes on all types of publication. All these problems will be avoided through the use of XML / XSL, as well as PHP. The creation of an XML file linked to a XSL stylesheet makes it possible to place the course in an XML file, the structure, and then manage its display through the XSL stylesheet. This method has several drawbacks. Firstly all browsers do not support XML. Individuals with such browsers could therefore not see the documents and made. In addition, consultation with one part of the course entails an obligation for the client to download the entire XML file containing the course. If the course is large, this is impractical because it would involve time downloads important to consult a few pages ... The solution that we use here is a mode added to PHP. This mode, XSLT allows server-side processing of all XML / XSL in an HTML page. This page created dynamically, could then be returned to the customer in the form of an HTML page. The browser client will therefore not need to recognize the XML. In addition, manipulation of XML being on the server side, the customer at no time will the need to download the XML file. On the client side, then everything will be as if the site had been achieved 'classic'.  We therefore have a sheet XML and XSL more sheets to show this sheet. Each sheet XSL to present the contents of XML file in a certain way. For example, the sheet 1 will print a simple index, the sheet 2 can view a particular item, while the sheet 3 will display the index and the overall progress following, in order to propose a printable version. According to the PHP page accessed, we will call for XSLT, passing the file name to use XSL, XML file is always the same. XSLT then converts the data in HTML and everything is returned to the client who has no knowledge of the mechanism to display the page. Creation of the project: We will first study the example set out above. We want to make a course, divided into chapters and then parties. All numbering chapters and parts will be carried out automatically, so as to avoid painful changes in the case of adding a party or a chapter. An index will be generated automatically. The course will be viewable part by part or in a print version. The print version will resume on one page index and the entire course. The section by section will have a header and footer to return to or move to the previous or next page. The header and footer will be generated automatically, so again to avoid changes in the case of an addition. The XML and XSL files, which are presented below will never be accessible to the customer. The customer will call a PHP page that will return the HTML page formatting. Here is an example XML file: <? xml version = "1.0" encoding = "ISO-8859-1"?> <root> <chapitre titre="Titre chapter 1"> <partie titre="Titre part of the 1"> Text of Part 1 of Chapter 1 </ section> <partie titre="Titre of part 2"> Text of Part 2 of Chapter 1 </ section> </ chapter> <chapitre titre="Titre chapter 2"> <partie titre="Titre part of the 1"> Text of Part 1 of Chapter 2 </ section> <partie titre="Titre of part 2"> Text of Part 2 of Chapter 2 </ section> </ chapter> </ root> We can clearly see here the structure of the course. It is divided into chapters, each chapter may contain as many parts as necessary. Note the complete absence of numbering. Once the structure of XML file specified, we must create 3 XSL files that will show the way. We will define 4 XSL files, which generate index.xsl index, article.xsl will display a portion of the course and full.xsl come up with the tutorial printable. An annex balises.xsl file will be created and included at the beginning of each file XSL. This file will contain data on the tags of text formatting. In this way changing the layout of the course require simply editing a file. File index.xsl: <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version="1.0"> <xsl:output encoding="ISO-8859-1"/> <xsl:template match="root"> <h2 align="center"> Index </ h2> <p> Print [<a href="full.php" target="_blank"> HTML </ a>] </ p> <xsl:apply-templates/> </ xsl: template> <xsl:template match="chapitre"> <br/> <xsl:variable name="cchap"> <xsl:value-of select="position() div 2" /> </ xsl: variable> <p style="text-indent=0cm;margin-top:2px;margin-bottom:2px;"> Chapter <b> <xsl:value-of select="$cchap"/>: <xsl:value-of select="./@titre"/> </ b> </ p> <xsl:for-each select="partie"> <xsl:variable name="n"> <xsl:value-of select="count(//chapitre[not(position()> = $ cchap)] / / part) + position ()"/> </ xsl: variable> <p style="text-indent=1cm;margin-top:2px;margin-bottom:2px;"> <a href="article.php?id={$n}"> <xsl:value-of select="position()"/>. <xsl:value-of select="@titre"/> </ a> </ p> </ xsl: for-each> </ xsl: template> </ xsl: stylesheet> This file is relatively short. It generates the index numbers and automatically chapters and the parties. The display of the parties will be managed by the page article.php and XSL file article.xsl. File article.xsl: <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version="1.0"> <xsl:output encoding="ISO-8859-1"/> <xsl:include href="balises.xsl"/> <xsl:param name="id"/> <xsl:variable name="tchap"> <xsl:value-of select="count(//chapitre)" /> </ xsl: variable> <xsl:variable name="mpart"> <xsl:value-of select="count(//chapitre//partie)"/> </ xsl: variable> <xsl:template match="root"> <xsl:apply-templates/> </ xsl: template> <xsl:template match="chapitre"> <xsl:variable name="cchap"> <xsl:value-of select="position() div 2" /> </ xsl: variable> <xsl:for-each select="partie"> <xsl:variable name="cpos"> <xsl:value-of select="count(//chapitre[not(position()> = $ cchap)] / / part) + position ()"/> </ xsl: variable> <xsl:variable name="pcpos"> <xsl:value-of select="$cpos-1"/> </ xsl: variable> <xsl:variable name="ncpos"> <xsl:value-of select="$cpos + 1"/> </ xsl: variable> <xsl:if test="$cpos = $id"> Our <div align="center"> </ div> <table border="0" width="100%"> <tr> <xsl:if test="$cpos = 1"> <td width="100" align="left"> Previous </ td> </ xsl: if> <xsl:if test="$cpos> 1 "> <td width="100" align="left"> <a href="article.php?id={$pcpos}"> Previous </ a> </ td> </ xsl: if> <td align="center"> <a href="index.php"> Index </ a> </ td> <xsl:if test="$cpos = $mpart"> <td width="100" align="right"> Next </ td> </ xsl: if> <xsl:if test="not ($cpos = $mpart)"> <td width="100" align="right"> <a href="article.php?id={$ncpos}"> Next </ a> </ td> </ xsl: if> </ tr> </ table> <hr size="1" width="100%"/> <h1 align="center"> Chapter <xsl:value-of select="$cchap"/> </ h1> <h2 align="center"> <xsl:value-of select="../@titre"/> </ h2> <h2> <xsl:value-of select="position()"/>. <xsl:value-of select="./@titre"/> </ H2> <xsl:apply-templates/> <hr size="1" width="100%"/> <table border="0" width="100%"> <tr> <xsl:if test="$cpos = 1"> <td width="100" align="left"> Previous </ td> </ xsl: if> <xsl:if test="$cpos> 1 "> <td width="100" align="left"> Previous <a href="article.php?id={$pcpos}"> </ a> </ td> </ xsl: if> <td align="center"> <a href="index.php"> Index </ a> </ td> <xsl:if test="$cpos = $mpart"> <td width="100" align="right"> Next </ td> </ xsl: if> <xsl:if test="not ($cpos = $mpart)"> <td width="100" align="right"> <a href="article.php?id={$ncpos}"> Next </ a> </ td> </ xsl: if> </ tr> </ table> </ xsl: if> </ xsl: for-each> </ xsl: template> </ xsl: stylesheet>
This file is responsible for posting an article. It creates the headers and footers and chapter numbers and party. Note the tag 'xsl: param' at the beginning of the file. This tag will retrieve the item number to display. This parameter is passed by the PHP file conducting the appeal. Here they were, therefore page article.php. File full.xsl <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version="1.0"> <xsl:output encoding="ISO-8859-1"/> <xsl:include href="balises.xsl"/> <xsl:param name="id"/> <xsl:variable name="tchap"> <xsl:value-of select="count(//chapitre)" /> </ xsl: variable> <xsl:variable name="mpart"> <xsl:value-of select="count(//chapitre//partie)"/> </ xsl: variable> <xsl:template match="root"> Our <h2 align="center"> </ h2> <xsl:for-each select="chapitre"> <p style="text-indent=0cm;margin-top:2px;margin-bottom:2px;"> <b> Chapter <xsl:value-of select="position()"/>: <xsl:value-of select="./@titre"/> </ b> </ p> <xsl:variable name="cchap"> <xsl:value-of select="position()"/> </ xsl: variable> <xsl:for-each select="partie"> <xsl:variable name="n"> <xsl:value-of select="count(//chapitre[not(position()> = $ cchap)] / / part) + position ()"/> </ xsl: variable> <p style="text-indent=1cm;margin-top:2px;margin-bottom:2px;"> <a href="#{$n}"> <xsl:value-of select="position()"/>. <xsl:value-of select="@titre"/> </ a> </ p> </ xsl: for-each> </ xsl: for-each> <br/> <br/> <br/> <xsl:apply-templates/> </ xsl: template> <xsl:template match="chapitre"> <xsl:variable name="cchap"> <xsl:value-of select="position() div 2" /> </ xsl: variable> <h1 align="center"> Chapter <xsl:value-of select="$cchap"/> </ h1> <h2 align="center"> <xsl:value-of select="./@titre"/> </ h2> <xsl:for-each select="partie"> <xsl:variable name="cpos"> <xsl:value-of select="count(//chapitre[not(position()> = $ cchap)] / / part) + position ()"/> </ xsl: variable> <xsl:variable name="pcpos"> <xsl:value-of select="$cpos-1"/> </ xsl: variable> <xsl:variable name="ncpos"> <xsl:value-of select="$cpos + 1"/> </ xsl: variable> <xsl:variable name="n"> <xsl:value-of select="count(//chapitre[not(position()> = $ cchap)] / / part) + position ()"/> </ xsl: variable> <h2> <a name="{$n}"/> <xsl:value-of select="position()"/>. <xsl:value-of select="./@titre"/> </ H2> <xsl:apply-templates/> </ xsl: for-each> </ xsl: template> </ xsl: stylesheet> This file shows the index followed by the complete course. The headers and footers have been deleted and the chapter headings is displayed only when moving from one chapter to another. File balises.xsl <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version="1.0"> <xsl:template match="b"> <b> <xsl:apply-templates/> </ b> </ xsl: template> <xsl:template match="br"> <br/> <xsl:apply-templates/> </ xsl: template> </ xsl: stylesheet> This file contains all the tags formatting. It is here in an overly concise version. However, it is very easy to add as many tags as necessary. This file can be edited to change the overall presentation of the course. The various parties will be consulted from PHP pages. We will now deal with the creation of PHP pages, index.php, article.php and full.php. These pages using PHP leaves XSL of the same name. Most implementations mode using XSLT SABLOTRON as XML parser. To find the parser used by PHP, use the command phpinfo (). Here is the index.php file: <? PHP $ xh = xslt_create (); $ file = fopen ( "cours.xml", "r"); $ xml = fread ($ file, 16384); fclose ($ file); $ file = fopen ( "index.xsl", "r"); $ xsl = fread ($ file, 16384); fclose ($ file); $ arguments = array ( '/ _xml' => $ xml, '/ _xsl' => $ xsl ); $ result = xslt_process ($ xh, 'arg: / _xml', 'arg: / _xsl', NULL, $ arguments); xslt_free ($ xh); print "$ result"; ?> We will analyse the contents of this file: $ xh = xslt_create (); We create here an instance of the XML parser. $ file = fopen ( "cours.xml", "r"); $ xml = fread ($ file, 16384); fclose ($ file); This part reads the content of the XML file (up to 16384 bytes). If your XML is larger, consider increasing the value. $ file = fopen ( "index.xsl", "r"); $ xsl = fread ($ file, 16384); fclose ($ file); This part is similar to the previous one. She read the XSL file. $ arguments = array ( '/ _xml' => $ xml, '/ _xsl' => $ xsl ); $ result = xslt_process ($ xh, 'arg: / _xml', 'arg: / _xsl', NULL, $ arguments); Here, the XML file and the file is passed to XSL parser instantiated earlier. The resulting HTML file will be recovered in the variable $ result. xslt_free ($ xh); It destroys the XML parser. print "$ result"; We just have to display the HTML file created. The file full.php does nothing special. It is similar to file index.php. The only change is the name of the style sheet used. File full.php: <? PHP $ xh = xslt_create (); $ file = fopen ( "cours.xml", "r"); $ xml = fread ($ file, 16384); fclose ($ file); $ file = fopen ( "full.xsl", "r"); $ xsl = fread ($ file, 16384); fclose ($ file); $ arguments = array ( '/ _xml' => $ xml, '/ _xsl' => $ xsl ); $ result = xslt_process ($ xh, 'arg: / _xml', 'arg: / _xsl', NULL, $ arguments); xslt_free ($ xh); print "$ result"; ?> The file article.php presents some differences: Here is an analysis of changes to this file: if (isset ($ _GET [ 'id'])) $ xslt_params [id] = $ _GET [ 'id']; Else $ xslt_params [id] = "1"; $ result = xslt_process ($ xh, 'arg: / _xml', 'arg: / _xsl', NULL, $ arguments, $ xslt_params); This differs from previous files and therefore deserves some explanation. First, we verify that the 'id' has been spent in the URL. This parameter represents the number of the party to display. A table containing a key 'id' is then created. If a parameter was passed in the URL, it is used. Otherwise, the default 1 is used. The parameters are then passed to XSL file. The XSL file may recover these parameters with the tag 'xsl: param'. In this way, the file XSL display a single article. Here is an example of complete and functional. We just have to modify the XML file and add the chapter titles and party as well as the text. It should also be added to the roster balises.php tags needed for the layout. This method of publication presents an astonishing flexibility. The modification or addition of parties on this course is extremely simple. Moreover, the disadvantage of the XML file size is set because the file is handled on the server side. Adding PHP code in files XSL For the moment we have not added to the PHP page generated by the leaf XSL. This has indeed some difficulties. It can be very useful to add PHP to the page generated. The PHP code will then be processed by PHP before displaying the page. In this way, it is possible to include such a header file additional PHP to top. It is impossible to display tags <? And php?> Directly into the XSL file. Indeed, the format of these tags does not conform to the standard. It will therefore be necessary to create tags <php> and </ php>. These tags have no particular meaning. They will subsequently be replaced by tags php real. Finally, the page will be increased to PHP. Once the page handled by PHP, the result will be sent to the customer. This treatment is more complex. It is not necessarily required. However, it may be very convenient to insert a dynamic content on pages (eg the time or date). As we have said, the tags <php> and </ php> have no precise meaning. The page referred to PHP therefore contain these beacons. We will use the function str_replace () 2 times to replace those tags with tags <? And php?>. Once this replacement performed the function eval () is called to deal with the PHP content on the page. The function eval () will then automatically result page. Here is the index.php page amended to manage tags <php> and </ php>: <? PHP $ xh = xslt_create (); $ file = fopen ( "cours.xml", "r"); $ xml = fread ($ file, 16384); fclose ($ file); $ file = fopen ( "index.xsl", "r"); $ xsl = fread ($ file, 16384); fclose ($ file); $ arguments = array ( '/ _xml' => $ xml, '/ _xsl' => $ xsl ); $ result = xslt_process ($ xh, 'arg: / _xml', 'arg: / _xsl', NULL, $ arguments); xslt_free ($ xh); $ result = str_replace ( "<php> ","<? php", $ result); $ result = str_replace ( "</ php >","?>",$ result); $ result = eval ("?". chr (62). result.chr $ (60 )."?"); ?> The tags <php> and </ php> are replaced, in the resulting HTML page, by tags PHP valid. Once this replacement is completed, all that remains is to spend the PHP page obtained for evaluation. The PHP code is processed by the function eval () and then displayed. Note that the function eval () poster itself the result. The print () used in the previous version of this page is no longer necessary. The function eval () can evaluate a simple PHP code (without tags) or a full page, including therefore tags <? And php?>. The analysis is made in the continuity of the current page. That is to say that the beginning of the file which calls eval () is taken into account in the assessment. It is therefore necessary to close the tags of the file by'"?". chr (62), then reopen by the char (60 )."?". Generation dynamic offline It can be very useful to generate dynamic content offline. For this, you must of course install PHP and XSLT on your machine. The simplest solution is therefore to generate pages as indicated above, then display the source and copy and paste in a separate file. This method is quite heavy. Here is an alternative to generate the content of the page and write directly to a file. Here is an example generating offline file index.php: <? PHP $ xh = xslt_create (); $ file = fopen ( "cours.xml", "r"); $ xml = fread ($ file, 16384); fclose ($ file); $ file = fopen ( "index.xsl", "r"); $ xsl = fread ($ file, 16384); fclose ($ file); $ arguments = array ( '/ _xml' => $ xml, '/ _xsl' => $ xsl ); $ result = xslt_process ($ xh, 'arg: / _xml', 'arg: / _xsl', NULL, $ arguments); xslt_free ($ xh); $ result = str_replace ( "<php> ","<? php", $ result); $ result = str_replace ( "</ php >","?>",$ result); ob_start (); $ result = eval ("?". chr (62). result.chr $ (60 )."?"); $ result = ob_get_contents (); ob_clean (); $ file = fopen ( "index.php", "w"); fwrite ($ file, "$ result"); fclose ($ file); print "Done"; ?> As the function eval () PHP directly displays the contents evaluated, we must find a way to recover it. The functions of buffering output supplied with the heart of PHP allow that. The function ob_start () indicates a PHP redirect the standard output (normally page PHP) to a buffer. It then recovers in a variable content of the buffer with the function ob_get_content (). The function ob_clean () indicates a PHP destroy buffers and used to redirect the standard output to the page PHP. It remains then is to write the buffer recovered in a file. If you want to generate several pages offline, you can use this type of code in a loop. Conclusion The use of XML / XSL with mode XSLT is very powerful. It can dynamically generate pages and create patterns. Amend the appearance of a page created in this way requires only changing XSL files. In addition, the copy and paste heavy are avoided although several presentations are proposed. We must still understand that this generation has a dynamic cost. The burden processor server that generates these pages will be more important. If these pages are often covered or if you do not have the mode XSLT at your host, you can install PHP and XSLT at home and generate pages offline. You then have to send more PHP static pages created on your server. In this way, you get the benefits of this technology while avoiding too big server loads.
|
|
|