Transformation XML + XSLT with help Sablotron
Alternative introduction in use XSL Transformations in PHP with help Sablotron.
The given material should be perceived as alternative introduction in use XSLT with Sablotron in PHP.
Terms XSL and XSLT are close to each other, and newbies of them can count synonyms. Details in what distinctions, are described in specification XSL Transformations W3C.
Everyone who was interested in opportunities XSLT, the standard example from a manual read, or the examples resulted{brought} in clauses{articles}, devoted XSLT, on different sites. A working example from same series:
<? php
$xmlData = ' <? xml version = " 1.0" encoding = "Windows-1251"?>
<document>
<game>
<title> Railroad Tycoon II Platinum </title>
<genre> economic strategy </genre>
<designer> PopTop software </designer>
<publisher> G.O.D. games </publisher>
<year> 2001 </year>
</game>
<game>
<title> Grand Prix 4 </title>
<genre> an autosimulator </genre>
<designer> Geoff Crammond and Simergy </designer>
<publisher> Infogrames Entertainment </publisher>
<year> 2002 </year>
</game>
</document> ';
$xslData = ' <? xml version = " 1.0" encoding = "windows-1251"?>
<! DOCTYPE xsl:stylesheet>
<xsl:stylesheet version = " 1.0" xmlns:xsl = " http: // www.w3.org/1999/XSL/Transform ">
<xsl:output method = "html" indent = "yes" encoding = "Windows-1251"/>
<xsl:template match = "/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match = "document">
<html> <head>
<title> Games </title>
</head>
<body>
<h1> Games </h1>
<table cellpadding = "2" cellspacing = "2" border = "1">
<tr>
<td> the Name </td>
<td> a genre </td>
<td> year </td>
<td> the developer </td>
<td> the publisher </td>
</tr>
<xsl:apply-templates select = "game"/>
</table>
</body> </html>
</xsl:template>
<xsl:template match = "game">
<tr>
<td> <b> <xsl:value-of select = "title"/> </b> </td>
<td> <xsl:value-of select = "genre"/> </td>
<td> <xsl:value-of select = "year"/> </td>
<td> <xsl:value-of select = "designer"/> </td>
<td> <xsl:value-of select = "publisher"/> </td>
</tr>
</xsl:template>
</xsl:stylesheet> ';
$xh = xslt_create ();
$arguments = array (
' / _ xml ' => $xmlData,
' / _ xsl ' => $xslData
);
$result = @xslt_process ($xh, ' arg: / _ xml ',' arg: / _ xsl ', NULL, $arguments);
if ($result)
print ($result);
else {
print (" There was an error that occurred in the XSL transformation ...\n ");
print (" \tError number: ". xslt_errno ($xh). "\n");
print (" \tError string: ". xslt_error ($xh). "\n");
exit;
}
?>
Of similar examples in the Network it is full. All of them well show, that XSL-transformation in php works, but after their perusal remains not clear, what for XSL is necessary, more likely even on the contrary - why XSL is not necessary.
"Really", - the reader will think, - " if the data lay in base, what for gorodit` a kitchen garden, forming at first XML, and then still to transform through XSL? With the same success it will make a class of a HTML-pattern. "
After that the disappointed programmer at all loses interest to XSL and hangs up on technology a shortcut " unnecessary zaum` ".
To you, dear readers, has carried to find such remarkable site, as " php in details ". Here you will read that XSL can not only transform XML in HTML, but also how it is possible to facilitate with help XSL job with php-scripts.
The beginning of job
The above mentioned example though it is too simple, well illustrates, how XSL-transformation in php is done{made}.
That this code worked, it is necessary to establish XSLT-processor Sablotron. On vindovoj to the machine it is done{made} so:
1. To put iconv(-1.3).dll, expat.dll and sablot.dll in C:\windows\System (all files are in the standard distribution kit php)
2. To open C:\windows\php.ini and in him to find parameter extension_dir. If an option value - "." Or something like ". / " to correct on, say, "f:\usr\local\php\extension" (or the address of a directory in which at you expansions php lay / will to lay). Now it will be a directory of expansions php.
3. To put in a directory of expansions a file php_xslt.dll (it for php versions 4.2.x), or php_sablot.dll (for the version 4.0.x)
4. In php.ini raskommentirujte a line extension=php_xslt.dll (4.2.x) or extension=php_sablot.dll (4.0.x)
The theory
Use XSLT allows to separate from php-scripts job on formatting and data presentation. It not only reduction of volume of a code, but also carrying out of a plenty of logic designs (if, else, switch), and consequently, simplification of job on a spelling and debugging of programs. I dare to assert{approve}, that the one who did not try to work with XSLT, does not imagine, as far as php-coding will be facilitated.
However, it is not necessary to be under a delusion: if you had some designs if... else in a php-script, they, most likely, will appear in the same quantity{amount} in a XSL-file.
Now to examples.
Conclusion of lists
All complications occuring from necessity to deduce{remove} the list in a legible kind, are transferred to shoulders XSL. An example *2. The list of clauses{articles} on a site with illumination of clause{article} which read now, alternation of color in lines and numbering of the list.
XML:
<current-date> 2002-05-30 </current-date>
<list-article date = "2002-10-03"> Catching of mistakes in PHP </list-article>
<list-article date = "2002-10-02"> the Alive project and dead magazine </list-article>
<list-article date = "2002-06-03"> Job with MySQL. A part 7. Trees </list-article>
<list-article date = "2002-05-30"> Manual sorting in the web - interface </list-article>
<list-article date = "2002-05-29"> How to get on to the designer with the programmer </list-article>
<list-article date = "2002-05-27"> Relax this is PHP </list-article>
XSLT:
...
<table>
<xsl:apply-templates select = "list-article"/>
</table>
...
<xsl:template match = "list-article">
<tr>
<xsl:if test = " position () mod 2 = 1 ">
<xsl:attribute name = "bgcolor"> *cccccc </xsl:attribute>
</xsl:if>
<td>
<xsl:value-of select = " position () ">
<a href = " / {date} .htm "> <xsl:value-of select = "."/> </a>
<xsl:if test = " date =../current-date "> *nbsp; *lt; </xsl:if>
</td>
</tr>
</xsl:template>
Any marking
Translating on XML a site with texts (as this), it is natural to want to make own marking of clauses{articles}. For example, in the container important to allocate very important places and to have an opportunity to allocate them not necessarily fat font, but, maybe, color, CSS-style. Or to write citations as <quote> the text of the citation <quote> and to have an opportunity to change style of their registration together with design of a site.
Slowly moving ahead from the most simple first example, many will come across this problem and cannot find the decision. In fact if to allocate the paragraph in teg <para> and to do{make} for him a pattern, at first sight, there are three ways of a conclusion of contents:
1. teg xsl:value-of deduces the text, but deletes all tegi in the paragraph
2. teg xsl:copy-of deduces a copy of all contents (without an opportunity to apply patterns to children - internal tegam) and the container <para...> </para> (that is not so beautiful in HTML).
3. At last, xsl:apply-templates will apply patterns to children, but will pass{miss} the text
The problem seems desperate, but the decision is. I use "magic" patterns which deduce also the text and tegi in him with all attributes and without changes. An example *3:
XML:
<text>
<para> the Given example uses <strong> magic patterns </strong>
For analysis of an any marking. It allows to avoid such complaints:
</para>
<quote> People, pamazhite we not local! I can not deduce{remove} tegi in the text
With the help value-of!
</quote>
<hr/>
<strong> Remember these patterns once and for all! </strong>
<para> Then you can process <u> any </u> <a href = " http: // www.txt.ru "> the text </a>
Almost any.
</para>
</text>
XSLT:
<xsl:template match = "text"> <xsl:apply-templates/> </xsl:template>
<xsl:template match = "strong">
<font color = " * cc0000 "> <b> <xsl:apply-templates/> </b> </font>
</xsl:template>
<! - three magic patterns->
<! - 1. general{common}->
<xsl:template match = "*">
<xsl:copy>
<xsl:apply-templates select = " * "/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<! - 2. for the text->
<xsl:template match = " text () ">
<xsl:value-of select = "." disable-output-escaping = "yes"/>
</xsl:template>
<! - 3. for tegov and attributov->
<xsl:template match = " * | node () ">
<xsl:copy>
<xsl:apply-templates select = " * | node () "/>
</xsl:copy>
</xsl:template>
First of all the XSLT-processor by a call of the instruction apply-templates searches for a pattern for each element. For an element strong the pattern is, and according to it such elements will be processed. For a hyperlink of a pattern no, therefore she will be deduced{removed}, as is. It is possible to add in XSL a pattern and for the link which would deduce{remove} near to each text link a picture for its{her} opening in a new window:
<xsl:template match = " a [@href] ">
<xsl:copy-of select = "."/> <a href = " {href} "
target = " _ blank "> <img src = "/window.gif " width = "15" height = "15"
alt = " to open in a new window "/> </a>
</xsl:template>
* In a pattern the parameter match = " a [@href] " is used - this pattern will be applied only to those tegam links in which there is a field href and will pass{miss} anchors (<a name = "xxx"> </a>).
Nevalidnyj a code and
Seeming necessity to write validnyj a XML-code as frightens off many neophytes XSLT. Well, since tomorrow's day we shall write clauses{articles} only validno, the blessing of a house can be checked up, whether no in the text of a XML-mistake - mismatched tag or invalid token, - with it somehow we shall consult. But in fact, in an amicable way, it is necessary to translate also all archive in validnyj a code! And I so too thought, when the opportunity to alter a site on XML has appeared.
The decision of a problem rather simple: you do not want - do not write validno. Write, how has got used, - without inverted commas in attributes tegov, use idle time <br> and other. It is enough to conclude the text in the container <! [CDATA [...]]> (the example is lower).
As to *nbsp;, here affairs such: the element nbsp in XML no. Is lt, gt, quot, but not nbsp (quite logically is in fact non-braking space which concerns to formatting and it is thought up for HTML). Therefore it{he} needs to be declared in the document, or to use only inside <! [CDATA [...]]>.
Example *4:
XML:
<text>
<bad-markup> <! [CDATA [In it <a href=http: // detail.phpclub.net> the text </a> it is applied
nevalidnaja a marking. <br> And no trouble.]]> </bad-markup>
<quote> People, pamazhite, we not local! </quote>
<hr/>
<strong> Remember also these patterns too! </strong>
</text>
XSLT:
<xsl:template match = "text"> <! [CDATA [>>> and in XSL it is possible to do{make} the same! <<<]]>
<xsl:apply-templates/> </xsl:template>
<xsl:template match = "bad-markup">
<xsl:value-of select = "." disable-output-escaping = "yes"/>
</xsl:template>
<xsl:template match = "*">
<xsl:copy>
<xsl:apply-templates select = " * "/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match = " text () ">
<xsl:value-of select = "." disable-output-escaping = "yes"/>
</xsl:template>
<xsl:template match = " * | node () ">
<xsl:copy>
<xsl:apply-templates select = " * | node () "/>
</xsl:copy>
</xsl:template>
Very conveniently! The big changes in archive to bring it is not necessary. It is possible to start to write validno, and to continue anyhow. And it is possible to combine these two approaches. To not write to archival files teg CDATA, I have made simple transformation by means of regular expressions (important as to remember, that one teg CDATA should not comprise another).
$doc = preg_replace (" ~ <(p|h [1-3] |pre)> (. *?) </\\ 1> ~ ", " <\\ 1> \\ 2 </\\ 1> ", $doc);
Cycles
We admit{allow}, we need to make the form for editing clause{article}, including its{her} date. For convenience of using it is necessary to make three drop-down lists (further - "krutilki") - date from 1 up to 31, month, year. The first decision which comes to mind - to make a HTML-code krutilok in php, to insert in XML in container CDATA, and then to deduce{remove} in XSL with parameter disable-output-escaping = "yes".
Actually, XSLT it can also. It is enough to insert number, number{room} of month and year into data XML. Krutilki it is possible to draw at once in XSLT.
Let's write the pattern which has been not intended for any element of the document. He will be caused by xsl:call-template command and to receive two parameters: value of the counter and a maximum. At first he will deduce{remove} the data necessary to us with value of the counter, then to cause itself(himself) with parameters a maximum and the counter increased on 1. An example *5:
XML:
<month-name> February </month-name>
<month-name> March </month-name>
<month-name> April </month-name>
<month-name> May </month-name>
<month-name> June </month-name>
<month-name> July </month-name>
<month-name> August </month-name>
<month-name> September </month-name>
<month-name> October </month-name>
<month-name> November </month-name>
<month-name> December </month-name>
<article>
...
<day> 7 </day>
<month> 10 </month>
<year> 2002 </year>
</article>
XSLT:
<xsl:template match = "article">
...
<select name = "d">
<xsl:call-template name = "day">
<xsl:with-param name = "count"> 1 </xsl:with-param>
</xsl:call-template>
</select>
<select name = "m">
<xsl:call-template name = "month">
<xsl:with-param name = "count"> 1 </xsl:with-param>
</xsl:call-template>
</select>
...
</xsl:template>
<xsl:template name = "day">
<xsl:param name = "count"/>
<option value = " {$ count} ">
<xsl:if test = " $ count = // artcile/day ">
<xsl:attribute name = "selected"> yes </xsl:attribute>
<xsl:if>
<xsl:value-of select = " $ count "/>
</option>
<xsl:if test = " $ count *lt; 31 ">
<xsl:call-template name = "day">
<xsl:with-param name = "count">
<xsl:value-of select = " $ count + 1 "/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name = "month">
<xsl:param name = "count"/>
<option value = " {$ count} ">
<xsl:if test = " $ count = // artcile/month ">
<xsl:attribute name = "selected"> yes </xsl:attribute>
<xsl:if>
<xsl:value-of select = " // month-name [position () = $count] "/>
</option>
<xsl:if test = " $ count *lt; 12 ">
<xsl:call-template name = "month">
<xsl:with-param name = "count">
<xsl:value-of select = " $ count + 1 "/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
I leave to you as the domestic task a pattern for a conclusion krutilki with one year.
The resume
As you can see, that is written in php-scripts, even at use of a class of a pattern, it is possible to lower much successfully in XSLT. But whether it is necessary to be engaged in it?
The answer depends on operating conditions in your project. The second moment - adaptability to manufacture of job.
We admit{allow}, I shall want to make on this site of the menu of fast navigation - a drop-down list with all clauses{articles}, - that the user could choose clause{article} from the list and at once proceed{pass} to her. Still I shall want to leave the list of last materials (now he is on the right above).
If to do{make} it by means of a class of a pattern such as FastTemplate, it is necessary two special blocks and an additional code in php which would declare in a pattern the block for the list of all clauses{articles} and separately the block for the list last 10. Similar actions are necessary in that case and at job without a class of a pattern. At job with XML Date => Clause{Article} " of which in the XSL-document are under construction and listboks fast transition, and the list of last clauses{articles} is enough only one data set ".
And if suddenly it is required to make never mind for what other registration of a site (for example, the version for WAP, or simply redesign) in which will be solved to refuse the list last 10 materials. In case of first two technologies - a class of a pattern and the mixed code - it will be necessary to clean{remove} a part php a code, in case XSLT of change will touch only a XSL-file. Such process is more technological, as it is impossible to make new mistakes in php-scripts (and now present a return case - the list last 10 clauses{articles} was not, but it have decided to add!).
So, the choice remains for you, and I as could have resulted strengths of technology and reasons for the benefit of use XML in projects.

© Web Development Company Conkurent, LLC 2007-2009. All rights reserved. |