libxml-libxml-perl/t/40reader.t

319 lines
9.0 KiB
Perl

#!/usr/bin/perl -w
use strict;
use warnings;
use Test::More;
use XML::LibXML;
BEGIN{
if (1000*$] < 5008) {
plan skip_all => "Reader interface only supported in Perl >= 5.8";
exit;
} elsif (!XML::LibXML::HAVE_READER()) {
plan skip_all => "Reader not supported in this libxml2 build";
exit;
} else {
plan tests => 100;
}
use_ok('XML::LibXML::Reader');
};
my $file = "test/textReader/countries.xml";
{
my $reader = XML::LibXML::Reader->new(location => $file, {expand_entities => 1});
isa_ok($reader, "XML::LibXML::Reader");
is($reader->read, 1, "read");
is($reader->byteConsumed, 488, "byteConsumed");
is($reader->attributeCount, 0, "attributeCount");
is($reader->baseURI, $file, "baseURI");
is($reader->encoding, 'UTF-8', "encoding");
is($reader->localName, 'countries', "localName");
is($reader->name, 'countries', "name");
is($reader->prefix, undef, "prefix");
is($reader->value, undef, "value");
is($reader->xmlLang, undef, "xmlLang");
is($reader->xmlVersion, '1.0', "xmlVersion");
$reader->read;
$reader->read;
$reader->read; # skipping to country node
is($reader->name, 'country', "skipping to country");
is($reader->depth, "1", "depth");
is($reader->getAttribute("acronym"), "AL", "getAttribute");
is($reader->getAttributeNo(0), "AL", "getAttributeNo");
is($reader->getAttributeNs("acronym", undef), "AL", "getAttributeNs");
is($reader->lineNumber, "20", "lineNumber");
is($reader->columnNumber, "1", "columnNumber");
ok($reader->hasAttributes, "hasAttributes");
ok(! $reader->hasValue, "hasValue");
ok(! $reader->isDefault, "isDefault");
ok(! $reader->isEmptyElement, "isEmptyElement");
ok(! $reader->isNamespaceDecl, "isNamespaceDecl");
ok(! $reader->isValid, "isValid");
is($reader->localName, "country", "localName");
is($reader->lookupNamespace(undef), undef, "lookupNamespace");
ok($reader->moveToAttribute("acronym"), "moveToAttribute");
ok($reader->moveToAttributeNo(0), "moveToAttributeNo");
ok($reader->moveToAttributeNs("acronym", undef), "moveToAttributeNs");
ok($reader->moveToElement, "moveToElement");
ok($reader->moveToFirstAttribute, "moveToFirstAttribute");
ok($reader->moveToNextAttribute, "moveToNextAttribute");
ok($reader->readAttributeValue, "attributeValue");
$reader->moveToElement;
is($reader->name, "country", "name");
is($reader->namespaceURI, undef, "namespaceURI");
ok($reader->nextSibling, "nextSibling");
is($reader->nodeType, XML_READER_TYPE_SIGNIFICANT_WHITESPACE, "nodeType");
is($reader->prefix, undef, "prefix");
is($reader->readInnerXml, "", "readInnerXml");
is($reader->readOuterXml, "\n", "readOuterXml");
ok($reader->readState, "readState");
is($reader->getParserProp('expand_entities'), 1, "getParserProp");
ok($reader->standalone, "standalone");
is($reader->value, "\n", "value");
is($reader->xmlLang, undef, "xmlLang");
ok($reader->close, "close");
}
# FD interface
for my $how (qw(FD IO)) {
# my $fd;
open my $fd, '<', $file or die "cannot open $file: $!\n";
my $reader = XML::LibXML::Reader->new($how => $fd, URI => $file);
isa_ok($reader, "XML::LibXML::Reader");
$reader->read;
$reader->read;
is($reader->name, "countries","name in fd");
$reader->read;
$reader->read;
$reader->read;
close $fd;
}
# scalar interface
{
open my $fd, '<', $file or die "cannot open $file: $!\n";
my $doc;
{
local $/;
$doc = <$fd>;
}
close $fd;
my $reader = XML::LibXML::Reader->new(string => $doc, URI => $file);
isa_ok($reader, "XML::LibXML::Reader");
$reader->read;
$reader->read;
is($reader->name, "countries","name in string");
}
# DOM
{
my $DOM = XML::LibXML->new->parse_file($file);
my $reader = XML::LibXML::Reader->new(DOM => $DOM);
isa_ok($reader, "XML::LibXML::Reader");
$reader->read;
$reader->read;
is($reader->name, "countries","name in string");
ok($reader->document,"document");
ok($reader->document->isSameNode($DOM),"document is DOM");
}
# Expand
{
my ($node1,$node2, $node3);
my $xml = <<'EOF';
<root>
<AA foo="FOO"> text1 <inner/> </AA>
<DD/><BB bar="BAR">text2<CC> xx </CC>foo<FF/> </BB>x
<EE baz="BAZ"> xx <PP>preserved</PP> yy <XX>FOO</XX></EE>
<a/>
<b/>
<x:ZZ xmlns:x="foo"/>
<QQ/>
<YY/>
</root>
EOF
{
my $reader = XML::LibXML::Reader->new(string => $xml);
$reader->preservePattern('//PP');
$reader->preservePattern('//x:ZZ',{ x => "foo"});
isa_ok($reader, "XML::LibXML::Reader");
$reader->nextElement;
is($reader->name, "root","root node");
$reader->nextElement;
$node1 = $reader->copyCurrentNode(1);
is($node1->nodeName, "AA","deep copy node");
$reader->next;
ok($reader->nextElement("DD"),"next named element");
is($reader->name, "DD","name");
is($reader->readOuterXml, "<DD/>","readOuterXml");
ok($reader->read,"read");
is($reader->name, "BB","name");
$node2 = $reader->copyCurrentNode(0);
is($node2->nodeName, "BB","shallow copy node");
$reader->nextElement;
is($reader->name, "CC","nextElement");
$reader->nextSibling;
is( $reader->nodeType(), XML_READER_TYPE_TEXT, "text node" );
is( $reader->value,"foo", "text content" );
$reader->skipSiblings;
is( $reader->nodeType(), XML_READER_TYPE_END_ELEMENT, "end element type" );
$reader->nextElement;
is($reader->name, "EE","name");
ok($reader->nextSiblingElement("ZZ","foo"),"namespace");
is($reader->namespaceURI, "foo","namespaceURI");
$reader->nextElement;
$node3= $reader->preserveNode;
is( $reader->readOuterXml(), $node3->toString(),"outer xml");
ok($node3,"preserve node");
$reader->finish;
my $doc = $reader->document;
ok($doc, "document");
ok($doc->documentElement, "doc root element");
is($doc->documentElement->toString,q(<root><EE baz="BAZ"><PP>preserved</PP></EE><x:ZZ xmlns:x="foo"/><QQ/></root>),
"preserved content");
}
ok($node1->hasChildNodes,"copy w/ child nodes");
ok($node1->toString(),q(<AA foo="FOO"> text1 <inner/> </AA>));
ok(!defined $node2->firstChild, "copy w/o child nodes");
ok($node2->toString(),q(<BB bar="BAR"/>));
ok($node3->toString(),q(<QQ/>));
}
{
my $bad_xml = <<'EOF';
<root>
<foo/>
<x>
foo
</u>
<x>
foo
</x>
</root>
EOF
my $reader = XML::LibXML::Reader->new(
string => $bad_xml,
URI => "mystring.xml"
);
eval { $reader->finish };
my $Err = $@;
use Data::Dumper;
# print Dumper($Err);
# print $Err;
ok((defined($Err) and $Err =~ /in mystring.xml at line 3:|mystring.xml:5:/),
'caught the error');
}
{
my $rng = "test/relaxng/demo.rng";
for my $RNG ($rng, XML::LibXML::RelaxNG->new(location => $rng)) {
{
my $reader = XML::LibXML::Reader->new(
location => "test/relaxng/demo.xml",
RelaxNG => $RNG,
);
ok($reader->finish, "validate using ".(ref($RNG) ? 'XML::LibXML::RelaxNG' : 'RelaxNG file'));
}
{
my $reader = XML::LibXML::Reader->new(
location => "test/relaxng/invaliddemo.xml",
RelaxNG => $RNG,
);
eval { $reader->finish };
print $@;
ok($@, "catch validation error for a ".(ref($RNG) ? 'XML::LibXML::RelaxNG' : 'RelaxNG file'));
}
}
}
SKIP: {
if ((!XML::LibXML::HAVE_SCHEMAS)
or (XML::LibXML::LIBXML_DOTTED_VERSION eq '2.9.4')
)
{
skip "https://github.com/shlomif/libxml2-2.9.4-reader-schema-regression", 4;
}
my $xsd = "test/schema/schema.xsd";
for my $XSD ($xsd, XML::LibXML::Schema->new(location => $xsd)) {
{
my $reader = XML::LibXML::Reader->new(
location => "test/schema/demo.xml",
Schema => $XSD,
);
ok($reader->finish, "validate using ".(ref($XSD) ? 'XML::LibXML::Schema' : 'Schema file'));
}
{
my $reader = XML::LibXML::Reader->new(
location => "test/schema/invaliddemo.xml",
Schema => $XSD,
);
eval { $reader->finish };
ok($@, "catch validation error for ".(ref($XSD) ? 'XML::LibXML::Schema' : 'Schema file'));
}
}
}
# Patterns
{
my ($node1,$node2, $node3);
my $xml = <<'EOF';
<root>
<AA foo="FOO"> text1 <inner/> </AA>
<DD/><BB bar="BAR">text2<CC> xx </CC>foo<FF/> </BB>x
<EE baz="BAZ"> xx <PP>preserved</PP> yy <XX>FOO</XX></EE>
<a/>
<b/>
<x:ZZ xmlns:x="foo"/>
<QQ/>
<YY/>
</root>
EOF
my $pattern = XML::LibXML::Pattern->new('//inner|CC|/root/y:ZZ',{y=>'foo'});
ok($pattern);
{
my $reader = XML::LibXML::Reader->new(string => $xml);
ok($reader);
my $matches='';
while ($reader->read) {
if ($reader->matchesPattern($pattern)) {
$matches.=$reader->nodePath.',';
}
}
ok($matches,'/root/AA/inner,/root/BB/CC,/root/*,');
}
{
my $reader = XML::LibXML::Reader->new(string => $xml);
ok($reader);
my $matches='';
while ($reader->nextPatternMatch($pattern)) {
$matches.=$reader->nodePath.',';
}
ok($matches,'/root/AA/inner,/root/BB/CC,/root/*,');
}
{
my $dom = XML::LibXML->new->parse_string($xml);
ok($dom);
my $matches='';
for my $node ($dom->findnodes('//node()|@*')) {
if ($pattern->matchesNode($node)) {
$matches.=$node->nodePath.',';
}
}
ok($matches,'/root/AA/inner,/root/BB/CC,/root/*,');
}
}