zotero-db/translators/Primo.js

323 lines
8.8 KiB
JavaScript

{
"translatorID": "1300cd65-d23a-4bbf-93e5-a3c9e00d1066",
"label": "Primo",
"creator": "Matt Burton, Avram Lyon, Etienne Cavalié, Rintze Zelle, Philipp Zumstein, Sebastian Karcher, Aurimas Vinckevicius",
"target": "/primo_library/|/nebis/|^https?://www\\.recherche-portal\\.ch/zbz/",
"minVersion": "2.1.9",
"maxVersion": "",
"priority": 101,
"inRepository": true,
"translatorType": 4,
"browserSupport": "gcsbv",
"lastUpdated": "2020-02-04 01:29:32"
}
/*
***** BEGIN LICENSE BLOCK *****
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
/*
Supports Primo 2:
Université de Nice, France (http://catalogue.unice.fr/) (looks like this is Primo3 now, too)
Supports Primo 3
Boston College (http://www.bc.edu/libraries/),
Oxford Libraries (http://solo.ouls.ox.ac.uk/)
Primos with showPNX.jsp installed:
(1) http://purdue-primo-prod.hosted.exlibrisgroup.com/primo_library/libweb/action/search.do?vid=PURDUE
(2) http://primo.bib.uni-mannheim.de/primo_library/libweb/action/search.do?vid=MAN_UB
(3) http://limo.libis.be/primo_library/libweb/action/search.do?vid=LIBISnet&fromLogin=true
(4.a) http://virtuose.uqam.ca/primo_library/libweb/action/search.do?vid=UQAM
(5) http://searchit.princeton.edu/primo_library/libweb/action/dlDisplay.do?docId=PRN_VOYAGER2778598&vid=PRINCETON&institution=PRN
*/
function getSearchResults(doc) {
// order dictates preference
var linkXPaths = ['.//li[starts-with(@id,"exlidResult") and substring(@id,string-length(@id)-10)="-DetailsTab"]/a[@href]', // details link
'.//h2[@class="EXLResultTitle"]/a[@href]']; // title link
var resultsXPath = '//*[self::tr or self::div][starts-with(@id, "exlidResult") and '
+ 'number(substring(@id,12))=substring(@id,12)][' + linkXPaths.join(' or ') + ']';
// Z.debug(resultsXPath);
var results = ZU.xpath(doc, resultsXPath);
results.titleXPath = './/h2[@class="EXLResultTitle"]';
results.linkXPaths = linkXPaths;
return results;
}
function detectWeb(doc) {
if (getSearchResults(doc).length) {
return 'multiple';
}
var contentDiv = doc.getElementsByClassName('EXLFullResultsHeader');
if (!contentDiv.length) contentDiv = doc.getElementsByClassName('EXLFullDisplay');
if (!contentDiv.length) contentDiv = doc.getElementsByClassName('EXLFullView');
if (contentDiv.length) return 'book';
return false;
}
function doWeb(doc, url) {
var searchResults = getSearchResults(doc);
if (searchResults.length) {
var items = {}, itemIDs = {}, title, link,
linkXPaths = searchResults.linkXPaths;
for (var i = 0, n = searchResults.length; i < n; i++) {
title = ZU.xpathText(searchResults[i], searchResults.titleXPath);
for (var j = 0, m = linkXPaths.length; j < m; j++) {
link = ZU.xpath(searchResults[i], linkXPaths[j])[0];
if (link) {
break;
}
}
if (!link || !title || !(title = ZU.trimInternal(title))) continue;
items[link.href] = title;
itemIDs[link.href] = { id: i, docID: getDocID(link.href) };
}
Z.selectItems(items, function (selectedItems) {
if (!selectedItems) return true;
var urls = [];
for (var i in selectedItems) {
urls.push({ url: i, id: itemIDs[i].id, docID: itemIDs[i].docID });
}
fetchPNX(urls);
return true;
});
}
else {
fetchPNX([{ url: url, id: 0, docID: getDocID(url) }]);
}
}
function getDocID(url) {
var id = url.match(/\bdoc(?:Id)?=([^&]+)/i);
if (id) return id[1];
else return false;
}
// keeps track of which URL format works for retrieving PNX record
// and applies the correct transformation function
var PNXUrlGenerator = new function () {
var functions = [
// showPNX.js
// using docIDs instead of IDs tied to a session
// e.g. http://searchit.princeton.edu/primo_library/libweb/showPNX.jsp?id=PRN_VOYAGER7343340
function (urlObj) {
return getUrlWithId(urlObj.url, urlObj.docID);
},
// fall back to IDs
// from: http://primo.bib.uni-mannheim.de/primo_library/libweb/action/search.do?...
// to: http://primo.bib.uni-mannheim.de/primo_library/libweb/showPNX.jsp?id=
function (urlObj) {
return getUrlWithId(urlObj.url, urlObj.id);
},
// simply add &showPnx=true
function (urlObj) {
var url = urlObj.url.split('#');
if (!url[0].includes("?")) {
url[0] += '?';
}
else {
url[0] += '&';
}
return url[0] + 'showPnx=true';
}
];
function getUrlWithId(url, id) {
url = url.match(/(https?:\/\/[^?#]+\/)[^?#]+\/[^/]*(?:[?#]|$)/);
if (!url) return false;
return url[1] + 'showPNX.jsp?id=' + id;
}
this.currentFunction = 0;
this.confirmed = false;
this.getUrl = function (data) {
var fun = functions[this.currentFunction];
if (!fun) return false;
return fun(data);
};
this.nextFunction = function () {
if (!this.confirmed && this.currentFunction < functions.length) {
Z.debug("Function " + this.currentFunction + " did not work.");
this.currentFunction++;
return true;
}
else {
return false;
}
};
};
// retrieve PNX records for given items sequentially
function fetchPNX(itemData) {
if (!itemData.length) return; // do this until we run out of URLs
var data = itemData.shift();
var url = PNXUrlGenerator.getUrl(data); // format URL if still possible
if (!url) {
if (PNXUrlGenerator.nextFunction()) {
itemData.unshift(data);
}
else if (!PNXUrlGenerator.confirmed) {
// in case we can't find PNX for a particular item,
// go to the next and start looking from begining
Z.debug("Could not determine PNX url from " + data.url);
PNXUrlGenerator.currentFunction = 0;
}
fetchPNX(itemData);
return;
}
var gotPNX = false;
Z.debug("Trying " + url);
ZU.doGet(url,
function (text) {
text = text.trim();
if (text.substr(0, 5) != '<?xml' || text.search(/<error\b/i) !== -1) {
// try a different PNX url
gotPNX = false;
return;
}
else {
gotPNX = true;
PNXUrlGenerator.confirmed = true;
}
importPNX(text, url);
},
function () {
if (!gotPNX && PNXUrlGenerator.nextFunction()) {
// if url function not confirmed, try another one on the same URL
// otherwise, we move on
itemData.unshift(data);
}
fetchPNX(itemData);
},
null,
null,
[200, 404, 500]
);
}
function importPNX(text, url) {
// Z.debug(text);
var translator = Zotero.loadTranslator("import");
translator.setTranslator("efd737c9-a227-4113-866e-d57fbc0684ca");
translator.setString(text);
translator.setHandler("itemDone", function (obj, item) {
if (url) {
item.libraryCatalog = url.match(/^https?:\/\/(.+?)\//)[1].replace(/\.hosted\.exlibrisgroup/, "");
}
item.complete();
});
translator.translate();
}
/** BEGIN TEST CASES **/
var testCases = [
{
"type": "web",
"url": "http://princeton-primo.hosted.exlibrisgroup.com/primo_library/libweb/action/dlDisplay.do?vid=PRINCETON&search_scope=All%20Princeton%20Libraries&docId=PRN_VOYAGER2778598&fn=permalink",
"items": [
{
"itemType": "book",
"title": "China and foreign missionaries.",
"creators": [
{
"lastName": "Great Britain Foreign Office",
"creatorType": "author",
"fieldMode": 1
}
],
"date": "1860",
"callNumber": "5552.406",
"language": "eng",
"libraryCatalog": "princeton-primo.com",
"place": "London",
"publisher": "1860-1912",
"attachments": [],
"tags": [
{
"tag": "China"
},
{
"tag": "China; China"
},
{
"tag": "Foreign relations"
},
{
"tag": "Foreign relations"
},
{
"tag": "Great Britain; Great Britain"
},
{
"tag": "Missions"
},
{
"tag": "Religion; China"
}
],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "http://digitale.beic.it/primo_library/libweb/action/display.do?doc=39bei_digitool2018516",
"items": [
{
"itemType": "book",
"title": "Grida per i Milanesi che avevano seguito Ludovico il Moro",
"creators": [
{
"lastName": "Milano",
"creatorType": "author",
"fieldMode": 1
}
],
"date": "1500",
"language": "ita",
"libraryCatalog": "digitale.beic.it",
"place": "Milano",
"publisher": "Ambrogio : da Caponago",
"attachments": [],
"tags": [
"LEGGI;ITALIA - STORIA MEDIOEVALE"
],
"notes": [],
"seeAlso": []
}
]
}
]
/** END TEST CASES **/