-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathblock.xslt.php
More file actions
166 lines (153 loc) · 5.19 KB
/
block.xslt.php
File metadata and controls
166 lines (153 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage plugins
*/
/**
* Smarty {xslt}{/xslt} block plugin
*
* Type: block function<br>
* Name: xslt<br>
* Purpose: Apply recursive transformations to complex data structures like
* nested array, classes, trees etc. Usage for simple data structures
* will end with great pain in the ass!<br>
* Requires: PHP-5 with MBString, DOM, XSL extensions<br>
*
* @author Keeper <hd_keeper at mail dot ru>
* @param array $params
* <pre>
* Params: from: mixed - array or class containing source data to display,
* ignored if 'from_xml' was provided
* from_xml: string - XML containing source data to display
* assign_xml: string - template variable the intermediate XML will be
* assigned to (useful for debugging)
* root_tag: string - name for the root element (default "root")
* default_tag: string - default name for tags (default "data")
* key_attribute: string - attribute name for array keys (default none)
* encoding: string - character set to use (default "UTF-8")
*
* You should provide either 'from' or 'from_xml' parameter!
* </pre>
* @param string $content - XSL-template to apply
* @param Smarty $smarty - clever simulation of a method
* @return string - generated HTML/XML data
*/
function smarty_block_xslt( $params, $content, &$smarty)
{
if (is_null( $content)) {
return;
}
// Setup default parameters
$from = null;
$from_xml = null;
$assign_xml = null;
$opts = array(
'root_tag' => "root",
'default_tag' => "data",
'key_attribute' => null,
'encoding' => "UTF-8"
);
// Obtain provided parameters
foreach ($params as $_key => $_val) {
switch ($_key) {
case 'from':
case 'from_xml':
case 'assign_xml':
$$_key = $_val;
break;
case 'root_tag':
case 'default_tag':
case 'key_attribute':
case 'encoding':
$opts[ $_key] = $_val;
break;
default:
$smarty->trigger_error( "xslt: unknown attribute '$_key'");
}
}
// Create DOM ducument containing provided data
$dom_data = new DOMDocument( '1.0', $opts['encoding']);
if (!is_null( $from_xml)) {
// Load provided raw XML-data into DOM document
$dom_data->loadXML( $from_xml);
} elseif (!is_null( $from)) {
// Build DOM document from provided source data
mb_regex_encoding( $opts['encoding']);
smarty_block_xslt_append( $dom_data, $opts['root_tag'], $from, $opts);
} else {
$smarty->trigger_error( "xslt: either 'from' or 'fromxml' attribute should be provided", E_USER_ERROR);
}
// Assign intermediate XML-data to the template variable
if (!is_null( $assign_xml)) {
$from_xml = $dom_data->saveXML();
$smarty->assign( $assign_xml, $from_xml);
}
// Create DOM document containing provided XSL-template
$dom_template = new DOMDocument( '1.0', $opts['encoding']);
$dom_template->loadXML( $content);
// Transform XML-data to make an output XML/HTML
$_output = "";
$processor = new XSLTProcessor();
$processor->importStyleSheet( $dom_template);
$_output = $processor->transformToXML( $dom_data);
return $_output;
}
/**
* Recursively walk through the provided variable,
* append all found data to the DOM document
*
* @access private
* @param DOMNode $dom_node - XML-element the childs are to be appended to
* @param string $use_key - suggested key to be used as tag name
* @param mixed $data - variable to be stored in the DOM document
* @param array $opts - set of immutable options
* @return void
*/
function smarty_block_xslt_append( DOMNode &$dom_node, $use_key, &$data, &$opts)
{
// For objects, use class name as tags
$use_tag = is_object($data) ? get_class( $data) : $use_key;
// Use default tag name instead of invalid tag names
if (!mb_ereg_match( '^[[:alpha:]_][[:alnum:]:_\.\-]*$', $use_tag))
$use_tag = $opts['default_tag'];
if (is_array($data) || is_object($data)) {
// Add a node for entire array or object
$dom_child = $dom_node->appendChild( new DOMElement(
smarty_block_xslt_conv( $use_tag, $opts)
));
// Enumerate array elements or object properties
foreach ($data as $_key => $_val) {
// Recurrent call for array element or object property
smarty_block_xslt_append( $dom_child, $_key, $_val, $opts);
}
} else {
// Plain data is added as leaf node
$dom_child = $dom_node->appendChild( new DOMElement(
smarty_block_xslt_conv( $use_tag, $opts),
htmlspecialchars( smarty_block_xslt_conv( $data, $opts), ENT_COMPAT, "UTF-8")
));
}
// Store key as attribute if required
if (!empty( $opts['key_attribute'])) {
$dom_child->setAttribute(
smarty_block_xslt_conv( $opts['key_attribute'], $opts),
smarty_block_xslt_conv( $use_key, $opts)
);
}
}
/**
* Convert data string to internal encoding of DOM document (UTF-8)
*
* @access private
* @param string $str - data to be converted
* @param array $opts - set of immutable options
* @return string - data converted to internal encoding
*/
function smarty_block_xslt_conv( $str, &$opts)
{
if (!mb_check_encoding( (string) $str, $opts['encoding']))
trigger_error( "xslt: data string '$str' has invalid encoding", E_USER_WARNING);
return mb_convert_encoding( (string) $str, "UTF-8", $opts['encoding']);
}
?>