package XML::XPathScript; use strict; use warnings; use Carp; # $Revision: 1012 $ - $Date: 2007-07-06T12:37:51.503257Z $ =pod =head1 NAME XML::XPathScript - a Perl framework for XML stylesheets =head1 SYNOPSIS use XML::XPathScript; # the short way my $xps = XML::XPathScript->new; my $transformed = $xps->transform( $xml, $stylesheet ); # having the output piped to STDOUT directly my $xps = XML::XPathScript->new( xml => $xml, stylesheet => $stylesheet ); $xps->process; # caching the compiled stylesheet for reuse and # outputting to multiple files my $xps = XML::XPathScript->new( stylesheetfile => $filename ) foreach my $xml (@xmlfiles) { my $transformed = $xps->transform( $xml ); # do stuff with $transformed ... }; # Making extra variables available to the stylesheet dialect: my $xps = XML::XPathScript->new; $xps->compile( qw/ $foo $bar / ); # in stylesheet, $foo will be set to 'a' # and $bar to 'b' $xps->transform( $xml, $stylesheet, [ 'a', 'b' ] ); =head1 DESCRIPTION XPathScript is a stylesheet language similar in many ways to XSLT (in concept, not in appearance), for transforming XML from one format to another (possibly HTML, but XPathScript also shines for non-XML-like output). Like XSLT, XPathScript offers a dialect to mix verbatim portions of documents and code. Also like XSLT, it leverages the powerful ``templates/apply-templates'' and ``cascading stylesheets'' design patterns, that greatly simplify the design of stylesheets for programmers. The availability of the I query language inside stylesheets promotes the use of a purely document-dependent, side-effect-free coding style. But unlike XSLT which uses its own dedicated control language with an XML-compliant syntax, XPathScript uses Perl which is terse and highly extendable. The result of the merge is an extremely powerful tool for rendering complex XML documents into other formats. Stylesheets written in XPathScript are very easy to create, extend and reuse, even if they manage hundreds of different XML tags. =head1 STYLESHEET WRITER DOCUMENTATION If you are interested to write stylesheets, refers to the B manpage. You might also want to take a peek at the manpage of B, a program bundled with this module to perform XPathScript transformations via the command line. =head1 STYLESHEET UTILITY METHODS Those methods are meants to be used from within a stylesheet. =head2 current $xps = XML::XPathScript->current This class method returns the stylesheet object currently being applied. This can be called from anywhere within the stylesheet, except a BEGIN or END block or similar. B that using the return value for altering (as opposed to reading) stuff from anywhere except the stylesheet's top level is unwise. =cut sub current { croak 'Wrong context for calling current()' unless defined $XML::XPathScript::current; return $XML::XPathScript::current; } =head2 interpolation $interpolate = $XML::XPathScript::current->interpolation $interpolate = $XML::XPathScript::current->interpolation( $boolean ) Gets (first call form) or sets (second form) the XPath interpolation boolean flag. If true, values set in C< pre > and C< post > may contain expressions within curly braces, that will be interpreted as XPath expressions and substituted in place. For example, when interpolation is on, the following code $template->set( link => { pre => '', post => '' } ); is enough for rendering a C<< >> element as an HTML hyperlink. The interpolation-less version is slightly more complex as it requires a C: sub link_testcode { my ($node, $t) = @_; my $url = $node->findvalue('@url'); $t->set({ pre => "", post => "" }); return DO_SELF_AND_KIDS(); }; Interpolation is on by default. =cut sub interpolation { my $self = shift; return $self->interpolating( @_ ); } sub interpolating { my $self=shift; if ( @_ ) { $self->processor->set_interpolation( $self->{interpolating} = shift ); } return $self->{interpolating} || 0; } =head2 interpolation_regex $regex = $XML::XPathScript::current->interpolation_regex $XML::XPathScript::current->interpolation_regex( $regex ) Gets or sets the regex to use for interpolation. The value to be interpolated must be capture by $1. By default, the interpolation regex is qr/{(.*?)}/. Example: $XML::XPathScript::current->interpolation_regex( qr#\|(.*?)\|# ); $template->set( bird => { pre => '|@name| |@gender| |@type|' } ); =cut sub interpolation_regex { my $self = shift; if ( my $regex = shift ) { $self->processor->set_interpolation_regex( $self->{interpolation_regex} = $regex ) } return $self->{interpolation_regex}; } =head2 binmode Declares that the stylesheet output is B in UTF-8, but instead in an (unspecified) character encoding embedded in the stylesheet source that neither Perl nor XPathScript should have any business dealing with. Calling C<< XML::XPathScript->current()->binmode() >> is an B operation with the consequences outlined in L. =cut " sub binmode { my ($self)=@_; $self->{binmode}=1; $self->{processor}->enable_binmode; binmode ORIGINAL_STDOUT if (! defined $self->{printer}); return; } =pod " =head1 TECHNICAL DOCUMENTATION The rest of this POD documentation is B useful to programmers who just want to write stylesheets; it is of use only to people wanting to call existing stylesheets or more generally embed the XPathScript engine into some wider framework. I is an object-oriented class with the following features: =over =item * an I that allows the merging of the stylesheet code with snippets of the output document. Don't be afraid, this is exactly the same kind of stuff as in I, I or other similar packages: instead of having text inside Perl (that one Is), we have Perl inside text, with a special escaping form that a preprocessor interprets and extracts. For XPathScript, this preprocessor is embodied by the I shell tool (see L) and also available through this package's API; =item * a I, that does the apply-templates loop, starting from the top XML node and applying templates to it and its subnodes as directed by the stylesheet. =back When run, the stylesheet is expected to fill in the I