XSLT

XML, Perl, Python, and other languages can be discussed here, even if it isn't PHP (We might forgive you).

Moderator: General Moderators

Post Reply
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

XSLT

Post by alex.barylski »

I'm missing something about how PHP uses XSLT to convert documents from one type to another, I'm hoping someone can explain.

I understand which each component does (i think).

You essemtially have two documents:

1) An well formed XML document
2) XSL

The latter is a specialized XML document which knows how to take the input (1) and transform it into a other output (ie: HTML, XHTML, etc). Fromwhat I have read in the past it sounds like XSL can be used to convert XML into a PDF file, so I assume that the XSL somehow can tap into the power of PHP, otherwise what PDF API would it use?

If in my XML document I have customized tags which require complicated processing, say for example the tag needs to pull it's data from MYSQL and expand into HTML for final rendering, how is this done? Is this possible inside the context of XSL?

I was thinking you could use a DOM object to traverse a XML document. Whenever I found specially marked tags, I could use them to locate the required objects and connect to MySQL, etc and basically convert the XML tags into the outputted XHTML tags for display.

Sounds like XSL may do this for me, without a DOM. :)

Can someone tell me if I'm on the right track or am I misunderstanding something? Hows does XSL as a rules based XML file take a XML document and convert it into and XHTML or other form? Is XSL simpler than using the DOM directly as I suggested above?

As I understand it, XSL files simply use trivial conditionals, constructs to say:

Code: Select all

<author name="Joe">
  <age value="29" />
</author>
transforms into:

Code: Select all

<div>
  <strong>Joe</strong><br />
  Age: 29
</div>
In this way XSL provides a simpler transformation than manipulating the DOM directly but is more restricting in that if some tag maps to a field in a DB how does XSL allow you to fetch it and use that data in the context of XSL?

Cheers :)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

XSLT will transform text into text but it's strengths lie in XML. So you can transform PHP in JavaScript for instance but I wouldn't attempt it. If your input source is XML things are going to be pretty straight-forward in XSLT and if your output source is as well that's a definite bonus. For certain transformation tasks there literally is nothing better than XSLT.

If you want to generate anything other than text you probably want to create an XML representation of it. For instance if you want to generate graphics than use XSLT to make SVG and then create an graphic from that.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

Ok, I hear ya. But I'm still confused. :P

My XML tags in my source indicate database objects which need to be executed. Can XSL invoke PHP code or am I best just using the DOM directly?
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Oh yeah I never answered that. As far as I know it cannot. So yeah you've got to use PHP. XPath is part of the PHP DOM implementation you know, basically a query() call and it has a context parameter that you can use to scope it to a specific part like the result of a previous XPath for instance.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

http://de2.php.net/manual/en/function.x ... ctions.php might be of interest.

e.g.

Code: Select all

<?php
function myDateFunction($x) {
	return date('Y-m-d');
}

$xml = <<< EOX
<root>
 <date>1182205912</date>
</root>
EOX;


$xsl = <<< EOX
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:php="http://php.net/xsl">
<xsl:output method="html" />
<xsl:template match="/">
	<html><title>...</title><body>
		<xsl:apply-templates />
  </body></html>
</xsl:template>
<xsl:template match="root">
	<div>
		<xsl:value-of select="php:function('myDateFunction',string(date))"/>
	</div>
</xsl:template>

</xsl:stylesheet>
EOX;

$dom = DOMDocument::loadXML($xsl);
$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStyleSheet($dom);

$dom = DOMDocument::loadXML($xml);
echo $proc->transformToXML($dom);
?>
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

That's cool. That's really cool. Both Hockey and I neglected to read the manual :oops:
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Although you can do that, I recommend against it. It seriously restricts the portability of your XSLT stylesheet (one of the main selling points of XSLT is that it's standards based: start using PHP functions willy-nilly and you lose that) and also can cause a mixture of presentation and business logic (one of the things XSLT is really good at preventing).

Based on your use-case, you probably want to implement multiple transformations. From my understanding, your initial XML file does not contain enough information to create the final output. That's fine: using the document() function, XSLT can actually reference nodes in another document.

The first step is to identify what data you need to pull from the database. Using XSLT, it should be possible to convert the original source XML file into a DOM that specifically states what MySQL data is needed and by what ID it should be referenced by. Instantiate that DOM with the necessary database data (or create another DOM, your choice), and save it somewhere temporary.

Now, perform the final conversion: you will be converting the source XML final to the final (presumably HTML) output, and the XSLT stylesheet will reference the other DB XML file you previously prepared to get any extra necessary information.

Another point that is really a topic in and of itself, is embedding HTML. There are two major points:

1. First, you need to be able to get it into the XML document. This can be achieved using document fragments, but be wary: the HTML must be well-formed otherwise big problems will happen. HTML Purifier is a good way of fixing things up, Tidy may work as well. Here's what I use:

Code: Select all

function appendHTMLDiv($document, $node, $html) {
        $purifier = HTMLPurifier::getInstance();
        $html = $purifier->purify($html);
        $dom_html = $document->createDocumentFragment();
        $dom_html->appendXML($html);
        
        $dom_div = $document->createElement('div');
        $dom_div->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
        $dom_div->appendChild($dom_html);
        
        $node->appendChild($dom_div);
    }
2. You'll also see in the above code that I set the xmlns to the XHTML URL. This is important, not so much for the well-functioning of your document, than for semantic correctness and validation. Just do it, and make sure you scrub any stray xmlns declarations off your document after converting to HTML.
alex.barylski
DevNet Evangelist
Posts: 6267
Joined: Tue Dec 21, 2004 5:00 pm
Location: Winnipeg

Post by alex.barylski »

Thanks all. Some interesting perspectives here. :)
Stefan Heitmann
Forum Newbie
Posts: 4
Joined: Tue Jun 19, 2007 8:38 am

Post by Stefan Heitmann »

The main advantage of XSLT prayed by many XML-Protagonits is that you can clearly separate your logic and your presentation layer.
A designer can easily make simple if-structures, for-each loops, and so on. If you develop in a team your designer will never have anything to
do with your PHP-Code directly.

I learn XSLT on my own at the moment, and i am absolutely surprised, this language is what many template-designers and cms-coder have been
searching for a long time.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Ambush Commander wrote:(one of the main selling points of XSLT is that it's standards based: start using PHP functions willy-nilly and you lose that)
I disagree on this one, at least in its generality.
Your approach is good. But imho neither does it preserve more abstraction/portability than extending the xsl processor nor is abstraction/portability always the limiting factor. Instead of adding php (or other) functions to the processor you have added php code (and another library) to the surrounding script. If the environment changes this code might have to change as well. It might also be that you have to (re-)implement behaviour in your pre-processor code that is already implemented in the xsl processor like traversing, ordering, selecting, ... nodes.
I don't think there's an "absolut good" and an "absolut bad" in weighing the pros and cons.

p.s.
http://www.w3.org/TR/xslt#extension wrote:14 Extensions

XSLT allows two kinds of extension, extension elements and extension functions.

This version of XSLT does not provide a mechanism for defining implementations of extensions. Therefore, an XSLT stylesheet that must be portable between XSLT implementations cannot rely on particular extensions being available. XSLT provides mechanisms that allow an XSLT stylesheet to determine whether the XSLT processor by which it is being processed has implementations of particular extensions available, and to specify what should happen if those extensions are not available. If an XSLT stylesheet is careful to make use of these mechanisms, it is possible for it to take advantage of extensions and still work with any XSLT implementation.
Post Reply