In the previous tutorial, data was pulled into a page using OU Campus’ Tags. In this tutorial, data will be pulled in based on a folder location, sorted and then displayed.
View a simplified but workable code on GitHub.
Get All the Journal Data Files and Organize them by File Name
In case you haven’t read the previous tutorial, Data files are standalone .pcf files that are similar to a database entry. Each file contains the information for a single journal entry: Journal Name, Description, URL and a dropdown for Active, which will tell the XSL if the data file should be pulled in or not.
All the data files exist in one folder and XSL can grab those files and parse the data. The XSL needs to get those file names and sort them alphabetically:
<!-- static folder to look for data files: -->
<xsl:variable name="data-folder" select="'/pcf/data'" />
<xsl:variable name="data-location" select="concat($ou:root, $ou:site, $data-folder)" />
<!-- Create Sorted Version First, this has to happen here so we can use preceding-sibling later -->
<xsl:variable name="sortedcopy">
<xsl:for-each select="doc($data-location)/list/file">
<xsl:sort select="." order="ascending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
Two variables are setup, the first tells the XSL where to look for our data files. In this demo, the value is hard coded in. The second variable is a variation of the first but for OU Campus includes the root and the site. These are separated out into individual variables because $data-folder
is used later when tags are pulled in.
Next a variable of $sortedcopy
is defined by looping through all of the files in the directory. This is stored as a variable because to use the functionality of preceding-sibling
is used in the next code snippet and this and <xsl:sort />
can not be used in the same loop.
Loop Through the Sorted Data Files
The following for-each statement is a bit longer, and could be separated out into multiple functions, but then the parameters would need to be passed to each function. This decision would depend on how much of the code is reused. For this tutorial, it is a single loop and is split up into three separate code snippets below:
<!-- Loop through list using the sibiling -->
<xsl:for-each select="$sortedcopy/file">
<!-- Variables for single data file -->
<xsl:variable name="file-name"><xsl:value-of select="."/></xsl:variable>
<xsl:variable name="page-content" select="doc(concat($data-location,'/', $file-name))" />
<!-- Check to make sure it is a data file -->
<xsl:if test="$page-content/document/page/@type = 'library-database'"> <!--library-database -->
<!-- Code continues... -->
Each data file in the $sortedcopy
variable is looped on line 2. The variables are setup for the file name (line 5) and then the content of that data file is stored into the second variable (line 6).
Next the page type is checked to make sure it is a library-database file. In many OU instances, a _props.pcf
file may exist that should not be pulled in.
Does the Journal Need an A-Z Heading?
On the A-Z Listing page, the journals should be listed out in alphabetical pagination. If the journal’s title starts with a new letter then a heading for that label should be displayed. XSL functions below have been separated out into individual lines for better readability, but in practice it could be on one line.
<!-- Get the first character of the title (example: If 'accounting' this will return 'A') -->
<xsl:variable name="current-letter" select="upper-case(
substring(
$page-content/document/ouc:properties/parameter[@name='database-name'],1,1
)
)"/>
<!-- If previous data file exists, get it, else leave the variable $previous-letter as blank -->
<xsl:variable name="previous-letter">
<xsl:if test="preceding-sibling::file[1] != ''">
<xsl:value-of select="upper-case(
substring(
doc(concat($data-location,'/', preceding-sibling::file[1]))/document/ouc:properties/parameter[@name='database-name'],1,1
)
)" />
</xsl:if>
</xsl:variable>
<!-- If the first character of the previous title does not equal the first character of the current title, display a header -->
<xsl:if test="$previous-letter != $current-letter">
<h2 class="break-above"><xsl:value-of select="$current-letter" /></h2>
</xsl:if>
Current Letter
Line 3 gets the first character of the current title using the XSL function substring(string, starting integer, ending integer)
. Then on Line 2 it converts it to uppercase with the XSL function upper-case(string)
. If the character is not converted to a uppercase, the lowercase version would be treated as a different letter.
Previous Letter
This is my favorite part of the code. To get the previous starting letter the XSL function preceding-sibling()
can be used. Line 10 should be true unless this is the first node in the data set. If this is not checked, the first item will fail and an XSL error will be thrown.
The first part of line 13: doc(concat($data-location,'/', preceding-sibling::file[1]))
starts by selecting the previous data file, then gets the database-name: /document/ouc:properties/parameter[@name='database-name']
. Similar to the current letter’s code it selects just the first letter and then capitalizes it. Now the current letter and previous letter are both stored as variables.
Need a Heading?
On line 20 the current letter is compared against the previous letter and if it isn’t the same, or if it is the first letter, a heading with that letter is displayed.
Display the Journal’s Information
The journals now need to be displayed. If there are a lot of journals, then the description could be hidden. Or in our final version of the UNC Libraries version accordions are used.
<!-- Display Journal content -->
<h3><xsl:value-of select="$page-content/document/ouc:properties/parameter[@name='database-name']" /></h3>
<p><xsl:value-of select="$page-content/document/ouc:properties/parameter[@name='database-description']" /></p>
<p><a href="{$page-content/ouc:properties[@label='config']/parameter[@name='database-url']}">Open Database</a></p>
<!-- GetTagsForPage function will get the tags associated with the data file -->
<xsl:call-template name="GetTagsForPage">
<xsl:with-param name="page-path" select="concat($data-folder,'/', $file-name)" />
</xsl:call-template>
<hr/>
<!-- FROM LoopThoughSortedList-Start.xsl on line 9 `if (@type=library-database)` -->
</xsl:if>
<!-- FROM LoopThoughtSortedList-Start.xsl on line 2 select="$sortedcopy/file" -->
</xsl:for-each>
Lines 2 – 4 display the name, description and create a link for the database.
Lines 7-9 call a template that will get the tags for the page. Here the $page-path parameter, that was defined in the first code example, is used again. This template is described next.
Finally, lines 14 and 17 close open tags from the code snippet above.
List the Subjects Associated with the Journal
Below the link to the journal database, there will be a list of the subject tags that this journal is associated with. This will help with usability for the end users who may not be aware that the categories exist. These subject tags will link to the subject page so the user can explore more databases.
<!-- Get the Tags that are associated with the data file -->
<xsl:template name="GetTagsForPage">
<xsl:param name="page-path" />
<xsl:variable name="page-tags" select="doc(concat('ou:/Tag/GetTags?site=', $ou:site, '&path=', $page-path))/tags" />
<xsl:for-each select="$page-tags/tag">
<xsl:call-template name="DisplayTag">
<xsl:with-param name="tag" select="." />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
$page-path
is passed to the function and on line 5, the tags associated with the data file are returned as the variable $page-tags. On line 6 the tags are looped and lines 8-10 the tag is passed to an additional template to display the tag.
Display the Tag and Link to the Subject Page
Bootstrap and Foundation have a class for tags called .label. This will be wrapped with an anchor to link to that subject page.
<!-- Template to display and format an Individual Tag -->
<xsl:template name="DisplayTag">
<xsl:param name="tag" />
<!-- Remove the `library-database-` from the tag name -->
<xsl:variable name="tag-name" select="replace($tag/name, 'library-database-', '')" />
<!-- Link the label to the page. This server uses aspx -->
<a href="{$tag-name}.aspx">
<span class="label label-success">
<!-- Replace Underscores with Spaces -->
<xsl:value-of select="replace($tag-name, '_', ' ')" />
</span>
</a>
</xsl:template>
The variable on line 6 removes the prefix of ‘library-database’ which was the naming convention used in the previous blog post. On line 9 an anchor is used to link to that subject page. This only works if the tag name and the subject file name are exactly the same. If the files are in a sub folder, that should be defined here.
Line 12 replaces the underscore in a tag with a dash. This naming convention allows for a tag with multiple words. As an example: library-database-hispanic_studies gets converted into hispanic studies but keeps the URL of hispanic_studies.aspx.
Thanks for Reading
Updates
- Feb 5, 2021 - Since I don't work at UNC anymore, they removed the demo and the library no longer uses OU Campus to manage their journals.