home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / Wrapper.pm < prev    next >
Encoding:
Perl POD Document  |  2002-06-14  |  27.0 KB  |  995 lines

  1. package XML::XSLT::Wrapper;
  2. # Copyright (C) 2001, Colin Muller: colin@durbanet.co.za
  3. # This module may be used, distributed and modified
  4. # under the same terms as Perl itself
  5. # $Id: Wrapper.pm,v 1.16 2001/06/02 12:49:21 colin Exp $
  6.  
  7. use strict;
  8. use vars qw($VERSION $AUTOLOAD);
  9.  
  10. $VERSION = '0.32';
  11. $XML::XSLT::Wrapper::debug = undef;
  12.  
  13. sub new {
  14.     my ($proto, %args) = @_;
  15.     my $class = ref($proto) || $proto;
  16.     my $self = {};
  17.     foreach my $key (keys %args) {
  18.     $self->{$key} = $args{$key};
  19.     }
  20.     if (defined($args{Debug})) {
  21.     $XML::XSLT::Wrapper::debug = 1;
  22.     }
  23.     unless (defined $self->{ProcessorList}) {
  24.     my @processors = qw(libxslt sablotron xalan xslt xt saxon);
  25.     $self->{ProcessorList} = \@processors;
  26.     }
  27.     bless ($self, $class);
  28.     my $processor_array_ref = $self->{ProcessorList};
  29.     for my $i (0 .. $#$processor_array_ref) {
  30.     my $processor_init = lc($processor_array_ref->[$i]) . '_init';
  31.     unless ($self->$processor_init()) {
  32. debug("Could not init $processor_init");
  33.         $processor_array_ref->[$i] = undef;
  34.     }
  35.     }
  36.     return $self;
  37. }
  38.  
  39. sub transform {
  40.     my ($self, %params) = @_;
  41. #debug("In sub transform");
  42.     my $processor_array_ref = $self->{ProcessorList};
  43. PROC:
  44.     for my $i (0 .. $#$processor_array_ref) {
  45.     if (defined($processor_array_ref->[$i])) {
  46. debug("Trying processor: $processor_array_ref->[$i]");
  47.         my $result;
  48.         my $processor = lc($processor_array_ref->[$i]);
  49.         eval { $result = $self->$processor(%params) };
  50.         unless ( ($@) || ( !defined($result) ) ) {
  51.         return $result;
  52.         last PROC;
  53.         }
  54.     }
  55.     } # for
  56.     return undef;
  57. }
  58.  
  59. sub parse_params {
  60. #    $parsed_params = parse_params($params->{'XSLParams'});
  61. #    $params->{'XSLParamString'} = $parsed_params->[0];
  62. #    $params->{'XSLParamHash'} = $parsed_params->[1];
  63. #    $params->{'XSLParamArray'} = $parsed_params->[2];
  64.     my $params_ref = shift;
  65.     my ($par_str, %par_hash, @par_array) = ('', {}, []);
  66.     if (ref($params_ref) eq 'HASH') {
  67.     foreach my $key (keys %$params_ref) {
  68.         my $q = '';
  69.         if ($params_ref->{$key} !~ /'/) {
  70.         $q = "'";
  71.         } elsif ($params_ref->{$key} !~ /"/) {
  72.         $q = '"';
  73.         }
  74.         $par_str .= $key . '='
  75.         . $q . $params_ref->{$key} . $q 
  76.         . ' '
  77.         ;
  78.     }
  79.     @par_array = %$params_ref;
  80.     %par_hash = %$params_ref;
  81.     } elsif (ref($params_ref) eq 'ARRAY') {
  82.     my $i;
  83.     for ($i=0; $i < $#$params_ref; $i = $i+2) {
  84.         my $q = '';
  85.         if ($params_ref->[$i+1] !~ /'/) {
  86.         $q = "'";
  87.         } elsif ($params_ref->[$i+1] !~ /"/) {
  88.         $q = '"';
  89.         }
  90.         $par_str .= $params_ref->[$i] . '=' . 
  91.         $q . $params_ref->[$i+1] . $q 
  92.         . ' '
  93.         ;
  94.         $par_hash{$params_ref->[$i]} = $params_ref->[$i+1];
  95.     }
  96.     @par_array = @$params_ref;
  97.     }
  98.     return [$par_str, \%par_hash, \@par_array];
  99.  
  100. sub debug {
  101.     if (defined($XML::XSLT::Wrapper::debug)) {
  102.     my ($message) = @_;
  103.     if (defined($message)) {
  104.         warn "DEBUG: ", $message, "\n";
  105.     }
  106.     }
  107.     return;
  108. }
  109.  
  110. my $_SUBS = {};
  111.  
  112. sub AUTOLOAD {
  113.     no strict "refs";
  114.     my ($self, %params) = @_;
  115. #debug("starting autoload: $AUTOLOAD");
  116.     unless (defined($_SUBS->{$AUTOLOAD})) { return undef; }
  117. debug("evaling autoload: $AUTOLOAD");
  118.     eval "$_SUBS->{$AUTOLOAD}";
  119. #debug("done autoload: $AUTOLOAD");
  120.     return $self->$AUTOLOAD(%params);
  121. }
  122.  
  123. sub DESTROY {
  124. }
  125.  
  126. # Everything below here is AUTOLOADed if required
  127. $_SUBS->{'XML::XSLT::Wrapper::libxslt_init'} = 
  128. <<'END_OF_SUB';
  129. sub libxslt_init {
  130.     my ($self, %params) = @_;
  131.     eval { require XML::LibXSLT; };
  132.     if ($@) {
  133.     return undef;
  134.     }
  135.     use XML::LibXSLT;
  136.     eval { require XML::LibXML; };
  137.     if ($@) {
  138.     return undef;
  139.     }
  140.     use XML::LibXML;
  141.     $XML::XSLT::Wrapper::libxmlparser = XML::LibXML->new();
  142.     $XML::XSLT::Wrapper::libxsltprocessor = XML::LibXSLT->new();
  143.     return 1;
  144. }
  145. END_OF_SUB
  146.  
  147. $_SUBS->{'XML::XSLT::Wrapper::pre_parse'} = 
  148. <<'END_OF_SUB';
  149. sub pre_parse {
  150.     my ($self, %params) = @_;
  151.     my $processor_array_ref = $self->{ProcessorList};
  152.     my %pre_parsed;
  153. PROC:
  154.     for my $i (0 .. $#$processor_array_ref) {
  155.     if (defined($processor_array_ref->[$i])) {
  156. debug("Preparsing with: $processor_array_ref->[$i]");
  157.         my ($parsed_xml, $parsed_xsl);
  158.         my $processor = lc($processor_array_ref->[$i]);
  159.         $pre_parsed{$processor} = {};
  160.         my $preparser = $processor . '_pre_parse';
  161.         eval
  162.         {
  163.         ($parsed_xml, $parsed_xsl) = $self->$preparser(%params);
  164.         };
  165.         unless ($@) {
  166.         $pre_parsed{$processor}{'xml'} = $parsed_xml;
  167.         $pre_parsed{$processor}{'xsl'} = $parsed_xsl;
  168.         }
  169.     }
  170.     }
  171.     return %pre_parsed;
  172. }
  173. END_OF_SUB
  174.  
  175. $_SUBS->{'XML::XSLT::Wrapper::libxslt_pre_parse'} = 
  176. <<'END_OF_SUB';
  177. sub libxslt_pre_parse {
  178. #debug("in libxslt_pre_parse");
  179.     my ($self, %params) = @_;
  180.     my ($xml_parsed, $xsl_parsed);
  181.     if (defined $params{XMLFile})
  182.     {
  183. debug($params{XMLFile});
  184.     $xml_parsed = $XML::XSLT::Wrapper::libxmlparser->parse_file($params{XMLFile});
  185.     }
  186.     if (defined $params{XSLFile})
  187.     {
  188. debug($params{XSLFile});
  189.     my $parsed_stylesheet = $XML::XSLT::Wrapper::libxmlparser->parse_file($params{XSLFile});
  190.     $xsl_parsed = $XML::XSLT::Wrapper::libxsltprocessor->parse_stylesheet($parsed_stylesheet)   
  191.     }
  192.     return ($xml_parsed, $xsl_parsed);
  193. }
  194. END_OF_SUB
  195.     
  196. $_SUBS->{'XML::XSLT::Wrapper::libxslt'} = 
  197. <<'END_OF_SUB';
  198. sub libxslt {
  199.     my ($self, %params) = @_;
  200. #debug("In sub libxslt");
  201.  
  202.     my $parsed_params;
  203.     if (
  204.     (!defined($params{XSLParamHash}))
  205.     && (defined($params{XSLParams}))
  206.     )
  207.     {
  208.     $parsed_params = parse_params($params{XSLParams});
  209.     $params{XSLParamHash} = $parsed_params->[1];
  210.     }
  211.  
  212.     my $parser = $XML::XSLT::Wrapper::libxmlparser;
  213.     my $xslt = $XML::XSLT::Wrapper::libxsltprocessor;
  214.     my ($stylesheet, $source, $style_doc);
  215.     if (defined $params{XMLParsed}) {
  216.     $source = $params{XMLParsed};
  217.     } else {
  218.     if (defined($params{XMLFile})) {
  219.         $source = $parser->parse_file($params{XMLFile});
  220.     } elsif (defined($params{XMLString})) {
  221.         $source = $parser->parse_string($params{XMLString});
  222.     } elsif (defined $params{xml}) {
  223.         if ($params{xml} =~ /^\s*</) {
  224.         $source = $parser->parse_string($params{xml});
  225.         } elsif (-f $params{xml}) {
  226.         $source = $parser->parse_file($params{xml});
  227.         }
  228.     } else {
  229.         return undef;
  230.     }
  231.     }
  232.  
  233.     if (defined $params{XSLParsed}) {
  234.     $stylesheet = $params{XSLParsed};
  235.     } else {
  236.     if (defined($params{XSLFile})) {
  237.         $style_doc = $parser->parse_file($params{XSLFile});
  238.     } elsif (defined($params{XSLString})) {
  239.         $style_doc = $parser->parse_string($params{XSLString});
  240.     } elsif (defined $params{xsl}) {
  241.         if ($params{xsl} =~ /^\s*</) {
  242.         $style_doc = $parser->parse_string($params{xsl});
  243.         } elsif (-f $params{xsl}) {
  244.         $style_doc = $parser->parse_file($params{xsl});
  245.         }
  246.     } else {
  247.         return undef;
  248.     }
  249.     $stylesheet = $xslt->parse_stylesheet($style_doc);
  250.     }
  251.  
  252.     my $results = undef;
  253.     if (defined($params{XSLParamHash})) {
  254.     $results
  255.     = $stylesheet->transform($source, %{$params{XSLParamHash}});
  256.     } else {
  257.     $results = $stylesheet->transform($source);
  258.     }
  259.  
  260.     if (defined $params{out}) {
  261.     warn "DEPRECATED: The parameter 'out' has been renamed 'OutFile'; future
  262.     versions of the Wrapper will not work with 'out'\n";
  263.     $params{OutFile} = $params{out};
  264.     }
  265.     if ( defined($params{OutFile}) ) {
  266.     unlink $params{OutFile};
  267.     $stylesheet->output_file($results, $params{OutFile});
  268.     if (-f $params{OutFile}) {
  269.         return "";
  270.     } else {
  271.         return undef
  272.     }
  273.     } else {
  274.     my $ret_str = $stylesheet->output_string($results);
  275.     return $ret_str;
  276.     }
  277. }
  278. END_OF_SUB
  279.  
  280. $_SUBS->{'XML::XSLT::Wrapper::xalan_init'} = 
  281. <<'END_OF_SUB';
  282. sub xalan_init {
  283.     my ($self, %params) = @_;
  284. #debug("In sub xalan_init");
  285.     eval { require XML::Xalan::Transformer; };
  286.     if ($@) { return undef; }
  287.     use XML::Xalan::Transformer;
  288.     my $xalan;
  289.     eval { $xalan = XML::Xalan::Transformer->new(); };
  290.     if ($@) { return undef };
  291.     $XML::XSLT::Wrapper::xalanprocessor = $xalan;
  292.     return 1;
  293. }
  294. END_OF_SUB
  295.  
  296. $_SUBS->{'XML::XSLT::Wrapper::xalan'} = 
  297. <<'END_OF_SUB';
  298. sub xalan {
  299.     my ($self, %params) = @_;
  300. #debug("In sub xalan");
  301.     
  302.     my $xml = '';
  303.     my $xml_temp_file;
  304.     if (defined($params{XMLFile})) {
  305.     $xml = $params{XMLFile};
  306.     } elsif (defined($params{XMLString})) {
  307.     $xml = $self->file_from_string($params{XMLString});
  308.     $xml_temp_file = 1;
  309.     } elsif (defined $params{xml}) {
  310.     if ($params{xml} =~ /^\s*</) {
  311.         $xml = $self->file_from_string($params{xml});
  312.         $xml_temp_file = 1;
  313.     } elsif (-f $params{xml}) {
  314.         $xml = $params{xml};
  315.     } else {
  316.         return undef;
  317.     }
  318.     } else {
  319.     return undef;
  320.     }
  321.     
  322.     my $xsl = '';
  323.     my $xsl_temp_file;
  324.     if (defined($params{XSLFile})) {
  325.     $xsl = $params{XSLFile};
  326.     } elsif (defined($params{XSLString})) {
  327.     $xsl = $self->file_from_string($params{XSLString});
  328.     $xsl_temp_file = 1;
  329.     } elsif (defined $params{xsl}) {
  330.     if ($params{xsl} =~ /^\s*</) {
  331.         $xsl = $self->file_from_string($params{xsl});
  332.         $xsl_temp_file = 1;
  333.     } elsif (-f $params{xsl}) {
  334.         $xsl = $params{xsl};
  335.     } else {
  336.         return undef;
  337.     }
  338.     } else {
  339.     return undef;
  340.     }
  341.  
  342.     my $xalan = $XML::XSLT::Wrapper::xalanprocessor;
  343.  
  344.     my $result_str;
  345.     if (defined($params{OutFile})) {
  346.     unlink $params{OutFile};
  347.     eval $xalan->transform_to_file($xml, $xsl, $params{OutFile});
  348.     if ($@) {  return undef };
  349.     if (-f $params{OutFile}) { $result_str = ''; }
  350.     } else {
  351.     eval { $result_str = $xalan->transform_to_data($xml, $xsl); };
  352.     if ($@) {  return undef };
  353.     }
  354.     if ($xml_temp_file) { unlink $xml; }
  355.     if ($xsl_temp_file) { unlink $xsl }
  356.     return $result_str;
  357. }
  358. END_OF_SUB
  359.  
  360. $_SUBS->{'XML::XSLT::Wrapper::sablotron_init'} =
  361. <<'END_OF_SUB';
  362. sub sablotron_init {
  363.     my ($self, %params) = @_;
  364.     eval { require XML::Sablotron; };
  365.     if ($@) { return undef; }
  366.     use XML::Sablotron;
  367.     $XML::XSLT::Wrapper::sablotronprocessor = XML::Sablotron->new();
  368.     $XML::XSLT::Wrapper::sablotronprocessor->RegHandler(
  369.             0,
  370.             { MHError => \&myMHError,
  371.             MHMakeCode => \&myMHMakeCode,
  372.             MHLog => \&myMHLog
  373.         });
  374.  
  375.     sub myMHMakeCode {
  376.     my ($s, $processor, $severity, $facility, $code);
  377. #    return $code;
  378.     return 1;
  379.     }
  380.  
  381.     sub myMHLog {
  382.     my ($s, $processor, $code, $level, @fields);
  383.     #       print LOGHANDLE "[Sablot: $code]\n" .  (join "\n", @fields, "");
  384.     return 1;
  385.     }
  386.  
  387.     sub myMHError {
  388.     my ($s, $processor, $code, $level, @fields) = @_;
  389. #    my $mess = "[Sablot: $code]\n" .  (join "\n", @fields, "");
  390.     return 1;
  391.     }
  392.  
  393.     return 1;
  394. }
  395. END_OF_SUB
  396.  
  397. $_SUBS->{'XML::XSLT::Wrapper::sablotron'} =
  398. <<'END_OF_SUB';
  399. sub sablotron {
  400.     my ($self, %params) = @_;
  401. $|=1;
  402. #debug("In sub sablotron");
  403.  
  404.     my $parsed_params;
  405.     if (
  406.     (!defined($params{XSLParamHash}))
  407.     && (defined($params{XSLParams}))
  408.     )
  409.     {
  410.     $parsed_params = parse_params($params{XSLParams});
  411.     $params{XSLParamArray} = $parsed_params->[2];
  412.     }
  413.     my $xsl_params_ref = $params{XSLParamArray};
  414.  
  415.     my ($xml_str, $xml_file);
  416.     if (defined($params{XMLFile})) {
  417.     $xml_file = $params{XMLFile};
  418.     } elsif (defined($params{XMLString})) {
  419.     $xml_str = $params{XMLString};
  420.     } elsif (defined $params{xml}) {
  421.     if ($params{xml} =~ /^\s*</) {
  422.         $xml_str = $params{xml};
  423.     } elsif (-f $params{xml}) {
  424.         $xml_file = $params{xml};
  425.     }
  426.     } else {
  427.     return undef;
  428.     }
  429.  
  430.     my ($xsl_str, $xsl_file);
  431.     if (defined($params{XSLFile})) {
  432.     $xsl_file = $params{XSLFile};
  433.     } elsif (defined($params{XSLString})) {
  434.     $xsl_str = $params{XSLString};
  435.     } elsif (defined $params{xsl}) {
  436.     if ($params{xsl} =~ /^\s*</) {
  437.         $xsl_str = $params{xsl};
  438.     } elsif (-f $params{xsl}) {
  439.         $xsl_file = $params{xsl};
  440.     }
  441.     } else {
  442.     return undef;
  443.     }
  444.  
  445.     my $sab = $XML::XSLT::Wrapper::sablotronprocessor;
  446.  
  447.     my $out_arg = "arg:/res";
  448.     if (defined $params{out}) {
  449.     warn "DEPRECATED: The parameter 'out' has been renamed 'OutFile'; future
  450.     versions of the Wrapper will not work with 'out'\n";
  451.     $params{OutFile} = $params{out};
  452.     }
  453.     if (defined $params{OutFile}) {
  454.     $out_arg = $params{OutFile};
  455.     unlink $params{OutFile};
  456.     }
  457.  
  458.     my $xsl_arg = "arg:/xsl_str";
  459.     my $xsl_arg_name = "xsl_str";
  460.     my $xsl_arg_val = $xsl_str;
  461.     if (defined $xsl_file) {
  462.     $xsl_arg = $xsl_file;
  463.     $xsl_arg_name = "xsl_file";
  464.     $xsl_arg_val = $xsl_file;
  465.     }
  466.     my $xml_arg = "arg:/xml_str";
  467.     my $xml_arg_name = "xml_str";
  468.     my $xml_arg_val = $xml_str;
  469.     if (defined $xml_file) {
  470.     $xml_arg = $xml_file;
  471.     $xml_arg_name = "xml_file";
  472.     $xml_arg_val = $xml_file;
  473.     }
  474.  
  475.     my $result_code;
  476.  
  477. eval {
  478.     $result_code = 
  479.     $sab->RunProcessor(
  480.         $xsl_arg, 
  481.         $xml_arg, 
  482.         $out_arg, 
  483.         $xsl_params_ref,
  484.         [$xsl_arg_name, $xsl_arg_val, 
  485.         $xml_arg_name, $xml_arg_val]
  486.         ); 
  487.     };
  488.     if ( ($@) || ($?) ){
  489.     return undef;
  490.     }
  491.  
  492.     $sab->ClearError();
  493.     my $result_str;
  494.     if (defined $params{OutFile}) {
  495.     $sab->FreeResultArgs();
  496.     if (-f $params{OutFile}) {
  497.         return '';
  498.     } else {
  499.         return undef;
  500.     }
  501.     } else {
  502.     eval { $result_str = $sab->GetResultArg("res"); };
  503.     if ($@) {
  504.         return undef;
  505.     }
  506.     $sab->FreeResultArgs();
  507.     }
  508.     return $result_str;
  509. }
  510. END_OF_SUB
  511.  
  512. $_SUBS->{'XML::XSLT::Wrapper::xslt_init'} =
  513. <<'END_OF_SUB';
  514. sub xslt_init {
  515.     eval { require XML::XSLT; };
  516.     if ($@) {
  517.     return undef;
  518.     }
  519.     return 1;
  520. }
  521. END_OF_SUB
  522.  
  523. $_SUBS->{'XML::XSLT::Wrapper::xslt'} =
  524. <<'END_OF_SUB';
  525. sub xslt {
  526.     my ($self, %params) = @_;
  527. #debug("In sub xslt");
  528.     my $xml = "";
  529.     my $xml_temp_file;
  530.     if (defined($params{XMLFile})) {
  531.     $xml = $params{XMLFile};
  532.     } elsif (defined($params{XMLString})) {
  533.     $xml = $self->file_from_string($params{XMLString});
  534.     $xml_temp_file = 1;
  535.     } elsif (defined $params{xml}) {
  536.     if ($params{xml} =~ /^\s*</) {
  537.         $xml = $self->file_from_string($params{xml});
  538.         $xml_temp_file = 1;
  539.     } elsif (-f $params{xml}) {
  540.         $xml = $params{xml};
  541.     }
  542.     } else {
  543.     return undef;
  544.     }
  545.  
  546.     my $xsl = "";
  547.     my $xsl_temp_file;
  548.     if (defined($params{XSLFile})) {
  549.     $xsl = $params{XSLFile};
  550.     } elsif (defined($params{XSLString})) {
  551.     $xsl = $self->file_from_string($params{XSLString});
  552.     $xsl_temp_file = 1;
  553.     } elsif (defined $params{xsl}) {
  554.     if ($params{xsl} =~ /^\s*</) {
  555.         $xsl = $self->file_from_string($params{xsl});
  556.         $xsl_temp_file = 1;
  557.     } elsif (-f $params{xsl}) {
  558.         $xsl = $params{xsl};
  559.     }
  560.     } else {
  561.     return undef;
  562.     }
  563.  
  564.     if (defined $params{out}) {
  565.     warn "DEPRECATED: The parameter 'out' has been renamed 'OutFile'; future
  566.     versions of the Wrapper will not work with 'out'\n";
  567.     $params{OutFile} = $params{out};
  568.     }
  569.     if (defined $params{OutFile}) { unlink $params{OutFile}; }
  570.  
  571.     my $xslt = XML::XSLT->new($xsl);
  572.     my $result_str;
  573.     eval { $result_str = $xslt->serve($xml); };
  574.     if ($@) {
  575.     return undef;
  576.     }
  577.     if ($xml_temp_file) { unlink $xml; }
  578.     if ($xsl_temp_file) { unlink $xsl }
  579.     if (defined $params{OutFile}) {
  580.     open F, ">$params{OutFile}";
  581.     print F $result_str;
  582.     close F;
  583.     if (-f $params{OutFile}) {
  584.         return '';
  585.     } else {
  586.         return undef;
  587.     }
  588.     }
  589.     return $result_str;
  590. }
  591. END_OF_SUB
  592.  
  593. $_SUBS->{'XML::XSLT::Wrapper::xt_init'} =
  594. <<'END_OF_SUB';
  595. sub xt_init {
  596.     my ($self, %params) = @_;
  597.     my $classpath = $self->{'JavaClassPath'} || $ENV{'CLASSPATH'} || '';
  598.     if (
  599.     ($classpath =~ /xt\.jar/)
  600.     && ($classpath =~ /xp\.jar/)
  601.     && ($classpath =~ /sax\.jar/)
  602.     )
  603.     { return 1 }
  604.     return undef;
  605. }
  606. END_OF_SUB
  607.  
  608. $_SUBS->{'XML::XSLT::Wrapper::xt'} =
  609. <<'END_OF_SUB';
  610. sub xt {
  611.     my ($self, %params) = @_;
  612. #debug("In sub xt");
  613.     my $parsed_params;
  614.     if (
  615.     (!defined($params{XSLParamString}))
  616.     && (defined($params{XSLParams}))
  617.     )
  618.     {
  619.     $parsed_params = parse_params($params{XSLParams});
  620.     $params{XSLParamString} = $parsed_params->[0];
  621.     }
  622.  
  623.     my ($xml_str, $xml_file);
  624.     my $xml_temp_file;
  625.     if (defined($params{XMLFile})) {
  626.     $xml_file = $params{XMLFile};
  627.     } elsif (defined($params{XMLString})) {
  628.     $xml_file = $self->file_from_string($params{XMLString});
  629.     $xml_temp_file = 1;
  630.     } elsif (defined $params{xml}) {
  631.     if ($params{xml} =~ /^\s*</) {
  632.         $xml_file = $self->file_from_string($params{xml});
  633.         $xml_temp_file = 1;
  634.     } elsif (-f $params{xml}) {
  635.         $xml_file = $params{xml};
  636.     }
  637.     } else {
  638.     return undef;
  639.     }
  640.  
  641.     my ($xsl_str, $xsl_file);
  642.     my $xsl_temp_file;
  643.     if (defined($params{XSLFile})) {
  644.     $xsl_file = $params{XSLFile};
  645.     } elsif (defined($params{XSLString})) {
  646.     $xsl_file = $self->file_from_string($params{XSLString});
  647.     $xsl_temp_file = 1;
  648.     } elsif (defined $params{xsl}) {
  649.     if ($params{xsl} =~ /^\s*</) {
  650.         $xsl_file = $self->file_from_string($params{xsl});
  651.         $xsl_temp_file = 1;
  652.     } elsif (-f $params{xsl}) {
  653.         $xsl_file = $params{xsl};
  654.     }
  655.     } else {
  656.     return undef;
  657.     }
  658.  
  659.     my $out_file;
  660.     if (defined $params{out}) {
  661.     warn "DEPRECATED: The parameter 'out' has been renamed 'OutFile'; future
  662.     versions of the Wrapper will not work with 'out'\n";
  663.     $params{OutFile} = $params{out};
  664.     }
  665.     if (defined $params{OutFile})
  666.     {
  667.         unlink $out_file;
  668.         $out_file = $params{OutFile};
  669.     } else {
  670.         $out_file = '';
  671.     }
  672.  
  673.     my $xsl_params = $params{XSLParamString} || "";
  674.     my $java_bin = $self->{JavaBin} || "java";
  675.     my $classpath = $ENV{CLASSPATH} || "";
  676.     $classpath = $self->{JavaClassPath} || $classpath;
  677.     $classpath = " -classpath " . $classpath;
  678.     my $java_command = "-Dcom.jclark.xsl.sax.parser=com.jclark.xml.sax.CommentDriver com.jclark.xsl.sax.Driver";
  679.     $java_command = $self->{'JavaCommand'} || $java_command;
  680.  
  681.     my $call = "$java_bin $classpath $java_command $xml_file $xsl_file $out_file $xsl_params";
  682. #debug($call);
  683.     my $result_str = undef;
  684.     $result_str = qx($call);
  685.     if ($?) { return undef; }
  686.     if (defined $params{OutFile}) {
  687.     if (-f $params{OutFile}) {
  688.         return '';
  689.     } else {
  690.         return undef;
  691.     }
  692.     }
  693.     if ($xml_temp_file) { unlink $xml_file; }
  694.     if ($xsl_temp_file) { unlink $xsl_file }
  695.     if ($result_str eq '') { return undef; }
  696.     return $result_str;
  697. } # sub xt
  698. END_OF_SUB
  699.  
  700. $_SUBS->{'XML::XSLT::Wrapper::saxon_init'} =
  701. <<'END_OF_SUB';
  702. sub saxon_init {
  703.     my ($self, %params) = @_;
  704.     my $classpath = $self->{'JavaClassPath'} || $ENV{'CLASSPATH'} || '';
  705.     if ($classpath =~ /saxon\.jar/) { return 1 }
  706.     return undef;
  707. }
  708. END_OF_SUB
  709.  
  710. $_SUBS->{'XML::XSLT::Wrapper::saxon'} =
  711. <<'END_OF_SUB';
  712. sub saxon {
  713. #debug("In sub saxon");
  714.     my ($self, %params) = @_;
  715.     my $parsed_params;
  716.     if (
  717.     (!defined($params{XSLParamString}))
  718.     && (defined($params{XSLParams}))
  719.     )
  720.     {
  721.     $parsed_params = parse_params($params{XSLParams});
  722.     $params{XSLParamString} = $parsed_params->[0];
  723.     }
  724.  
  725.     my ($xml_str, $xml_file);
  726.     my $xml_temp_file;
  727.     if (defined($params{XMLFile})) {
  728.     $xml_file = $params{XMLFile};
  729.     } elsif (defined($params{XMLString})) {
  730.     $xml_file = $self->file_from_string($params{XMLString});
  731.     $xml_temp_file = 1;
  732.     } elsif (defined $params{xml}) {
  733.     if ($params{xml} =~ /^\s*</) {
  734.         $xml_file = $self->file_from_string($params{xml});
  735.         $xml_temp_file = 1;
  736.     } elsif (-f $params{xml}) {
  737.         $xml_file = $params{xml};
  738.     }
  739.     } else {
  740.     return undef;
  741.     }
  742.  
  743.     my ($xsl_str, $xsl_file);
  744.     my $xsl_temp_file;
  745.     if (defined($params{XSLFile})) {
  746.     $xsl_file = $params{XSLFile};
  747.     } elsif (defined($params{XSLString})) {
  748.     $xsl_file = $self->file_from_string($params{XSLString});
  749.     $xsl_temp_file = 1;
  750.     } elsif (defined $params{xsl}) {
  751.     if ($params{xsl} =~ /^\s*</) {
  752.         $xsl_file = $self->file_from_string($params{xsl});
  753.         $xsl_temp_file = 1;
  754.     } elsif (-f $params{xsl}) {
  755.         $xsl_file = $params{xsl};
  756.     }
  757.     } else {
  758.     return undef;
  759.     }
  760.  
  761.     my $xsl_params = $params{XSLParamString} || '';
  762.     my $java_bin = $self->{JavaBin} || "java";
  763.     my $out_file;
  764.     if (defined $params{out}) {
  765.     warn "DEPRECATED: The parameter 'out' has been renamed 'OutFile'; future
  766.     versions of the Wrapper will not work with 'out'\n";
  767.     $params{OutFile} = $params{out};
  768.     }
  769.     if (defined $params{OutFile}) { $out_file = $params{OutFile}; }
  770.     if (defined $out_file)
  771.     {
  772.         unlink $out_file;
  773.         $out_file = ' -o ' . $out_file;
  774.     } else {
  775.         $out_file = '';
  776.     }
  777.  
  778.     my $classpath = $ENV{CLASSPATH} || '';
  779.     $classpath = $self->{JavaClassPath} || $classpath;
  780.     $classpath = " -classpath " . $classpath;
  781. $xsl_params =~ s/\n/ /g;
  782. #debug($xsl_params);
  783.     my $java_args = $self->{JavaArgs} || "";
  784.     my $java_command = $self->{JavaCommand} || "com.icl.saxon.StyleSheet";
  785.     my $call = "$java_bin $java_args $classpath $java_command $out_file $xml_file $xsl_file $xsl_params";
  786. #debug($call);
  787.     my $result_str = undef;
  788.     eval { $result_str = qx($call); };
  789.     if ($?) { return undef; }
  790.     if (defined $params{OutFile}) {
  791.     if (-f $params{OutFile}) {
  792.         return '';
  793.     } else {
  794.         return undef;
  795.     }
  796.     }
  797.     if ($xml_temp_file) { unlink $xml_file; }
  798.     if ($xsl_temp_file) { unlink $xsl_file; }
  799.     if ($result_str eq '') { return undef; }
  800.     return $result_str;
  801. }
  802. END_OF_SUB
  803.  
  804. $_SUBS->{'XML::XSLT::Wrapper::file_from_string'} =
  805. <<'END_OF_SUB';
  806. sub file_from_string {
  807.     my ($self, $xml_string) = @_;
  808. #debug($xml_string);
  809.     use POSIX;
  810.     my $fn;
  811.     do {
  812.     $fn = tmpnam();
  813.     } until sysopen(TMP,$fn,O_WRONLY|O_CREAT|O_EXCL,0600);
  814.     print TMP $xml_string;
  815.     close TMP;
  816.     return $fn;
  817. }
  818. END_OF_SUB
  819.  
  820. 1;
  821. __END__
  822.  
  823. =head1 NAME
  824.  
  825. XML::XSLT::Wrapper - Consistent interface to XSLT processors
  826.  
  827. =head1 SYNOPSIS
  828.  
  829.     use XML::XSLT::Wrapper;
  830.     my $xslt = XML::XSLT::Wrapper->new(
  831.         ProcessorList => ['libxslt', 'sablotron'],
  832.         )
  833.  
  834.     $result = $xslt->transform(
  835.         XMLFile => $xml_filename
  836.         XSLFile => $xsl_filename
  837. #OR:        XMLString => $xml_string
  838. #OR:        XSLString => $xsl_string
  839. #OR:        xml => $xml_filename_or_string,
  840. #OR:        xsl => $xsl_filename_or_string,
  841.         XSLParams => { 'COMEIN' => 'knock knock',
  842.                 'GOAWAY' => 'conk conk' },
  843.         );
  844.  
  845.     $result = $xslt->transform(
  846.         OutFile => $output_filename,
  847.         XMLFile => $xml_filename
  848.         XSLFile => $xsl_filename
  849.         XSLParams => [ 'COMEIN', 'knock knock',
  850.                 'GOAWAY', 'conk conk' ],
  851.         );
  852.  
  853.  
  854.     # NB: The pre_parsing interface is likely to change:
  855.     %pre_parsed = $xslt->pre_parse(
  856.         XSLFile => $xsl_filename
  857.         );
  858.     $pre_parsed{$processor}{'xsl'} = $parsed_xsl;
  859.  
  860.     foreach (@xml_files) {
  861.     $result = $xslt->transform(
  862.             XSLParsed = $parsed_xsl;
  863.             OutFile => $output_filename,
  864.             XMLFile => $_,
  865.             XSLParams => [ 'COMEIN', 'knock knock',
  866.                     'GOAWAY', 'conk conk' ],
  867.         );
  868.     }
  869.  
  870. See also examples/*.pl, t/*.t and Driver/*.pm in the distribution directory.
  871.  
  872. =head1 DESCRIPTION
  873.  
  874. Provides a consistent interface to various XSLT processors.  Tries each
  875. of a supplied list of processors in turn until one performs a successful
  876. transform. If no list is given, tries all the processors it knows until
  877. one works. Does its best to fail gracefully whenever a processor does
  878. not work for some reason.
  879.  
  880. Can return the result of the transform as a string, or write it to a
  881. specified file.
  882.  
  883. For those processors which can accept parameters to an XSLT stylesheet,
  884. XML::XSLT::Wrapper can accept these as hash of name-value pairs, or as
  885. an array of [name, value, name, value, ...]
  886.  
  887. On completion, returns:
  888.     - '' if it has written an output file
  889.     - the result string if it has succeeded but not written an output file
  890.     - undef if it has failed
  891.  
  892. Currently knows how to use XML::LibXSLT, XML::Xalan, XML::Sablotron,
  893. XML::XSLT as well as the Java processors XT and Saxon. You need to set
  894. your CLASSPATH environment variable first for the Java processors, or
  895. pass it to the transform in a JavaClassPath hash element.  In a future
  896. version, there will be a parameter to turn off support for the Java
  897. processors. The XML::Sablotron I've tested with is 0.52.
  898.  
  899. =head1 METHODS
  900.  
  901. new - The constructor for XML::XSLT::Wrapper. Options are passed as
  902. keyword value pairs. Recognized options are:
  903.  
  904.     - ProcessorList - A list of Processor names, any of:
  905.  
  906.     libxslt sablotron xalan xslt xt saxon
  907.  
  908.     The Wrapper will try each processor in turn, in the order given
  909.     in the list. The names are matched case-insensitively, so
  910.     LibXSLT will achieve the same as libxslt, etc.
  911.  
  912.     If this option is not supplied, the Wrapper will attempt each of
  913.     these processors in turn.
  914.  
  915.     - Debug - if defined, turns on some debugging output.
  916.  
  917. transform - Processes the specified XML using the specified XSL stylesheet. Either or both of the XML and XSL can be given as filenames or strings. Options are passed as keyword value pairs. Recognized options are:
  918.  
  919.     - XMLFile - The name of the XML file to process
  920.  
  921.     - XSLFile - The name of the XSL file to use in processing the
  922.       XML
  923.  
  924.     - XMLString - A string containing the XML to process
  925.  
  926.     - XSLString - A string containing the XSLT Stylesheet to use in
  927.       processing the XML
  928.  
  929.     - XMLParsed - A reference to a pre-parsed version of the XSL
  930.       stylesheet to be used in processing the XML. Use of this is
  931.       not sensible unless you specified just a single processor.
  932.  
  933.     - XSLParsed - A reference to a pre-parsed version of the XML to
  934.       process. Use of this is not sensible unless you specified just
  935.       a single processor.
  936.  
  937.     - OutFile - the name of a file to which the result of the
  938.       transformation should be written. The file will be created if
  939.       it does not exist, and will be replaced if it does.
  940.  
  941.     - xml - Either the name of the XML file to process or a string
  942.       containing the XML to process. The Wrapper will detect which
  943.       it is.
  944.  
  945.     - xsl - Either the name of the XSL file to use in processing the
  946.       XML or a string containing the XSLT Stylesheet to use in
  947.       processing the XML. The Wrapper will detect which it is.
  948.  
  949.     - out - DEPRECATED: replaced by OutFile, and will disappear in
  950.       time. Has exactly the same meaning and usage as OutFile.
  951.  
  952.     - XSLParams - Either a hash of name-value pairs or an array of
  953.       [name, value, name, value, ...]. These will be passed as
  954.       parameters to the XSL Stylesheet.
  955.  
  956. pre_parse - WARNING: While any part of the Wrapper may change, this
  957. method is particularly likely to. Takes XMLFile and/or XSLFile
  958. parameters, and returns a hash with two key-value pairs:
  959.     $pre_parsed{$processor}{'xml'} = $parsed_xml;
  960.     $pre_parsed{$processor}{'xsl'} = $parsed_xsl;
  961.     where $processor is the
  962. lower-cased name of a processor know to XML::XSLT::Wrapper
  963.  
  964. =head1 BUGS
  965.  
  966. This is still an early version, and subject to change.
  967.  
  968. Does not recover gracefully when XML::Sablotron dumps core on
  969. XSLTMark tests.
  970.  
  971. (?) The check on whether the classpath contains the necessary Java
  972. programs may be a bit iffy. Suggestions on how to improve it welcome.
  973.  
  974. The tests ("make test") are not at all comprehensive
  975.  
  976. =head1 AUTHOR
  977.  
  978. Colin Muller, colin@durbanet.co.za
  979.  
  980. Copyright (C) 2001, Colin Muller, colin@durbanet.co.za
  981. This module may be used, distributed and modified
  982. under the same terms as Perl itself
  983.  
  984. =head1 CONTRIBUTORS
  985.  
  986. Saxon support and various ideas contributed by Steve Tinney,
  987. stinney@sas.upenn.edu.
  988.  
  989. =head1 SEE ALSO
  990.  
  991. XML::LibXSLT, XML::Xalan, XML::Sablotron, XML::XSLT.
  992.  
  993. =cut
  994.