# function question

**URL:** <https://discourse.citationstyles.org/t/function-question/61>\
**Category:** CSL Development\
**Created:** [April 20, 2005, 1:46pm UTC](https://discourse.citationstyles.org/t/function-question/61 "2005-04-20T13:46:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 20, 2005, 1:46pm UTC](https://discourse.citationstyles.org/t/function-question/61/1 "2005-04-20T13:46:57Z")

</div>

It may be time to sign up for the xsl list again, but David if you get  
a chance, does this look like a sensible way to correctly handle  
different mods:name roles? In other words, a translator gets processed  
differently than an author or editor. I’m most concerned with how I’m  
using it in the function at the bottom.

\<xsl:variable name=“primary-contributors” select="(‘author’,  
‘editor’, ‘creator’)"/\>  
\<xsl:variable name=“secondary-contributors” select="(‘translator’)"/\>

\<xsl:function name=“bib:contributor-role” as=“xs:string”\>  
\<xsl:param name=“name” as=“element(mods:name)?”/\>  
xsl:value-of  
xsl:choose  
\<xsl:when  
test="$name/mods:role/mods:roleTerm[@type=‘text’]=$primary-  
contributors"\>  
xsl:textprimary\</xsl:text\>  
\</xsl:when\>  
\<xsl:when  
test="$name/mods:role/mods:roleTerm[@type=‘text’]=$secondary-  
contributors"\>  
xsl:textsecondary\</xsl:text\>  
\</xsl:when\>  
\</xsl:choose\>  
\</xsl:value-of\>  
\</xsl:function\>

\<xsl:function name=“bib:grouping-key” as=“xs:string”\>  
\<xsl:param name=“bibref” as=“element(mods:mods)”/\>  
xsl:choose  
\<!–  
Is the below the best way to condition the processing?

Also, needs to be “and $csl-bib/position[1]=‘not(cs:creator)’”, to  
enable to properly handle reference types  
where, for example, title may be the first content/sort key (like with  
legal cases)  
–\>  
\<xsl:when  
test="$bibref/mods:name[bib:contributor-role(.)=‘primary’]"\>  
\<xsl:value-of separator=";"\>  
\<xsl:for-each select="$bibref/mods:name"\>  
\<xsl:value-of  
select=“string-join((mods:namePart[@type =  
‘family’]|mods:namePart[not(@type)], mods:namePart[@type = ‘given’]),  
’,’)”  
/\>  
\</xsl:for-each\>  
\</xsl:value-of\>  
\</xsl:when\>

---

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 20, 2005, 7:30pm UTC](https://discourse.citationstyles.org/t/function-question/61/2 "2005-04-20T19:30:45Z")

</div>

Followup:

How do I get this position() function to apply only to those mods:name  
elements that correspond to the “primary” contributor-role values?

\<xsl:when test="$contributor-role=‘primary’ and position() = last()"/\>

The (global) role variable is:

\<xsl:variable name=“primary-contributors” select="(‘author’, ‘editor’,  
‘creator’, ‘reporter’)"/\>

Source example would be:

 Jane Doe translator Jane Doe author John Smith translator 

The position of the second mods:name element with the author role should  
be ‘1’ and it should be ‘true’ for last().

Bruce

---

<div class="post-metadata">

