The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.


URI::OpenURL - Parse and construct OpenURL's (NISO Z39.88-2004)


This module provides an implementation of OpenURLs encoded as URIs (Key/Encoded-Value (KEV) Format), this forms only a part of the OpenURL spec. It does not check that OpenURLs constructed are sane according to the OpenURL specification (to a large extent sanity will depend on the community of use).

From the implementation guidelines:

The description of a referenced resource, and the descriptions of the associated resources that comprise the context of the reference, bundled together are called a ContextObject. It is a ContextObject that is transported when a user makes a request by clicking a link. A KEV OpenURL may contain only one ContextObject.

The ContextObject may contain up to six Entities. One of these, the Referent, conveys information about the referenced item. It must always be included in a ContextObject. The other five entities - ReferringEntity, Requester, Resolver, ServiceType and Referrer - hold information about the context of the reference and are optional.


From the implementation guidelines:

The OpenURL Framework for Context-Sensitive Services Standard provides a means of describing a referenced resource along with a description of the context of the reference. Additionally it defines methods of transporting these descriptions between networked systems. It is anticipated that it will be used to request services pertaining to the referenced resource and appropriate for the requester.

The OpenURL Framework is very general and has the potential to be used in many application domains and by many communities. Concrete instantiations of the various core components within the framework are defined within the OpenURL Registry. The OpenURL Framework is currently a .draft standard for ballot.. During the ballot and public review period, the content of the Registry will be static and has been pre-defined by the NISO AX Committee. There is also an experimental registry where components under development are held. In the future it will be possible to register further items.

