www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit dcdef746e569b3c336cc099587851517cd53948d
parent 67fb2f6fc223f19a08bdbcec16b1a808a361474c
Author: Simon Kornblith <simon@simonster.com>
Date:   Sun, 30 May 2010 12:39:48 +0000

automatically apply XSLT to convert CSL 0.8 styles to CSL 1.0 styles on the fly
do we want to re-save the converted files over the old ones?


Diffstat:
Mchrome/content/zotero/xpcom/style.js | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
AupdateCSL.xsl | 410+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 466 insertions(+), 14 deletions(-)

diff --git a/chrome/content/zotero/xpcom/style.js b/chrome/content/zotero/xpcom/style.js @@ -346,6 +346,7 @@ Zotero.Style = function(file) { this.styleID = Zotero.Styles.ios.newFileURI(this.file).spec; this.title = file.leafName.substr(0, file.leafName.length-4); this.updated = Zotero.Date.dateToSQL(new Date(file.lastModifiedTime)); + this._versino = "0.8"; } else if(extension == ".csl") { // "with ({});" needed to fix default namespace scope issue // See https://bugzilla.mozilla.org/show_bug.cgi?id=330572 @@ -360,6 +361,8 @@ Zotero.Style = function(file) { this.updated = xml.info.updated.toString().replace(/(.+)T([^\+]+)\+?.*/, "$1 $2"); this._class = xml.@class.toString(); this._hasBibliography = !!xml.bibliography.length(); + this._version = xml.@version.toString(); + if(this._version == "") this._version = "0.8"; this.source = null; for each(var link in xml.info.link) { @@ -389,7 +392,40 @@ function() { } } - return new Zotero.CiteProc.CSL.Engine(Zotero.Cite.System, this.getXML(), Zotero.locale); + if(this._version == "0.8") { + // get XSLT file + let updateXSLTFile = Zotero.getInstallDirectory(); + updateXSLTFile.append("updateCSL.xsl"); + + // read XSLT file as DOM XML + let xmlFiles = []; + let fis = Components.classes["@mozilla.org/network/file-input-stream;1"]. + createInstance(Components.interfaces.nsIFileInputStream); + fis.init(updateXSLTFile, 0x01, 0664, 0); + let updateXSLT = Components.classes["@mozilla.org/xmlextras/domparser;1"] + .createInstance(Components.interfaces.nsIDOMParser) + .parseFromStream(fis, "UTF-8", updateXSLTFile.fileSize, "text/xml"); + fis.close(); + + // load XSLT file into XSLTProcessor + let xsltProcessor = Components.classes["@mozilla.org/document-transformer;1?type=xslt"] + .createInstance(Components.interfaces.nsIXSLTProcessor); + xsltProcessor.importStylesheet(updateXSLT); + + // read style file as DOM XML + let styleDOMXML = Components.classes["@mozilla.org/xmlextras/domparser;1"] + .createInstance(Components.interfaces.nsIDOMParser) + .parseFromString(this.getXML(), "text/xml"); + + // apply XSLT and serialize output + let newDOMXML = xsltProcessor.transformToDocument(styleDOMXML); + var xml = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"] + .createInstance(Components.interfaces.nsIDOMSerializer).serializeToString(newDOMXML); + } else { + var xml = this.getXML(); + } + + return new Zotero.CiteProc.CSL.Engine(Zotero.Cite.System, xml, Zotero.locale); }); Zotero.Style.prototype.__defineGetter__("class", @@ -413,6 +449,24 @@ function() { return this._hasBibliography; }); +Zotero.Style.prototype.__defineGetter__("independentFile", +/** + * Retrieves the file corresponding to the independent CSL + * (the parent if this style is dependent, or this style if it is not) + */ +function() { + if(this.source) { + // parent/child + var formatCSL = Zotero.Styles.get(this.source); + if(!formatCSL) { + throw(new Error('Style references '+this.source+', but this style is not installed', + Zotero.Styles.ios.newFileURI(this.file).spec, null)); + } + return formatCSL.file; + } + return this.file; +}); + /** * Retrieves the XML corresponding to this style * @type String @@ -432,19 +486,7 @@ Zotero.Style.prototype.getXML = function() { return XML.toXMLString(); } else { - if(this.source) { - // parent/child - var formatCSL = Zotero.Styles.get(this.source); - if(!formatCSL) { - throw(new Error('Style references '+this.source+', but this style is not installed', - Zotero.Styles.ios.newFileURI(this.file).spec, null)); - } - var file = formatCSL.file; - } else { - var file = this.file; - } - - return Zotero.File.getContents(file); + return Zotero.File.getContents(this.independentFile); } }; diff --git a/updateCSL.xsl b/updateCSL.xsl @@ -0,0 +1,410 @@ +<xsl:stylesheet xmlns:cs="http://purl.org/net/xbiblio/csl" xmlns="http://purl.org/net/xbiblio/csl" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" exclude-result-prefixes="cs"> + + <xsl:output indent="yes" method="xml" encoding="utf-8"/> + <xsl:strip-space elements="*"/> + + <!-- * xml:lang is no longer allowed on cs:style to eliminate confusion with + the default-locale attribute. If xml:lang was set, its value is + transferred to the default-locale attribute. + * cs:style now indicates CSL version compatibility via the version + attribute. --> + <xsl:template match="/cs:style"> + <xsl:copy> + <xsl:copy-of select="@*[not(name()='xml:lang')]"/> + <xsl:choose> + <xsl:when test="@xml:lang and not(@xml:lang='en' or @xml:lang='en-US' or @xml:lang='en-us')"> + <xsl:attribute name="default-locale"> + <xsl:value-of select="@xml:lang"/> + </xsl:attribute> + </xsl:when> + </xsl:choose> + <xsl:attribute name="version">1.0</xsl:attribute> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- Elements that themselves can be copied verbatim but whose child nodes + might require modification. --> + <xsl:template + match="cs:choose|cs:else|cs:info|cs:names|cs:substitute|cs:macro|cs:layout"> + <xsl:copy> + <xsl:copy-of select="@*"/> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- Elements that can be copied verbatim together with any child nodes. --> + <xsl:template match="cs:sort|cs:number|comment()"> + <xsl:copy-of select="."/> + </xsl:template> + + <!-- Child elements of cs:info that can be copied verbatim. --> + <xsl:template + match="cs:author|cs:contributor|cs:id|cs:issn|cs:published|cs:rights|cs:source|cs:summary|cs:title|cs:updated"> + <xsl:copy-of select="."/> + </xsl:template> + + <!-- For the rel attribute on cs:link, "documentation" will be used instead of + "homepage", and "source" has been renamed to "independent-parent". The + URL of a dependent style is now accompanied with a rel value of "self". --> + <xsl:template match="cs:link"> + <xsl:variable name="rel-value"> + <xsl:choose> + <xsl:when test="@rel='documentation' or @rel='homepage'">documentation</xsl:when> + <xsl:when test="@rel='template'">template</xsl:when> + <xsl:when test="@rel='source'">independent-parent</xsl:when> + <xsl:otherwise>self</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:copy> + <xsl:attribute name="href"> + <xsl:value-of select="@href"/> + </xsl:attribute> + <xsl:attribute name="rel"> + <xsl:value-of select="$rel-value"/> + </xsl:attribute> + </xsl:copy> + </xsl:template> + + <!-- The citation-format and field attributes have replaced the term attribute + on cs:category, and the "in-text" category has been removed. Styles with + the "in-text" category are assigned the "numeric" citation-format if the + "citation-number" variable is used in citations, and the "author-date" + format in all other cases. --> + <xsl:template match="cs:category"> + <xsl:choose> + <xsl:when test="@term='in-text'"> + <xsl:choose> + <xsl:when test="/cs:style/cs:citation//cs:text[@variable='citation-number']"> + <xsl:copy> + <xsl:attribute name="citation-format">numeric</xsl:attribute> + </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:attribute name="citation-format">author-date</xsl:attribute> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="@term='author-date' or @term='numeric' or @term='label' or @term='note'"> + <xsl:copy> + <xsl:attribute name="citation-format"> + <xsl:value-of select="@term"/> + </xsl:attribute> + </xsl:copy> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:attribute name="field"> + <xsl:value-of select="@term"/> + </xsl:attribute> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- The hierarchy cs:terms/cs:locale/cs:term has been replaced by + cs:locale/cs:terms/cs:term. --> + <xsl:template match="cs:terms/cs:locale"> + <xsl:copy> + <xsl:copy-of select="@*"/> + <xsl:element name="terms"> + <xsl:copy-of select="cs:term"/> + </xsl:element> + </xsl:copy> + </xsl:template> + + <!-- Citation-specific CSL options are now set as attributes on cs:citation, + instead of via cs:option elements. --> + <xsl:template match="cs:citation"> + <xsl:copy> + <xsl:for-each select="cs:option"> + <xsl:attribute name="{@name}"> + <xsl:value-of select="@value"/> + </xsl:attribute> + </xsl:for-each> + <xsl:apply-templates select="cs:layout|cs:sort"/> + </xsl:copy> + </xsl:template> + + <!-- * Bibliography-specific CSL options are now set as attributes on + cs:bibliography, instead of via cs:option elements. + * second-field-align now uses the value "flush" instead of "true". --> + <xsl:template match="cs:bibliography"> + <xsl:copy> + <xsl:for-each select="cs:option"> + <xsl:choose> + <xsl:when test="@name='second-field-align' and @value='true'"> + <xsl:attribute name="second-field-align">flush</xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="{@name}"> + <xsl:value-of select="@value"/> + </xsl:attribute> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + <xsl:apply-templates select="cs:layout|cs:sort"/> + </xsl:copy> + </xsl:template> + + <!-- CSL 1.0 eliminates item type fallback behavior in conditionals + ("article", "book" and "chapter" used to be type archetypes, e.g. + "article-journal" would be a subtype of "article", see + http://docs.google.com/View?id=dg6h9k72_64hzmsmqgb). For the conversion, + each archetype is replaced by all subtypes of that archetype (while + making sure that "song" is only present once in the attribute string, as + "song" is a subtype of both "article" and "book"). If an archetype is + replaced by its subtypes, the match attribute is set to "any", unless + match was set to "none". This is done as "type='chapter' match='all'" can + test true, but "type='chapter paper-conference' match='all' can not (each + item is of a single type). cs:if and cs:if-else elements that, in + addition to the type conditional, test with match="all" (the default + attribute value) and carry additional conditionals are split into a + nested conditional (an example of this case is given at + http://forums.zotero.org/discussion/11960/item-type-testing-in-csl-10-and-fallbacks/#Comment_58392 + ). --> + <xsl:template match="cs:if|cs:else-if"> + <xsl:copy> + <xsl:choose> + <xsl:when test="contains(@type,'book') or (contains(@type,'article') and not(contains(@type,'article-'))) or contains(@type,'chapter')"> + <xsl:choose> + <xsl:when test="(not(@match='any') and not(@match='none')) and (@variable or @is-numeric or @position or @disambiguate)"> + <xsl:call-template name="fallback-replacement"/> + <xsl:attribute name="match">any</xsl:attribute> + <xsl:element name="choose"> + <xsl:element name="if"> + <xsl:copy-of select="@*[not(name()='type')]"/> + <xsl:apply-templates/> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="@*"/> + <xsl:call-template name="fallback-replacement"/> + <xsl:if test="not(@match='none')"> + <xsl:attribute name="match">any</xsl:attribute> + </xsl:if> + <xsl:apply-templates/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="@*"/> + <xsl:apply-templates/> + </xsl:otherwise> + </xsl:choose> + </xsl:copy> + </xsl:template> + + <xsl:template name="fallback-replacement"> + <xsl:choose> + <xsl:when test="contains(@type,'book')"> + <xsl:attribute name="type"> + <xsl:call-template name="book-sans-space"/> + <xsl:call-template name="article"/> + <xsl:call-template name="chapter"/> + </xsl:attribute> + </xsl:when> + <xsl:when test="contains(@type,'article') and not(contains(@type,'article-'))"> + <xsl:attribute name="type"> + <xsl:call-template name="article-sans-space"/> + <xsl:call-template name="book"/> + <xsl:call-template name="chapter"/> + </xsl:attribute> + </xsl:when> + <xsl:when test="contains(@type,'chapter')"> + <xsl:attribute name="type"> + <xsl:call-template name="chapter-sans-space"/> + <xsl:call-template name="article"/> + <xsl:call-template name="book"/> + </xsl:attribute> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template name="book-sans-space"> + <xsl:text>bill book graphic legal_case motion_picture report song</xsl:text> + </xsl:template> + + <xsl:template name="article-sans-space"> + <xsl:choose> + <xsl:when test="contains(@type,'article') and not(contains(@type,'article-')) and contains(@type,'book')">article-journal article-magazine article-newspaper broadcast interview manuscript map patent personal_communication speech thesis webpage</xsl:when> + <xsl:when test="contains(@type,'article') and not(contains(@type,'article-'))">article-journal article-magazine article-newspaper broadcast interview manuscript map patent personal_communication song speech thesis webpage</xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template name="chapter-sans-space"> + <xsl:text>chapter paper-conference</xsl:text> + </xsl:template> + + <xsl:template name="book"> + <xsl:choose> + <xsl:when test="contains(@type,'book')"> bill book graphic legal_case motion_picture report song</xsl:when> + <xsl:otherwise> + <xsl:if test="contains(@type,'bill')"> bill</xsl:if> + <xsl:if test="contains(@type,'graphic')"> graphic</xsl:if> + <xsl:if test="contains(@type,'legal_case')"> legal_case</xsl:if> + <xsl:if test="contains(@type,'motion_picture')"> motion_picture</xsl:if> + <xsl:if test="contains(@type,'report')"> report</xsl:if> + <xsl:if test="contains(@type,'song')"> song</xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="article"> + <xsl:choose> + <xsl:when test="contains(@type,'article') and not(contains(@type,'article-')) and contains(@type,'book')"> article-journal article-magazine article-newspaper broadcast interview manuscript map patent personal_communication speech thesis webpage</xsl:when> + <xsl:when test="contains(@type,'article') and not(contains(@type,'article-'))"> article-journal article-magazine article-newspaper broadcast interview manuscript map patent personal_communication song speech thesis webpage</xsl:when> + <xsl:otherwise> + <xsl:if test="contains(@type,'article-journal')"> article-journal</xsl:if> + <xsl:if test="contains(@type,'article-magazine')"> article-magazine</xsl:if> + <xsl:if test="contains(@type,'article-newspaper')"> article-newspaper</xsl:if> + <xsl:if test="contains(@type,'broadcast')"> broadcast</xsl:if> + <xsl:if test="contains(@type,'interview')"> interview</xsl:if> + <xsl:if test="contains(@type,'manuscript')"> manuscript</xsl:if> + <xsl:if test="contains(@type,'map')"> map</xsl:if> + <xsl:if test="contains(@type,'patent')"> patent</xsl:if> + <xsl:if test="contains(@type,'personal_communication')"> personal_communication</xsl:if> + <xsl:if test="contains(@type,'speech')"> speech</xsl:if> + <xsl:if test="contains(@type,'thesis')"> thesis</xsl:if> + <xsl:if test="contains(@type,'map')"> map</xsl:if> + <xsl:if test="contains(@type,'webpage')"> webpage</xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="chapter"> + <xsl:choose> + <xsl:when test="contains(@type,'chapter')"> chapter paper-conference</xsl:when> + <xsl:otherwise> + <xsl:if test="contains(@type,'paper-conference')"> paper-conference</xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- The class attribute on cs:group has been removed in favor of the display + attribute. --> + <xsl:template match="cs:group"> + <xsl:copy> + <xsl:copy-of select="@*[not(name()='class')]"/> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- The text-case attribute can no longer be used on cs:name. In cases + where text-case was used on cs:name, the attribute and its value are + transferred to the "family" and "given" cs:name-part children. --> + <xsl:template match="cs:name"> + <xsl:copy> + <xsl:copy-of select="@*[not(name()='text-case')]"/> + <xsl:choose> + <xsl:when test="@text-case"> + <xsl:element name="name-part"> + <xsl:attribute name="name">family</xsl:attribute> + <xsl:attribute name="text-case"> + <xsl:value-of select="@text-case"/> + </xsl:attribute> + </xsl:element> + <xsl:element name="name-part"> + <xsl:attribute name="name">given</xsl:attribute> + <xsl:attribute name="text-case"> + <xsl:value-of select="@text-case"/> + </xsl:attribute> + </xsl:element> + </xsl:when> + </xsl:choose> + </xsl:copy> + </xsl:template> + + <!-- * In CSL 1.0, abbreviated terms are defined with periods, if applicable, + and the include-period attribute has replaced the strip-periods + attribute. For the conversion, strip-periods is set to "true" for any + cs:label element with form="short" or "verb-short", except when + include-period was set to "true". + * plural on cs:label now uses "always"/"never" instead of "true"/"false". --> + <xsl:template match="cs:label"> + <xsl:copy> + <xsl:copy-of select="@*[not(name()='include-period')]"/> + <xsl:choose> + <xsl:when test="(@form='short' or @form='verb-short') and not(@include-period='true')"> + <xsl:attribute name="strip-periods">true</xsl:attribute> + </xsl:when> + </xsl:choose> + <xsl:choose> + <xsl:when test="@plural='false'"> + <xsl:attribute name="plural">never</xsl:attribute> + </xsl:when> + <xsl:when test="@plural='true'"> + <xsl:attribute name="plural">always</xsl:attribute> + </xsl:when> + </xsl:choose> + </xsl:copy> + </xsl:template> + + <!-- The "event" date variable has been renamed to "event-date" to eliminate + the name conflict with the 'standard' "event" variable. --> + <xsl:template match="cs:date"> + <xsl:copy> + <xsl:copy-of select="@*"/> + <xsl:choose> + <xsl:when test="@variable='event'"> + <xsl:attribute name="variable">event-date</xsl:attribute> + </xsl:when> + </xsl:choose> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + <!-- In CSL 1.0, abbreviated terms are defined with periods, if applicable, + and the include-period attribute has replaced the strip-periods + attribute. For the conversion, strip-periods is set to "true" for any + "month" cs:date-part element with form="short", except when + include-period was set to "true". --> + <xsl:template match="cs:date-part"> + <xsl:choose> + <xsl:when test="@name='year' or @name='month' or @name='day'"> + <xsl:copy> + <xsl:copy-of select="@*[not(name()='include-period')]"/> + <xsl:choose> + <xsl:when + test="@form='short' and @name='month' and not(@include-period='true')"> + <xsl:attribute name="strip-periods">true</xsl:attribute> + </xsl:when> + </xsl:choose> + </xsl:copy> + </xsl:when> + </xsl:choose> + </xsl:template> + + <!-- * In CSL 1.0, abbreviated terms are defined with periods, if applicable, + and the include-period attribute has replaced the strip-periods + attribute. For the conversion, strip-periods is set to "true" for any + cs:text element with form="short" or "verb-short", except when + include-period was set to "true". + * The CSL 0.8 en-US locale file only included the "long" form of the + "no date" term, with a value of "n.d.". In the CSL 1.0 locale file, the + value has been changed to "no date", and a "short" form ("n.d.") has + been introduced. For the conversion, any cs:text element that called + the "long" form of the "no date" term will now call the "short" form, + unless the "long" form had been redefined in the style. --> + <xsl:template match="cs:text"> + <xsl:copy> + <xsl:copy-of select="@*[not(name()='include-period')]"/> + <xsl:choose> + <xsl:when + test="(@form='short' or @form='verb-short') and not(@include-period='true') and @term"> + <xsl:attribute name="strip-periods">true</xsl:attribute> + </xsl:when> + </xsl:choose> + <xsl:choose> + <xsl:when test="@term='no date' and not(/cs:style/cs:terms/cs:locale/cs:term/@name='no date')"> + <xsl:attribute name="form">short</xsl:attribute> + </xsl:when> + </xsl:choose> + </xsl:copy> + </xsl:template> + +</xsl:stylesheet>