日向夏特殊応援部隊

俺様向けメモ

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));