When using the DOM api to add xsl commands to your stylesheet dynamically, be sure to use createElementNS() rather than createElement() otherwise the XSLTProcessor will not recognise these DOM nodes.
Eg:
$xsl->createElementNS('http://www.w3.org/1999/XSL/Transform', 'xsl:element');
XSL 関数
導入
XSL エクステンションは、XSL の標準規格を実装したもので、 libxslt ライブラリを用いて » XSLT 変換 を行います。
要件
このテクステンションは » http://xmlsoft.org/XSLT/ にある libxslt を使用します。 libxslt バージョン 1.1.0 以降が必要です。
インストール手順
PHP 5には、デフォルトでXSLエクステンションが含まれており、 configureに引数--with-xsl[=DIR] を追加することにより有効にすることができます。 DIR は libxslt をインストールしたディレクトリです。
定義済みクラス
XSLTProcessor
コンストラクタ
-
XSLTProcessor::__construct - 新規 XSLTProcessor オブジェクトを生成する
メソッド
-
XSLTProcessor::getParameter - パラメータの値を取得する
-
XSLTProcessor::hasExsltSupport - PHP が EXSLT をサポートしているかどうかを判定する
-
XSLTProcessor::importStylesheet - スタイルシートを取り込む
-
XSLTProcessor::registerPHPFunctions - XSLT 関数として PHP 関数を使用できるようにする
-
XSLTProcessor::removeParameter - パラメータを取り除く
-
XSLTProcessor::setParameter - パラメータの値を設定する
-
XSLTProcessor::transformToDoc - DOMDocument に変換する
-
XSLTProcessor::transformToURI - URI に変換する
-
XSLTProcessor::transformToXML - XML に変換する
例
このリファレンスにある多くの例は、XML ファイルと XSL ファイルの両方を必要とします。 例では、以下の内容を含む collection.xml と collection.xsl を使用します。
Example#1 collection.xml
<collection> <cd> <title>Fight for your mind</title> <artist>Ben Harper</artist> <year>1995</year> </cd> <cd> <title>Electric Ladyland</title> <artist>Jimi Hendrix</artist> <year>1997</year> </cd> </collection>
Example#2 collection.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="owner" select="'Nicolas Eliaszewicz'"/> <xsl:output method="html" encoding="iso-8859-1" indent="no"/> <xsl:template match="collection"> Hey! Welcome to <xsl:value-of select="$owner"/>'s sweet CD collection! <xsl:apply-templates/> </xsl:template> <xsl:template match="cd"> <h1><xsl:value-of select="title"/></h1> <h2>by <xsl:value-of select="artist"/> - <xsl:value-of select="year"/></h2> <hr /> </xsl:template> </xsl:stylesheet>
定義済み定数
以下の定数が定義されています。 この関数の拡張モジュールが PHP 組み込みでコンパイルされているか、 実行時に動的にロードされている場合のみ使用可能です。
- XSL_CLONE_AUTO (integer)
- XSL_CLONE_NEVER (integer)
- XSL_CLONE_ALWAYS (integer)
- LIBXSLT_VERSION (integer)
- libxslt のバージョンを 10117 のように表します。PHP 5.1.2 以降で使用可能です。
- LIBXSLT_DOTTED_VERSION (string)
- libxslt のバージョンを 1.1.17 のように表します。PHP 5.1.2 以降で使用可能です。
- LIBEXSLT_VERSION (integer)
- libexslt のバージョンを 813 のように表します。PHP 5.1.2 以降で使用可能です。
- LIBEXSLT_DOTTED_VERSION (string)
- libexslt のバージョンを 1.1.17 のように表します。PHP 5.1.2 以降で使用可能です。
目次
- XSLTProcessor::__construct — 新規 XSLTProcessor オブジェクトを生成する
- XSLTProcessor::getParameter — パラメータの値を取得する
- XSLTProcessor::hasExsltSupport — PHP が EXSLT をサポートしているかどうかを判定する
- XSLTProcessor::importStylesheet — スタイルシートを取り込む
- XSLTProcessor::registerPHPFunctions — PHP 関数を XSLT 関数として利用できるようにする
- XSLTProcessor::removeParameter — パラメータを削除する
- XSLTProcessor::setParameter — パラメータの値を設定する
- XSLTProcessor::transformToDoc — DOMDocument に変換する
- XSLTProcessor::transformToURI — URI に変換する
- XSLTProcessor::transformToXML — XML に変換する
XSL
11-Jan-2008 10:38
12-Oct-2007 07:13
Calling the Saxon XSLT Processor is a very esay task to do!
You just need to do some simple task
1. Install the JavaBridge for PHP
2. Download the freeware (B) Saxon distribution from http://saxon.sourceforge.net/
3. Put the jar files in a directory whre you have access
4. Use this sample of code
// Directory where the jar files are located
define("SAXON_DIR", $_SERVER['DOCUMENT_ROOT']."/saxonb8.9.0/");
// include the jars
java_require(SAXON_DIR."saxon8.jar;".SAXON_DIR."saxon8-dom.jar");
$sXslFile = $_SERVER['DOCUMENT_ROOT']."/myfirst.xsl"; // The xsl file
$sXmlFile = $_SERVER['DOCUMENT_ROOT']."/myfirst.xml"; // The xml file
try
{
$oXslSource = new java("javax.xml.transform.stream.StreamSource", "file://".$sXslFile);
$oXmlSource = new java("javax.xml.transform.stream.StreamSource", "file://".$sXmlFile);
$oFeatureKeys = new JavaClass("net.sf.saxon.FeatureKeys");
// Create the Factory
$oTransformerFactory = new java("net.sf.saxon.TransformerFactoryImpl");
//Disable source document validation
$oTransformerFactory->setAttribute($oFeatureKeys->SCHEMA_VALIDATION, 4);
// Create a new Transformer
$oTransFormer = $oTransformerFactory->newTransformer($oXslSource);
// Create a StreamResult to store the output
$oResultStringWriter = new java("java.io.StringWriter");
$oResultStream = new java("javax.xml.transform.stream.StreamResult", $oResultStringWriter);
// Transform
$oTransFormer->transform($oXmlSource, $oResultStream);
// Echo the output from the transformation
echo java_cast($oResultStringWriter->toString(), "string");
}
catch(JavaException $e){
echo java_cast($e->getCause()->toString(), "string");
exit;
}
5. Enjoy
This is working quite well.
21-Aug-2007 11:31
@basslines at gmail dot com
"
As far as I can tell, the most recent stable versions of LibXML/LibXSLT/LibEXSLT do NOT support xPath 2.0 / XSLT 2.0 transformations. The only support for XSLT 2.0 that I've found is in Java's SAXON processor (http://saxon.sourceforge.net/).
"
Using SAXON or AltovaXML by using their JAVA bindings could prove to be a difficult task to do, and .NET seems to be buggy (at least for me). However, I've made a class that uses SAXON or AltovaXML from the command line. AltovaXML could also be used with COM, provided it's registered as a COM component.
You can download my wrapper from:
http://xslt2processor.sourceforge.net/
I still need to implement a more graceful error handling (the way the XSL extension uses the Libxml functions), and once the bug
http://bugs.php.net/bug.php?id=41577
is fixed, I'll implement the .NET interfaces too.
I'll appreciate any feedback.
02-Jul-2007 03:02
Here are a couple useful tips for those who care about cross-browser compatibility.
Given:
<script type="text/javascript" src="test.js"></script>
XSLT will automatically condense it to:
<script type="text/javascript" src="test.js"/>
While this is good, Internet Explorer breaks on empty script tags. So, the simple solution is to add something to prevent an empty tag. For example:
<script type="text/javascript" src="test.js"><xsl:comment/></script>
Produces:
<script type="text/javascript" src="test.js">
</script>
------------------------
Also, here is a way to use IE's conditional comments:
<xsl:comment>[if gte IE 5]>
<link rel="stylesheet" type="text/css" href="ie.css" />
<![endif]</xsl:comment>
Produces:
<!--[if gte IE 5]>
<link rel="stylesheet" type="text/css" href="ie.css" />
<![endif]-->
This will let you isolate IE-related CSS without needing to use ugly CSS hacks.
10-May-2007 07:19
Each <xsl:message> tag will generate a PHP error (level Warning). If you want to collect and pretty-print them, you could use a custom error handling function that collects the warnings in a static variable.
09-May-2007 12:59
You can set an HTTP proxy for the XSLT document() function to use (as well as DTD external references) by setting http_proxy in the environment.
E.g., in Apache configuration;
SetEnv http_proxy http://127.0.0.1:3128/
02-May-2007 05:14
Looking for php_xsl.dll?
If you installed on Windows using the MSI Installer - you may not have it.
1.) Add/Remove Programs and Change PHP Installation. Select XSL Extension.
OR
2.) Download complete .zip file of PHP and you can copy php_xsl.dll into your PHP/etc directory.
Just a note.
Ryan D. Hatch
14-Sep-2006 06:45
If you want to use the document()-function inside your XSL stylesheet, please note that you have to use an absolute path there.
Important for windows users: the absolute path *has* to be with forward slashes, so subsitute windows-path-backslashes to forward slashes before you transform the document.
Examples:
This will NOT work:
<xsl:copy-of select="document('test.xml')" />
This will also NOT work:
<xsl:copy-of select="document('c:\temp\test.xml')" />
But this WILL work:
<xsl:copy-of select="document('c:/temp/test.xml')" />
Enable libxslt library, PHP 5, under windows:
To Enable:
In your php.ini
1. Uncomment ;extension=php_xsl.dll
2. Change extension_dir to
extension_dir = "./ext"
To Confirm:
1. In a test.php page:
<?php phpinfo() ?>
2. Run test.php
3. Search for "libxslt Version". It should return a version number in a XSL headed table.
Further info Google
"Configuring and Testing PHP Servers for XSL Support"
30-Mar-2006 06:34
In response to how to use entities from DTD (internal or external) in XSLT. It works if you do this way:
$xsl = new DOMDocument;
$xsl->resolveExternals = TRUE;
$xsl->substituteEntities = TRUE;
$xsl->load(...);
Hope this helps! ;-)
30-Mar-2006 03:07
As far as I can tell, the most recent stable versions of LibXML/LibXSLT/LibEXSLT do NOT support xPath 2.0 / XSLT 2.0 transformations. The only support for XSLT 2.0 that I've found is in Java's SAXON processor (http://saxon.sourceforge.net/).
In response to appletalk at gmail dot com
<snip>
As many of you may have noticed, DOM parser gives errors if the ' ' entity is present. The E_WARN message looks like:
Warning: DOMDocument::load() [function.load]: Entity 'nbsp' not defined in ...
There're many ways to solve this:
.....
b) Defining
At the top of the document, after the <?xml?> definition, add:
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " " >
]>
.......</snip>
Just wanted to let people know that option b does NOT work. I'm not sure why this isn't implemented correctly, but it isn't, so don't waste your time. It's unfortunate the DOMXSL transform is so much less capable than the old xslt function.
05-Aug-2005 10:27
if you have 'XML parser error 4: not well-formed (invalid token)' error without but your are sure to do no error at all, try this:
<?
function
XSL_transformation($XMLFile,$XSLFile,$ResultFile,$xsl_params){
$Str = '';
$xp = xslt_create() or trigger_error('Could not create XSLT process.', E_USER_ERROR);
xslt_set_encoding($xp, 'ISO-8859-1');
// read the files into memory
$xsl_string = join('', file($XSLFile));
$xml_string = join('', file($XMLFile));
// set the argument buffer
$arg_buffer = array('/xml' => $xml_string, '/xsl' => $xsl_string);
// process the two files to get the desired output
if (($Str = xslt_process($xp, 'arg:/xml', 'arg:/xsl', NULL, $arg_buffer, $xsl_params))){
//Saves transformation result into '$ResultFile'
$fp = fopen($ResultFile,"w+");
fwrite($fp,$Str);
fclose($fp);
return true;
}
return false;
}
?>
found here: http://bugs.php.net/bug.php?id=16193
01-Mar-2005 11:17
Here is function to read from the XSL sheet which is saved as a text file.
function ReadExcelSheet($filename){
$test=file($filename);
$ar1=str_replace("~[^\t]*\t","\t",$test);
$ar2=str_replace("~","",$ar1);
$ar=str_replace("","",$ar2);
$temp=array();
for ($i=0; $i<count($ar); $i++) {
if((substr($ar[$i],0,1)!= "\t")){
if($ar[$i]!=="\r\n"){
array_push($temp,$ar[$i]);
}
}
}
$name=split("\t",$temp[0]);
$ExcelList=array();
for($i=1;$i<count($temp);$i++){
$split_result=split("\t",$temp[$i]);
array_push($ExcelList,$split_result);
}
$result=insert_into_array($ExcelList,0,$name);
return($result);
}
05-Feb-2005 03:32
As many of you may have noticed, DOM parser gives errors if the ' ' entity is present. The E_WARN message looks like:
Warning: DOMDocument::load() [function.load]: Entity 'nbsp' not defined in ...
There're many ways to solve this:
a) The hard way
<xsl:text disable-output-escaping="yes"> &nbsp;</xsl:text>
b) Defining
At the top of the document, after the <?xml?> definition, add:
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " " >
]>
c) External Doctype
Just in case you want need other HTML entities, you can call an external doctype with the proper definitions
<!DOCTYPE page SYSTEM "http://gv.ca/dtd/character-entities.dtd">
Of course, you can download the file and place it in your server.
23-Dec-2004 07:07
Wow, I spent the better part of a day looking for how one could pass an entire test expression to an XSL stylesheet. It seems that the XSLT 1.0 specification doesn't support it but PHP 5 (and maybe 4s) inclusion of EXSLT allows one to do exactly that...
simply add these lines...
xmlns:dyn="http://exslt.org/dynamic"
extension-element-prefixes="dyn"
to the <xsl:stylesheet> element and when using an expression stored in a <xsl:param> element write
<xsl:if test="dyn:evaluate($param-name)">
and viola! you can now use expressions generated externally in your stylesheet!
EXSLT adds many useful functions that can be integrated into your XSL in a similar fashion. You can go to http://exslt.org/ to learn more...
24-Sep-2004 07:58
If you get the following warning message:
xsltApplyOneTemplate: _if_ was not compiled in (if can for example be apply-template or some other method), i've found that the problem seems to be an directly before the <xsl:if> or what ever is causing the problem.
One way to get thru the problem is to use span tags around like : <span> </span>
06-Sep-2004 06:23
The following code is a wrapper to support calls to some of the old xslt_* functions:
<?
if (PHP_VERSION >= 5) {
// Emulate the old xslt library functions
function xslt_create() {
return new XsltProcessor();
}
function xslt_process($xsltproc,
$xml_arg,
$xsl_arg,
$xslcontainer = null,
$args = null,
$params = null) {
// Start with preparing the arguments
$xml_arg = str_replace('arg:', '', $xml_arg);
$xsl_arg = str_replace('arg:', '', $xsl_arg);
// Create instances of the DomDocument class
$xml = new DomDocument;
$xsl = new DomDocument;
// Load the xml document and the xsl template
$xml->loadXML($args[$xml_arg]);
$xsl->loadXML($args[$xsl_arg]);
// Load the xsl template
$xsltproc->importStyleSheet($xsl);
// Set parameters when defined
if ($params) {
foreach ($params as $param => $value) {
$xsltproc->setParameter("", $param, $value);
}
}
// Start the transformation
$processed = $xsltproc->transformToXML($xml);
// Put the result in a file when specified
if ($xslcontainer) {
return @file_put_contents($xslcontainer, $processed);
} else {
return $processed;
}
}
function xslt_free($xsltproc) {
unset($xsltproc);
}
}
$arguments = array(
'/_xml' => file_get_contents("newxslt.xml"),
'/_xsl' => file_get_contents("newxslt.xslt")
);
$xsltproc = xslt_create();
$html = xslt_process(
$xsltproc,
'arg:/_xml',
'arg:/_xsl',
null,
$arguments
);
xslt_free($xsltproc);
print $html;
?>
24-Jun-2004 11:43
If you're want to use XML from a variable e.g. $xmldata but the XSLT-StyleSheet from a file, you can do it also the following way:
<?php
$xslt = new xsltProcessor;
$xslt->importStyleSheet(DomDocument::load('filename.xsl'));
print $xslt->transformToXML(DomDocument::loadXML($xmldata));
?>