1<?php
2/**
3 * Plugin XSLT : Perform XSL Transformation on provided XML data
4 *
5 * To be run with Dokuwiki only
6 *
7 * Sample data provided at the end of the file
8 *
9 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
10 * @author     R�mi Peyronnet  <remi+xslt@via.ecp.fr>
11 */
12
13if(!defined('DOKU_INC')) die();
14if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
15require_once(DOKU_PLUGIN.'syntax.php');
16
17class syntax_plugin_xslt extends DokuWiki_Syntax_Plugin {
18
19    function getInfo(){
20      return array(
21        'author' => 'R�mi Peyronnet',
22        'email'  => 'remi+xslt@via.ecp.fr',
23        'date'   => '2009-03-07',
24        'name'   => 'XSLT Plugin',
25        'desc'   => 'Perform XSL Transformation on provided XML data',
26        'url'    => 'http://people.via.ecp.fr/~remi/',
27      );
28    }
29
30    function getType() { return 'substition'; }
31    function getPType() { return 'block'; }
32    function getSort() { return 1242; }
33    function connectTo($mode) { $this->Lexer->addSpecialPattern('&&XML&&\n.*\n&&XSLT&&\n.*\n&&END&&',$mode,'plugin_xslt'); }
34
35    function handle($match, $state, $pos, Doku_Handler $handler)
36    {
37        switch ($state) {
38          case DOKU_LEXER_SPECIAL :
39                $matches = preg_split('/(&&XML&&\n*|\n*&&XSLT&&\n*|\n*&&END&&)/', $match, 5);
40                $data = "XML: " . $matches[1] . "\nXSLT: ". $matches[2] . "(" . $match . ")";
41                $xsltproc = new XsltProcessor();
42                $xml = new DomDocument;
43                $xsl = new DomDocument;
44                $xml->loadXML($matches[1]);
45                $xsl->loadXML($matches[2]);
46                $xsltproc->registerPHPFunctions();
47                $xsltproc->importStyleSheet($xsl);
48                $data = $xsltproc->transformToXML($xml);
49
50                if (!$data) {
51                    $errors = libxml_get_errors();
52                    foreach ($errors as $error) {
53                        $data = display_xml_error($error, $xml);
54                    }
55                    libxml_clear_errors();
56                }
57
58                unset($xsltproc);
59                return array($state, $data);
60
61          case DOKU_LEXER_UNMATCHED :  return array($state, $match);
62          case DOKU_LEXER_EXIT :       return array($state, '');
63        }
64        return array();
65    }
66
67    function render($mode, Doku_Renderer $renderer, $data)
68    {
69         if($mode == 'xhtml'){
70            list($state, $match) = $data;
71            switch ($state) {
72              case DOKU_LEXER_SPECIAL :
73                $renderer->doc .= $match;
74                break;
75
76              case DOKU_LEXER_UNMATCHED :  $renderer->doc .= $renderer->_xmlEntities($match); break;
77              case DOKU_LEXER_EXIT :       $renderer->doc .= ""; break;
78            }
79            return true;
80        }
81        return false;
82    }
83}
84
85
86function display_xml_error($error, $xml)
87{
88    $return  = $xml[$error->line - 1] . "\n";
89    $return .= str_repeat('-', $error->column) . "^\n";
90
91    switch ($error->level) {
92        case LIBXML_ERR_WARNING:
93            $return .= "Warning $error->code: ";
94            break;
95         case LIBXML_ERR_ERROR:
96            $return .= "Error $error->code: ";
97            break;
98        case LIBXML_ERR_FATAL:
99            $return .= "Fatal Error $error->code: ";
100            break;
101    }
102
103    $return .= trim($error->message) .
104               "\n  Line: $error->line" .
105               "\n  Column: $error->column";
106
107    if ($error->file) {
108        $return .= "\n  File: $error->file";
109    }
110
111    return "$return\n\n--------------------------------------------\n\n";
112}
113
114/*
115
116Sample data :
117
118This is my list of books, maintained in XML/XSLT inside Dokuwiki.
119&&XML&&
120
121<xml>
122<book>Book 1</book>
123<book>Book 2</book>
124</xml>
125
126&&XSLT&&
127
128<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/REC-html40">
129<xsl:template match="/">List of books : <ul><xsl:apply-templates /></ul></xsl:template>
130<xsl:template match="book"><li><b><xsl:apply-templates /></b></li></xsl:template>
131</xsl:stylesheet>
132
133&&END&&
134
135
136*/
137
138?>