There are currently two formats for ContextObjects defined in the OpenURL Framework, Key/Encoded-Value and XML. This document provides implementation guidelines for the Key/Encoded-Value Format, concentrating mainly, but not exclusively, on components from the San Antonio Level 1 Community Profile (SAP1).


        use URI::OpenURL;

        # Construct an OpenURL
        # This is the first example from the implementation specs,
        # with additional resolver and serviceType entities.
        print URI::OpenURL->new('http://other.service/cgi/openURL'
                        id => 'info:sid/my.service',
                        id => 'mailto:john@invalid.domain',
                        id => 'info:sid/other.service',
                        fulltext => 'yes',
                )->referringEntity(id => 'info:doi/10.1045/march2001-vandesompel')->journal(
                        genre => 'article',
                        aulast => 'Van de Sompel',
                        aufirst => 'Herbert',
                        issn => '1082-9873',
                        volume => '7',
                        issue => '3',
                        date => '2001',
                        atitle => 'Open Linking in the Scholarly Information Environment using the OpenURL Framework',
                )->referent(id => 'info:doi/10.1045/july99-caplan')->journal(
                        genre => 'article',
                        aulast => 'Caplan',
                        aufirst => 'Priscilla',
                        issn => '1082-9873',
                        volume => '5',
                        issue => '7/8',
                        date => '1999',
                        atitle => 'Reference Linking for Journal Articles',

        # Parsing (wrappers for $uri->query_form())
        my $uri = URI::OpenURL->new('http://a.OpenURL/?url_ver=Z39.88-2004&...');
        my @referent = $uri->referent->metadata();
        print join(',',@referent), "\n";
        # This could lose data if there is more than one id
        my %ds = $uri->referent->descriptors();
        if( !exists($ds{val_fmt}) ) {
                warn "No by-value metadata for referent in OpenURL";
        } elsif($ds{val_fmt} eq 'info:ofi/fmt:kev:mtx:journal') {
                my %md = $uri->referent->metadata();
                print ($md{genre} || 'Unknown journal article genre'), "\n";
        if( $uri->referent->val_fmt() eq 'info:ofi/fmt:kev:mtx:journal' ) {
                print "The referent is a journal article.\n";


    $uri = URI::OpenURL->new([$url])

    Create a new URI::OpenURL object and optionally initialize with $url. If $url does not contain a query component (...?key=value) the object will be initialized to a valid contextobject, but without any entities.

    If you don't want the context object version and encoding specify url_ver e.g.

            use URI::OpenURL;
            my $uri = URI::OpenURL->new(

    $uri = URI::OpenURL->new_from_hybrid($uri)

    Create a new URI::OpenURL object from a hybrid OpenURL (version 0.1 and/or 1.0 KEVS). Use this to parse a version 0.1 (SFX) style OpenURL.

    @qry = $uri->query_form([key, value, [key, value]])

    Equivalent to URI::query_form, but with support for UTF-8 encoding.


    Add ContextObject versioning.

    $ts = $uri->init_timestamps([ctx_timestamp, [url_timestamp]])

    Add ContextObject and URL timestamps, returns the old timestamp(s) or undef on none.

    $uri = $uri->as_hybrid()

    Return the OpenURL as a hybrid 0.1/1.0 OpenURL (contains KEVs for both versions). Returns a new URI::OpenURL object.

    $uri = $uri->canonical()

    Return a canonical OpenURL by removing anything that isn't part of the version 1.0 specification.

    $str = $uri->dump()

    Return the OpenURL as a human-readable string (useful for debugging).

    $uri = $uri->referent()

    Every ContextObject must have a Referent, the referenced resource for which the ContextObject is created. Within the scholarly information community the Referent will probably be a document-like object, for instance: a book or part of a book; a journal publication or part of a journal; a report; etc.


    The ReferringEntity is the Entity that references the Referent. It is optional in the ContextObject. Within the scholarly information community the ReferringEntity could be a journal article that cites the Referent. Or it could be a record within an abstracting and indexing database.

    $uri = $uri->requester()

    The Requester is the Entity that requests services pertaining to the Referent. It is optional in the ContextObject. Within the scholarly information community the Requester is generally a human end-user who clicks a link within a digital library application.

    $uri = $uri->serviceType()

    The ServiceType is the Entity that defines the type of service requested. It is optional in the ContextObject. Within the scholarly information community the ServiceType could be a request for; the full text of an article; the abstract of an article; an inter-library loan request, etc.

    $uri = $uri->resolver()

    The Resolver is the Entity at which a request for services is targeted. It is optional in the ContextObject. This need not be the same Resolver as that specified as the base URL for an OpenURL Transport and does not replace that base URL.

    $uri = $uri->referrer()

    The Referrer is the Entity that generated the ContextObject. It is optional in the ContextObject, but its inclusion is strongly encouraged. Within the scholarly information community the Referrer will be an information provider such as an electronic journal application or an 'abstracting and indexing' service.

    $uri = $uri->referent->dublinCore(key => value)

    $uri = $uri->referent->book(key => value)

    $uri = $uri->referent->dissertation(key => value)

    $uri = $uri->referent->journal(key => value)

    $uri = $uri->referent->patent(key => value)

    $uri = $uri->serviceType->scholarlyService(key => value)

    Add metadata to the current entity (referent is given only as an example). Dublin Core is an experimental format.

    @descs = $uri->referent->descriptors([$key=>$value[, $key=>$value]])

    Return the descriptors as a list of key-value pairs for the current entity (referent is given as an example).

    Optionally add descriptors (functionally equivalent to $uri->referent($key=>$value)).

    @metadata = $uri->referent->metadata([$schema_url, $key=>$value[, $key=>$value]])

    Returns by-value metadata as a list of key-value pairs for the current entity (referent is given as an example).

    Optionally, if you wish to add metadata that does not use one of the standard schemas (journal, book etc.) then you can add them using metadata.

    @vals = $uri->referent->descriptor('id')

    Return a list of values given for an entity descriptor (id, ref, dat, val_fmt, ref_fmt).

    $dat = $uri->referent->dat()

    @ids = $uri->referent->id()

    $ref = $uri->referent->ref()

    $val_fmt = $uri->referent->val_fmt()

    $ref_fmt = $uri->referent->ref_fmt()

    Return the respective descriptor using a method interface. An entity may contain 0 or more ids, and optionally a by-reference URI, private data, by-value format and by-reference format.


                - Removed ContextObject versioning from default
                - Support for URL utf-8 encoding
                - Added methods for parsing/writing hybrid OpenURLs
                - Timestamps no longer included in default initialization
                - Added method "init_timestamps" to add timestamps
                - Initial release


Quotes from the OpenURL implementation guidelines are from:

Copyright 2004 Tim Brody.

This module is released under the same terms as the main Perl distribution.


Tim Brody <> Intelligence, Agents, Multimedia Group University of Southampton, UK

3 POD Errors

The following errors were encountered while parsing the POD:

Around line 86:

You can't have =items (as at line 106) unless the first thing after the =over is an =item

Around line 473:

You forgot a '=back' before '=head1'

Around line 502:

=back without =over