I am trying to use XSLT to turn an XML document into plain text tables for human consumption. I am using xsltproc
, which only implements XSLT 1.0 (so max
is from EXSLT actually).
I tried the below, but the commented-out definition fails because string-length
returns only a single value (the length of the first node's string value), not a node-set like max
wants.
Transformation:
<?xml version="1.0" encoding="utf-8"?>
<!-- vim: set sts=2 sw=2: -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math" xmlns:str="http://exslt.org/strings">
<xsl:output method="text"/>
<xsl:template match="/root">
<!-- <xsl:variable name="max_a_width" select="math:max(string-length(data/@a))"/> -->
<xsl:variable name="max_a_width" select="string-length(data/@a)"/>
<xsl:text>+-</xsl:text><xsl:value-of select="str:padding($max_a_width, '-')"/><xsl:text>-+ </xsl:text>
<xsl:for-each select="data">
<xsl:text>| </xsl:text><xsl:value-of select="@a"/><xsl:value-of select="str:padding($max_a_width - string-length(@a), ' ')"/><xsl:text> | </xsl:text>
</xsl:for-each>
<xsl:text>+-</xsl:text><xsl:value-of select="str:padding($max_a_width, '-')"/><xsl:text>-+ </xsl:text>
</xsl:template>
</xsl:stylesheet>
Input:
<?xml version="1.0" encoding="utf-8"?>
<!-- vim: set sts=2 sw=2: -->
<root>
<data a="aa"/>
<data a="aaa"/>
<data a="a"/>
</root>
Output:
+----+
| aa |
| aaa |
| a |
+----+
In order to make the right border line up, I need to have the actual maximum value in the variable. (In my real example I will have column headers and multiple columns, but they are not necessary to reproduce the problem).
If it makes it easier to find a solution, I can guarantee that the data values will never contain spaces.
This is the general method of picking from an ordered list of derived values in XSLT 1.0.
If you want to pick the minimum/maximum from actual (natively sortable) values, you can take a short-cut: