Commit 163ca68f authored by gregor herrmann's avatar gregor herrmann

New upstream release.

parent 277af447
Revision history for Perl extension XML::LibXSLT.
1.62pre
1.66pre
- bump requirements to libxslt 1.1.8
- sync the binary internals to those of XML::LibXML 1.66
1.63
- fix SIGSEGV regarding freeing nodes created by extension functions
(reported by Elizabeth Mattijsen)
- use pkg-config to determine linker flags for libexslt
1.62
- security callback interface contributed by Shane Corgatelli
- check libxslt version
- added XML::LibXML-like API to retrieve libxslt version
......
# $Id: LibXSLT.pm 192 2006-11-17 21:01:06Z pajas $
# $Id: LibXSLT.pm 205 2008-01-29 21:02:48Z pajas $
package XML::LibXSLT;
use strict;
use vars qw($VERSION @ISA $USE_LIBXML_DATA_TYPES $MatchCB $ReadCB $OpenCB $CloseCB);
use XML::LibXML 1.60;
use XML::LibXML 1.66;
use XML::LibXML::Literal;
use XML::LibXML::Boolean;
use XML::LibXML::Number;
use XML::LibXML::NodeList;
BEGIN {
use Carp;
require Exporter;
$VERSION = "1.62";
$VERSION = "1.66";
require DynaLoader;
......@@ -22,7 +23,11 @@ require DynaLoader;
bootstrap XML::LibXSLT $VERSION;
# the following magic lets XML::LibXSLT internals know
# where to register XML::LibXML proxy nodes
__lib_init_proxy_registry(XML::LibXML::__proxy_registry());
$USE_LIBXML_DATA_TYPES = 0;
}
sub new {
my $class = shift;
......@@ -930,19 +935,19 @@ runtime version of the library is less then the compile-time version.
=item XML::LibXSLT::LIBXSLT_VERSION()
Returns version number of libxslt library which was used to compile
XML::LibXSLT as an integer. For example, for libxslt-1.1.15, it will
return 10115.
XML::LibXSLT as an integer. For example, for libxslt-1.1.18, it will
return 10118.
=item XML::LibXSLT::LIBXSLT_DOTTED_VERSION()
Returns version number of libxslt library which was used to compile
XML::LibXSLT as a string, e.g. "1.1.15".
XML::LibXSLT as a string, e.g. "1.1.18".
=item XML::LibXSLT::LIBXSLT_RUNTIME_VERSION()
Returns version number of libxslt library to which XML::LibXSLT is
linked at runtime (either dynamically or statically). For example, for
example, for libxslt.so.1.1.15, it will return 10115.
example, for libxslt.so.1.1.18, it will return 10118.
=back
......@@ -952,7 +957,17 @@ Matt Sergeant, matt@sergeant.org
Security callbacks implementation contributed by Shane Corgatelli.
Copyright 2001-2006, AxKit.com Ltd. All rights reserved.
Copyright 2001-2008, AxKit.com Ltd. All rights reserved.
=head1 MAINTAINER
Petr Pajas , pajas@matfyz.org
=head1 BUGS
Please report bugs via
http://rt.cpan.org/NoAuth/Bugs.html?Dist=XML-LibXSLT
=head1 SEE ALSO
......
/* $Id: LibXSLT.xs 191 2006-11-17 18:27:58Z pajas $ */
/* $Id: LibXSLT.xs 205 2008-01-29 21:02:48Z pajas $ */
#ifdef __cplusplus
extern "C" {
......@@ -54,6 +54,8 @@ extern "C" {
static SV * LibXSLT_debug_cb = NULL;
static HV * LibXSLT_HV_allCallbacks = NULL;
ProxyNodePtr* PROXY_NODE_REGISTRY_PTR = NULL;
void
LibXSLT_free_all_callbacks(void)
......@@ -224,18 +226,19 @@ LibXSLT_generic_function (xmlXPathParserContextPtr ctxt, int nargs) {
int i;
STRLEN len;
SV * perl_result;
ProxyNodePtr owner = NULL;
char * tmp_string;
STRLEN n_a;
double tmp_double;
int tmp_int;
AV * array_result;
xmlNodePtr tmp_node, tmp_node1;
xmlNodePtr tmp_node, tmp_node1, tmp_node2;
SV *key;
char *strkey;
const char *function, *uri;
SV **perl_function;
AV *arguments;
xmlDocPtr container;
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
dSP;
function = (const char *) ctxt->context->function;
......@@ -274,11 +277,6 @@ LibXSLT_generic_function (xmlXPathParserContextPtr ctxt, int nargs) {
len = nodelist->nodeNr;
for( ; i < len; i++ ){
tnode = nodelist->nodeTab[i];
/*
if( tnode != NULL && tnode->doc != NULL) {
owner = SvPROXYNODE(sv_2mortal(x_PmmNodeToSv((xmlNodePtr)(tnode->doc), NULL)));
}
*/
if (tnode->type == XML_NAMESPACE_DECL) {
element = sv_newmortal();
cls = x_PmmNodeTypeName( tnode );
......@@ -286,11 +284,10 @@ LibXSLT_generic_function (xmlXPathParserContextPtr ctxt, int nargs) {
(const char *)cls,
(void *)xmlCopyNamespace((xmlNsPtr)tnode)
);
}
else {
} else {
/* need to copy the node as libxml2 will free it */
xmlNodePtr tnode_cpy = xmlCopyNode(tnode, 1);
element = x_PmmNodeToSv(tnode_cpy, owner);
element = x_PmmNodeToSv(tnode_cpy, NULL);
}
XPUSHs( sv_2mortal(element) );
}
......@@ -345,44 +342,62 @@ LibXSLT_generic_function (xmlXPathParserContextPtr ctxt, int nargs) {
SvTYPE(SvRV(perl_result)) == SVt_PVAV))
{
if (sv_derived_from(perl_result, "XML::LibXML::NodeList")) {
if (tctxt == NULL) {
croak("LibXSLT: perl-dispatcher: internal error tctxt == NULL\n");
}
container = xsltCreateRVT(tctxt);
if (container == NULL) {
croak("LibXSLT: perl-dispatcher: cannot create container RVT\n");
}
xsltRegisterLocalRVT(tctxt,container);
ret = xmlXPathNewNodeSet(NULL);
ret->boolval = 1; /* free children */
ret->boolval = 0;
array_result = (AV*)SvRV(perl_result);
while (av_len(array_result) >= 0) {
tmp_node1 = (xmlNodePtr)x_PmmSvNode(sv_2mortal(av_shift(array_result)));
tmp_node = xmlDocCopyNode(tmp_node1, ctxt->context->doc, 1);
xmlXPathNodeSetAdd(ret->nodesetval, tmp_node);
/*
* this seems unnecessary with recent libxslt versions
*
if (ret->user == NULL) {
ret->user = (void*)tmp_node;
}
*
* this even causes segmentation faults:
*
else {
xmlNodePtr old = (xmlNodePtr)(ret->user);
old->prev = tmp_node;
tmp_node->next = old;
ret->user = (void*)tmp_node;
}
*/
tmp_node1 = (xmlNodePtr)x_PmmSvNode(sv_2mortal(av_shift(array_result)));
if (tmp_node1) {
if (ctxt->context->doc == tmp_node1->doc) {
/* special case: no copy */
xmlXPathNodeSetAdd(ret->nodesetval, tmp_node1);
} else {
tmp_node = xmlDocCopyNode(tmp_node1, container, 1);
/* a wraper element is needed to prevent libxml2 from merging adjacent text nodes */
tmp_node2 = xmlNewDocNode(container,NULL,"x",NULL);
xmlAddChild((xmlNodePtr)container,tmp_node2);
xmlAddChild(tmp_node2,tmp_node);
xmlXPathNodeSetAdd(ret->nodesetval, tmp_node);
}
} else {
croak("LibXSLT: perl-dispatcher returned nodelist with non-node elements\n");
}
}
goto FINISH;
}
else if (sv_derived_from(perl_result, "XML::LibXML::Node")) {
ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
ret->boolval = 1; /* free children */
tmp_node1 = (xmlNodePtr)x_PmmSvNode(perl_result);
tmp_node = xmlDocCopyNode(tmp_node1, ctxt->context->doc, 1);
xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
/*
* this seems unnecessary with recent libxslt versions
*
ret->user = (void*)tmp_node;
*/
goto FINISH;
tmp_node1 = (xmlNodePtr)x_PmmSvNode(perl_result);
ret = (xmlXPathObjectPtr)xmlXPathNewNodeSet(NULL);
ret->boolval = 0;
if (tmp_node1) {
if (ctxt->context->doc == tmp_node1->doc) {
/* special case: no copy */
xmlXPathNodeSetAdd(ret->nodesetval, tmp_node1);
} else {
if (tctxt == NULL) {
croak("LibXSLT: perl-dispatcher: internal error tctxt == NULL\n");
}
container = xsltCreateRVT(tctxt);
if (container == NULL) {
croak("LibXSLT: perl-dispatcher: cannot create container RVT\n");
}
xsltRegisterLocalRVT(tctxt,container);
tmp_node = xmlDocCopyNode(tmp_node1, container, 1);
xmlAddChild((xmlNodePtr)container,tmp_node);
xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
}
} else {
croak("LibXSLT: perl-dispatcher returned a null XML::LibXML::Node object\n");
}
goto FINISH;
}
else if (sv_derived_from(perl_result, "XML::LibXML::Boolean")) {
tmp_int = SvIV(SvRV(perl_result));
......@@ -897,6 +912,20 @@ lib_cleanup_callbacks( self )
xmlCleanupInputCallbacks();
xmlRegisterDefaultInputCallbacks();
void
__lib_init_proxy_registry( scalar )
SV* scalar;
CODE:
if (PROXY_NODE_REGISTRY_PTR != NULL) {
croak("XML::LibXSLT::__lib_init_proxy_registry must be called only once!\n");
}
if (scalar!=NULL && scalar != &PL_sv_undef) {
PROXY_NODE_REGISTRY_PTR = (ProxyNodePtr*) SvIV((SV*)SvRV(scalar));
}
if (PROXY_NODE_REGISTRY_PTR == NULL) {
croak("XML::LibXSLT::__lib_init_proxy_registry failed to initialize the proxy registry!\n");
}
MODULE = XML::LibXSLT PACKAGE = XML::LibXSLT::Stylesheet
PROTOTYPES: DISABLE
......
# http://module-build.sourceforge.net/META-spec.html
#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
name: XML-LibXSLT
version: 1.62
version_from: LibXSLT.pm
installdirs: site
requires:
XML::LibXML: 1.60
distribution_type: module
generated_by: ExtUtils::MakeMaker version 6.30
--- #YAML:1.0
name: XML-LibXSLT
version: 1.66
abstract: Interface to Gnome libxslt library
license: ~
author:
- Matt Sergeant
generated_by: ExtUtils::MakeMaker version 6.42
distribution_type: module
requires:
XML::LibXML: 1.66
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.3.html
version: 1.3
# $Id: Makefile.PL 184 2006-08-26 17:49:07Z pajas $
# $Id: Makefile.PL 205 2008-01-29 21:02:48Z pajas $
use ExtUtils::MakeMaker;
use Config;
$|=0;
......@@ -31,7 +32,8 @@ unless ( $is_Win32 ) { # cannot get config in W32
print "running xslt-config... ";
my $ver = backtick("$xsltcfg --version");
my ($major, $minor, $point) = $ver =~ /(\d+)\.(\d+)\.(\d+)/g;
die "VERSION" unless $major > 1 || $minor > 0 || $point >= 6;
die "VERSION" unless $major > 1 || $minor > 1 ||
($major>=1 and $minor >=1 and $point >= 18);
$config{LIBS} ||= backtick("$xsltcfg --libs");
$config{INC} ||= backtick("$xsltcfg --cflags");
print "ok\n";
......@@ -39,7 +41,8 @@ unless ( $is_Win32 ) { # cannot get config in W32
if ($@) {
print "failed\n";
if ($@ =~ /^VERSION/) {
die "XML::LibXSLT needs libxslt version 1.0.6 or higher\n";
print STDERR "XML::LibXSLT needs libxslt version 1.1.18 or higher\n";
exit 0; # 0 recommended by http://cpantest.grango.org (Notes for CPAN Authors)
}
warn "*** ", $@ if $DEBUG;
warn "using fallback values for LIBS and INC\n";
......@@ -64,7 +67,7 @@ if ($config{LIBS} !~ /\-lxslt/) {
}
if (!have_library("xslt")) {
die <<DEATH;
print STDERR <<DEATH;
libxslt not found
Try setting LIBS and INC values on the command line
Or get libxslt and libxml2 from
......@@ -72,11 +75,39 @@ Or get libxslt and libxml2 from
If you install via RPMs, make sure you also install the -devel
RPMs, as this is where the headers (.h files) are.
DEATH
exit 0; # 0 recommended by http://cpantest.grango.org (Notes for CPAN Authors)
}
if (have_library("exslt")) {
$config{LIBS} =~ s/-lxslt/-lxslt -lexslt/;
$config{DEFINE} .= " -DHAVE_EXSLT"
my $exslt_defaults = q/-lexslt -lgcrypt -lgpg-error/;
my $exsltcfg = 'pkg-config libexslt';
my ($exslt_libs,$exslt_inc);
eval {
print "running $exsltcfg... ";
$exslt_libs = backtick("$exsltcfg --libs");
$exslt_inc = backtick("$exsltcfg --cflags");
$exslt_libs =~ s/-l(xml2|xslt|z|m)\s+//g;
print "ok\n";
};
if ($@) {
print "failed\n";
warn "*** ", $@ if $DEBUG;
warn "using fallback values for LIBS and INC\n";
# backtick fails if gnome-config didn't exist...
$exslt_libs = $exslt_defaults;
$exslt_inc = '';
}
$config{LIBS} .= ' '.$exslt_libs;
$config{INC} .= ' '.$exslt_inc;
$config{DEFINE} .= " -DHAVE_EXSLT"
}
$config{LIBS}.=' '.$Config{libs};
if ($DEBUG) {
print "LIBS: $config{LIBS}\n";
print "INC: $config{INC}\n";
}
WriteMakefile(
......@@ -84,7 +115,7 @@ WriteMakefile(
'VERSION_FROM' => 'LibXSLT.pm', # finds $VERSION
'AUTHOR' => 'Matt Sergeant',
'ABSTRACT' => 'Interface to Gnome libxslt library',
'PREREQ_PM' => { 'XML::LibXML' => "1.60", },
'PREREQ_PM' => { 'XML::LibXML' => "1.66", },
'OBJECT' => '$(O_FILES)',
%config,
);
......
libxml-libxslt-perl (1.62-2) UNRELEASED; urgency=low
libxml-libxslt-perl (1.66-1) UNRELEASED; urgency=low
* Take over for the Debian Perl Group with maintainer's permission
(http://lists.debian.org/debian-perl/2008/06/msg00039.html)
......@@ -10,6 +10,8 @@ libxml-libxslt-perl (1.62-2) UNRELEASED; urgency=low
Uploaders.
* debian/watch: use dist-based URL.
* New upstream release.
-- gregor herrmann <gregoa@debian.org> Sun, 15 Jun 2008 19:07:57 +0200
libxml-libxslt-perl (1.62-1.1) unstable; urgency=low
......
This diff is collapsed.
/**
* perl-libxml-mm.h
* $Id: perl-libxml-mm.h 125 2002-08-03 20:09:35Z matt $
* $Id: perl-libxml-mm.h 200 2008-01-28 11:32:58Z pajas $
*
* Basic concept:
* perl varies in the implementation of UTF8 handling. this header (together
......@@ -40,23 +40,40 @@ extern "C" {
* for warn!!
*/
#ifdef XS_WARNINGS
#define xs_warn(string) warn(string)
#define xs_warn(string) warn("%s",string)
#else
#define xs_warn(string)
#endif
struct _ProxyNode;
struct _ProxyNode {
xmlNodePtr node;
xmlNodePtr owner;
int count;
int encoding;
struct _ProxyNode * _registry;
};
/* helper type for the proxy structure */
typedef struct _ProxyNode ProxyNode;
/* pointer to the proxy structure */
typedef ProxyNode* ProxyNodePtr;
/* this my go only into the header used by the xs */
#define SvPROXYNODE(x) ((ProxyNodePtr)SvIV(SvRV(x)))
#define SvNAMESPACE(x) ((xmlNsPtr)SvIV(SvRV(x)))
#define x_PmmPROXYNODE(x) ((ProxyNodePtr)x->_private)
#define x_PmmREFCNT(node) node->count
#define x_PmmREFCNT_inc(node) node->count++
#define x_PmmNODE(xnode) xnode->node
#define x_PmmOWNER(node) node->owner
#define x_PmmOWNERPO(node) ((node && x_PmmOWNER(node)) ? (ProxyNodePtr)x_PmmOWNER(node)->_private : node)
#define x_PmmENCODING(node) node->encoding
#define x_PmmNodeEncoding(node) ((ProxyNodePtr)(node->_private))->encoding
#define x_PmmDocEncoding(node) (node->charset)
ProxyNodePtr
x_PmmNewNode(xmlNodePtr node);
......@@ -64,25 +81,173 @@ x_PmmNewNode(xmlNodePtr node);
ProxyNodePtr
x_PmmNewFragment(xmlDocPtr document);
SV*
x_PmmCreateDocNode( unsigned int type, ProxyNodePtr pdoc, ...);
int
x_PmmREFCNT_dec( ProxyNodePtr node );
SV*
x_PmmNodeToSv( xmlNodePtr node, ProxyNodePtr owner );
/* x_PmmFixProxyEncoding
* TYPE
* Method
* PARAMETER
* @dfProxy: The proxystructure to fix.
*
* DESCRIPTION
*
* This little helper allows to fix the proxied encoding information
* after a not standard operation was done. This is required for
* XML::LibXSLT
*/
void
x_PmmFixProxyEncoding( ProxyNodePtr dfProxy );
/* x_PmmSvNodeExt
* TYPE
* Function
* PARAMETER
* @perlnode: the perl reference that holds the scalar.
* @copy : copy flag
*
* DESCRIPTION
*
* The function recognizes XML::LibXML and XML::GDOME
* nodes as valid input data. The second parameter 'copy'
* indicates if in case of GDOME nodes the libxml2 node
* should be copied. In some cases, where the node is
* cloned anyways, this flag has to be set to '0', while
* the default value should be allways '1'.
*/
xmlNodePtr
x_PmmSvNodeExt( SV * perlnode, int copy );
/* x_PmmSvNode
* TYPE
* Macro
* PARAMETER
* @perlnode: a perl reference that holds a libxml node
*
* DESCRIPTION
*
* x_PmmSvNode fetches the libxml node such as x_PmmSvNodeExt does. It is
* a wrapper, that sets the copy always to 1, which is good for all
* cases XML::LibXML uses.
*/
#define x_PmmSvNode(n) x_PmmSvNodeExt(n,1)
xmlNodePtr
x_PmmSvNode( SV * perlnode );
x_PmmSvOwner( SV * perlnode );
SV*
x_PmmSetSvOwner(SV * perlnode, SV * owner );
void
x_PmmFixOwner(ProxyNodePtr node, ProxyNodePtr newOwner );
void
x_PmmFixOwnerNode(xmlNodePtr node, ProxyNodePtr newOwner );
int
x_PmmContextREFCNT_dec( ProxyNodePtr node );
SV*
x_PmmContextSv( xmlParserCtxtPtr ctxt );
xmlParserCtxtPtr
x_PmmSvContext( SV * perlctxt );
/**
* NAME domNodeTypeName
* NAME x_PmmCopyNode
* TYPE function
*
* returns libxml2 node
*
* DESCRIPTION
* This function implements a nodetype independant node cloning.
*
* Note that this function has to stay in this module, since
* XML::LibXSLT reuses it.
*/
xmlNodePtr
x_PmmCloneNode( xmlNodePtr node , int deep );
/**
* NAME x_PmmNodeToGdomeSv
* TYPE function
*
* returns XML::GDOME node
*
* DESCRIPTION
* creates an Gdome node from our XML::LibXML node.
* this function is very usefull for the parser.
*
* the function will only work, if XML::LibXML is compiled with
* XML::GDOME support.
*
*/
SV *
x_PmmNodeToGdomeSv( xmlNodePtr node );
/**
* NAME x_PmmNodeTypeName
* TYPE function
*
* returns the perl class name for the given node
*
* SYNOPSIS
* CLASS = domNodeTypeName( node );
* CLASS = x_PmmNodeTypeName( node );
*/
const char*
x_PmmNodeTypeName( xmlNodePtr elem );
xmlChar*
x_PmmEncodeString( const char *encoding, const char *string );
char*
x_PmmDecodeString( const char *encoding, const xmlChar *string);
/* string manipulation will go elsewhere! */
/*
* NAME c_string_to_sv
* TYPE function
* SYNOPSIS
* SV *my_sv = c_string_to_sv( "my string", encoding );
*
* this function converts a libxml2 string to a SV*. although the
* string is copied, the func does not free the c-string for you!
*
* encoding is either NULL or a encoding string such as provided by
* the documents encoding. if encoding is NULL UTF8 is assumed.
*
*/
SV*
C2Sv( const xmlChar *string, const xmlChar *encoding );
/*
* NAME sv_to_c_string
* TYPE function
* SYNOPSIS
* SV *my_sv = sv_to_c_string( my_sv, encoding );
*
* this function converts a SV* to a libxml string. the SV-value will
* be copied into a *newly* allocated string. (don't forget to free it!)
*
* encoding is either NULL or a encoding string such as provided by
* the documents encoding. if encoding is NULL UTF8 is assumed.
*
*/
xmlChar *
Sv2C( SV* scalar, const xmlChar *encoding );
SV*
nodeC2Sv( const xmlChar * string, xmlNodePtr refnode );
xmlChar *
nodeSv2C( SV * scalar, xmlNodePtr refnode );
#endif
This diff is collapsed.
use Test;
BEGIN { plan tests => 18 }
BEGIN { plan tests => 33 }
use XML::LibXSLT;
my $parser = XML::LibXML->new();
my $xslt = XML::LibXSLT->new();
ok($parser); ok($xslt);
$xslt->register_function('urn:foo' => 'test', sub { ok(1); defined $_[1] ? return $_[0] . $_[1] : return $_[0] });
$xslt->register_function('urn:foo' => 'test2', sub { ok(ref($_[0]), 'XML::LibXML::NodeList'); ref($_[0]) });
$xslt->register_function('urn:foo' => 'test3', sub { ok(@_ == 0); return; });
my $source = $parser->parse_string(<<'EOT');
{
my $parser = XML::LibXML->new();
my $xslt = XML::LibXSLT->new();
ok($parser); ok($xslt);
$xslt->register_function('urn:foo' => 'test', sub { ok(1); defined $_[1] ? return $_[0] . $_[1] : return $_[0] });
$xslt->register_function('urn:foo' => 'test2', sub { ok(ref($_[0]), 'XML::LibXML::NodeList'); ref($_[0]) });
$xslt->register_function('urn:foo' => 'test3', sub { ok(@_ == 0); return; });
my $source = $parser->parse_string(<<'EOT');
<?xml version="1.0" encoding="ISO-8859-1"?>
<document></document>
EOT
my $style = $parser->parse_string(<<'EOT');
my $style = $parser->parse_string(<<'EOT');
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
......@@ -40,50 +41,122 @@ my $style = $parser->parse_string(<<'EOT');
</xsl:stylesheet>
EOT
ok($style);
my $stylesheet = $xslt->parse_stylesheet($style);
ok($style);
my $stylesheet = $xslt->parse_stylesheet($style);
my $results = $stylesheet->transform($source);
ok($results);
my $results = $stylesheet->transform($source);
ok($results);
ok($stylesheet->output_string($results), qr(Foo!));
ok($stylesheet->output_string($results), qr(NodeList));
ok($stylesheet->output_string($results), qr(Foo!));
ok($stylesheet->output_string($results), qr(NodeList));
print $stylesheet->output_string($results), "\n";
$xslt->register_function('urn:foo' => 'get_list', \&get_nodelist );
our @words = qw( one two three );
$xslt->register_function('urn:foo' => 'get_list', \&get_nodelist );
sub get_nodelist {
my $nl = XML::LibXML::NodeList->new();
$nl -> push( map { XML::LibXML::Text->new($_) } @words );
return $nl;
}
our @words = qw( one two three );
sub get_nodelist {
my $nl = XML::LibXML::NodeList->new();
$nl -> push( map { XML::LibXML::Text->new($_) } @words );
return $nl;
}
$style = $parser->parse_string(<<'EOT');
$style = $parser->parse_string(<<'EOT');
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo="urn:foo">
<xsl:template match="/">
<xsl:for-each select='foo:get_list()'>
<li><xsl:value-of select='.'/></li>
</xsl:for-each>
<xsl:for-each select='foo:get_list()'>
<li><xsl:value-of select='.'/></li>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
EOT
ok($style);
ok($style);
$stylesheet = $xslt->parse_stylesheet($style);
$results = $stylesheet->transform($source);
$stylesheet = $xslt->parse_stylesheet($style);
for (1..5) {
$results = $stylesheet->transform($source);
ok($results);
ok($results);
ok($stylesheet->output_string($results), qr(<li>one</li>));
ok($stylesheet->output_string($results), qr(<li>one</li><li>two</li><li>three</li>));
}
}
ok($stylesheet->output_string($results), qr(<li>one</li>));
ok($stylesheet->output_string($results), qr(<li>one</li><li>two</li><li>three</li>));
{
# testcase by Elizabeth Mattijsen
my $parser = XML::LibXML->new;
my $xsltproc = XML::LibXSLT->new;
my $xml = $parser->parse_string( <<'XML' );
<html><head/></html>
XML
my $xslt = $parser->parse_string( <<'XSLT' );
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo="http://foo"
version="1.0">
<xsl:template match="/html">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="/html/head">
<head>
<xsl:copy-of select="foo:custom()/foo"/>
<xsl:apply-templates/>
</head>
</xsl:template>
</xsl:stylesheet>
XSLT
my $aux = <<'XML';
<bar>
<y><foo>1st</foo></y>
<y><foo>2nd</foo></y>
</bar>
XML
{
XML::LibXSLT->register_function(
('http://foo', 'custom') => sub { $parser->parse_string( $aux )->findnodes('//y') }
);
my $stylesheet = $xsltproc->parse_stylesheet($xslt);