/[cvs]/nfo/perl/libs/XML/XUpdate/XSLT.pm
ViewVC logotype

Annotation of /nfo/perl/libs/XML/XUpdate/XSLT.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (hide annotations)
Wed May 7 03:11:28 2003 UTC (21 years ago) by joko
Branch: MAIN
Changes since 1.5: +32 -6 lines
updated pod: new section "References", added item to "Todo" section

1 joko 1.1 ##############################################################################
2     #
3     # Perl module: XML::XUpdate::XSLT
4     #
5     # By Andreas Motl, andreas.motl@ilo.de
6     #
7 joko 1.6 # $Id: XSLT.pm,v 1.5 2003/05/06 14:24:06 joko Exp $
8 joko 1.1 #
9     # $Log: XSLT.pm,v $
10 joko 1.6 # Revision 1.5 2003/05/06 14:24:06 joko
11     # doesn't use Carp any more
12     # updated pod
13     # attempt to rewrite xml to make it more human readable using helper modules from CPAN (node indentation, etc.)
14     #
15 joko 1.5 # Revision 1.4 2003/05/01 23:40:32 joko
16     # minor update: commented debugging part
17     #
18 joko 1.4 # Revision 1.3 2003/05/01 20:11:49 joko
19     # * added pod from xupdate.pl
20     # - extracted xml to external files
21     #
22 joko 1.2 # Revision 1.1 2003/04/30 02:36:32 joko
23     # initial commit
24     #
25 joko 1.1 #
26     ###############################################################################
27    
28 joko 1.3 =pod
29    
30    
31 joko 1.1 =head1 NAME
32    
33 joko 1.5 XML::XUpdate::XSLT - A perl module for updating xml documents using XUpdate via XSLT.
34 joko 1.1
35 joko 1.3
36     =head3 Overview
37    
38     This is not the same xupdate currently available from CPAN at
39     http://search.cpan.org/author/PAJAS/XML-XUpdate-LibXML-0.4.0/xupdate .
40    
41     Its intention - however - is identical:
42     xupdate - Process XUpdate commands against an XML document.
43    
44    
45 joko 1.6 =head4 Their implementations differ:
46 joko 1.3
47     1. xupdate (by Petr Pajas) uses ...
48     XML::XUpdate::LibXML - Simple implementation of XUpdate format
49    
50     ... which is based on XML::LibXML which in turn is:
51     [...]
52     This module is an interface to the gnome libxml2 DOM parser (no SAX parser support yet),
53     and the DOM tree. It also provides an XML::XPath-like findnodes() interface, providing
54     access to the XPath API in libxml2.
55     [...]
56    
57     2. This xupdate attempts to implement the XUpdate specs using XSLT only.
58    
59    
60 joko 1.6 =head4 Yet another xupdate - facts in short:
61 joko 1.3
62     S: It would be nice to have a pure perl thingy which does (almost) the same stuff....
63    
64     Q: Can we achieve compliance with its (XML::XUpdate::LibXML) API? (or just a subset ....)
65    
66     Q: Can we achieve the processing using CPAN's XML::XSLT?
67     S: Proposal: XML::XUpdate::XSLT!?
68    
69     Q: Can we mimic/use the interface of the - already established - 'xupdate' program???
70    
71 joko 1.5 Q: Should we follow the CRUD path first?
72     (CRUD is the acronym for the datastore action primitives: Create, Retrieve, Update, Delete)
73 joko 1.3 S?: Proposal: XML::XUpdate::XSLT::API uses XML::XUpdate::XSLT::CRUD
74    
75    
76 joko 1.6 =head3 References
77    
78     - XUpdate:
79     Requirements: http://www.xmldb.org/xupdate/xupdate-req.html
80     Working Draft: http://www.xmldb.org/xupdate/xupdate-wd.html
81     - XML API:
82     - XML::XUpdate::LibXML: http://search.cpan.org/author/PAJAS/XML-XUpdate-LibXML-0.4.0/lib/XML/XUpdate/LibXML.pm
83     - XSL / XSLT:
84     http://www.w3.org/TR/xslt
85     http://www.xsl-rp.de/
86     http://xml.klute-thiemann.de/w3c-de/REC-xslt-20020318/
87     http://xmlxslt.sourceforge.net/
88     - misc pointers:
89     "Re: Modify XML documents": http://aspn.activestate.com/ASPN/Mail/Message/perl-xml/1265431
90     XSL Extensions: http://xmlsoft.org/XSLT/extensions.html
91     EXSLT: http://www.exslt.org/set/functions/difference/index.html
92     "how to insert element at required position in document tree?": http://p2p.wrox.com/archive/xslt/2001-06/98.asp
93     XML APIs for Databases: http://www.javaworld.com/javaworld/jw-01-2000/jw-01-dbxml.html
94    
95    
96     =head3 Todo
97 joko 1.3
98     o What about proper encoding? (ISO-8859-1 or UTF-8)
99     o Is it possible to create the required "xsl_template.xml" at runtime via XSL itself?
100     o Cache contents of external files (*.xml). Performance!
101 joko 1.5 o Can exception / error-code handling be improved somehow?
102     Esp.: It would be interesting, if the XUpdate payload actually could be applied, or not...
103 joko 1.6 o <xupdate:if>, etc.
104 joko 1.3
105    
106 joko 1.1 =cut
107    
108    
109     ######################################################################
110     package XML::XUpdate::XSLT;
111     ######################################################################
112    
113     use strict;
114     use warnings;
115    
116 joko 1.5 use Data::Dumper;
117     use File::Basename;
118 joko 1.1 use XML::XSLT 0.41;
119 joko 1.5 use XML::XUpdate::Rewrite;
120 joko 1.1
121     # Namespace constants
122    
123     use constant NS_XUPDATE => 'http://www.xmldb.org/xupdate';
124    
125     use vars qw ( $VERSION );
126    
127 joko 1.3 $VERSION = '0.01';
128 joko 1.1
129    
130     ######################################################################
131     # PUBLIC DEFINITIONS
132    
133     sub new {
134     my $class = shift;
135     my $self = bless {}, $class;
136     my $args = $self->__parse_args(@_);
137    
138 joko 1.2 $self->{DEBUG} = $args->{debug};
139     $self->{WARNINGS} = $args->{warnings};
140    
141 joko 1.3 $self->__init_default_stylesheets();
142 joko 1.1
143 joko 1.2 return $self;
144 joko 1.1
145 joko 1.2 }
146 joko 1.1
147 joko 1.2 sub get_stylesheet {
148     my $self = shift;
149     my $name = shift;
150     return $self->{XML}->{xsl}->{$name};
151 joko 1.1 }
152    
153 joko 1.2 sub set_stylesheet {
154 joko 1.1 my $self = shift;
155     my $name = shift;
156 joko 1.2 my $xml = shift;
157     my $options = shift;
158     if ($options->{encap}) {
159 joko 1.3 my $template = $self->__slurp_file("xsl_template.xml");
160     # FIXME! What about the quirky? Is there a better one?
161     $template =~ s!<xsl:quirky_placeholder />!$xml!;
162     $xml = $template;
163 joko 1.2 }
164     $self->{XML}->{xsl}->{$name} = $xml;
165 joko 1.1 }
166    
167     sub open_document {
168     my $self = shift;
169     my $xml = shift;
170     # FIXME: check for filename, filehandle and URL (etc.)
171     $self->{XML}->{document} = $xml;
172     }
173    
174     sub open_xupdate {
175     my $self = shift;
176     my $xml = shift;
177 joko 1.6 # FIXME: check for filename, filehandle and URL (etc.)
178 joko 1.1 $self->{XML}->{xupdate} = $xml;
179     }
180    
181     sub process {
182     my $self = shift;
183 joko 1.2 $self->_calculate();
184     $self->_apply();
185 joko 1.1 }
186    
187 joko 1.2 # First, translate the xupdate payload to xsl.
188 joko 1.5 # FIXME: do DOM only! (don't use "->toString")
189 joko 1.2 sub _calculate {
190     my $self = shift;
191     $self->{XSLT_ENGINE_PREP} = XML::XSLT->new(
192     Source => $self->get_stylesheet("xupdate2xsl"),
193     debug => $self->{DEBUG},
194     warnings => $self->{WARNINGS}
195     );
196     $self->{XSLT_ENGINE_PREP}->open_xml( $self->{XML}->{xupdate} );
197     $self->{XSLT_ENGINE_PREP}->process();
198     $self->set_stylesheet( "_worker", $self->{XSLT_ENGINE_PREP}->toString(), { encap => 1 } );
199     }
200    
201     # After that, use this worker xsl to actually apply the changes to the original document.
202     # FIXME: do DOM only!
203     sub _apply {
204     my $self = shift;
205 joko 1.4
206     # debug - print the calculated xsl on STDERR
207 joko 1.6 print STDERR $self->get_stylesheet("_worker"), "\n";
208 joko 1.4
209 joko 1.2 #return;
210     $self->{XSLT_ENGINE_LIVE} = XML::XSLT->new(
211     Source => $self->get_stylesheet("_worker"),
212     debug => $self->{DEBUG},
213     warnings => $self->{WARNINGS}
214     );
215     $self->{XSLT_ENGINE_LIVE}->open_xml( $self->{XML}->{document} );
216     $self->{XSLT_ENGINE_LIVE}->process();
217     $self->{XML}->{result} = $self->{XSLT_ENGINE_LIVE}->toString();
218     }
219    
220 joko 1.1 sub toString {
221     my $self = shift;
222 joko 1.5
223     # use rest of argument list as hash of option values
224     my $options = {@_};
225    
226     # short circuit - just return what we have - don't modify anything
227     return $self->{XML}->{result} unless $options and $options->{rewrite};
228    
229     # Rewrite the xml document with certain engine to desired style.
230     # 'engine' defaults to "XMLParser" if not specified.
231     my $rewrite = XML::XUpdate::Rewrite->new( style => $options->{mode}, engine => $options->{using} );
232     $rewrite->set_document( $self->{XML}->{result} );
233     # TODO: Implement a configurable fallback here to return the un-rewritten payload if desired.
234     $rewrite->process() or die(__PACKAGE__ . ": Error while rewriting XML document.");
235     return $rewrite->get_document();
236 joko 1.1 }
237 joko 1.5
238 joko 1.1
239     ######################################################################
240     # AUXILIARY METHODS
241    
242 joko 1.5 # Argument list parsing.
243     # ... from XML::XUpdate::LibXML (w/o backwards compatibility hook).
244     # Could this make up a Class::AutoFill::__read_arglist which transparently
245     # makes object attributes from constructor arguments in a configurable way?
246 joko 1.1 sub __parse_args {
247     my $self = shift;
248     my %args;
249    
250 joko 1.5 if ( @_ % 2 ) {
251 joko 1.1 $args{dummy} = shift;
252     %args = (%args, @_);
253     } else {
254     %args = @_;
255     }
256    
257     return \%args;
258     }
259    
260    
261 joko 1.3 sub __init_default_stylesheets {
262     my $self = shift;
263     if (my $payload = $self->__slurp_file("xupdate2xsl.xml")) {
264     $self->{XML}->{xsl}->{xupdate2xsl} = $payload;
265     }
266     }
267    
268     sub __slurp_file {
269 joko 1.1 my $self = shift;
270 joko 1.3 my $filename = shift;
271 joko 1.1
272 joko 1.3 # does file exist?
273     if (! -e $filename) {
274     $filename = dirname(__FILE__) . "/$filename";
275     if (! -e $filename) {
276 joko 1.5 die("File $filename does not exist.");
277 joko 1.3 }
278     }
279 joko 1.1
280 joko 1.3 open(FH, "<" . $filename);
281     my @lines = <FH>;
282     my $content = join("", @lines);
283     close(FH);
284     return $content;
285 joko 1.1 }
286    
287     1;
288     __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed