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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by joko, Thu May 1 17:03:52 2003 UTC revision 1.8 by joko, Fri Jun 6 04:01:52 2003 UTC
# Line 7  Line 7 
7  #    $Id$  #    $Id$
8  #  #
9  #    $Log$  #    $Log$
10  #    Revision 1.2  2003/05/01 17:03:52  joko  #    Revision 1.8  2003/06/06 04:01:52  joko
11  #    revamped processing: a) _calculate and b) _apply (NEW)  #    just write to STDERR in debug mode
12    #
13    #    Revision 1.7  2003/05/13 09:32:22  joko
14    #    minor update to pod
15    #
16    #    Revision 1.6  2003/05/07 03:11:28  joko
17    #    updated pod: new section "References", added item to "Todo" section
18    #
19    #    Revision 1.5  2003/05/06 14:24:06  joko
20    #    doesn't use Carp any more
21    #    updated pod
22    #    attempt to rewrite xml to make it more human readable using helper modules from CPAN (node indentation, etc.)
23    #
24    #    Revision 1.4  2003/05/01 23:40:32  joko
25    #    minor update: commented debugging part
26    #
27    #    Revision 1.3  2003/05/01 20:11:49  joko
28    #    * added pod from xupdate.pl
29    #    - extracted xml to external files
30  #  #
31  #    Revision 1.1  2003/04/30 02:36:32  joko  #    Revision 1.1  2003/04/30 02:36:32  joko
32  #    initial commit  #    initial commit
# Line 16  Line 34 
34  #  #
35  ###############################################################################  ###############################################################################
36    
37    =pod
38    
39    
40  =head1 NAME  =head1 NAME
41    
42  XML::XUpdate::XSLT - A perl module for updating xml documents using XUpdate via XSLT.    XML::XUpdate::XSLT - A perl module for updating xml documents using XUpdate via XSLT.
43    
44    
45    =head3 Overview
46    
47      This is not the same xupdate currently available from CPAN at
48      http://search.cpan.org/author/PAJAS/XML-XUpdate-LibXML-0.4.0/xupdate .
49      
50      Its intention - however - is identical:
51      xupdate - Process XUpdate commands against an XML document.
52    
53    
54    =head4 Their implementations differ:
55    
56        1. xupdate (by Petr Pajas) uses ...
57        XML::XUpdate::LibXML - Simple implementation of XUpdate format
58        
59        ... which is based on XML::LibXML which in turn is:
60        [...]
61        This module is an interface to the gnome libxml2 DOM parser (no SAX parser support yet),
62        and the DOM tree. It also provides an XML::XPath-like findnodes() interface, providing
63        access to the XPath API in libxml2.
64        [...]
65    
66        2. This xupdate attempts to implement the XUpdate specs using XSLT only.
67        
68    
69    =head4 Yet another xupdate - facts in short:
70    
71      S: It would be nice to have a pure perl thingy which does (almost) the same stuff....
72      
73      Q: Can we achieve compliance with its (XML::XUpdate::LibXML) API? (or just a subset ....)
74      
75      Q: Can we achieve the processing using CPAN's XML::XSLT?
76      S: Proposal: XML::XUpdate::XSLT!?
77      
78      Q: Can we mimic/use the interface of the - already established - 'xupdate' program???
79      
80      Q: Should we follow the CRUD path first?
81          (CRUD is the acronym for the datastore action primitives: Create, Retrieve, Update, Delete)
82      S?: Proposal: XML::XUpdate::XSLT::API uses XML::XUpdate::XSLT::CRUD
83    
84    
85    =head3 References
86    
87        - XUpdate:
88          Requirements: http://www.xmldb.org/xupdate/xupdate-req.html
89          Working Draft: http://www.xmldb.org/xupdate/xupdate-wd.html
90        - XML API:
91        - XML::XUpdate::LibXML: http://search.cpan.org/author/PAJAS/XML-XUpdate-LibXML-0.4.0/lib/XML/XUpdate/LibXML.pm
92        - XSL / XSLT:
93          http://www.w3.org/TR/xslt
94          http://www.xsl-rp.de/
95          http://xml.klute-thiemann.de/w3c-de/REC-xslt-20020318/
96          http://xmlxslt.sourceforge.net/
97        - misc pointers:
98          "Re: Modify XML documents": http://aspn.activestate.com/ASPN/Mail/Message/perl-xml/1265431
99          XSL Extensions: http://xmlsoft.org/XSLT/extensions.html
100          EXSLT: http://www.exslt.org/set/functions/difference/index.html
101          "how to insert element at required position in document tree?": http://p2p.wrox.com/archive/xslt/2001-06/98.asp
102          XML APIs for Databases: http://www.javaworld.com/javaworld/jw-01-2000/jw-01-dbxml.html
103    
104    
105    =head3 Todo
106    
107      o What about proper encoding? (ISO-8859-1 or UTF-8)
108      o Is it possible to create the required "xsl_template.xml" at runtime via XSL itself?
109      o Cache contents of external files (*.xml). Performance!
110      o Can exception / error-code handling be improved somehow?
111          Esp.: It would be interesting, if the XUpdate payload actually could be applied, or not...
112      o Conditional processing: <xupdate:if>, etc.
113      
114    
115  =cut  =cut
116    
# Line 30  package XML::XUpdate::XSLT; Line 122  package XML::XUpdate::XSLT;
122  use strict;  use strict;
123  use warnings;  use warnings;
124    
 use XML::XSLT 0.41;  
 use Carp;  
125  use Data::Dumper;  use Data::Dumper;
126    use File::Basename;
127    use XML::XSLT 0.41;
128    use XML::XUpdate::Rewrite;
129    
130  # Namespace constants  # Namespace constants
131    
# Line 40  use constant NS_XUPDATE         => 'http Line 133  use constant NS_XUPDATE         => 'http
133    
134  use vars qw ( $VERSION );  use vars qw ( $VERSION );
135    
136  $VERSION = '0.02';  $VERSION = '0.01';
137    
138    
139  ######################################################################  ######################################################################
# Line 54  sub new { Line 147  sub new {
147    $self->{DEBUG} = $args->{debug};    $self->{DEBUG} = $args->{debug};
148    $self->{WARNINGS} = $args->{warnings};    $self->{WARNINGS} = $args->{warnings};
149    
150    $self->__init_default_macros();    $self->__init_default_stylesheets();
151    
152    return $self;    return $self;
153    
# Line 72  sub set_stylesheet { Line 165  sub set_stylesheet {
165    my $xml = shift;    my $xml = shift;
166    my $options = shift;    my $options = shift;
167    if ($options->{encap}) {    if ($options->{encap}) {
168      $xml = qq(<?xml version="1.0" encoding="ISO-8859-1"?>      my $template = $self->__slurp_file("xsl_template.xml");
169          # FIXME! What about the quirky? Is there a better one?
170      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      $template =~ s!<xsl:quirky_placeholder />!$xml!;
171            $xml = $template;
         <!--  
         This XML Stylesheet is the result of a translation from  
         XUpdate lingo. It actually applies the payload to the  
         original xml document. (it's the second processing step!)  
         -->  
           
         <xsl:output method="xml" />  
   
 $xml  
           
     </xsl:stylesheet>  
   );  
172    }    }
173    $self->{XML}->{xsl}->{$name} = $xml;    $self->{XML}->{xsl}->{$name} = $xml;
174  }  }
# Line 113  sub process { Line 194  sub process {
194  }  }
195    
196  # First, translate the xupdate payload to xsl.  # First, translate the xupdate payload to xsl.
197  # FIXME: do DOM only!  # FIXME: do DOM only! (don't use "->toString")
198  sub _calculate {  sub _calculate {
199    my $self = shift;    my $self = shift;
200    $self->{XSLT_ENGINE_PREP} = XML::XSLT->new(    $self->{XSLT_ENGINE_PREP} = XML::XSLT->new(
# Line 130  sub _calculate { Line 211  sub _calculate {
211  # FIXME: do DOM only!  # FIXME: do DOM only!
212  sub _apply {  sub _apply {
213    my $self = shift;    my $self = shift;
214    #print $self->get_stylesheet("_worker"), "\n";    
215      # debug - print the calculated xsl on STDERR
216      print STDERR $self->get_stylesheet("_worker"), "\n" if $self->{DEBUG};
217      
218    #return;    #return;
219    $self->{XSLT_ENGINE_LIVE} = XML::XSLT->new(    $self->{XSLT_ENGINE_LIVE} = XML::XSLT->new(
220      Source => $self->get_stylesheet("_worker"),      Source => $self->get_stylesheet("_worker"),
# Line 142  sub _apply { Line 226  sub _apply {
226    $self->{XML}->{result} = $self->{XSLT_ENGINE_LIVE}->toString();    $self->{XML}->{result} = $self->{XSLT_ENGINE_LIVE}->toString();
227  }    }  
228        
   
229  sub toString {  sub toString {
230    my $self = shift;    my $self = shift;
231    return $self->{XML}->{result};    
232      # use rest of argument list as hash of option values
233      my $options = {@_};
234      
235      # short circuit - just return what we have - don't modify anything
236      return $self->{XML}->{result} unless $options and $options->{rewrite};
237      
238      # Rewrite the xml document with certain engine to desired style.
239      # 'engine' defaults to "XMLParser" if not specified.
240      my $rewrite = XML::XUpdate::Rewrite->new( style => $options->{mode}, engine => $options->{using} );
241      $rewrite->set_document( $self->{XML}->{result} );
242      # TODO: Implement a configurable fallback here to return the un-rewritten payload if desired.
243      $rewrite->process() or die(__PACKAGE__ . ": Error while rewriting XML document.");
244      return $rewrite->get_document();
245  }  }
246    
247    
248  ######################################################################  ######################################################################
249  # AUXILIARY METHODS  # AUXILIARY METHODS
250    
251  # Argument parsing (with backwards compatibility hook).  # Argument list parsing.
252    # ... from XML::XUpdate::LibXML (w/o backwards compatibility hook).
253    # Could this make up a Class::AutoFill::__read_arglist which transparently
254    # makes object attributes from constructor arguments in a configurable way?
255  sub __parse_args {  sub __parse_args {
256    my $self = shift;    my $self = shift;
257    my %args;    my %args;
258    
259    if(@_ % 2 ) {    if ( @_ % 2 ) {
260      $args{dummy} = shift;      $args{dummy} = shift;
261      %args = (%args, @_);      %args = (%args, @_);
262    } else {    } else {
# Line 168  sub __parse_args { Line 267  sub __parse_args {
267  }  }
268    
269    
270  sub __init_default_macros {  sub __init_default_stylesheets {
271    my $self = shift;    my $self = shift;
272    $self->{XML}->{xsl}->{xupdate2xsl} = qq(<?xml version="1.0" encoding="ISO-8859-1"?>    if (my $payload = $self->__slurp_file("xupdate2xsl.xml")) {
273          $self->{XML}->{xsl}->{xupdate2xsl} = $payload;
274    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    }
275    }
276    
277    sub __slurp_file {
278      my $self = shift;
279      my $filename = shift;
280        
281        <!--    # does file exist?
282        Purpose of this XML Stylesheet is to implement a set of templates    if (! -e $filename) {
283        to translate XUpdate lingo into an intermediate xslt stylesheet      $filename = dirname(__FILE__) . "/$filename";
284        which actually performs the update to the original xml document      if (! -e $filename) {
285        in a second step.        die("File $filename does not exist.");
286        -->      }
287            }
       <xsl:output method="xml" />  
     
       <!-- 1. This is the passthru logic (copy all untouched nodes). -->  
       <xsl:template name="passthru"><xsl:copy><xsl:apply-templates /></xsl:copy></xsl:template>  
       <!-- activate this -->  
       <xsl:template match="*"><xsl:call-template name="passthru" /></xsl:template>  
       <!-- override some builtin rules: see http://www.w3.org/TR/xslt#built-in-rule -->  
       <xsl:template match="comment()"><xsl:call-template name="passthru" /></xsl:template>  
     
       <!-- 2. This is the translation part: XUpdate becomes XSLT -->  
         
       <!-- This node "encapsulates" common infrastructure. -->  
       <xsl:template match="xupdate:modifications">  
     
           <!-- 1. This is the passthru logic (copy all untouched nodes). -->  
           <!-- in fact this is the xsl from above translated to be able to be generated by xsl itself! -->  
               <xsl:comment> 1. passthru logic </xsl:comment>  
               <xsl:element name="xsl:template">  
                   <xsl:attribute name="name">passthru</xsl:attribute>  
                   <xsl:element name="xsl:copy"><xsl:element name="xsl:apply-templates" /></xsl:element>  
               </xsl:element>  
               <xsl:element name="xsl:template">  
                   <xsl:attribute name="match">*</xsl:attribute>  
                   <xsl:element name="xsl:call-template"><xsl:attribute name="name">passthru</xsl:attribute></xsl:element>  
               </xsl:element>  
               <xsl:element name="xsl:template">  
                   <xsl:attribute name="match">comment()</xsl:attribute>  
                   <xsl:element name="xsl:call-template"><xsl:attribute name="name">passthru</xsl:attribute></xsl:element>  
               </xsl:element>  
     
           <!-- continue with all inline nodes -->  
               <xsl:apply-templates />  
     
       </xsl:template>  
     
       <!-- This node "encapsulates" infrastructure for handling the directives. -->  
       <xsl:template match="xupdate:insert-after">  
           <xsl:comment> 2. context finder </xsl:comment>  
           <xsl:apply-templates />  
       </xsl:template>  
     
       <!-- This node passes through all attributes and childnodes rewriting the tagname only. -->  
       <xsl:template match="xupdate:element">  
           <xsl:comment> 3. rewrite / vivify elements/attributes </xsl:comment>  
           <xsl:element name="xsl:element">  
               <xsl:copy-of select="@*"/>  
               <xsl:apply-templates />  
           </xsl:element>  
       </xsl:template>  
     
       <!-- This node passes through all attributes and childnodes rewriting the tagname only. -->  
       <xsl:template match="xupdate:attribute">  
           <xsl:element name="xsl:attribute">  
               <xsl:copy-of select="@*"/>  
               <xsl:apply-templates />  
           </xsl:element>  
       </xsl:template>  
     
   </xsl:stylesheet>  
288        
289    );    open(FH, "<" . $filename);
290      my @lines = <FH>;
291      my $content = join("", @lines);
292      close(FH);
293      return $content;
294  }  }
295    
296  1;  1;

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.8

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