4 |
## $Id$ |
## $Id$ |
5 |
## ------------------------------------------------------------------------- |
## ------------------------------------------------------------------------- |
6 |
## $Log$ |
## $Log$ |
7 |
|
## Revision 1.4 2003/05/01 19:47:09 joko |
8 |
|
## attempts to get things going |
9 |
|
## |
10 |
|
## Revision 1.3 2003/04/26 01:42:39 joko |
11 |
|
## first attempt to make up a crud template |
12 |
|
## |
13 |
|
## Revision 1.2 2003/04/25 12:35:23 joko |
14 |
|
## added some pod |
15 |
|
## revamped xsl |
16 |
|
## |
17 |
## Revision 1.1 2003/04/24 21:07:36 joko |
## Revision 1.1 2003/04/24 21:07:36 joko |
18 |
## initial commit |
## initial commit |
19 |
## |
## |
41 |
access to the XPath API in libxml2. |
access to the XPath API in libxml2. |
42 |
|
|
43 |
|
|
44 |
=head3 In short: |
=head3 Yet another xupdate - facts in short: |
45 |
|
|
46 |
S: It would be nice to have a pure perl thingy which does the same stuff.... |
S: It would be nice to have a pure perl thingy which does (almost) the same stuff.... |
47 |
|
|
48 |
Q: Can we achieve compliance with its API? (just a subset ....) |
Q: Can we achieve compliance with its (XML::XUpdate::LibXML) API? (just a subset ....) |
49 |
|
|
50 |
Q: Can we achieve the processing declared as a XSL document processed using CPAN's XML::XSLT? |
Q: Can we achieve the processing declared as a XSL document processed using CPAN's XML::XSLT? |
51 |
|
|
53 |
|
|
54 |
Q: Can we mimic/use the interface of the - already established - 'xupdate' program??? |
Q: Can we mimic/use the interface of the - already established - 'xupdate' program??? |
55 |
|
|
56 |
|
Q: Should we follow the CRUD path first? |
57 |
|
|
58 |
|
|
59 |
=cut |
=cut |
60 |
|
|
76 |
|
|
77 |
my $file = 'c:/home/amo/develop/top-scores.net/ts/backend/var/resources/control/import_select.xml'; |
my $file = 'c:/home/amo/develop/top-scores.net/ts/backend/var/resources/control/import_select.xml'; |
78 |
|
|
79 |
my $stylesheet = '<?xml version="1.0" encoding="ISO-8859-1"?> |
|
80 |
|
#my $stylesheet_xupdate = ' |
81 |
|
|
82 |
|
my $stylesheet_xupdate = '<?xml version="1.0" encoding="ISO-8859-1"?> |
83 |
|
|
84 |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
85 |
|
|
115 |
|
|
116 |
<xsl:output method="raw"/> |
<xsl:output method="raw"/> |
117 |
|
|
118 |
<!-- 0. The root node dispatcher. --> |
<!-- 1. This is the passthru logic (copy all untouched nodes). --> |
119 |
<xsl:template match="*"><xsl:call-template name="passthru"/></xsl:template> |
<xsl:template name="passthru"><xsl:copy><xsl:apply-templates /></xsl:copy></xsl:template> |
120 |
<!-- <xsl:template match="source"><xsl:call-template name="insertChildNode"/></xsl:template> --> |
<!-- activate this --> |
121 |
|
<xsl:template match="*"><xsl:call-template name="passthru" /></xsl:template> |
122 |
|
<!-- override some builtin rules: see http://www.w3.org/TR/xslt#built-in-rule --> |
123 |
|
<xsl:template match="comment()"><xsl:call-template name="passthru" /></xsl:template> |
124 |
|
|
125 |
<!-- 1. This is the passthru logic (copy all). --> |
<!-- 2. This is the crud API. --> |
|
<xsl:template name="passthru"><xsl:copy><xsl:apply-templates/></xsl:copy></xsl:template> |
|
126 |
|
|
127 |
<!-- 2. This is the manipulation logic: insertChildNode --> |
<!-- 2.a. The context finder. --> |
128 |
|
|
129 |
<!-- 2.a. The "API" method. --> |
<!-- query part one: the node name --> |
130 |
<xsl:template name="insertChildNode"> |
<xsl:template match="source"> |
131 |
|
<xsl:choose> |
132 |
|
<!-- query part two: the attrib key and value --> |
133 |
|
<xsl:when test="@key=expekt"> |
134 |
|
<xsl:call-template name="crud" > |
135 |
|
<xsl:with-param name="action">CREATE</xsl:with-param> |
136 |
|
<xsl:with-param name="mode">callback</xsl:with-param> |
137 |
|
<xsl:with-param name="cbname">abc</xsl:with-param> |
138 |
|
</xsl:call-template> |
139 |
|
</xsl:when> |
140 |
|
<xsl:otherwise> |
141 |
|
<xsl:call-template name="passthru_kay" /> |
142 |
|
</xsl:otherwise> |
143 |
|
</xsl:choose> |
144 |
|
</xsl:template> |
145 |
|
|
146 |
<!-- manipulate node --> |
|
147 |
<xsl:comment> node - begin </xsl:comment> |
<!-- 2.b. The node manipulators: They translate the current context. --> |
148 |
|
|
149 |
<!-- <xsl:copy-of select="source" /> --> |
<!-- by Mike Kay, Software AG [http://p2p.wrox.com/archive/xslt/2001-06/98.asp] --> |
150 |
<xsl:copy> |
<!-- enhancements & comments: Andreas Motl, rotamente.de --> |
151 |
|
<!-- <xsl:template match="source"> --> |
152 |
|
<xsl:template name="passthru_kay"> |
153 |
|
<xsl:copy> |
154 |
|
<xsl:copy-of select="@*" /> |
155 |
|
<xsl:apply-templates /> |
156 |
|
</xsl:copy> |
157 |
|
</xsl:template> |
158 |
|
|
159 |
|
<xsl:template name="inject_kay_motl"> |
160 |
|
<xsl:param name="payload" /> |
161 |
|
<xsl:value-of select="$payload" /> |
162 |
|
<xsl:copy> |
163 |
|
<xsl:copy-of select="@*" /> |
164 |
|
<xsl:apply-templates /> |
165 |
|
<!-- <xsl:apply-templates select="*[3]" /> --> |
166 |
|
<!-- <xsl:value-of select="text()" /> --> |
167 |
|
<!-- Multiple handlers here now: a) create fressshhhh element, b) clone s.th. --> |
168 |
|
<!-- TODO: Do switch/case or couple of if/then statements here to be able to handle that "at runtime". --> |
169 |
|
<xsl:call-template name="create_fresh_element" /> |
170 |
|
<xsl:call-template name="clone_last_element" /> |
171 |
|
<xsl:call-template name="clone_element_nr" /> |
172 |
|
</xsl:copy> |
173 |
|
</xsl:template> |
174 |
|
|
175 |
|
<xsl:template name="crud"> |
176 |
|
|
177 |
|
<xsl:param name="action" /> |
178 |
|
<xsl:param name="payload" /> |
179 |
|
<xsl:param name="mode" /> |
180 |
|
<xsl:param name="cbname" /> |
181 |
|
|
182 |
|
<!-- |
183 |
|
action: <xsl:value-of select="$action" /> |
184 |
|
payload: <xsl:value-of select="$payload" /> |
185 |
|
--> |
186 |
|
|
187 |
|
<!-- |
188 |
|
<xsl:if test="$action=5"> |
189 |
|
CRUD: CREATE - if |
190 |
|
</xsl:if> |
191 |
|
--> |
192 |
|
|
193 |
|
<xsl:copy> |
194 |
|
|
195 |
|
<xsl:copy-of select="@*" /> |
196 |
|
<xsl:apply-templates /> |
197 |
|
|
198 |
|
<!-- crud action dispatcher --> |
199 |
|
<xsl:choose> |
200 |
|
|
201 |
|
<!-- CREATE --> |
202 |
|
<xsl:when test="{$action}=CREATE"> |
203 |
|
|
204 |
|
<!-- thats a (compact) switch case in xsl lingo! --> |
205 |
|
<xsl:choose> |
206 |
|
|
207 |
<!-- Pass through children 1:1. --> |
<xsl:when test="$payload!="> |
208 |
<xsl:apply-templates /> |
<xsl:comment> Payload injected on {timestamp} </xsl:comment> |
209 |
|
<xsl:value-of select="$payload" /> |
210 |
|
</xsl:when> |
211 |
|
|
212 |
|
<xsl:when test="$mode=callback"> |
213 |
|
<xsl:comment> Payload injected via callback <xsl:value-of select="{$cbname}" /> on {$timestamp} </xsl:comment> |
214 |
|
<xsl:call-template name="xupdate_element_create_embedded" /> |
215 |
|
</xsl:when> |
216 |
|
|
217 |
|
<xsl:otherwise> |
218 |
|
<xsl:comment> Cloned last element as template on {timestamp} </xsl:comment> |
219 |
|
<xsl:call-template name="clone_last_element" /> |
220 |
|
</xsl:otherwise> |
221 |
|
|
222 |
<!-- Call one of the manipulators - this implements injection behavior. --> |
</xsl:choose> |
223 |
<xsl:call-template name="clone_last_element" /> |
|
224 |
<xsl:call-template name="inject_template" /> |
</xsl:when> |
225 |
|
|
226 |
</xsl:copy> |
<xsl:otherwise> |
227 |
<xsl:comment> node - end </xsl:comment> |
<xsl:comment> |
228 |
|
UNKOWN CRUD ACTION: "<xsl:value-of select="$action" />" on <xsl:value-of select="$now" />. |
229 |
|
</xsl:comment> |
230 |
|
</xsl:otherwise> |
231 |
|
|
232 |
|
</xsl:choose> |
233 |
|
|
234 |
|
</xsl:copy> |
235 |
|
|
236 |
</xsl:template> |
</xsl:template> |
237 |
|
|
238 |
|
|
|
<!-- 2.b. The context finder. --> |
|
239 |
|
|
240 |
<!-- 2.c. The node manipulators: They mungle the current context. --> |
<!-- 2.c. The element manipulators: They mungle a specific element inside the current context. --> |
241 |
|
|
242 |
<!-- copy over node 1:1 (use last element as a template) --> |
<!-- copy over node 1:1 (use last element as a template) --> |
243 |
<xsl:template name="clone_last_element"> |
<xsl:template name="clone_last_element"> |
244 |
<xsl:copy-of select="*[last()]" /> |
<xsl:copy-of select="*[last()]" /> |
245 |
</xsl:template> |
</xsl:template> |
246 |
|
|
247 |
<xsl:template name="clone_element_nr"> |
<xsl:template name="clone_element_nr"> |
248 |
<xsl:copy-of select="*[last()]" /> |
<!-- TODO: let idx be passed in via "with-param" or s.th.l.th. --> |
249 |
|
<xsl:copy-of select="*[2]" /> |
250 |
</xsl:template> |
</xsl:template> |
251 |
|
|
252 |
<!-- creates instance of new element --> |
<!-- creates instance of new element --> |
253 |
<xsl:template name="create_fresh_element"> |
<xsl:template name="create_fresh_element"> |
254 |
<xsl:element name="new">content</xsl:element> |
<xsl:element name="new">content</xsl:element> |
255 |
|
</xsl:template> |
256 |
|
|
257 |
|
<xsl:template name="xupdate_element_create_embedded"> |
258 |
|
<xsl:variable name="huhu" select="*[0]/@key">haha</xsl:variable> |
259 |
|
<!-- <xsl:transform version="1.1" xmlns:xupdate="http://www.xmldb.org/xupdate"> --> |
260 |
|
<!-- <xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate"> --> |
261 |
|
<!-- <xsl:append select="/addresses" child="last()"> --> |
262 |
|
<xsl:element name="address"> |
263 |
|
<town>San Francisco</town> |
264 |
|
</xsl:element> |
265 |
|
<xsl:value-of select="*[0]/@key" /> |
266 |
|
<xsl:value-of select="$huhu" /> |
267 |
|
<!-- </xupdate:modifications> --> |
268 |
|
<!-- </xsl:append> --> |
269 |
|
<!-- </xsl:transform> --> |
270 |
</xsl:template> |
</xsl:template> |
271 |
|
|
272 |
|
|
277 |
</xsl:template> |
</xsl:template> |
278 |
|
|
279 |
|
|
|
<!-- Fine stuff from others. --> |
|
280 |
|
|
281 |
<!-- by Mike Kay, Software AG [http://p2p.wrox.com/archive/xslt/2001-06/98.asp] --> |
|
282 |
<!-- enhancements & comments: Andreas Motl, rotamente.de --> |
<!-- 0. The root node dispatcher. --> |
283 |
<xsl:template match="source"> |
<!-- <xsl:template match="source"><xsl:call-template name="insertChildNode"/></xsl:template> --> |
284 |
|
|
285 |
|
<!-- 2. This is the manipulation logic: insertChildNode --> |
286 |
|
|
287 |
|
<!-- 2.a. The "API" method. - now deprecated --> |
288 |
|
<xsl:template name="insertChildNode"> |
289 |
|
|
290 |
|
<!-- manipulate node --> |
291 |
|
<xsl:comment> node - begin </xsl:comment> |
292 |
|
|
293 |
|
<!-- <xsl:copy-of select="source" /> --> |
294 |
<xsl:copy> |
<xsl:copy> |
295 |
<xsl:copy-of select="@*" /> |
|
296 |
|
<!-- Pass through children 1:1. --> |
297 |
<xsl:apply-templates /> |
<xsl:apply-templates /> |
298 |
<!-- multiple handlers here now: a) create fressshhhh element, b) clone s.th. --> |
|
299 |
<!-- TODO: Do switch/case or couple of if/then statements here to be able to handle that "at runtime". --> |
<!-- Call one of the manipulators - this implements injection behavior. --> |
|
<xsl:call-template name="create_fresh_element" /> |
|
300 |
<xsl:call-template name="clone_last_element" /> |
<xsl:call-template name="clone_last_element" /> |
301 |
</xsl:copy> |
<xsl:call-template name="inject_template" /> |
302 |
|
|
303 |
|
</xsl:copy> |
304 |
|
<xsl:comment> node - end </xsl:comment> |
305 |
|
|
306 |
</xsl:template> |
</xsl:template> |
307 |
|
|
308 |
|
|
310 |
|
|
311 |
'; |
'; |
312 |
|
|
313 |
|
|
314 |
|
|
315 |
|
|
316 |
|
# examples from http://www.xmldb.org/xupdate/xupdate-wd.html#N238f4 |
317 |
|
|
318 |
|
my $xml_document = qq(<?xml version="1.0"?> |
319 |
|
<addresses version="1.0"> |
320 |
|
<address id="1"> |
321 |
|
<fullname>Andreas Laux</fullname> |
322 |
|
<born day='1' month='12' year='1978'/> |
323 |
|
<town>Leipzig</town> |
324 |
|
<country>Germany</country> |
325 |
|
</address> |
326 |
|
</addresses> |
327 |
|
); |
328 |
|
|
329 |
|
# a stripped example (the "xupdate payload") |
330 |
|
my $xml_xupdate_stripped = qq( |
331 |
|
<xupdate:element name="address"> |
332 |
|
<xupdate:attribute name="id">2</xupdate:attribute> |
333 |
|
<fullname>Lars Martin</fullname> |
334 |
|
<born day='2' month='12' year='1974'/> |
335 |
|
<town>Leizig</town> |
336 |
|
<country>Germany</country> |
337 |
|
</xupdate:element> |
338 |
|
); |
339 |
|
|
340 |
|
# a full xupdate example (including the directive) |
341 |
|
my $xml_xupdate_full = qq(<?xml version="1.0"?> |
342 |
|
<xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate"> |
343 |
|
|
344 |
|
<xupdate:insert-after select="/addresses/address[1]" > |
345 |
|
|
346 |
|
<xupdate:element name="address"> |
347 |
|
<xupdate:attribute name="id">2</xupdate:attribute> |
348 |
|
<fullname>Lars Martin</fullname> |
349 |
|
<born day='2' month='12' year='1974'/> |
350 |
|
<town>Leizig</town> |
351 |
|
<country>Germany</country> |
352 |
|
</xupdate:element> |
353 |
|
|
354 |
|
</xupdate:insert-after> |
355 |
|
|
356 |
|
</xupdate:modifications> |
357 |
|
); |
358 |
|
|
359 |
|
sub main_old { |
360 |
|
#$xslt->open_xml( Source => f2s($file) ); |
361 |
|
#$xslt->open_xml( Source => $xml_xupdate_full ); |
362 |
|
#$xslt->xsl_ns('xupdate', 'xsl'); |
363 |
|
|
364 |
|
#$xslt->process(); |
365 |
|
#print $xslt->toString(), "\n"; |
366 |
|
} |
367 |
|
|
368 |
|
|
369 |
sub main { |
sub main { |
370 |
|
|
371 |
my $xslt = XML::XSLT->new( |
use XML::XUpdate::XSLT; |
372 |
Source => $stylesheet, |
my $xupdate = XML::XUpdate::XSLT->new( |
|
#debug => 1, |
|
373 |
warnings => 1 |
warnings => 1 |
374 |
); |
); |
375 |
|
|
376 |
|
#print Dumper($xupdate); |
377 |
|
|
378 |
|
$xupdate->open_document( $xml_document ); |
379 |
|
#exit; |
380 |
|
|
381 |
#print f2s($file), "\n"; |
$xupdate->open_xupdate( $xml_xupdate_full ); |
382 |
|
|
383 |
$xslt->open_xml( Source => f2s($file) ); |
$xupdate->process(); |
384 |
|
my $result = $xupdate->toString(); |
385 |
$xslt->process(); |
if ($result) { |
386 |
print $xslt->toString(), "\n"; |
print $result, "\n"; |
387 |
|
} else { |
388 |
|
print "No result.", "\n"; |
389 |
|
} |
390 |
|
|
391 |
} |
} |
392 |
|
|
393 |
main(); |
main(); |
394 |
print "ready.", "\n"; |
print "ready.", "\n"; |
395 |
|
|
|
|
|
396 |
1; |
1; |
397 |
__END__ |
__END__ |