<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.ext-9.eprints-hosting.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ma3I6n</id>
	<title>EPrints Documentation - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.ext-9.eprints-hosting.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ma3I6n"/>
	<link rel="alternate" type="text/html" href="https://wiki.ext-9.eprints-hosting.org/w/Special:Contributions/Ma3I6n"/>
	<updated>2026-05-10T00:09:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://wiki.ext-9.eprints-hosting.org/w/index.php?title=Create_Export_Plugins&amp;diff=5389</id>
		<title>Create Export Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.ext-9.eprints-hosting.org/w/index.php?title=Create_Export_Plugins&amp;diff=5389"/>
		<updated>2007-08-31T18:15:43Z</updated>

		<summary type="html">&lt;p&gt;Ma3I6n: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://xxxenichkaa.ifrance.com/la-bicicletta.html la bicicletta] [http://snakeystil.ifrance.com/jade/index.html jade] [http://thecrownless.ifrance.com/i-don-t-want-to/index.html i don t want to be] [http://katzella.ifrance.com/i-n-p-s-it/index.html i n p s it] [http://katzella.ifrance.com/hai/index.html hai] [http://starcross33.ifrance.com/ljepi-dani/index.html ljepi dani] [http://child-ofadot.ifrance.com/inquinmento.html inquinmento] [http://plyuh-vios.ifrance.com/i-want-internet.html i want internet in english] [http://thecrownless.ifrance.com/iheb-tawfik/index.html iheb tawfik] [http://starcross33.ifrance.com/l-amore-piu-grande/index.html l amore piu grande] [http://carbonphoenix.ifrance.com/jem-boy.html jem boy] [http://cuivenarius.ifrance.com/hot-party-2002.html hot party 2002] [http://risdimpuka.ifrance.com/la-vita-loca/index.html la vita loca] [http://busjavka.ifrance.com/hotel-capo-noli/index.html hotel capo noli] [http://angeljazz711.ifrance.com/incontri-a-letto.html incontri a letto] [http://snakeystil.ifrance.com/jennifer-sky/index.html jennifer sky] [http://taylors-acolyte.ifrance.com/inizio-scuole-superiori.html inizio scuole superiori montebelluna] [http://plyuh-vios.ifrance.com/isn-t-it-beautiful.html isn t it beautiful suteki da ne] [http://thecrownless.ifrance.com/il-futurismo-in/index.html il futurismo in arte] [http://oddonpurpose.ifrance.com/lil-jon-and.html lil jon and the eastside boyz] [http://taylors-acolyte.ifrance.com/imbarco-olbia.html imbarco olbia] [http://eliasn5gh.ifrance.com/los-machucambos.html los machucambos pepito] [http://angeljazz711.ifrance.com/ipostenia.html ipostenia] [http://listmishyk.ifrance.com/katy-playground/index.html katy playground] [http://pupsik1993.ifrance.com/l-aumour-toujours.html l aumour toujours] [http://carbonphoenix.ifrance.com/judy-weiss.html judy weiss] [http://taylors-acolyte.ifrance.com/innamorarsi-in-riviera.html innamorarsi in riviera] [http://risdimpuka.ifrance.com/la-serenella/index.html la serenella] [http://carbonphoenix.ifrance.com/jericho-di-rosetta.html jericho di rosetta tharpe] [http://oddonpurpose.ifrance.com/laudato-sii-mio.html laudato sii mio dolcissimo signore] [http://xxxenichkaa.ifrance.com/last-minute-offerte.html last minute offerte viaggi] [http://carbonphoenix.ifrance.com/jingle-bell-rock-joe.html jingle bell rock joe beal e jim boothe] [http://snakeystil.ifrance.com/julieta-veniegas/index.html julieta veniegas] [http://risdimpuka.ifrance.com/lenceria-sexi/index.html lenceria sexi] [http://cuivenarius.ifrance.com/harry-potter-com.html harry potter com] [http://oddonpurpose.ifrance.com/lineadeigolfi.html lineadeigolfi] [http://eliasn5gh.ifrance.com/la-cesta.html la cesta] [http://xxxenichkaa.ifrance.com/libertango.html libertango] [http://pupsik1993.ifrance.com/ludmilla-radchenko.html ludmilla radchenko letterina] [http://busjavka.ifrance.com/hamman-della-rosa/index.html hamman della rosa] [http://taylors-acolyte.ifrance.com/igrale-se-delije.html igrale se delije] [http://angeljazz711.ifrance.com/intimissimo.html intimissimo] [http://plyuh-vios.ifrance.com/inno-rifondazione-comunista.html inno rifondazione comunista] [http://fluffy-mind.ifrance.com/kim-sunill.html kim sunill] [http://busjavka.ifrance.com/http-www-bdsm-sex/index.html http www bdsm sex ru] [http://carbonphoenix.ifrance.com/jaclyn-smith.html jaclyn smith] [http://fluffy-mind.ifrance.com/kury.html kury] [http://katzella.ifrance.com/haiduchi-dragostea/index.html haiduchi dragostea din tei mai ai hii] [http://pupsik1993.ifrance.com/low-rider.html low rider] [http://taylors-acolyte.ifrance.com/il-mondo-insieme-a-te.html il mondo insieme a te mp3] [http://alexandraa80.ifrance.com/la-citta-de-pullecenella/index.html la citta de pullecenella] [http://alexandraa80.ifrance.com/lady-be-beatles/index.html lady be beatles] [http://alexandraa80.ifrance.com/lecabloc/index.html lecabloc] [http://child-ofadot.ifrance.com/il-secondo-tragico.html il secondo tragico fantozzi] [http://thecrownless.ifrance.com/italia-d-oro/index.html italia d oro] [http://child-ofadot.ifrance.com/il-film-un-principo.html il film un principo tutto mio] [http://cuivenarius.ifrance.com/hotel-canazei.html hotel canazei] [http://starcross33.ifrance.com/la-festa-dei-folli/index.html la festa dei folli] [http://cuivenarius.ifrance.com/hello-evanescene.html hello evanescene] [http://child-ofadot.ifrance.com/i-ll-drown-in-my.html i ll drown in my own tears] [http://plyuh-vios.ifrance.com/in-the-shadows.html in the shadows] [http://child-ofadot.ifrance.com/inno-brigata.html inno brigata sassari] [http://chasingspaces.ifrance.com/hotel-5-stelle-roma/index.html hotel 5 stelle roma hotel] [http://thecrownless.ifrance.com/italo-janne/index.html italo janne] [http://plyuh-vios.ifrance.com/i-vatussi-mp3.html i vatussi mp3] [http://busjavka.ifrance.com/hit-mania-dnce-2004/index.html hit mania dnce 2004] [http://eliasn5gh.ifrance.com/lisa-gerrad.html lisa gerrad] [http://alexandraa80.ifrance.com/laura-andresan-e-mutu/index.html laura andresan e mutu] [http://taylors-acolyte.ifrance.com/irvin-goffman.html irvin goffman] [http://plyuh-vios.ifrance.com/illeone.html illeone] [http://snakeystil.ifrance.com/juegos-olimpicos/index.html juegos olimpicos atenas 2004] [http://busjavka.ifrance.com/hymne-a-l-amour/index.html hymne a l amour] [http://cuivenarius.ifrance.com/hector-y-tito-gata.html hector y tito gata salvage] [http://oddonpurpose.ifrance.com/lucybell.html lucybell] [http://child-ofadot.ifrance.com/isola-dei-famosi.html isola dei famosi 2003] [http://pupsik1993.ifrance.com/let-s-go-trick-dady.html let s go trick dady] [http://cuivenarius.ifrance.com/hey-ho-lets-go.html hey ho lets go] [http://angeljazz711.ifrance.com/iwan-i-delfin.html iwan i delfin czarne oczy mp3] [http://alexandraa80.ifrance.com/la-vie-rose-testo/index.html la vie rose testo canzone] [http://oddonpurpose.ifrance.com/love-my-live.html love my live] [http://taylors-acolyte.ifrance.com/inbet.html inbet] [http://xxxenichkaa.ifrance.com/le-vent-nous-portera.html le vent nous portera noir desire] [http://plyuh-vios.ifrance.com/il-ballo-di-simoni.html il ballo di simoni] [http://cuivenarius.ifrance.com/haiuch.html haiuch] [http://angeljazz711.ifrance.com/imprenditoria.html imprenditoria] [http://xxxenichkaa.ifrance.com/la-danse-de-zorba.html la danse de zorba] [http://cuivenarius.ifrance.com/himno-nacional-colombiano.html himno nacional colombiano] [http://chasingspaces.ifrance.com/garante-della-privacy/index.html garante della privacy] [http://eliasn5gh.ifrance.com/luoghi-sadomaso.html luoghi sadomaso] [http://child-ofadot.ifrance.com/i-delfino-pesci.html i delfino pesci] [http://child-ofadot.ifrance.com/il-gladiatore-di-russel.html il gladiatore di russel crowe] [http://plyuh-vios.ifrance.com/i-life.html i life] [http://taylors-acolyte.ifrance.com/il-dopo-guerra.html il dopo guerra] [http://katzella.ifrance.com/icarito-cl/index.html icarito cl] [http://xxxenichkaa.ifrance.com/lubrificanti-oli.html lubrificanti oli e grassi] [http://snakeystil.ifrance.com/jessyca-rizzo/index.html jessyca rizzo] [http://alexandraa80.ifrance.com/lupo-animale/index.html lupo animale] [http://child-ofadot.ifrance.com/il-mondo-che-non.html il mondo che non c e] [http://listmishyk.ifrance.com/karama/index.html karama] [http://starcross33.ifrance.com/le-donne-di-baggio/index.html le donne di baggio] [http://pupsik1993.ifrance.com/los-vanvan.html los vanvan] [http://pupsik1993.ifrance.com/lei-cerca-gigolo.html lei cerca gigolo] [http://chasingspaces.ifrance.com/giorgio-vanni/index.html giorgio vanni dragon ball gt] [http://chasingspaces.ifrance.com/hex-tv-cabo/index.html hex tv cabo] [http://chasingspaces.ifrance.com/henya/index.html henya] [http://starcross33.ifrance.com/luana-piovanni/index.html luana piovanni] [http://cuivenarius.ifrance.com/heavy-on-my-heart.html heavy on my heart anastacia] [http://xxxenichkaa.ifrance.com/lettere-giapponesi.html lettere giapponesi] [http://busjavka.ifrance.com/hombres-y-mujeres/index.html hombres y mujeres desnudas] [http://carbonphoenix.ifrance.com/j-five.html j five] [http://angeljazz711.ifrance.com/immobiliare.html immobiliare argentario] [http://plyuh-vios.ifrance.com/illusion-benassi-bros.html illusion benassi bros f sandy] [http://busjavka.ifrance.com/http-www-rosasalvatore/index.html http www rosasalvatore com] [http://xxxenichkaa.ifrance.com/la-funzione-del.html la funzione del riscaldamento nello spor] [http://chasingspaces.ifrance.com/greco-esame-maturita/index.html greco esame maturita 2004] [http://listmishyk.ifrance.com/katal/index.html katal] [http://taylors-acolyte.ifrance.com/if-i-could.html if i could] [http://eliasn5gh.ifrance.com/la-chanson-des.html la chanson des vieux amants] [http://thecrownless.ifrance.com/io-cisaro/index.html io cisaro] [http://snakeystil.ifrance.com/juliana-bbb/index.html juliana bbb] [http://eliasn5gh.ifrance.com/loreena-mackennitt.html loreena mackennitt] [http://katzella.ifrance.com/hoang-oanh/index.html hoang oanh] [http://pupsik1993.ifrance.com/leone-alato.html leone alato] [http://pupsik1993.ifrance.com/lancio-del-pinguino.html lancio del pinguino] [http://risdimpuka.ifrance.com/lsass-exe/index.html lsass exe] [http://angeljazz711.ifrance.com/iraq-baldoni-foto.html iraq baldoni foto] [http://alexandraa80.ifrance.com/l-italiano-karaoke/index.html l italiano karaoke] [http://plyuh-vios.ifrance.com/io-della-vita-non.html io della vita non ha capito un cazzo] [http://fluffy-mind.ifrance.com/katrin-grande-fratello.html katrin grande fratello europeo] [http://eliasn5gh.ifrance.com/lunove-price.html lunove price] [http://pupsik1993.ifrance.com/la-conga.html la conga] [http://risdimpuka.ifrance.com/laetitia-casta/index.html laetitia casta nuda] [http://snakeystil.ifrance.com/j-veux-d-la-tendresse/index.html j veux d la tendresse] [http://eliasn5gh.ifrance.com/let-outside-alona.html let outside alona] [http://alexandraa80.ifrance.com/lyrics-y-m-c-a/index.html lyrics y m c a] [http://busjavka.ifrance.com/hotel-on-line/index.html hotel on line] [http://alexandraa80.ifrance.com/locman/index.html locman] [http://snakeystil.ifrance.com/jinatera/index.html jinatera] [http://carbonphoenix.ifrance.com/just-for-jou.html just for jou] [http://alexandraa80.ifrance.com/le-vent-nour/index.html le vent nour portera] [http://fluffy-mind.ifrance.com/k-mari.html k mari] [http://eliasn5gh.ifrance.com/lumydee.html lumydee] [http://taylors-acolyte.ifrance.com/in-the-disco.html in the disco] [http://pupsik1993.ifrance.com/lo-strano-percorso-pezzali.html lo strano percorso pezzali max] [http://snakeystil.ifrance.com/i-piu-gattonati/index.html i piu gattonati] [http://eliasn5gh.ifrance.com/legge-20-maggio-1970.html legge 20 maggio 1970 n 300] [http://eliasn5gh.ifrance.com/locali-prive.html locali prive] [http://angeljazz711.ifrance.com/in-alto-mare-di.html in alto mare di 2black] [http://snakeystil.ifrance.com/jelena-brocic/index.html jelena brocic] [http://risdimpuka.ifrance.com/lyon-sorties/index.html lyon sorties] [http://listmishyk.ifrance.com/kal-ho/index.html kal ho] [http://eliasn5gh.ifrance.com/les-deux-alpes.html les deux alpes] [http://oddonpurpose.ifrance.com/la-sorpresa-un.html la sorpresa un raggio di sole] [http://starcross33.ifrance.com/la-fattoria-danza-del/index.html la fattoria danza del ventre] [http://katzella.ifrance.com/helene-sviden/index.html helene sviden] [http://chasingspaces.ifrance.com/htomail/index.html htomail] [http://fluffy-mind.ifrance.com/kanye-west-jesus.html kanye west jesus walks] [http://xxxenichkaa.ifrance.com/las-mejores-tetas.html las mejores tetas del mundo] [http://fluffy-mind.ifrance.com/k-amaro-femme.html k amaro femme like u] [http://snakeystil.ifrance.com/jennifer-lopez/index.html jennifer lopez sex images] [http://alexandraa80.ifrance.com/lucchesi-ad-atene/index.html lucchesi ad atene] [http://carbonphoenix.ifrance.com/jennifer-saunders.html jennifer saunders holding out for a hero] [http://listmishyk.ifrance.com/karl/index.html karl] [http://chasingspaces.ifrance.com/howell/index.html howell] [http://plyuh-vios.ifrance.com/i-don-t-wona-know.html i don t wona know] [http://child-ofadot.ifrance.com/il-gran-sole-di-hiroshima.html il gran sole di hiroshima] [http://pupsik1993.ifrance.com/let-s-dance.html let s dance] [http://eliasn5gh.ifrance.com/linear-assicurazioni.html linear assicurazioni] [http://busjavka.ifrance.com/hombres-en-calzoncillos/index.html hombres en calzoncillos] [http://angeljazz711.ifrance.com/it-s-al-right.html it s al right] [http://angeljazz711.ifrance.com/immagini-di-persone.html immagini di persone] [http://pupsik1993.ifrance.com/lauro-prenna.html lauro prenna] [http://taylors-acolyte.ifrance.com/indicatore-della.html indicatore della situazione economica eq] [http://thecrownless.ifrance.com/isac-hugo/index.html isac hugo] [http://snakeystil.ifrance.com/jordan-james/index.html jordan james] [http://snakeystil.ifrance.com/jasmin-muharemovic-nocima/index.html jasmin muharemovic nocima i danima] [http://listmishyk.ifrance.com/kiosque-code/index.html kiosque code] [http://eliasn5gh.ifrance.com/lupus-in-fabula.html lupus in fabula] [http://alexandraa80.ifrance.com/la-vita-e-bella-nicola/index.html la vita e bella nicola piovani] [http://risdimpuka.ifrance.com/linee-erotiche/index.html linee erotiche] [http://busjavka.ifrance.com/hallospank/index.html hallospank] [http://oddonpurpose.ifrance.com/liviu-gut-mp3.html liviu gut mp3] [http://angeljazz711.ifrance.com/ingres-il-bagno.html ingres il bagno turco] [http://angeljazz711.ifrance.com/inchiappettare.html inchiappettare] [http://cuivenarius.ifrance.com/hundai.html hundai] [http://fluffy-mind.ifrance.com/koftos.html koftos] [http://plyuh-vios.ifrance.com/island-of-ustica.html island of ustica] [http://eliasn5gh.ifrance.com/latin.html latin] [http://starcross33.ifrance.com/le-ghiaie/index.html le ghiaie] [http://pupsik1993.ifrance.com/laps-dance.html laps dance] [http://starcross33.ifrance.com/legge-sulla-praivasi/index.html legge sulla praivasi] [http://alexandraa80.ifrance.com/lg-5410/index.html lg 5410] [http://pupsik1993.ifrance.com/lungotevere-dorme.html lungotevere dorme] [http://eliasn5gh.ifrance.com/loyd.html loyd] [http://cuivenarius.ifrance.com/hilltop-hoods-the-nosebleed.html hilltop hoods the nosebleed section] [http://listmishyk.ifrance.com/khoa-than/index.html khoa than] [http://oddonpurpose.ifrance.com/l-elefante-e.html l elefante e la formica] [http://chasingspaces.ifrance.com/gioditonnofansclub/index.html gioditonnofansclub] [http://alexandraa80.ifrance.com/les-demoiselles/index.html les demoiselles d avignon] [http://risdimpuka.ifrance.com/la-bella-pastorella/index.html la bella pastorella] {{development}}&lt;br /&gt;
