/[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.5 - (hide annotations)
Tue May 6 14:24:06 2003 UTC (21 years ago) by joko
Branch: MAIN
Changes since 1.4: +35 -13 lines
doesn't use Carp any more
updated pod
attempt to rewrite xml to make it more human readable using helper modules from CPAN (node indentation, etc.)

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

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