XRI::Resolution::Liteのサンプル
解説はあとで。
priorityも考慮に入れて、OpenID サービスを取得する場合はこんな感じかなぁ。
#!/usr/bin/perl use strict; use warnings; use Data::Dump qw(dump); use Math::BigInt; use Perl6::Say; use XML::LibXML; use XRI::Resolution::Lite; my $claim_id = $ARGV[0]; sub rand_array { my @list = @_; return map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [$_, rand] } @list; } sub get_services { my $claimd_id = shift; my $resolution = XRI::Resolution::Lite->new; my $xrds = $resolution->resolve($claim_id); my $xpc = XML::LibXML::XPathContext->new($xrds); $xpc->registerNs('xrd', 'xri://$xrd*($v*2.0)'); my %services = (); my @services = $xpc->findnodes('//xrd:Type[text() = "http://openid.net/signon/1.0" or text() = "http://openid.net/signon/1.1" or text() = "http://specs.openid.net/auth/2.0/signon"]/ancestor::xrd:Service'); for my $service (@services) { my $priority = int ($service->getAttribute("priority")) || Math::BigInt->binf; $services{$priority} = [] unless (exists $services{$priority}); push(@{$services{$priority}}, $service); } return map { $_->toString } map { rand_array(@{$services{$_}}) } sort { $a <=> $b } keys %services; } say dump(get_services($claim_id));