{ "translatorID":"0e2235e7-babf-413c-9acf-f27cce5f059c", "translatorType":3, "label":"MODS", "creator":"Simon Kornblith", "target":"xml", "minVersion":"2.1b3", "maxVersion":"", "priority":50, "configOptions":{"dataMode":"xml/e4x"}, "displayOptions":{"exportNotes":true}, "inRepository":true, "lastUpdated":"2011-01-27 19:35:57" } function detectImport() { var name = Zotero.getXML().name(); if (!name) { return false; } return name.uri == "http://www.loc.gov/mods/v3" && (name.localName == "modsCollection" || name.localName == "mods"); } var partialItemTypes = ["bookSection", "journalArticle", "magazineArticle", "newspaperArticle"]; function doExport() { Zotero.setCharacterSet("utf-8"); var modsCollection = ; var item; while(item = Zotero.nextItem()) { var isPartialItem = partialItemTypes.indexOf(item.itemType) !== -1; var mods = ; /** CORE FIELDS **/ // XML tag titleInfo; object field title if(item.title) { mods.titleInfo.title = item.title; } // XML tag typeOfResource/genre; object field type var modsType, marcGenre; if(item.itemType == "book" || item.itemType == "bookSection") { modsType = "text"; marcGenre = "book"; } else if(item.itemType == "journalArticle" || item.itemType == "magazineArticle") { modsType = "text"; marcGenre = "periodical"; } else if(item.itemType == "newspaperArticle") { modsType = "text"; marcGenre = "newspaper"; } else if(item.itemType == "thesis") { modsType = "text"; marcGenre = "thesis"; } else if(item.itemType == "letter") { modsType = "text"; marcGenre = "letter"; } else if(item.itemType == "manuscript") { modsType = "text"; modsType.@manuscript = "yes"; } else if(item.itemType == "interview") { modsType = "text"; marcGenre = "interview"; } else if(item.itemType == "film") { modsType = "moving image"; marcGenre = "motion picture"; } else if(item.itemType == "artwork") { modsType = "still image"; marcGenre = "art original"; } else if(item.itemType == "webpage") { modsType = "multimedia"; marcGenre = "web site"; } else if(item.itemType == "note" || item.itemType == "attachment") { continue; } mods.typeOfResource = modsType; mods.genre += {item.itemType}; if(marcGenre) { mods.genre += {marcGenre}; } // XML tag genre; object field thesisType, type if(item.thesisType) { mods.genre += {item.thesisType}; } if(item.type) { mods.genre += {item.type}; } // XML tag name; object field creators for(var j in item.creators) { var roleTerm = ""; if(item.creators[j].creatorType == "author") { roleTerm = "aut"; } else if(item.creators[j].creatorType == "editor") { roleTerm = "edt"; } else { roleTerm = "ctb"; } // FIXME - currently all names are personal if(item.creators[j].fieldMode == 1) { mods.name += {item.creators[j].lastName} {roleTerm} ; } else { mods.name += {item.creators[j].lastName} {item.creators[j].firstName} {roleTerm} ; } } // XML tag recordInfo.recordOrigin; used to store our generator note //mods.recordInfo.recordOrigin = "Zotero for Firefox "+Zotero.Utilities.getVersion(); /** FIELDS ON NEARLY EVERYTHING BUT NOT A PART OF THE CORE **/ // XML tag recordInfo.recordContentSource; object field source if(item.source) { mods.recordInfo.recordContentSource = item.source; } // XML tag recordInfo.recordIdentifier; object field accessionNumber if(item.accessionNumber) { mods.recordInfo.recordIdentifier = item.accessionNumber; } // XML tag accessCondition; object field rights if(item.rights) { mods.accessCondition = item.rights; } /** SUPPLEMENTAL FIELDS **/ // Make part its own tag so we can figure out where it goes later var part = new XML(); // XML tag detail; object field volume if(item.volume) { if(parseInt(item.volume) == item.volume) { part += {item.volume}; } else { part += {item.volume}; } } // XML tag detail; object field number if(item.issue) { if(parseInt(item.issue) == item.issue) { part += {item.issue}; } else { part += {item.issue}; } } // XML tag detail; object field section if(item.section) { if(parseInt(item.section) == item.section) { part += {item.section}; } else { part += {item.section}; } } // XML tag detail; object field pages if(item.pages) { var range = Zotero.Utilities.getPageRange(item.pages); part += {range[0]}{range[1]}; } // Assign part if something was assigned if(part.length() != 1) { if(isPartialItem) { // For a journal article, bookSection, etc., the part is the host mods.relatedItem.part += {part}; } else { mods.part += {part}; } } // XML tag originInfo; object fields edition, place, publisher, year, date var originInfo = new XML(); if(item.edition) { originInfo += {item.edition}; } if(item.place) { originInfo += {item.place}; } if(item.publisher) { originInfo += {item.publisher}; } else if(item.distributor) { originInfo += {item.distributor}; } if(item.date) { if(["book", "bookSection"].indexOf(item.itemType) !== -1) { // Assume year is copyright date var dateType = "copyrightDate"; } else if(["journalArticle", "magazineArticle", "newspaperArticle"].indexOf(item.itemType) !== -1) { // Assume date is date issued var dateType = "dateIssued"; } else { // Assume date is date created var dateType = "dateCreated"; } var tag = <{dateType}>{item.date}; originInfo += tag; } if(item.accessDate) { originInfo += {item.accessDate}; } if(originInfo.length() != 1) { if(isPartialItem) { // For a journal article, bookSection, etc., this goes under the host mods.relatedItem.originInfo += {originInfo}; } else { mods.originInfo += {originInfo}; } } // XML tag identifier; object fields ISBN, ISSN if(isPartialItem) { var identifier = mods.relatedItem; } else { var identifier = mods; } if(item.ISBN) { identifier.identifier += {item.ISBN}; } if(item.ISSN) { identifier.identifier += {item.ISSN}; } if(item.DOI) { mods.identifier += {item.DOI}; } // XML tag relatedItem.titleInfo; object field publication if(item.publicationTitle) { mods.relatedItem.titleInfo += {item.publicationTitle}; } // XML tag classification; object field callNumber if(item.callNumber) { mods.classification = item.callNumber; } // XML tag location.physicalLocation; object field archiveLocation if(item.archiveLocation) { mods.location.physicalLocation = item.archiveLocation; } // XML tag location.url; object field archiveLocation if(item.url) { mods.location.url = item.url; } // XML tag title.titleInfo; object field journalAbbreviation if(item.journalAbbreviation) { mods.relatedItem.titleInfo += {item.journalAbbreviation}; } // XML tag abstract; object field abstractNote if(item.abstractNote) { mods.abstract = item.abstractNote; } if(mods.relatedItem.length() == 1 && isPartialItem) { mods.relatedItem.@type = "host"; } /** NOTES **/ if(Zotero.getOption("exportNotes")) { for(var j in item.notes) { // Add note tag var note = {item.notes[j].note}; mods.note += note; } } /** TAGS **/ for(var j in item.tags) { mods.subject += {item.tags[j].tag}; } // XML tag relatedItem.titleInfo; object field series if(item.seriesTitle || item.series || item.seriesNumber || item.seriesText) { var series = ; if(item.series) { series.titleInfo.title = item.series; } if(item.seriesTitle) { series.titleInfo.partTitle = item.seriesTitle; } if(item.seriesText) { series.titleInfo.subTitle = item.seriesText; } if(item.seriesNumber) { series.titleInfo.partNumber = item.seriesNumber; } // TODO: make this work in import /*if(item.itemType == "bookSection") { // For a book section, series info must go inside host tag mods.relatedItem.relatedItem = series; } else {*/ mods.relatedItem += series; //} } modsCollection.mods += mods; } Zotero.write(''+"\n"); Zotero.write(modsCollection.toXMLString()); } function processIdentifiers(newItem, identifier) { for each(var myIdentifier in identifier) { if(myIdentifier.@type == "isbn") { newItem.ISBN = myIdentifier.text().toString() } else if(myIdentifier.@type == "issn") { newItem.ISSN = myIdentifier.text().toString() } else if(myIdentifier.@type == "doi") { newItem.DOI = myIdentifier.text().toString() } } } function doImport() { var marcGenres = { // "abstract or summary":XXX, // "abstract":XXX, // "summary":XXX, "art reproduction":"artwork", "article":"journalArticle", "autobiography":"book", "bibliography":"book", "biography":"book", "book":"book", // "calendar":XXX, // "catalog":XXX, "chart":"artwork", "comic or graphic novel":"book", "comic":"book", "graphic novel":"book", "comic strip":"artwork", "conference publication":"conferencePaper", // "database":XXX, "dictionary":"dictionaryEntry", "diorama":"artwork", // "directory":XXX, "drama":"book", "encyclopedia":"encyclopediaArticle", // "essay":XXX, "festschrift":"book", "fiction":"book", // "filmography":XXX, "filmstrip":"videoRecording", // "findingaid":XXX, // "flash card":XXX, "folktale":"book", // "font":XXX, // "game":XXX, "government publication":"book", "graphic":"artwork", "globe":"map", "handbook":"book", "history":"book", "hymnal":"book", "humor,satire":"book", "humor":"book", "satire":"book", // "index":XXX, // "instruction":XXX, // "interview":XXX, // "issue":XXX, "journal":"journalArticle", "kit":"artwork", // "language instruction":XXX, "law report or digest":"journalArticle", "law report":"journalArticle", "digest":"journalArticle", "law digest":"journalArticle", "legal article":"journalArticle", "legal case and case notes":"case", "legal case":"case", "case notes":"case", "legislation":"statute", "loose-leaf":"manuscript", "map":"map", "memoir":"book", "microscope slide":"artwork", "model":"artwork", // "multivolume monograph":XXX, "novel":"book", // "numeric data":XXX, // "offprint":XXX, "online system or service":"webpage", "online system":"webpage", "service":"webpage", "online service":"webpage", "patent":"patent", "periodical":"journalArticle", "picture":"artwork", // "poetry":XXX, // "programmed text":XXX, "realia":"artwork", // "rehearsal":XXX, // "remote sensing image":XXX, // "reporting":XXX, // "review":XXX, "script":"book", // "series":XXX, // "short story":XXX, "slide":"artwork", "sound":"audioRecording", "speech":"audioRecording", // "standard or specification":XXX, // "standard":XXX, // "specification":XXX, // "statistics":XXX, // "survey of literature":XXX, "technical report":"report", "newspaper":"newspaperArticle", "theses":"thesis", "thesis":"thesis", // "toy":XXX, "transparency":"artwork", // "treaty":XXX, "videorecording":"videoRecording", "letter":"letter", "motion picture":"film", "art original":"artwork", "web site":"webpage", "yearbook":"book" }; var dctGenres = { //"collection":XXX, //"dataset":XXX, //"event":XXX, "image":"artwork", "interactiveresource":"webpage", //"model":XXX, "movingimage":"videoRecording", //"physical object":XXX, //"place":XXX, //"resource":XXX, //"service":XXX, "software":"computerProgram", "sound":"audioRecording", "stillimage":"artwork" //"text":XXX }; var modsTypeOfResources = { //"text":XXX, "cartographic":"map", //"notated music":XXX, "sound recording-musical":"audioRecording", "sound recording-nonmusical":"audioRecording", "sound recording":"audioRecording", "still image":"artwork", "moving image":"videoRecording", //"three dimensional object":XXX, "software, multimedia":"computerProgram" }; // parse with E4X var m = new Namespace("http://www.loc.gov/mods/v3"); // why does this default namespace declaration not work!? default xml namespace = m; var xml = Zotero.getXML(); if(xml.m::mods.length()) { var modsElements = xml.m::mods; } else { var modsElements = [xml]; } for each(var mods in modsElements) { var newItem = new Zotero.Item(); // title for each(var titleInfo in mods.m::titleInfo) { // dropping other title types so they don't overwrite the main title // we have same behaviour in the MARC translator if(!titleInfo.@type.toString()) { if(titleInfo.m::title.length()) { newItem.title = titleInfo.m::title.text().toString(); if(titleInfo.m::subTitle.length()) { newItem.title = newItem.title + ": " + titleInfo.m::subTitle.text().toString(); } } else { newItem.title = titleInfo.*.text(); // including text from sub elements } } } // try to get genre from local genre for each(var genre in mods.m::genre) { if(genre.@authority == "local" && Zotero.Utilities.itemTypeExists(genre.text().toString())) { newItem.itemType = genre.text().toString(); } else if(!newItem.itemType && (genre.@authority == "marcgt" || genre.@authority == "marc")) { // otherwise, look at the marc genre newItem.itemType = marcGenres[genre.text().toString()]; } else if(!newItem.itemType && (genre.@authority == "dct")) { // otherwise, look at the dct genre newItem.itemType = dctGenres[genre.text().toString().replace(/\s+/g,"")]; } } if(!newItem.itemType) { //try to get type information from typeOfResource for each(var typeOfResource in mods.m::typeOfResource) { newItem.itemType = modsTypeOfResources[typeOfResource.text().toString()]; } if(!newItem.itemType) { // try to get genre data from host for each(var relatedItem in mods.m::relatedItem) { if(relatedItem.@type == "host") { for each(var genre in relatedItem.m::genre) { if(genre.@authority == "marcgt" || genre.@authority == "marc") { newItem.itemType = marcGenres[genre.text().toString()]; break; } } } } } if(!newItem.itemType) newItem.itemType = "document"; } var isPartialItem = partialItemTypes.indexOf(newItem.itemType) !== -1; // TODO: thesisType, type for each(var name in mods.m::name) { // TODO: institutional authors var creator = {}; creator.firstName = ""; for each(var namePart in name.m::namePart) { if(namePart.@type == "given") { if(creator.firstName != "") creator.firstName = creator.firstName + " "; creator.firstName = creator.firstName + namePart.text().toString(); } else if(namePart.@type == "family") { creator.lastName = namePart.text().toString(); } else if(namePart.@type == "date" || namePart.@type == "termsOfAddress") { // ignore these non name types for now } else { var backupName = namePart.text().toString(); } } if(backupName && !creator.firstName && !creator.lastName) { creator = Zotero.Utilities.cleanAuthor(backupName, "author", true); creator.fieldMode = 1; } // look for roles for each(var role in name.m::role.m::roleTerm) { if(role.@type == "code" && role.@authority == "marcrelator") { if(role == "edt") { creator.creatorType = "editor"; } else if(role == "ctb") { creator.creatorType = "contributor"; } else if(role == "trl") { creator.creatorType = "translator"; } } } if(!creator.creatorType) creator.creatorType = "author"; newItem.creators.push(creator); } // source newItem.source = mods.m::recordInfo.m::recordContentSource.text().toString(); // accessionNumber newItem.accessionNumber = mods.m::recordInfo.m::recordIdentifier.text().toString(); // rights newItem.rights = mods.m::accessCondition.text().toString(); /** SUPPLEMENTAL FIELDS **/ var part = false, originInfo = false; // series for each(var relatedItem in mods.m::relatedItem) { if(relatedItem.@type == "host") { for each(var titleInfo in relatedItem.m::titleInfo) { if(titleInfo.@type == "abbreviated") { newItem.journalAbbreviation = titleInfo.m::title.text().toString(); if(!newItem.publicationTitle) newItem.publicationTitle = newItem.journalAbbreviation; } else { newItem.publicationTitle = titleInfo.m::title.text().toString(); } } part = relatedItem.m::part; originInfo = relatedItem.m::originInfo; processIdentifiers(newItem, relatedItem.m::identifier); } else if(relatedItem.@type == "series") { newItem.series = relatedItem.m::titleInfo.m::title.text().toString(); newItem.seriesTitle = relatedItem.m::titleInfo.m::partTitle.text().toString(); newItem.seriesText = relatedItem.m::titleInfo.m::subTitle.text().toString(); newItem.seriesNumber = relatedItem.m::titleInfo.m::partNumber.text().toString(); } } // get part if(!part) { part = mods.m::part; originInfo = mods.m::originInfo; } if(part) { for each(var detail in part.m::detail) { // volume if(detail.@type == "volume") { newItem.volume = detail.m::number.text().toString(); if(!newItem.volume) { newItem.volume = detail.m::text.text().toString(); } } // number if(detail.@type == "issue") { newItem.issue = detail.m::number.text().toString(); if(!newItem.issue) { newItem.issue = detail.m::text.text().toString(); } } // section if(detail.@type == "section") { newItem.section = detail.m::number.text().toString(); if(!newItem.section) { newItem.section = detail.m::text.text().toString(); } } } // pages for each(var extent in part.m::extent) { if(extent.@unit == "pages" || extent.@unit == "page") { var pagesStart = extent.m::start.text().toString(); var pagesEnd = extent.m::end.text().toString(); if(pagesStart || pagesEnd) { if(pagesStart == pagesEnd) { newItem.pages = pagesStart; } else if(pagesStart && pagesEnd) { newItem.pages = pagesStart+"-"+pagesEnd; } else { newItem.pages = pagesStart+pagesEnd; } } } } } // identifier processIdentifiers(newItem, mods.m::identifier); // edition newItem.edition = originInfo.m::edition.text().toString(); // place for each(var placeTerm in originInfo.m::place.m::placeTerm) { if(placeTerm.@type == "text") { newItem.place = placeTerm.text().toString(); } } // publisher/distributor if(originInfo.m::publisher.length()) { if(newItem.itemType == "webpage" || newItem.itemType == "website") { newItem.publicationTitle = originInfo.m::publisher[0].text().toString(); } else { newItem.publisher = originInfo.m::publisher[0].text().toString(); } } // date if(originInfo.m::copyrightDate.length()) { newItem.date = originInfo.m::copyrightDate[0].text().toString(); } else if(originInfo.m::dateIssued.length()) { newItem.date = originInfo.m::dateIssued[0].text().toString(); } else if(originInfo.m::dateCreated.length()) { newItem.date = originInfo.m::dateCreated[0].text().toString(); } // lastModified newItem.lastModified = originInfo.m::dateModified.text().toString(); // accessDate newItem.accessDate = originInfo.m::dateCaptured.text().toString(); // call number newItem.callNumber = mods.m::classification.text().toString(); // archiveLocation newItem.archiveLocation = mods.m::location.m::physicalLocation.text().toString(); // attachments and url for each(var url in mods.m::location.m::url) { var value = url.text().toString(); if (url.@access == "raw object") { var filetitle; if (url.@displayLabel){ filetitle = url.@displayLabel; } else { filetitle = "Attachment"; } if (value.substr(-4,4)==".pdf") { newItem.attachments.push({url:value, mimeType:"application/pdf", title:filetitle, downloadable:true}); } else { newItem.attachments.push({url:value, title:filetitle, downloadable:true}); } } else { newItem.url = value; } } // abstract newItem.abstractNote = mods.m::abstract.text().toString(); /** NOTES **/ for each(var note in mods.m::note) { newItem.notes.push({note:note.text().toString()}); } /** TAGS **/ for each(var subject in mods.m::subject.m::topic) { newItem.tags.push(subject.text().toString()); } // Language // create an array of languages var languages = new Array(); // E4X filter might need to be updated to include languageTerms that are @type="code" only for each(var language in mods.m::language.m::languageTerm.(@type == "text")) { languages.push(language.text().toString()); } // join the list separated by semicolons & add it to zotero item newItem.language = languages.join('; '); Zotero.debug(newItem); newItem.complete(); } }