{
"translatorID": "24d9f058-3eb3-4d70-b78f-1ba1aef2128d",
"label": "CTX",
"creator": "Avram Lyon and Simon Kornblith",
"target": "^https?://freecite\\.library\\.brown\\.edu",
"minVersion": "2.0",
"maxVersion": "",
"priority": 100,
"configOptions": {
"dataMode": "line"
},
"inRepository": true,
"translatorType": 5,
"browserSupport": "gcv",
"lastUpdated": "2014-04-03 16:47:18"
}
/*
ContextObjects in XML Translator
Copyright (C) 2010 Avram Lyon, 2013 Sebastian Karcher
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*This translator imports OpenURL ContextObjects encapsulated in XML
* documents, as described at:
* http://alcme.oclc.org/openurl/servlet/OAIHandler?verb=GetRecord&metadataPrefix=oai_dc&identifier=info:ofi/fmt:xml:xsd:ctx
* The schema for such XML documents is at:
* http://www.openurl.info/registry/docs/xsd/info:ofi/fmt:xml:xsd:ctx
*
* This format is used in several places online, including Brown University's FreeCite
* Citation parser (http://freecite.library.brown.edu/welcome) and Oslo University's
* X-Port (http://www.ub.uio.no/portal/gs.htm or http://x-port.uio.no/).
* Our input looks like this:
info:ofi/fmt:xml:xsd:journal
Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes
2530
1992
Journal of the American Medical Association
article
18
2536
I S Udvarhelyi
C A Gatsonis
A M Epstein
C L Pashos
J P Newhouse
B J McNeil
*
* The approach we will take is to convert this into COinS, so that we can
* piggy-back off of the perhaps more robust support in the core Zotero code.
*/
function detectWeb(doc, url) {
var texts = [], text = "";
var codes = doc.getElementsByTagName("code");
for(var i = 0; i < codes.length; i++) {
text = codes[i].textContent;
text.replace(//g,">");
texts.push(text);
}
return detectInString(texts);
};
function doWeb(doc, url) {
var texts = [], text = "";
var codes = doc.getElementsByTagName("code");
for(var i = 0; i < codes.length; i++) {
text = codes[i].textContent;
text.replace(//g,">");
texts.push(text);
}
doImportFromText(texts, true);
};
function doImport() {
var text = "";
var line;
while(line = Zotero.read()) {
text += line;
}
return doImportFromText(text, false);
}
function detectImport() {
var text = "";
var line;
while(line = Zotero.read()) {
text += line;
}
return detectInString(text) != false;
}
function detectInString(text) {
var detectedType = false;
var spans = [];
Z.debug(text)
// This is because we want to be able to read multiple such CTX elements in a single page
if (typeof text != "string" && text.length >= 1) {
spans = text.map(contextObjectXMLToCOinS).reduce(function(a,b){return a.concat(b);});
} else {
spans = contextObjectXMLToCOinS(text);
}
for (var i = 0 ; i < spans.length ; i++) {
var item = new Zotero.Item;
var success = Zotero.Utilities.parseContextObject(spans[i], item);
if(item.itemType) {
Zotero.debug("Found " + item.itemType);
if (detectedType) {
return "multiple";
}
detectedType = item.itemType;
} else {
Zotero.debug("Type not found");
}
}
return detectedType;
};
/* Takes the string of the ContextObject XML format
* and returns an array of COinS titles of the same, per the COinS
* specification.
*/
function contextObjectXMLToCOinS (text) {
//Z.debug(text);
var parser = new DOMParser();
try {
var doc = parser.parseFromString(text, "text/xml");
}
catch (e) {
return [];
}
ns = { "xsi" : "http://www.w3.org/2001/XMLSchema-instance",
"ctx" : "info:ofi/fmt:xml:xsd:ctx",
"rft" : "info:ofi/fmt:xml:xsd:journal"
};
/* Here and elsewhere, we are using the E4X syntax for XML */
var objects = ZU.xpath(doc, '//ctx:context-object', ns)
/* Bail out if no object */
if(objects.length === 0) {
Zotero.debug("No context object");
return [];
}
var titles = [];
for (var i = 0; i < objects.length; i++) {
Zotero.debug("Processing object: " + objects[i].textContent);
var pieces = [];
var version = ZU.xpathText(objects[i], './@version', ns)
pieces.push("ctx_ver="+encodeURIComponent(version));
var format = ZU.xpathText(objects[i], '//ctx:format', ns)
// Now conert this to the corresponding Key/Encoded-Value format; see note below.
// Check if this is unknown; if it is, skip
if (format == "info:ofi/fmt:xml:xsd:unknown") {
Zotero.debug("Skipping object of type 'unknown'");
continue;
}
format = mapXMLtoKEV[format];
pieces.push("rft_val_fmt=" + encodeURIComponent(format));
var fields = ZU.xpath(objects[i], '//ctx:metadata/*/*', ns);
var field;
for (var j in fields) {
var name = fields[j].nodeName;
// turn this into html
name = name.replace(/:/, ".")
var value = encodeURIComponent(fields[j].textContent);
pieces.push(name + "=" + value);
}
var title = pieces.join("&");
var span = "\n";
Zotero.debug("Made span: " + span);
titles.push(title);
}
return titles;
};
function doImportFromText(text, showPrompt) {
var spans = [], items = [], zoteroItems = [];
// This is because we want to be able to read multiple such CTX elements in a single page
if (typeof text != "string" && text.length >= 1) {
spans = text.map(contextObjectXMLToCOinS).reduce(function(a,b){return a.concat(b);});
} else {
spans = contextObjectXMLToCOinS(text);
}
for (var i = 0 ; i < spans.length ; i++) {
Zotero.debug("Processing span: "+spans[i]);
var item = new Zotero.Item;
Zotero.Utilities.parseContextObject(spans[i], item);
if(item.itemType) {
Zotero.debug("Found " + item.itemType);
items.push(item.title);
zoteroItems.push(item);
// Set publicationTitle to the short title if only the latter is specified
if (item.journalAbbreviation && !item.publicationTitle) {
item.publicationTitle = item.journalAbbreviation;
}
// If we're in non-prompting mode, save right away
if (showPrompt === false) {
item.complete();
}
} else {
Zotero.debug("Type not found");
}
}
// Since we want to prompt, we have to parse twice.
if(showPrompt === true) {
if(items.length == 1) {
item.complete();
} else {
items = Zotero.selectItems(items);
if(!items) return true;
for(var i in items) {
zoteroItems[i].complete();
}
}
}
};
/* These two arrays are needed because COinS uses Key/Escaped-Value, which has a different
* set of format codes. Codes from "Registry for the OpenURL Framework - ANSI/NISO Z39.88-2004":
* http://alcme.oclc.org/openurl/servlet/OAIHandler?verb=ListRecords&metadataPrefix=oai_dc&set=Core:Metadata+Formats
*/
var mapKEVtoXML = {
'info:ofi/fmt:kev:mtx:book' : 'info:ofi/fmt:xml:xsd:book', // Books
'info:ofi/fmt:kev:mtx:dc' : 'info:ofi/fmt:xml:xsd:oai_dc', // Dublin Core
'info:ofi/fmt:kev:mtx:dissertation' : 'info:ofi/fmt:xml:xsd:dissertation', // Dissertations
'info:ofi/fmt:kev:mtx:journal' : 'info:ofi/fmt:xml:xsd:journal', // Journals
'info:ofi/fmt:kev:mtx:patent' : 'info:ofi/fmt:xml:xsd:patent', // Patents
'info:ofi/fmt:kev:mtx:sch_svc' : 'info:ofi/fmt:xml:xsd:sch_svc' // Scholarly ServiceTypes
};
var mapXMLtoKEV = {
'info:ofi/fmt:xml:xsd:book' : 'info:ofi/fmt:kev:mtx:book', // Books
'info:ofi/fmt:xml:xsd:oai_dc' : 'info:ofi/fmt:kev:mtx:dc', // Dublin Core
'info:ofi/fmt:xml:xsd:dissertation' : 'info:ofi/fmt:kev:mtx:dissertation', // Dissertations
'info:ofi/fmt:xml:xsd:journal' : 'info:ofi/fmt:kev:mtx:journal', // Journals
'info:ofi/fmt:xml:xsd:patent' : 'info:ofi/fmt:kev:mtx:patent', // Patents
'info:ofi/fmt:xml:xsd:sch_svc' : 'info:ofi/fmt:kev:mtx:sch_svc' // Scholarly ServiceTypes
};
/** BEGIN TEST CASES **/
var testCases = [
{
"type": "import",
"input": "\n\n \n \n info:ofi/fmt:xml:xsd:journal\n \n \n\t Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes\n\t 2530\n\t 1992\n\t Journal of the American Medical Association\n\t article\n\t 18\n\t 2536\n\t I S Udvarhelyi\n\t C A Gatsonis\n\t A M Epstein\n\t C L Pashos\n\t J P Newhouse\n\t B J McNeil\n\t\n \n \n \n\n",
"items": [
{
"itemType": "journalArticle",
"creators": [
{
"firstName": "I. S.",
"lastName": "Udvarhelyi",
"creatorType": "author"
},
{
"firstName": "C. A.",
"lastName": "Gatsonis",
"creatorType": "author"
},
{
"firstName": "A. M.",
"lastName": "Epstein",
"creatorType": "author"
},
{
"firstName": "C. L.",
"lastName": "Pashos",
"creatorType": "author"
},
{
"firstName": "J. P.",
"lastName": "Newhouse",
"creatorType": "author"
},
{
"firstName": "B. J.",
"lastName": "McNeil",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes",
"pages": "2530-2536",
"date": "1992",
"journalAbbreviation": "Journal of the American Medical Association",
"volume": "18",
"publicationTitle": "Journal of the American Medical Association"
}
]
}
]
/** END TEST CASES **/