Digital humanities

Maintained by: David J. Birnbaum ( [Creative Commons BY-NC-SA 3.0 Unported License] Last modified: 2022-04-12T22:01:33+0000

Test #6: Schematron

The data

The data for this test came from the Songs of Colonization project, which we edited for our purposes. You can download the XML from

The task

Your task was to create a stacked bar chart of instances of violence in the songs, represented in the markup by <violence> elements, which have @victim attributes. @victim can take one of three values: "settler", "native", and "ambiguous". Your chart should show the proportion of each of those values to the total instances of violence in each song.

Our solution

            Proportion of Victims
            % Instances of Violence



Stylesheet variables

Bar charts don’t care about the exact width or height of the bars, and we chose values that looked proportionally attractive to us. We made the interbar spacing equal to half the width of the bars (which is a common convention), and because we don’t like the look of squat bars, we used a multiplier of 3 to stretch their length. We used variables for the colors for two reasons. First, we use each color twice (bar and legend), and with a variable we can change a color by making one change instead of tracking down two and keeping them synchronized. Second, the hex notation is not human-readable, and had we used the raw hex values in the body of the stylesheet we would have struggled to remember which color we were working with when.

Drawing order and visual prominence

We want the data bars to mask the mid-height ruling line where they overlap because the ruling line is supposed to be a subtle hint, and it shouldn’t attract more attention than the data bars, so we have to draw the line first and the bars second. Where the bars meet the X axis we want the X axis to mask the bars, so that the bars don’t appear to bite into the axis line. That means that we need to draw the X axis after the bars. The other chart components do not overlap, which means that we could draw them in any order.

We made the ruling line gray and dashed (using the @stroke-dasharray attribute) to reduce its prominence.

We use the @stroke-linecap attribute on the axis lines so that they meet squarely.

Calculating bar heights

To compute the height of the bar segments for "settler" and "native" violence we divide the count of <violence> elements with a specific @victim attribute value by the total count of <violence> elements in the song, which yields a value between 0 and 1. We bind these values to variables. For reasons we explain in the instructions we don’t have to perform this computation for ambiguous victims.

Notice in the code above that we write descendant::violence. We could, alternatively, have written .//violence, using the dot to anchor the expression in the song that is the current context. That would work, but it’s perilously easy to write //violence (without the dot) by accident, and that would find all the instances of violence in the entire document, which isn’t what we want when we’re looking at one song at a time. The takeaway is that although descendant::violence and .//violence mean the same thing in this situation, we make fewer mistakes when we use descendant::violence.


The comments we wrote in the stylesheet above are the ones we would have written had we developed the code for a real project. One goal of the comments is to help us find a particular location in the stylesheet easily. Another goal is to explain decisions we made that we might forget over time, such as why we drew the components in a particular order.