&lt;br /&gt;
Export plugins increase the value of your repository by allowing users to get data out in the format they want. &lt;br /&gt;
&lt;br /&gt;
Export plugins also help Integrate your repository with other systems by allowing the systems to exchange data via an interchange format.&lt;br /&gt;
&lt;br /&gt;
EPrints 3 is packaged with a number of export plugins, and export plugins are also developed and shared by other EPrints users. &lt;br /&gt;
&lt;br /&gt;
The purpose of this guide is to describe how to create new export plugins for your repository. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Before getting started&#039;&#039;&#039;, check that the output/interchange format that you want to add to your repository has not already been made available in the EPrints Files repository: http://files.eprints.org/view/type/plugin.html &lt;br /&gt;
&lt;br /&gt;
Plugins are written in Perl, so some coding experience is required, as is a familiarity with the EPrints API.&lt;br /&gt;
&lt;br /&gt;
==Export plugin overview==&lt;br /&gt;
&lt;br /&gt;
An EPrints export plugin is typically a standalone Perl module. There are 2 key functions that an export plugin must carry out:&lt;br /&gt;
&lt;br /&gt;
# Register with EPrints&lt;br /&gt;
# Define how to convert EPrint records to the output/interchange format&lt;br /&gt;
&lt;br /&gt;
===Registration===&lt;br /&gt;
&lt;br /&gt;
Export plugins register the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;name&#039;&#039; - the name of the plugin&lt;br /&gt;
* &#039;&#039;visible&#039;&#039; - who can use it&lt;br /&gt;
* &#039;&#039;accept&#039;&#039; - what the plugin can convert&lt;br /&gt;
** lists of records or single records (or both)&lt;br /&gt;
** type of record (eprints, users, subjects.. see [[Data_Object|EPrints data objects]])&lt;br /&gt;
* &#039;&#039;suffix&#039;&#039;  and &#039;&#039;mimetype&#039;&#039; - file extension and MIME type of format it converts to&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: BibTeX export plugin (extract from registration section)&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;BibTeX&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/eprint&#039;, &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.bib&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/plain&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This BibTeX export plugin can convert lists of [[EPrint_Object|eprints]] or single eprints, is available to all users, and produces a plain text file with a .bib extension.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: XML (with embedded files) export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;EP3 XML with Files Embeded&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/eprint&#039;, &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;staff&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.xml&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This XML export plugin is available to repository staff only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: DIDL export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;DIDL&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.xml&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This DIDL export plugin can handle only a single eprint record at a time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: FOAF export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;FOAF Export&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;dataobj/user&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.rdf&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This FOAF export plugin converts a single [[User_Object|user]] record.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: XML export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;EP3 XML&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/*&#039;, &#039;dataobj/*&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.xml&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This XML export plugin can handle lists or individual records of [[Data_Object|any type]].&lt;br /&gt;
&lt;br /&gt;
===Conversion===&lt;br /&gt;
&lt;br /&gt;
This might include &#039;&#039;&#039;mapping&#039;&#039;&#039; EPrints fields to output/interchange format fields and &#039;&#039;&#039;serialising&#039;&#039;&#039; the output/interchange format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: EndNote export plugin (extract from conversion section)&lt;br /&gt;
&lt;br /&gt;
        # K Keywords&lt;br /&gt;
        $data-&amp;gt;{K} = $dataobj-&amp;gt;get_value( &amp;quot;keywords&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;keywords&amp;quot; );&lt;br /&gt;
        # T Title&lt;br /&gt;
        $data-&amp;gt;{T} = $dataobj-&amp;gt;get_value( &amp;quot;title&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;title&amp;quot; );&lt;br /&gt;
        # U URL&lt;br /&gt;
        $data-&amp;gt;{U} = $dataobj-&amp;gt;get_url;&lt;br /&gt;
        # X Abstract&lt;br /&gt;
        $data-&amp;gt;{X} = $dataobj-&amp;gt;get_value( &amp;quot;abstract&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;abstract&amp;quot; );&lt;br /&gt;
        # Z Notes&lt;br /&gt;
        $data-&amp;gt;{Z} = $dataobj-&amp;gt;get_value( &amp;quot;note&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;note&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
This extract shows how the values of the EndNote fields %K, %T, %U, %X and %Z are mapped from the [[EPrint_Object]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: Text export plugin (extract from conversion section)&lt;br /&gt;
&lt;br /&gt;
        my $cite = $dataobj-&amp;gt;render_citation;&lt;br /&gt;
        return EPrints::Utils::tree_to_utf8( $cite ).&amp;quot;\n\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To serialise an [[EPrint_Object]], the Text export plugin simply outputs the citation.&lt;br /&gt;
&lt;br /&gt;
==Hello World export plugin==&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Hello_world_program&lt;br /&gt;
&lt;br /&gt;
Export plugins are stored in:&lt;br /&gt;
&lt;br /&gt;
 /opt/eprints3/perl_lib/EPrints/Plugin/Export/&lt;br /&gt;
&lt;br /&gt;
Create a new file in this directory called &#039;&#039;HelloWorld.pm&#039;&#039;, and paste the following code into it (this is a useful template for writing export plugins!):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package EPrints::Plugin::Export::HelloWorld;&lt;br /&gt;
&lt;br /&gt;
use EPrints::Plugin::Export;&lt;br /&gt;
@ISA = ( &amp;quot;EPrints::Plugin::Export&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
        my( $class, %opts ) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub output_dataobj&lt;br /&gt;
{&lt;br /&gt;
        my( $plugin, $dataobj ) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;new&#039;&#039; subroutine creates the plugin - this is where you &#039;&#039;&#039;register&#039;&#039;&#039; the plugin with EPrints. The &#039;&#039;output_dataobj&#039;&#039; subroutine is where you &#039;&#039;&#039;convert&#039;&#039;&#039; EPrints data to the output format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Perl notes:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tt&amp;gt;package ...&amp;lt;/tt&amp;gt; - the plugin (Perl module) namespace, which should always be EPrints::Plugin::Export::&#039;&#039;PluginID&#039;&#039; (note that the file should be called &#039;&#039;PluginID&#039;&#039;.pm)&lt;br /&gt;
# &amp;lt;tt&amp;gt;use EPrints::Plugin::Export, @ISA=...&amp;lt;/tt&amp;gt; - inherit all the internal wiring needed for EPrints to use your plugin&lt;br /&gt;
&lt;br /&gt;
===Register Hello World plugin===&lt;br /&gt;
&lt;br /&gt;
Add the following to the &#039;&#039;new&#039;&#039; subroutine to register the plugin with EPrints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
        my( $class, %opts ) = @_;&lt;br /&gt;
&lt;br /&gt;
        my $self = $class-&amp;gt;SUPER::new( %opts );&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;Hello, World!&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;dataobj/eprint&#039;, &#039;list/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.txt&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/plain; charset=utf-8&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        return $self;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert EPrints data to Hello World data===&lt;br /&gt;
&lt;br /&gt;
Add the following to the &#039;&#039;output_dataobj&#039;&#039; subroutine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub output_dataobj&lt;br /&gt;
{&lt;br /&gt;
        my( $plugin, $dataobj ) = @_;&lt;br /&gt;
&lt;br /&gt;
        my $title = $dataobj-&amp;gt;get_value( &amp;quot;title&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        return &amp;quot;Hello, World! $title\n\n&amp;quot;;&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This subroutine &amp;quot;converts&amp;quot; an eprint object by getting its title and using it in a Hello, World! message.&lt;br /&gt;
&lt;br /&gt;
===Testing the Hello World plugin===&lt;br /&gt;
&lt;br /&gt;
Save the &#039;&#039;HelloWorld.pm&#039;&#039; file and then restart the Web server, eg.:&lt;br /&gt;
&lt;br /&gt;
 service httpd restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Why do I need to restart the Web server?&#039;&#039;&#039; EPrints uses mod_perl which loads all Perl modules at start up; therefore whenever these modules change they need to be reloaded.&lt;br /&gt;
&lt;br /&gt;
The Hello World export plugin handles lists of eprints and single eprints. Therefore, EPrints displays it in the list of export plugins on the search results page: &lt;br /&gt;
&lt;br /&gt;
[[Image:Hello-world-export.png|frame|none|Selecting the Hello World export plugin from the search results page]]&lt;br /&gt;
&lt;br /&gt;
When the Hello World export plugin is activated, the &#039;&#039;convert_dataobj&#039;&#039; subroutine is applied to every item in the list to produce the result:&lt;br /&gt;
&lt;br /&gt;
[[Image:Hello-world-export-result.png|frame|none|The output of the Hello World export plugin]]&lt;br /&gt;
&lt;br /&gt;
==Walkthough: Using existing plugins to build new plugins==&lt;br /&gt;
&lt;br /&gt;
==Walkthrough: Deposit activity plugin== &lt;br /&gt;
&lt;br /&gt;
Imagine we want to create an export plugin that will take a group of eprints (or a single eprint) and output a csv file containing a list of who deposited the eprints, and the dates on which they were deposited.&lt;br /&gt;
&lt;br /&gt;
===Registration===&lt;br /&gt;
&lt;br /&gt;
The top of the plugin should look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 package EPrints::Plugin::Export::DepositorActivity;&lt;br /&gt;
 &lt;br /&gt;
 use Unicode::String qw( utf8 );&lt;br /&gt;
 use EPrints::Plugin::Export;&lt;br /&gt;
 use EPrints::DataObj::User;&lt;br /&gt;
 @ISA = ( &amp;quot;EPrints::Plugin::Export&amp;quot; );&lt;br /&gt;
 use strict;&lt;br /&gt;
 &lt;br /&gt;
 sub new&lt;br /&gt;
 {&lt;br /&gt;
        my( $class, %params ) = @_;&lt;br /&gt;
 &lt;br /&gt;
        my $self = $class-&amp;gt;SUPER::new( %params );&lt;br /&gt;
 &lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;Depositor Activity&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/eprint&#039;, &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.csv&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/csv&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
        return $self;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will create a filter object, and set a number of configuration constants:&lt;br /&gt;
&lt;br /&gt;
* name - The name of the filter&lt;br /&gt;
* accept - A list detailing what the filter will take as inputs.  In this case, a list of eprints or a single eprint.  It is possible to write filters for dataobj types &#039;eprint&#039;, &#039;user&#039;, &#039;subject&#039;, &#039;history&#039;, &#039;access&#039; and &#039;*&#039; (all).&lt;br /&gt;
* visible - Who can see this filter.  It&#039;s set to &#039;all&#039; above so that anyone can use it.  It could be set to &#039;staff&#039; to only allow repository staff to use it.  If set to &#039;API&#039; then the filter is not available through the web interface.&lt;br /&gt;
* suffix - Appended to the url to create a filename extension.&lt;br /&gt;
* mimetype - Should be set to the correct mime type for the output of the filter.&lt;br /&gt;
&lt;br /&gt;
Note that &#039;name&#039; and &#039;accept&#039; are essential.  These allow the filter to register itself with EPrints.&lt;br /&gt;
&lt;br /&gt;
We will be extracting the username of the depositor, so we need to use &#039;EPrints::DataObj::User&#039;.&lt;br /&gt;
&lt;br /&gt;
===Conversion===&lt;br /&gt;
&lt;br /&gt;
The &#039;output_dataobj&#039; function takes a dataobj (in our case an eprint object) and returns a perl scalar which will be the output.  We are going to extract some data from the dataobj using EPrints API calls.&lt;br /&gt;
&lt;br /&gt;
Note that by convention, &#039;$plugin&#039; is used instead of &#039;$self&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_dataobj&lt;br /&gt;
 {&lt;br /&gt;
       my( $plugin, $dataobj ) = @_;&lt;br /&gt;
 &lt;br /&gt;
       my $r = &amp;quot;&amp;quot;;&lt;br /&gt;
       if ($dataobj-&amp;gt;exists_and_set(&amp;quot;userid&amp;quot;))                                       #userid may not be set if the deposit was done by a script.&lt;br /&gt;
       {&lt;br /&gt;
               my $session = $plugin-&amp;gt;{&amp;quot;session&amp;quot;}; &lt;br /&gt;
               my $userid = $dataobj-&amp;gt;get_value( &amp;quot;userid&amp;quot; );&lt;br /&gt;
               my $depositor_obj = new EPrints::DataObj::User($session, $userid);    #create a user object&lt;br /&gt;
               my $depositor = $depositor_obj-&amp;gt;get_value( &amp;quot;username&amp;quot; );              #get the user ID&lt;br /&gt;
               if ($depositor =~ m/[\n&amp;quot; ,]/)                                         #Check for illegal CSV characters&lt;br /&gt;
               {&lt;br /&gt;
                       $depositor =~ s/&amp;quot;/&amp;quot;&amp;quot;/g;                                       #escape quotes&lt;br /&gt;
                       $depositor = &#039;&amp;quot;&#039; . $depositor . &#039;&amp;quot;&#039;;                          #delimit text&lt;br /&gt;
               }&lt;br /&gt;
               $r .= $depositor;&lt;br /&gt;
       }&lt;br /&gt;
       else&lt;br /&gt;
       {&lt;br /&gt;
               $r .= &#039;&amp;quot;Depositor Unknown&amp;quot;&#039;;&lt;br /&gt;
       }&lt;br /&gt;
       $r .= &#039;,&amp;quot;&#039; . $dataobj-&amp;gt;get_value( &amp;quot;datestamp&amp;quot; ) . &#039;&amp;quot;&#039; .&amp;quot;\n&amp;quot;;                   #datestamp is always set, and contains a space so needs delimiting&lt;br /&gt;
 &lt;br /&gt;
       return $r;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
* Retreiving the username takes a little fancy footwork because the EPrints object contains depositor userids.  We need to create a user object and get the username from that.&lt;br /&gt;
* We use &#039;$dataobj-&amp;gt;get_value&#039; to retrieve metadata from the eprint (or user) objects.&lt;br /&gt;
* As we&#039;re outputting in CSV, we need to do a little normalisation.&lt;br /&gt;
&lt;br /&gt;
===Put it in a Module===&lt;br /&gt;
&lt;br /&gt;
Put all this into a file called &#039;DepositorActivity.pm&#039; and save the file into the &#039;eprints3/perl_lib/EPrints/Plugin/Export/&#039; directory.  Don&#039;t forget to add this to the bottom of the file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Before you can use the plugin, you must restart the webserver.  This will cause EPrints to load it.&lt;br /&gt;
&lt;br /&gt;
===Adding Column Headings===&lt;br /&gt;
&lt;br /&gt;
The &#039;output_dataobj&#039; runs on a single EPrint.  If the plugin runs over a list of eprints (we&#039;ve given it that capability), the default behaviour is to run &#039;output_dataobj&#039; on every eprint in the list and concatenate the results.&lt;br /&gt;
&lt;br /&gt;
The output_list function is what handles the lists.  This takes itself ($plugin) and a hash (%opts) as arguments.  The %opt hash contains the list.  It could also contain a filehandle.  When writing &#039;output_list&#039;, you need to check for the filehandle and if present, print to it.  If it&#039;s not present, return the results as a scalar.&lt;br /&gt;
&lt;br /&gt;
Here is an output_list function that will add column headings to our CSV file.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_list&lt;br /&gt;
 {&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my $r = [];                                                      #array for results accumulation&lt;br /&gt;
        my $part;&lt;br /&gt;
 &lt;br /&gt;
        $part = &#039;&amp;quot;User ID&amp;quot;,&amp;quot;Date Stamp&amp;quot;&#039; . &amp;quot;\n&amp;quot;;                         #column headings&lt;br /&gt;
        if( defined $opts{fh} )                                          #write to file or accumulate headings&lt;br /&gt;
        {&lt;br /&gt;
                print {$opts{fh}} $part;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
                push @{$r}, $part;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        foreach my $dataobj ( $opts{list}-&amp;gt;get_records )                 #Iterate over list&lt;br /&gt;
        {&lt;br /&gt;
                $part = $plugin-&amp;gt;output_dataobj( $dataobj, %opts );      #call output_dataobj&lt;br /&gt;
                if( defined $opts{fh} )                                  #write to file or accumulate results&lt;br /&gt;
                {&lt;br /&gt;
                         print {$opts{fh}} $part;&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                {&lt;br /&gt;
                        push @{$r}, $part;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        if( defined $opts{fh} )                                          #Don&#039;t return results if writing to file.&lt;br /&gt;
        {&lt;br /&gt;
                return;&lt;br /&gt;
        }&lt;br /&gt;
        return join( &#039;&#039;, @{$r} );&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The conditionals for printing to a file make the function look overly complex.  Here it is if you ignore file handles (which you certainly shouldn&#039;t do):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_list&lt;br /&gt;
 {&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my $r = [];                                                      #array for results accumulation&lt;br /&gt;
        my $part;&lt;br /&gt;
 &lt;br /&gt;
        $part = &#039;&amp;quot;User ID&amp;quot;,&amp;quot;Date Stamp&amp;quot;&#039; . &amp;quot;\n&amp;quot;;                         #column headings&lt;br /&gt;
        push @{$r}, $part;&lt;br /&gt;
        foreach my $dataobj ( $opts{list}-&amp;gt;get_records )                 #Iterate over list&lt;br /&gt;
        {&lt;br /&gt;
                $part = $plugin-&amp;gt;output_dataobj( $dataobj, %opts );      #call output_dataobj&lt;br /&gt;
                push @{$r}, $part;&lt;br /&gt;
        }&lt;br /&gt;
        return join( &#039;&#039;, @{$r} );&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===More Complex List Processing===&lt;br /&gt;
&lt;br /&gt;
output_list can be used to do more than simple concatenating results from output_dataobj.  For example, the plugin above will output a table containing one entry for every eprint showing the depositor and the deposit date.  Perhaps this could be made more useful by changing the table so that it contains a row for each user that deposited an eprint.  Perhaps three columns (userid, number of deposits, datestamp of latest deposit) could be useful.&lt;br /&gt;
&lt;br /&gt;
For readability, output_list is shown without filehandle handling.  If this were a real filter, IT WOULD BE NECESSARY!&lt;br /&gt;
&lt;br /&gt;
Firstly, an auxhillary function that will return a CSV normalised username.  It&#039;s similar to the output_data function above, so should be easy to understand.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub get_username&lt;br /&gt;
 {&lt;br /&gt;
       my( $plugin, $dataobj ) = @_;&lt;br /&gt;
 &lt;br /&gt;
       my $username;&lt;br /&gt;
       if ($dataobj-&amp;gt;exists_and_set(&amp;quot;userid&amp;quot;))                                     #userid may not be set if the deposit was done by a script.&lt;br /&gt;
       {&lt;br /&gt;
               my $session = $plugin-&amp;gt;{&amp;quot;session&amp;quot;};&lt;br /&gt;
               my $userid = $dataobj-&amp;gt;get_value( &amp;quot;userid&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
               my $depositor_obj = new EPrints::DataObj::User($session, $userid);  #create a user object&lt;br /&gt;
               my $depositor = $depositor_obj-&amp;gt;get_value( &amp;quot;username&amp;quot; );            #get the user ID&lt;br /&gt;
               if ($depositor =~ m/[\n&amp;quot; ,]/)         #Check for illegal CSV characters&lt;br /&gt;
               {&lt;br /&gt;
                       $depositor =~ s/&amp;quot;/&amp;quot;&amp;quot;/g; #escape quotes&lt;br /&gt;
                       $depositor = &#039;&amp;quot;&#039; . $depositor . &#039;&amp;quot;&#039;; #delimit text&lt;br /&gt;
               }&lt;br /&gt;
               $username = $depositor;&lt;br /&gt;
       }&lt;br /&gt;
       else&lt;br /&gt;
       {&lt;br /&gt;
               $username = &#039;&amp;quot;Depositor Unknown&amp;quot;&#039;;&lt;br /&gt;
       }&lt;br /&gt;
       return $username;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The new output_list function uses a hash to accumlate the results:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_list&lt;br /&gt;
 {&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my %r = ();&lt;br /&gt;
 &lt;br /&gt;
        #Iterate over the list&lt;br /&gt;
        foreach my $dataobj ( $opts{list}-&amp;gt;get_records )&lt;br /&gt;
        {&lt;br /&gt;
                my $username = $plugin-&amp;gt;get_username( $dataobj );&lt;br /&gt;
                my $datestamp = &#039;&amp;quot;&#039; . $dataobj-&amp;gt;get_value( &amp;quot;datestamp&amp;quot; ) . &#039;&amp;quot;&#039;;&lt;br /&gt;
                if (defined $r{$username})                                        #if it&#039;s defined, increment and compare timestamps&lt;br /&gt;
                {&lt;br /&gt;
                        $r{$username}-&amp;gt;{count}   ;&lt;br /&gt;
                        if ($r{$username}-&amp;gt;{most_recent} lt $datestamp)&lt;br /&gt;
                        {&lt;br /&gt;
                                $r{$username}-&amp;gt;{most_recent} = $datestamp;&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                else                                                              #if it&#039;s not defined, create a hash for this user&#039;s results&lt;br /&gt;
                {&lt;br /&gt;
                        $r{$username} = {count =&amp;gt; 1, most_recent =&amp;gt; $datestamp};&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        # Construct the CSV and return it.&lt;br /&gt;
        my $csv = &#039;&amp;quot;User Name&amp;quot;,&amp;quot;Number of Deposits&amp;quot;,&amp;quot;Most Recent Deposit&amp;quot;&#039; . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        foreach my $username (sort keys %r)&lt;br /&gt;
        {&lt;br /&gt;
                $csv .= $username . &amp;quot;,&amp;quot; . $r{$username}-&amp;gt;{count} . &amp;quot;,&amp;quot; . $r{$username}-&amp;gt;{most_recent} . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        return $csv;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that because this plugin can take a single eprint as well as a list of eprints, you must have a output_dataobj function that will do something sensible.  However, bear in mind that search results are always a list, even if there&#039;s only one result.&lt;/div&gt;</summary>
		<author><name>Ma3I6n</name></author>
	</entry>
	<entry>
		<id>https://wiki.ext-9.eprints-hosting.org/w/index.php?title=Create_Export_Plugins&amp;diff=4396</id>
		<title>Create Export Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.ext-9.eprints-hosting.org/w/index.php?title=Create_Export_Plugins&amp;diff=4396"/>
		<updated>2007-06-07T03:42:35Z</updated>

		<summary type="html">&lt;p&gt;Ma3I6n: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{development}}&lt;br /&gt;
&lt;br /&gt;
Export plugins increase the value of your repository by allowing users to get data out in the format they want. &lt;br /&gt;
&lt;br /&gt;
Export plugins also help Integrate your repository with other systems by allowing the systems to exchange data via an interchange format.&lt;br /&gt;
&lt;br /&gt;
EPrints 3 is packaged with a number of export plugins, and export plugins are also developed and shared by other EPrints users. &lt;br /&gt;
&lt;br /&gt;
The purpose of this guide is to describe how to create new export plugins for your repository. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Before getting started&#039;&#039;&#039;, check that the output/interchange format that you want to add to your repository has not already been made available in the EPrints Files repository: http://files.eprints.org/view/type/plugin.html &lt;br /&gt;
&lt;br /&gt;
Plugins are written in Perl, so some coding experience is required, as is a familiarity with the EPrints API.&lt;br /&gt;
&lt;br /&gt;
==Export plugin overview==&lt;br /&gt;
&lt;br /&gt;
An EPrints export plugin is typically a standalone Perl module. There are 2 key functions that an export plugin must carry out:&lt;br /&gt;
&lt;br /&gt;
# Register with EPrints&lt;br /&gt;
# Define how to convert EPrint records to the output/interchange format&lt;br /&gt;
&lt;br /&gt;
===Registration===&lt;br /&gt;
&lt;br /&gt;
Export plugins register the following properties:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;name&#039;&#039; - the name of the plugin&lt;br /&gt;
* &#039;&#039;visible&#039;&#039; - who can use it&lt;br /&gt;
* &#039;&#039;accept&#039;&#039; - what the plugin can convert&lt;br /&gt;
** lists of records or single records (or both)&lt;br /&gt;
** type of record (eprints, users, subjects.. see [[Data_Object|EPrints data objects]])&lt;br /&gt;
* &#039;&#039;suffix&#039;&#039;  and &#039;&#039;mimetype&#039;&#039; - file extension and MIME type of format it converts to&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: BibTeX export plugin (extract from registration section)&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;BibTeX&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/eprint&#039;, &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.bib&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/plain&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This BibTeX export plugin can convert lists of [[EPrint_Object|eprints]] or single eprints, is available to all users, and produces a plain text file with a .bib extension.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: XML (with embedded files) export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;EP3 XML with Files Embeded&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/eprint&#039;, &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;staff&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.xml&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This XML export plugin is available to repository staff only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: DIDL export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;DIDL&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.xml&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This DIDL export plugin can handle only a single eprint record at a time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: FOAF export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;FOAF Export&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;dataobj/user&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.rdf&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This FOAF export plugin converts a single [[User_Object|user]] record.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: XML export plugin&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;EP3 XML&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/*&#039;, &#039;dataobj/*&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.xml&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/xml&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
This XML export plugin can handle lists or individual records of [[Data_Object|any type]].&lt;br /&gt;
&lt;br /&gt;
===Conversion===&lt;br /&gt;
&lt;br /&gt;
This might include &#039;&#039;&#039;mapping&#039;&#039;&#039; EPrints fields to output/interchange format fields and &#039;&#039;&#039;serialising&#039;&#039;&#039; the output/interchange format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: EndNote export plugin (extract from conversion section)&lt;br /&gt;
&lt;br /&gt;
        # K Keywords&lt;br /&gt;
        $data-&amp;gt;{K} = $dataobj-&amp;gt;get_value( &amp;quot;keywords&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;keywords&amp;quot; );&lt;br /&gt;
        # T Title&lt;br /&gt;
        $data-&amp;gt;{T} = $dataobj-&amp;gt;get_value( &amp;quot;title&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;title&amp;quot; );&lt;br /&gt;
        # U URL&lt;br /&gt;
        $data-&amp;gt;{U} = $dataobj-&amp;gt;get_url;&lt;br /&gt;
        # X Abstract&lt;br /&gt;
        $data-&amp;gt;{X} = $dataobj-&amp;gt;get_value( &amp;quot;abstract&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;abstract&amp;quot; );&lt;br /&gt;
        # Z Notes&lt;br /&gt;
        $data-&amp;gt;{Z} = $dataobj-&amp;gt;get_value( &amp;quot;note&amp;quot; ) if $dataobj-&amp;gt;exists_and_set( &amp;quot;note&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
This extract shows how the values of the EndNote fields %K, %T, %U, %X and %Z are mapped from the [[EPrint_Object]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example: Text export plugin (extract from conversion section)&lt;br /&gt;
&lt;br /&gt;
        my $cite = $dataobj-&amp;gt;render_citation;&lt;br /&gt;
        return EPrints::Utils::tree_to_utf8( $cite ).&amp;quot;\n\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To serialise an [[EPrint_Object]], the Text export plugin simply outputs the citation.&lt;br /&gt;
&lt;br /&gt;
==Hello World export plugin==&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Hello_world_program&lt;br /&gt;
&lt;br /&gt;
Export plugins are stored in:&lt;br /&gt;
&lt;br /&gt;
 /opt/eprints3/perl_lib/EPrints/Plugin/Export/&lt;br /&gt;
&lt;br /&gt;
Create a new file in this directory called &#039;&#039;HelloWorld.pm&#039;&#039;, and paste the following code into it (this is a useful template for writing export plugins!):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
package EPrints::Plugin::Export::HelloWorld;&lt;br /&gt;
&lt;br /&gt;
use EPrints::Plugin::Export;&lt;br /&gt;
@ISA = ( &amp;quot;EPrints::Plugin::Export&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
        my( $class, %opts ) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub output_dataobj&lt;br /&gt;
{&lt;br /&gt;
        my( $plugin, $dataobj ) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;new&#039;&#039; subroutine creates the plugin - this is where you &#039;&#039;&#039;register&#039;&#039;&#039; the plugin with EPrints. The &#039;&#039;output_dataobj&#039;&#039; subroutine is where you &#039;&#039;&#039;convert&#039;&#039;&#039; EPrints data to the output format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Perl notes:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tt&amp;gt;package ...&amp;lt;/tt&amp;gt; - the plugin (Perl module) namespace, which should always be EPrints::Plugin::Export::&#039;&#039;PluginID&#039;&#039; (note that the file should be called &#039;&#039;PluginID&#039;&#039;.pm)&lt;br /&gt;
# &amp;lt;tt&amp;gt;use EPrints::Plugin::Export, @ISA=...&amp;lt;/tt&amp;gt; - inherit all the internal wiring needed for EPrints to use your plugin&lt;br /&gt;
&lt;br /&gt;
===Register Hello World plugin===&lt;br /&gt;
&lt;br /&gt;
Add the following to the &#039;&#039;new&#039;&#039; subroutine to register the plugin with EPrints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub new&lt;br /&gt;
{&lt;br /&gt;
        my( $class, %opts ) = @_;&lt;br /&gt;
&lt;br /&gt;
        my $self = $class-&amp;gt;SUPER::new( %opts );&lt;br /&gt;
&lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;Hello, World!&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;dataobj/eprint&#039;, &#039;list/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.txt&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/plain; charset=utf-8&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        return $self;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Convert EPrints data to Hello World data===&lt;br /&gt;
&lt;br /&gt;
Add the following to the &#039;&#039;output_dataobj&#039;&#039; subroutine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub output_dataobj&lt;br /&gt;
{&lt;br /&gt;
        my( $plugin, $dataobj ) = @_;&lt;br /&gt;
&lt;br /&gt;
        my $title = $dataobj-&amp;gt;get_value( &amp;quot;title&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
        return &amp;quot;Hello, World! $title\n\n&amp;quot;;&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This subroutine &amp;quot;converts&amp;quot; an eprint object by getting its title and using it in a Hello, World! message.&lt;br /&gt;
&lt;br /&gt;
===Testing the Hello World plugin===&lt;br /&gt;
&lt;br /&gt;
Save the &#039;&#039;HelloWorld.pm&#039;&#039; file and then restart the Web server, eg.:&lt;br /&gt;
&lt;br /&gt;
 service httpd restart&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Why do I need to restart the Web server?&#039;&#039;&#039; EPrints uses mod_perl which loads all Perl modules at start up; therefore whenever these modules change they need to be reloaded.&lt;br /&gt;
&lt;br /&gt;
The Hello World export plugin handles lists of eprints and single eprints. Therefore, EPrints displays it in the list of export plugins on the search results page: &lt;br /&gt;
&lt;br /&gt;
[[Image:Hello-world-export.png|frame|none|Selecting the Hello World export plugin from the search results page]]&lt;br /&gt;
&lt;br /&gt;
When the Hello World export plugin is activated, the &#039;&#039;convert_dataobj&#039;&#039; subroutine is applied to every item in the list to produce the result:&lt;br /&gt;
&lt;br /&gt;
[[Image:Hello-world-export-result.png|frame|none|The output of the Hello World export plugin]]&lt;br /&gt;
&lt;br /&gt;
==Walkthough: Using existing plugins to build new plugins==&lt;br /&gt;
&lt;br /&gt;
==Walkthrough: Deposit activity plugin== &lt;br /&gt;
&lt;br /&gt;
Imagine we want to create an export plugin that will take a group of eprints (or a single eprint) and output a csv file containing a list of who deposited the eprints, and the dates on which they were deposited.&lt;br /&gt;
&lt;br /&gt;
===Registration===&lt;br /&gt;
&lt;br /&gt;
The top of the plugin should look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 package EPrints::Plugin::Export::DepositorActivity;&lt;br /&gt;
 &lt;br /&gt;
 use Unicode::String qw( utf8 );&lt;br /&gt;
 use EPrints::Plugin::Export;&lt;br /&gt;
 use EPrints::DataObj::User;&lt;br /&gt;
 @ISA = ( &amp;quot;EPrints::Plugin::Export&amp;quot; );&lt;br /&gt;
 use strict;&lt;br /&gt;
 &lt;br /&gt;
 sub new&lt;br /&gt;
 {&lt;br /&gt;
        my( $class, %params ) = @_;&lt;br /&gt;
 &lt;br /&gt;
        my $self = $class-&amp;gt;SUPER::new( %params );&lt;br /&gt;
 &lt;br /&gt;
        $self-&amp;gt;{name} = &amp;quot;Depositor Activity&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{accept} = [ &#039;list/eprint&#039;, &#039;dataobj/eprint&#039; ];&lt;br /&gt;
        $self-&amp;gt;{visible} = &amp;quot;all&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{suffix} = &amp;quot;.csv&amp;quot;;&lt;br /&gt;
        $self-&amp;gt;{mimetype} = &amp;quot;text/csv&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
        return $self;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will create a filter object, and set a number of configuration constants:&lt;br /&gt;
&lt;br /&gt;
* name - The name of the filter&lt;br /&gt;
* accept - A list detailing what the filter will take as inputs.  In this case, a list of eprints or a single eprint.  It is possible to write filters for dataobj types &#039;eprint&#039;, &#039;user&#039;, &#039;subject&#039;, &#039;history&#039;, &#039;access&#039; and &#039;*&#039; (all).&lt;br /&gt;
* visible - Who can see this filter.  It&#039;s set to &#039;all&#039; above so that anyone can use it.  It could be set to &#039;staff&#039; to only allow repository staff to use it.  If set to &#039;API&#039; then the filter is not available through the web interface.&lt;br /&gt;
* suffix - Appended to the url to create a filename extension.&lt;br /&gt;
* mimetype - Should be set to the correct mime type for the output of the filter.&lt;br /&gt;
&lt;br /&gt;
Note that &#039;name&#039; and &#039;accept&#039; are essential.  These allow the filter to register itself with EPrints.&lt;br /&gt;
&lt;br /&gt;
We will be extracting the username of the depositor, so we need to use &#039;EPrints::DataObj::User&#039;.&lt;br /&gt;
&lt;br /&gt;
===Conversion===&lt;br /&gt;
&lt;br /&gt;
The &#039;output_dataobj&#039; function takes a dataobj (in our case an eprint object) and returns a perl scalar which will be the output.  We are going to extract some data from the dataobj using EPrints API calls.&lt;br /&gt;
&lt;br /&gt;
Note that by convention, &#039;$plugin&#039; is used instead of &#039;$self&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_dataobj&lt;br /&gt;
 {&lt;br /&gt;
       my( $plugin, $dataobj ) = @_;&lt;br /&gt;
 &lt;br /&gt;
       my $r = &amp;quot;&amp;quot;;&lt;br /&gt;
       if ($dataobj-&amp;gt;exists_and_set(&amp;quot;userid&amp;quot;))                                       #userid may not be set if the deposit was done by a script.&lt;br /&gt;
       {&lt;br /&gt;
               my $session = $plugin-&amp;gt;{&amp;quot;session&amp;quot;}; &lt;br /&gt;
               my $userid = $dataobj-&amp;gt;get_value( &amp;quot;userid&amp;quot; );&lt;br /&gt;
               my $depositor_obj = new EPrints::DataObj::User($session, $userid);    #create a user object&lt;br /&gt;
               my $depositor = $depositor_obj-&amp;gt;get_value( &amp;quot;username&amp;quot; );              #get the user ID&lt;br /&gt;
               if ($depositor =~ m/[\n&amp;quot; ,]/)                                         #Check for illegal CSV characters&lt;br /&gt;
               {&lt;br /&gt;
                       $depositor =~ s/&amp;quot;/&amp;quot;&amp;quot;/g;                                       #escape quotes&lt;br /&gt;
                       $depositor = &#039;&amp;quot;&#039; . $depositor . &#039;&amp;quot;&#039;;                          #delimit text&lt;br /&gt;
               }&lt;br /&gt;
               $r .= $depositor;&lt;br /&gt;
       }&lt;br /&gt;
       else&lt;br /&gt;
       {&lt;br /&gt;
               $r .= &#039;&amp;quot;Depositor Unknown&amp;quot;&#039;;&lt;br /&gt;
       }&lt;br /&gt;
       $r .= &#039;,&amp;quot;&#039; . $dataobj-&amp;gt;get_value( &amp;quot;datestamp&amp;quot; ) . &#039;&amp;quot;&#039; .&amp;quot;\n&amp;quot;;                   #datestamp is always set, and contains a space so needs delimiting&lt;br /&gt;
 &lt;br /&gt;
       return $r;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
* Retreiving the username takes a little fancy footwork because the EPrints object contains depositor userids.  We need to create a user object and get the username from that.&lt;br /&gt;
* We use &#039;$dataobj-&amp;gt;get_value&#039; to retrieve metadata from the eprint (or user) objects.&lt;br /&gt;
* As we&#039;re outputting in CSV, we need to do a little normalisation.&lt;br /&gt;
&lt;br /&gt;
===Put it in a Module===&lt;br /&gt;
&lt;br /&gt;
Put all this into a file called &#039;DepositorActivity.pm&#039; and save the file into the &#039;eprints3/perl_lib/EPrints/Plugin/Export/&#039; directory.  Don&#039;t forget to add this to the bottom of the file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Before you can use the plugin, you must restart the webserver.  This will cause EPrints to load it.&lt;br /&gt;
&lt;br /&gt;
===Adding Column Headings===&lt;br /&gt;
&lt;br /&gt;
The &#039;output_dataobj&#039; runs on a single EPrint.  If the plugin runs over a list of eprints (we&#039;ve given it that capability), the default behaviour is to run &#039;output_dataobj&#039; on every eprint in the list and concatenate the results.&lt;br /&gt;
&lt;br /&gt;
The output_list function is what handles the lists.  This takes itself ($plugin) and a hash (%opts) as arguments.  The %opt hash contains the list.  It could also contain a filehandle.  When writing &#039;output_list&#039;, you need to check for the filehandle and if present, print to it.  If it&#039;s not present, return the results as a scalar.&lt;br /&gt;
&lt;br /&gt;
Here is an output_list function that will add column headings to our CSV file.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_list&lt;br /&gt;
 {&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my $r = [];                                                      #array for results accumulation&lt;br /&gt;
        my $part;&lt;br /&gt;
 &lt;br /&gt;
        $part = &#039;&amp;quot;User ID&amp;quot;,&amp;quot;Date Stamp&amp;quot;&#039; . &amp;quot;\n&amp;quot;;                         #column headings&lt;br /&gt;
        if( defined $opts{fh} )                                          #write to file or accumulate headings&lt;br /&gt;
        {&lt;br /&gt;
                print {$opts{fh}} $part;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
                push @{$r}, $part;&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        foreach my $dataobj ( $opts{list}-&amp;gt;get_records )                 #Iterate over list&lt;br /&gt;
        {&lt;br /&gt;
                $part = $plugin-&amp;gt;output_dataobj( $dataobj, %opts );      #call output_dataobj&lt;br /&gt;
                if( defined $opts{fh} )                                  #write to file or accumulate results&lt;br /&gt;
                {&lt;br /&gt;
                         print {$opts{fh}} $part;&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                {&lt;br /&gt;
                        push @{$r}, $part;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        if( defined $opts{fh} )                                          #Don&#039;t return results if writing to file.&lt;br /&gt;
        {&lt;br /&gt;
                return;&lt;br /&gt;
        }&lt;br /&gt;
        return join( &#039;&#039;, @{$r} );&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The conditionals for printing to a file make the function look overly complex.  Here it is if you ignore file handles (which you certainly shouldn&#039;t do):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_list&lt;br /&gt;
 {&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my $r = [];                                                      #array for results accumulation&lt;br /&gt;
        my $part;&lt;br /&gt;
 &lt;br /&gt;
        $part = &#039;&amp;quot;User ID&amp;quot;,&amp;quot;Date Stamp&amp;quot;&#039; . &amp;quot;\n&amp;quot;;                         #column headings&lt;br /&gt;
        push @{$r}, $part;&lt;br /&gt;
        foreach my $dataobj ( $opts{list}-&amp;gt;get_records )                 #Iterate over list&lt;br /&gt;
        {&lt;br /&gt;
                $part = $plugin-&amp;gt;output_dataobj( $dataobj, %opts );      #call output_dataobj&lt;br /&gt;
                push @{$r}, $part;&lt;br /&gt;
        }&lt;br /&gt;
        return join( &#039;&#039;, @{$r} );&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===More Complex List Processing===&lt;br /&gt;
&lt;br /&gt;
output_list can be used to do more than simple concatenating results from output_dataobj.  For example, the plugin above will output a table containing one entry for every eprint showing the depositor and the deposit date.  Perhaps this could be made more useful by changing the table so that it contains a row for each user that deposited an eprint.  Perhaps three columns (userid, number of deposits, datestamp of latest deposit) could be useful.&lt;br /&gt;
&lt;br /&gt;
For readability, output_list is shown without filehandle handling.  If this were a real filter, IT WOULD BE NECESSARY!&lt;br /&gt;
&lt;br /&gt;
Firstly, an auxhillary function that will return a CSV normalised username.  It&#039;s similar to the output_data function above, so should be easy to understand.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub get_username&lt;br /&gt;
 {&lt;br /&gt;
       my( $plugin, $dataobj ) = @_;&lt;br /&gt;
 &lt;br /&gt;
       my $username;&lt;br /&gt;
       if ($dataobj-&amp;gt;exists_and_set(&amp;quot;userid&amp;quot;))                                     #userid may not be set if the deposit was done by a script.&lt;br /&gt;
       {&lt;br /&gt;
               my $session = $plugin-&amp;gt;{&amp;quot;session&amp;quot;};&lt;br /&gt;
               my $userid = $dataobj-&amp;gt;get_value( &amp;quot;userid&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
               my $depositor_obj = new EPrints::DataObj::User($session, $userid);  #create a user object&lt;br /&gt;
               my $depositor = $depositor_obj-&amp;gt;get_value( &amp;quot;username&amp;quot; );            #get the user ID&lt;br /&gt;
               if ($depositor =~ m/[\n&amp;quot; ,]/)         #Check for illegal CSV characters&lt;br /&gt;
               {&lt;br /&gt;
                       $depositor =~ s/&amp;quot;/&amp;quot;&amp;quot;/g; #escape quotes&lt;br /&gt;
                       $depositor = &#039;&amp;quot;&#039; . $depositor . &#039;&amp;quot;&#039;; #delimit text&lt;br /&gt;
               }&lt;br /&gt;
               $username = $depositor;&lt;br /&gt;
       }&lt;br /&gt;
       else&lt;br /&gt;
       {&lt;br /&gt;
               $username = &#039;&amp;quot;Depositor Unknown&amp;quot;&#039;;&lt;br /&gt;
       }&lt;br /&gt;
       return $username;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The new output_list function uses a hash to accumlate the results:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sub output_list&lt;br /&gt;
 {&lt;br /&gt;
        my( $plugin, %opts ) = @_;&lt;br /&gt;
        my %r = ();&lt;br /&gt;
 &lt;br /&gt;
        #Iterate over the list&lt;br /&gt;
        foreach my $dataobj ( $opts{list}-&amp;gt;get_records )&lt;br /&gt;
        {&lt;br /&gt;
                my $username = $plugin-&amp;gt;get_username( $dataobj );&lt;br /&gt;
                my $datestamp = &#039;&amp;quot;&#039; . $dataobj-&amp;gt;get_value( &amp;quot;datestamp&amp;quot; ) . &#039;&amp;quot;&#039;;&lt;br /&gt;
                if (defined $r{$username})                                        #if it&#039;s defined, increment and compare timestamps&lt;br /&gt;
                {&lt;br /&gt;
                        $r{$username}-&amp;gt;{count}   ;&lt;br /&gt;
                        if ($r{$username}-&amp;gt;{most_recent} lt $datestamp)&lt;br /&gt;
                        {&lt;br /&gt;
                                $r{$username}-&amp;gt;{most_recent} = $datestamp;&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                else                                                              #if it&#039;s not defined, create a hash for this user&#039;s results&lt;br /&gt;
                {&lt;br /&gt;
                        $r{$username} = {count =&amp;gt; 1, most_recent =&amp;gt; $datestamp};&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
 &lt;br /&gt;
        # Construct the CSV and return it.&lt;br /&gt;
        my $csv = &#039;&amp;quot;User Name&amp;quot;,&amp;quot;Number of Deposits&amp;quot;,&amp;quot;Most Recent Deposit&amp;quot;&#039; . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        foreach my $username (sort keys %r)&lt;br /&gt;
        {&lt;br /&gt;
                $csv .= $username . &amp;quot;,&amp;quot; . $r{$username}-&amp;gt;{count} . &amp;quot;,&amp;quot; . $r{$username}-&amp;gt;{most_recent} . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        return $csv;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that because this plugin can take a single eprint as well as a list of eprints, you must have a output_dataobj function that will do something sensible.  However, bear in mind that search results are always a list, even if there&#039;s only one result.&lt;/div&gt;</summary>
		<author><name>Ma3I6n</name></author>
	</entry>
</feed>