Maintained by: David J. Birnbaum (djbpitt@gmail.com)
Last modified:
2023-04-26T00:39:30+0000
We asked you to produce an SVG visualization using data from the Federalist Papers. The test instructions explain our expectations, including required components of the graph and some optional bonus tasks.
The XSLT below produces output that meets our requirements and demonstrates proper use of variables, comments, and XSLT Best Practice. Your code doesn’t have to look exactly like ours, so treat this solution as a guideline for how to approach the task.
]]>
descendant::
axis<federalism>
is a descendant of
<paper>
, so inside the template that matches
papers, we have to navigate along the descendant axis to find and count
<federalism>
. You may have noticed that if
you tried to use simply
//federalism => count()
, you found all the
<federalism>
elements in the entire
document, rather than just those inside the paper being processed. That’s because
//
says start from the document node and
find all instances of
. To circumvent this issue, we usually write out
<federalism>
on
its descendant axisdescendant::
, which looks along the descendant
axis of the current context.
Because the highest count of <federalism>
in
any single paper was 33 (a value we found by doing some exploratory document
anaylsis with XPath), we set the maximum value of the Y axis to 40. We prefer to
work with nice, even values in SVG, because human viewers think best in multiples of
10. We created a variable called $maxHeight
and
gave it a value of 40, but a graph with a maximum height of 40px is pretty small. To
scale the graph and make it look larger, we used a
$yScale
variable. Its value is 10, and we
multiplied it by $maxHeight
when setting the
length of our Y axis. We could have set
$maxHeight
to a value of 400 in the first
place, and it’s perfectly fine to take that approach. We like having a
$yScale
variable, though, because it allows us
to keep track of the scale of the graph and ensure that the bar heights are
appropriately proportionate to the Y axis. When calculating the heights of the bars,
we found the raw count of <federalism>
, then
multiplied it by our $yScale
. If every Y value
is scaled by the same amount, we know that our graph is proportionate: 400px on the
graph represents 40 <federalism>
elements,
290px represents 29 <federalism>
elements,
etc. If we wanted to adjust the height of the entire graph, we would then only have
to change the $yScale
value, and everything
else adjusts accordingly.
Below is a possible solution to the optional bonus tasks, which asked you to:
Find the number of characters in
<federalism>
elements using
string-length()
.
Arrange the graph so that the tallest bar appears first, then the next tallest bar, etc.
Add some styling!
]]>
normalize-space()
and
string-length()
functionsWe used XPath to find the total character count within all the
<federalism>
descendants of each
paper. We start by feeding each <federalism>
element into normalize-space()
using the bang
operator, which operates over each element, one-by-one.
normalize-space()
, which removes sequences of
whitespaces inside the input. This means that if a
<federalism>
element has newline characters
and lots of leading whitespace as a result of pretty-printing, XPath will ignore it.
From here, we use string-length()
to get the
character count, now that extraneous whitespace has been removed. We’ve been
operating over each <federalism>
descendant
with the bang because these functions can only take one argument at a time. We use
the arrow operator to feed all the string lengths into
sum()
, which gets us the total number of
whitespace-normalized characters in the
<federalism>
descendants of our paper. You
might have taken a different approach here, as with most tasks in this class,
there’s more than one way to reach a working solution. Other approaches may, for
example, have used string-join()
to join the
contents of <federalism>
elements before
performing whitespace normalization and finding the string length.