# $Id: 1_buffer.t,v 1.2 2005/04/20 20:03:52 grantm Exp $
use strict;
use Test::More;
BEGIN { # Seems to be required by older Perls
unless(eval { require XML::SAX::Writer }) {
plan skip_all => 'XML::SAX::Writer not installed';
}
unless(eval { require XML::SAX::ParserFactory }) {
plan skip_all => 'XML::SAX::ParserFactory not installed';
}
}
plan tests => 17;
$^W = 1;
##############################################################################
# Confirm that the module compiles
#
use XML::Filter::Sort::Buffer;
ok(1, 'XML::Filter::Sort::Buffer compiled OK');
##############################################################################
# Try creating a Buffer object
#
my $buffer = XML::Filter::Sort::Buffer->new(
Keys => [
[ '.', 'a', 'a' ] # All text alpha ascending
]
);
ok(ref($buffer), 'Created a buffer object');
isa_ok($buffer, 'XML::Filter::Sort::Buffer');
##############################################################################
# Poke some SAX events into it, close it and confirm the sort key value was
# extracted correctly.
#
my $rec_elem = {
Name => 'record',
LocalName => 'record',
Prefix => '',
NamespaceURI => '',
Attributes => {},
};
$buffer->start_element($rec_elem);
$buffer->characters({ Data => 'text content'});
$buffer->end_element($rec_elem);
my($keyval) = $buffer->close();
is($keyval, 'text content', 'Extracted sort key value from element content');
##############################################################################
# Spool the buffered contents out via SAX to a Writer and confirm it is what
# we expected.
#
my $xmlout = '';
my $writer = XML::SAX::Writer->new(Output => \$xmlout);
$writer->start_document();
$buffer->to_sax($writer);
$writer->end_document();
is($xmlout, 'text content', 'Simple XML buffered OK');
##############################################################################
# Now try again but with sort key value in an attribute
#
$buffer = XML::Filter::Sort::Buffer->new(
Keys => [
[ './@height', 'n', 'a' ] # value of 'height' attribute
]
);
$rec_elem->{Attributes} = {
'{}width' => {
Name => 'width',
LocalName => 'width',
Prefix => '',
NamespaceURI => '',
Value => '1024',
},
'{}height' => {
Name => 'height',
LocalName => 'height',
Prefix => '',
NamespaceURI => '',
Value => '768',
},
};
$buffer->characters({ Data => ' '});
$buffer->start_element($rec_elem);
$buffer->characters({ Data => 'text content'});
$buffer->end_element($rec_elem);
($keyval) = $buffer->close();
is($keyval, '768', 'Extracted sort key value from attribute');
##############################################################################
# Make sure it comes back out as expected XML
#
$xmlout = '';
$writer = XML::SAX::Writer->new(Output => \$xmlout);
$writer->start_document();
$buffer->to_sax($writer);
$writer->end_document();
$xmlout =~ s/"/'/sg;
like($xmlout,
qr{^ text content},
'XML containing attributes returned OK'
);
##############################################################################
# Try creating a Buffer object configured with multiple (3) sort keys. This
# time use a parser to generate SAX events rather than doing it manually.
# Confirm correct sort key values were extracted and that output from the
# buffer exactly matches the input.
#
my $xmlin = q(
Zebedee
Boozle
35
0
);
my(@keyvals);
($buffer, @keyvals) = buffer_from_xml(
[
[ './lastname', 'a', 'a' ],
[ './firstname', 'a', 'a' ],
[ './age', 'a', 'a' ],
],
$xmlin
);
is_deeply(\@keyvals, [qw(Boozle Zebedee 35)], 'Multiple sort keys returned OK');
$xmlout = xml_from_buffer($buffer);
$xmlout =~ s/"year"/'year'/;
$xmlout =~ s{/>}{/>};
$xmlout =~ s{}{};
is($xmlout, $xmlin, 'Round-tripped XML containing elements and attributes');
##############################################################################
# Throw an XML comment into the mix. Confirm that the key value extraction
# mechanism ignores the comment contents (obviously) and also that the
# comment is correctly buffered and regurgitated.
#
$xmlin = q(
Dougal
Boozle
);
($buffer, @keyvals) = buffer_from_xml(
[ [ './firstname', 'a', 'a' ], ],
$xmlin
);
is_deeply(\@keyvals, [qw(Dougal)], 'Ignored value in comment');
$xmlout = xml_from_buffer($buffer, 'simple sort key value');
$xmlout =~ s{<}{<}sg; # work around (old) XML::SAX::Writer bug
$xmlout =~ s{>}{>}sg;
is($xmlout, $xmlin, 'Round-tripped XML containing a comment');
##############################################################################
# Similar test, but with a Processing Instruction
#
$xmlin = q(
Zebedee
Boozle
);
ok(($buffer, @keyvals) = buffer_from_xml(
[ [ './lastname', 'a', 'a' ], ],
$xmlin
),
'No crash when presented with PI'
);
is_deeply(\@keyvals, [qw(Boozle)], 'Extracted another simple sort key value');
$xmlout = xml_from_buffer($buffer);
is($xmlout, $xmlin, 'Round-tripped XML containing a Processing Instruction');
##############################################################################
# Ask for matches against non-existant elements confirm we get one empty
# string back for each.
#
$xmlin = q(
Zebedee
Boozle
);
($buffer, @keyvals) = buffer_from_xml(
[
[ './address', 'a', 'a' ],
[ './email', 'a', 'a' ],
],
$xmlin
);
is_deeply(\@keyvals, ['', ''], 'Correct key values returned when match failed');
##############################################################################
# Now create a buffer configured with a long list of sort keys of varying
# forms and confirm they all match what we expect them to match.
#
$xmlin = q(
Boozle
Zebedee
35
100x???Fore!
);
($buffer, @keyvals) = buffer_from_xml(
[
['lastname'],
['firstname'],
['age'],
['./lastname'],
['./alpha/beta/carotine'],
['./firstname/@initial'],
['firstname/@initial'],
['@initial'],
['@age'],
['@gender'],
['alpha/age'],
['alpha/beta/gamma'],
['alpha/beta'],
],
$xmlin
);
is_deeply(\@keyvals, [
'Boozle', 'Zebedee', '35', 'Boozle', 'Fore!', 'Z', 'Z', 'Z',
12, '', 100, '???', 'x???Fore!'
], 'Longish list of more complex keys');
##############################################################################
# Now do a similar test, but this time with namespaces thrown into the mix.
#
$xmlin = q(
Smith
Jones
O'Toole
Xavier
Yorick
Patrick
);
($buffer, @keyvals) = buffer_from_xml(
[
['./names/lastname'],
['./names/{}lastname'],
['./names/alias/{pat.ie}lastname'],
['lastname'],
['{}lastname'],
['{pat.ie}lastname'],
['firstname/@initial'],
['firstname/@{}initial'],
['firstname/@{pat.ie}initial'],
['./names/firstname/@initial'],
['./names/firstname/@{}initial'],
['./names/alias/firstname/@{pat.ie}initial'],
],
$xmlin
);
is_deeply(\@keyvals, [
'Smith',
'Jones',
'O\'Toole',
'Smith',
'Jones',
'O\'Toole',
'X',
'Y',
'P',
'X',
'Y',
'P',
], 'Keys with namespace elements');
##############################################################################
# S U B R O U T I N E S
##############################################################################
sub buffer_from_xml {
my($keys, $xml) = @_;
$buffer = XML::Filter::Sort::Buffer->new(Keys => $keys);
my $parser = XML::SAX::ParserFactory->parser(Handler => $buffer);
$parser->parse_string($xml);
my @keyvals = $buffer->close();
return($buffer, @keyvals);
}
sub xml_from_buffer {
my($buffer) = @_;
my $xml = '';
$writer = XML::SAX::Writer->new(Output => \$xml);
$writer->start_document();
$buffer->to_sax($writer);
$writer->end_document();
return($xml);
}