**Author:** ![M\_David\_Peterson1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@M\_David\_Peterson1](https://discourse.citationstyles.org/u/M_David_Peterson1)\
**Post date:** [April 21, 2005, 12:37am UTC](https://discourse.citationstyles.org/t/function-question/61/3 "2005-04-21T00:37:22Z")

</div>

Bruce,

I just got back in. My plan now is to simply shut down and head off  
to bed now and then start with this in the morning with a fresh mind.  
Ping me when you are around.

Cheers 🙂

\<M:D/

---

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 21, 2005, 12:13pm UTC](https://discourse.citationstyles.org/t/function-question/61/4 "2005-04-21T12:13:06Z")

</div>

I’ve almost got this bit working. Bib formatting on this is now  
correct; am just stuck on the citation formatting.

The example, BTW, was a book with an author (let’s say “John Doe”) and  
a translator (“Susan Smith”). Earlier, both were treated the same, so I  
incorrectly had (Doe and Smith) in the citation, and “Doe, J. and S.  
Smith” in the bib list.

Now, I get (Doe and) for the citation, so the positional logic isn’t  
working right there (a familiar theme; yes?).

Anyway, will I guess check that in when I’m in the office, and hope you  
can help me fix it.

BTW, in looking through the code, I’m wondering if it’d make life  
easier if we broke out the current citeproc.xsl content into two  
separate files. Citeproc.xsl would only be focused on the core  
processing, which is grouping/sorting/enhancing. All of the  
formatting-only mods templates would then be broken out into another  
file; maybe called format-mods.xsl. Or maybe we could also use another  
file called group-sort.xsl, so that citeproc.xsl is then fairly  
compact?

This raises a larger issue, which is whether this project will only  
ever support MODS, or if there’s an elegant way to also allow other bib  
formats (the most obvious one that would be suitable is the new TEI  
stuff that’s coming with v5). I don’t really want to get distracted  
with that now, but it’s worth keeping in mind.

Bruce

---

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 21, 2005, 12:37pm UTC](https://discourse.citationstyles.org/t/function-question/61/5 "2005-04-21T12:37:10Z")

</div>

Thinking abstractly in terms of the kind of processing that needs to  
happen:

The most complex two citation classes are author-year and  
footnote/endnote based. The first is complex because it involves a  
multi-level grouping and sorting operation – in both the bibliography  
and the citations – and then along with that passing through  
information (either through constructed nodes in a temporary tree, as I  
do now, or in the form of parameters) that allows proper formatting in  
the next step.

IIRC, that information is:

```
citation-style
citation-class
year publisher/issued
position within an author group (and I guess the count)
position within an author-year group (and I guess the count)

```

The first two are determined with a function, but given that they’re  
used to sort, I assume it’s easier to just pass along the information  
than to hit the functions again later?? I’m really sure about  
performance optimization.

Both of the last two need to take into account what to do when there is  
not an “author.” “author” in this context might be better thought of  
as “primary-contributor” or “creator.”

Bruce

---

<div class="post-metadata">

**Author:** ![M\_David\_Peterson1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@M\_David\_Peterson1](https://discourse.citationstyles.org/u/M_David_Peterson1)\
**Post date:** [April 21, 2005, 1:23pm UTC](https://discourse.citationstyles.org/t/function-question/61/6 "2005-04-21T13:23:27Z")

</div>

Bruce,

As you mentioned earlier I think its a really good idea to now start  
over with a clean sheet of paper and begin to take this to the next  
level that will allows a simple format definition file be enough to be  
able to output to another format.

More in a bit… Im on a coding challenge at the moment which could  
finally open the doors to getting a community wide push to develop an  
open sylesheet template and extension library underway.

---

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 21, 2005, 1:31pm UTC](https://discourse.citationstyles.org/t/function-question/61/7 "2005-04-21T13:31:53Z")

</div>

M. David Peterson wrote:

> As you mentioned earlier I think its a really good idea to now start  
> over with a clean sheet of paper and begin to take this to the next  
> level that will allows a simple format definition file be enough to be  
> able to output to another format.

The issue I was mentioning as an aside (re: TEI) was not about output;  
it was about input.

The crucial thing is fixing the sorting/grouping stuff, and perhaps now  
is a good time to redo the core citeproc.xsl stuff that handles that, as  
I have a small bit of of breathing space (I think!).

> More in a bit… Im on a coding challenge at the moment which could  
> finally open the doors to getting a community wide push to develop an  
> open sylesheet template and extension library underway.

OK.

Bruce

---

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 21, 2005, 5:43pm UTC](https://discourse.citationstyles.org/t/function-question/61/8 "2005-04-21T17:43:52Z")

</div>

OK, I checked in a partial fix for the citation author/translator  
problem. The rest of the fix seems to need the same thing you did to  
fix the other grouping problems, since if you look at lines 368-94,  
you’ll see I’m using the same variable approach there.

David, if you can find the time, could you perhaps could suggest how to  
fix this? I’m tired and your solution is a bit hard to wrap my brain  
around at the moment.

Bruce

---

<div class="post-metadata">

**Author:** ![Bruce\_D\_Arcus](https://avatars.discourse-cdn.com/v4/letter/b/f9ae1b/32.png) [@Bruce\_D\_Arcus](https://discourse.citationstyles.org/u/Bruce_D_Arcus)\
**Post date:** [April 22, 2005, 1:33am UTC](https://discourse.citationstyles.org/t/function-question/61/9 "2005-04-22T01:33:40Z")

</div>

Well, I didn’t hear back, so I took a look again at the earlier code  
that correctly handled grouping and sorting, and incorporated it into a  
file with the existing functions. Result of messages are:

```
         author-position: <value-of select="1"/>
         author-year-position: <value-of select="1"/>

         author-position: <value-of select="2"/>
         author-year-position: <value-of select="1"/>

         author-position: <value-of select="2"/>
         author-year-position: <value-of select="1"/>

         author-position: <value-of select="3"/>
         author-year-position: <value-of select="1"/>

         author-position: <value-of select="4"/>
         author-year-position: <value-of select="1"/>

         author-position: <value-of select="4"/>
         author-year-position: <value-of select="2"/>

         author-position: <value-of select="5"/>
         author-year-position: <value-of select="1"/>

```

… which is close, but the author-position values are wrong. Also,  
this take about 700 ms on my machine when run against the mods test  
doc, which is not that fast (even if I have a slow machine, and am  
running an older version of Saxon).

David, is this a better approach, just passing the parameter through?  
Or did you have something else in mind?

\<?xml version="1.0" encoding="UTF-8"?\>

\<xsl:stylesheet xmlns:xsl="[http://www.w3.org/1999/XSL/Transform](http://www.w3.org/1999/XSL/Transform)"  
version="2.0"  
xmlns:xdoc="[http://www.pnp-software.com/XSLTdoc](http://www.pnp-software.com/XSLTdoc)"  
xmlns:xs="[http://www.w3.org/2001/XMLSchema](http://www.w3.org/2001/XMLSchema)"  
xmlns:mods="[http://www.loc.gov/mods/v3](http://www.loc.gov/mods/v3)"  
xmlns:cs="[http://purl.org/NET/xbiblio/csl](http://purl.org/NET/xbiblio/csl)"  
xmlns:bib="[http://purl.org/NET/xbiblio/citeproc](http://purl.org/NET/xbiblio/citeproc)"  
exclude-result-prefixes=“xdoc mods xs cs bib”\>

\<xsl:variable name=“biblist”\>  
\<xsl:copy-of select=“mods:modsCollection”/\>  
\</xsl:variable\>

\<xsl:template match="/"\>  
\<xsl:apply-templates mode=“enhanced-biblist”/\>  
\</xsl:template\>

\<xsl:template name=“bib-enhanced-biblist” match=“mods:modsCollection"  
mode=“enhanced-biblist”\>  
\<xsl:variable name=“bibref” select=“mods:mods” /\>  
\<xsl:for-each-group select=”$bibref"  
group-by=“bib:grouping-key(.)”\>  
\<xsl:sort select=“current-grouping-key()”/\>  
\<xsl:variable name=“author-position” select=“position()”/\>  
\<xsl:for-each-group select="current-group()“  
group-by=“bib:year(.)”\>  
\<xsl:sort select=“current-grouping-key()” /\>  
\<xsl:variable name=“author-year-position"  
select=“position()”/\>  
\<xsl:variable name=“year” select=“current-grouping-key()”/\>  
\<xsl:variable name=“first” as=“xs:boolean” select=“position() = 1” /\>  
\<xsl:for-each select=“current-group()”\>  
\<xsl:copy-of select=”.”/\>  
xsl:message  
author-position:   
author-year-position:   
\</xsl:message\>  
\</xsl:for-each\>  
\</xsl:for-each-group\>  
\</xsl:for-each-group\>  
\</xsl:template\>

\<xsl:variable name=“primary-contributors” select="(‘author’,  
‘editor’, ‘creator’)"/\>  
\<xsl:variable name=“secondary-contributors” select="(‘translator’)"/\>

\<xsl:function name=“bib:contributor-role” as=“xs:string”\>  
\<xsl:param name=“name” as=“element(mods:name)?”/\>  
xsl:value-of  
xsl:choose  
\<xsl:when  
test="$name/mods:role/mods:roleTerm[@type=‘text’]=$primary-  
contributors"\>  
xsl:textprimary\</xsl:text\>  
\</xsl:when\>  
\<xsl:when  
test="$name/mods:role/mods:roleTerm[@type=‘text’]=$secondary-  
contributors"\>  
xsl:textsecondary\</xsl:text\>  
\</xsl:when\>  
\</xsl:choose\>  
\</xsl:value-of\>  
\</xsl:function\>

\<xsl:function name=“bib:year”\>  
\<xsl:param name=“bibref” as=“element(mods:mods)”/\>  
\<xsl:for-each select="$bibref"\>  
\<xsl:value-of  
select=“substring((mods:originInfo/mods:dateIssued,  
mods:relatedItem/mods:originInfo/mods:dateIssued,  
mods:relatedItem/mods:part/mods:date)[1],1,4)”  
/\>  
\</xsl:for-each\>  
\</xsl:function\>  
xdoc:docCollapses a page range according to the Chicago algorithm.  
Probably  
needs to be generalized.\</xdoc:doc\>  
\<xsl:function name=“bib:number-condense”\>  
\<xsl:param name=“begin”/\>  
\<xsl:param name=“end”/\>  
xsl:choose  
\<xsl:when test="$begin castable as xs:integer"\>  
\<xsl:variable name=“begin” select=“xs:integer($begin)“  
as=“xs:integer”/\>  
xsl:choose  
\<xsl:when  
test=”$begin gt 100 and $begin mod 100 and $begin idiv 100  
eq $end idiv 100”\>  
\<xsl:value-of select="$end mod 100"/\>  
\</xsl:when\>  
xsl:otherwise  
\<xsl:value-of select="$end"/\>  
\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:when\>  
xsl:otherwise  
\<xsl:value-of select="$end"/\>  
\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:function\>

\<xsl:function name=“bib:grouping-key” as=“xs:string”\>  
\<xsl:param name=“bibref” as=“element(mods:mods)”/\>  
xsl:choose  
  
\<xsl:when  
test="$bibref/mods:name[bib:contributor-role(.)=‘primary’]"\>  
\<xsl:value-of separator=";"\>  
\<xsl:for-each select="$bibref/mods:name"\>  
\<xsl:value-of  
select=“string-join((mods:namePart[@type =  
‘family’]|mods:namePart[not(@type)], mods:namePart[@type = ‘given’]),  
’,’)”  
/\>  
\</xsl:for-each\>  
\</xsl:value-of\>  
\</xsl:when\>  
xsl:otherwise  
xsl:choose  
\<xsl:when

test="$bibref/mods:relatedItem[@type=‘host’]/mods:originInfo/mods:  
issuance = ‘continuing’"\>  
\<xsl:for-each select="$bibref"\>  
\<xsl:value-of

select=“mods:relatedItem[@type=‘host’]/mods:titleInfo[not(@type)]/mods:  
title”  
/\>  
\</xsl:for-each\>  
\</xsl:when\>  
xsl:otherwise  
  
xsl:textAnonymous\</xsl:text\>  
\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:function\>

\<xsl:function name=“bib:refclass” as=“xs:string”\>  
\<xsl:param name=“bibref” as=“element(mods:mods)?”/\>  
xsl:choose  
\<xsl:when test="$bibref/mods:relatedItem[@type=‘host’]"\>  
\<xsl:variable name=“issuance”

select="$bibref/mods:relatedItem/mods:originInfo/mods:issuance"/\>  
xsl:choose  
\<xsl:when  
test="$issuance=‘monographic’"\>part-inMonograph\</xsl:when\>  
xsl:otherwisepart-inSerial\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:when\>  
xsl:otherwisemonograph\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:function\>

\<xsl:function name=“bib:reftype” as=“xs:string”\>  
\<xsl:param name=“bibref” as=“element(mods:mods)?”/\>  
xsl:value-of  
xsl:choose  
\<xsl:when test="$bibref/mods:relatedItem/@type = ‘host’"\>  
\<xsl:variable name=“issuance”

select="$bibref/mods:relatedItem/mods:originInfo/mods:issuance"/\>  
xsl:choose  
\<xsl:when test=“bib:refclass($bibref) = ‘part-inSerial’”\>  
\<xsl:if  
test="$bibref/mods:relatedItem/mods:genre=‘periodical’"\>  
xsl:textarticle\</xsl:text\>  
xsl:text-\</xsl:text\>  
\</xsl:if\>  
\<xsl:value-of  
select="$bibref/mods:relatedItem/mods:genre"/\>  
\</xsl:when\>  
\<xsl:when test=“bib:refclass($bibref) = ‘part-inMonograph’”\>  
xsl:choose  
\<xsl:when test="$bibref/mods:genre"\>  
\<xsl:value-of select="$bibref/mods:genre"/\>  
\</xsl:when\>  
xsl:otherwise  
xsl:textchapter\</xsl:text\>  
\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:when\>  
xsl:otherwise  
\<xsl:value-of select="$bibref/mods:genre"/\>  
\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:when\>  
xsl:otherwisebook\</xsl:otherwise\>  
\</xsl:choose\>  
\</xsl:value-of\>  
\</xsl:function\>

\</xsl:stylesheet
