[xslt_select_csv/]

‘xslt_select_xml’ is a helper function. It reads XML and returns a subset of the data, based on a supplied XPATH expression. Used to pre-filter data passed to ‘xslt_transform_xml’, ‘xslt_select_xml’ allows for more generic, reuseable stylesheets.

[xslt_select_csv/] is a helper function for converting CSV data to XML. Once reformatted, the result can be output directly to the page as an HTML <table>, or the result can be passed to [xslt_transform_xml/] for further processing.

There are two (2) options for specifying the source CSV when using the csv attribute:

local file: csv="/path/to/local/spreadsheet.csv"
remote file: csv="http://abc.de/remote/spreadsheet.csv"

Source data can also be input directly in the body of the shortcode. This results in two (2) usage patterns:

  • [xslt_select_csv csv="{file|url}" /]
  • [xslt_select_csv]{my,csv,data}[/xslt_select_csv]

Of course, either pattern may be used in combination with [xslt_transform_xml/].

  • [xslt_transform_xml][xslt_select_csv/][/xslt_transform_xml]

When no additional parameters are given, [xslt_select_csv/] returns a <table class="table"> element containing every row –<tr>– and every column –<td>– from the CSV. If you are using the output directly as HTML, styles can be applied by setting the table’s CSS class name(s) in the class shortcode attribute:

  • [xslt_select_csv class="{css-classnames}" /]

CSV parameters

Three parameters control the process of reading CSV data: separator, enclosure, and escape. The default values describe a standard comma-separated file, with fields enclosed by quotes, and with quotes optionally escaped by backslash. To read a standard tab-separated file, setting separator="\t" is the only required change.

  • CSV: [xslt_select_csv separator="," enclosure="\"" escape="\\" /]
  • TSV: [xslt_select_csv separator="\t" enclosure="\"" escape="\\" /]

For more info on these options, see https://www.php.net/manual/en/function.fgetcsv.php


Column parameters

The col shortcode attribute is used to specify which columns are returned by [xslt_select_csv/]. By itself, col accepts either column numbers or column letters as values, and it accepts multiple values separated by commas. Alternatively, if key_row is specified, column labels matching that row can be used in col.

  • [xslt_select_csv col="{num|letter}+" /]
  • [xslt_select_csv key_row="{num}" col="{label}+" /]

The following (3) shortcodes are equivalent when the output is used as HTML. If key_row is defined, as in the third example, then label attributes are added in the XML to each <td> element.

[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" col="1,2,3" /]
[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" col="A,B,C" /]
[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" key_row="1" col="ID,NAME,TITLE" /]
Output:
ID NAME TITLE
1001 name-one Name One
1002 name-two Name Two
1003 name-three Name Three
1004 name-four Name Four
1005 name-five Name Five
Output - XML source
<table class="table" rows="6" cols="6">
  <tr row="1" cols="6">
    <td row="1" col="1" label="ID">ID</td>
    <td row="1" col="2" label="NAME">NAME</td>
    <td row="1" col="3" label="TITLE">TITLE</td>
  </tr>
  <tr row="2" cols="6">
    <td row="2" col="1" label="ID">1001</td>
    <td row="2" col="2" label="NAME">name-one</td>
    <td row="2" col="3" label="TITLE">Name One</td>
  </tr>
  <tr row="3" cols="6">
    <td row="3" col="1" label="ID">1002</td>
    <td row="3" col="2" label="NAME">name-two</td>
    <td row="3" col="3" label="TITLE">Name Two</td>
  </tr>
  <tr row="4" cols="6">
    <td row="4" col="1" label="ID">1003</td>
    <td row="4" col="2" label="NAME">name-three</td>
    <td row="4" col="3" label="TITLE">Name Three</td>
  </tr>
  <tr row="5" cols="6">
    <td row="5" col="1" label="ID">1004</td>
    <td row="5" col="2" label="NAME">name-four</td>
    <td row="5" col="3" label="TITLE">Name Four</td>
  </tr>
  <tr row="6" cols="6">
    <td row="6" col="1" label="ID">1005</td>
    <td row="6" col="2" label="NAME">name-five</td>
    <td row="6" col="3" label="TITLE">Name Five</td>
  </tr>
</table>

Row parameters

The row shortcode attribute is used to include specific rows in the result. Only numbers are accepted as values, and multiple values should be separated by commas.

The second, dynamic method of adding rows to the result uses a combination of two (2) attributes: key_col and key. The first specifies a column to search, and the second specifies a value to match in that column. The key_col attribute accepts numbers, letters, or a label - like colabove - but only one value is allowed. The key attribute accepts one or more comma-separated search values.

  • [xslt_select_csv row="{num}+" /]
  • [xslt_select_csv key_col="{num|letter}" key="{val}+" /]
  • [xslt_select_csv key_row="{num}" key_col="{label}" key="{val}+" /]

The following (3) shortcodes are equivalent when output as HTML. As before, when key_row is defined, label attributes are added in the XML to each <td> element.

[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" row="1,5,6" /]
[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" row="1" key_col="1" key="1004,1005" /]
[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" row="1" key_row="1" key_col="ID" key="1004,1005" /]
Output:
ID NAME TITLE MONEY DATE DESCRIPTION
1004 name-four Name Four $444.00 4/4/2004 this is some longer content for name four
1005 name-five Name Five $555.00 5/5/2005 this is some longer content, for name five
Output - XML source
<table class="table" rows="6" cols="6">
  <tr row="1" cols="6">
    <td row="1" col="1" label="ID">ID</td>
    <td row="1" col="2" label="NAME">NAME</td>
    <td row="1" col="3" label="TITLE">TITLE</td>
    <td row="1" col="4" label="MONEY">MONEY</td>
    <td row="1" col="5" label="DATE">DATE</td>
    <td row="1" col="6" label="DESCRIPTION">DESCRIPTION</td>
  </tr>
  <tr row="5" cols="6">
    <td row="5" col="1" label="ID">1004</td>
    <td row="5" col="2" label="NAME">name-four</td>
    <td row="5" col="3" label="TITLE">Name Four</td>
    <td row="5" col="4" label="MONEY">$444.00</td>
    <td row="5" col="5" label="DATE">4/4/2004</td>
    <td row="5" col="6" label="DESCRIPTION">this is some longer content for name  four</td>
  </tr>
  <tr row="6" cols="6">
    <td row="6" col="1" label="ID">1005</td>
    <td row="6" col="2" label="NAME">name-five</td>
    <td row="6" col="3" label="TITLE">Name Five</td>
    <td row="6" col="4" label="MONEY">$555.00</td>
    <td row="6" col="5" label="DATE">5/5/2005</td>
    <td row="6" col="6" label="DESCRIPTION">this is some longer content, for name five</td>
  </tr>
</table>

Pivot sample

The previous examples, for column and row selection, have shown the output of [xslt_select_csv/] when used directly, without further changes. Here, as an example of combined usage with [xslt_transform_xml/], we'll apply an XSL stylesheet to "pivot" the previous XML result, and layout the data in a new table.

For convenience, we're passing key_row to the pivot stylesheet so we can easily identify and modify label values in the output. A more specialized version of the stylesheet might use the label attributes to vary the output of other cells, reformatting DATE values, for instance, or converting newlines to breaks in the DESCRIPTION column.

[xslt_transform_xml xsl="csv-pivot-xsl" key_row="1"]
[xslt_select_csv csv="case-study-gsheets/Sheet1.csv" row="1" key_row="1" key_col="ID" key="1004,1005" /]
[/xslt_transform_xml]
Output:
ID 1004 1005
NAME name-four name-five
TITLE Name Four Name Five
MONEY $444.00 $555.00
DATE 4/4/2004 5/5/2005
DESCRIPTION this is some longer content for name four this is some longer content, for name five
csv-pivot-xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
    <!-- params -->
    <xsl:param name="key_row" select="0"/>
    <!-- compound key for data -->
    <xsl:key name="csv-col" match="//td" use="concat(@row,'|',@col)"/>

    <!-- main -->
    <xsl:template match="/">

        <xsl:element name="table">
            <xsl:attribute name="class"><xsl:value-of select="//table/@class"/></xsl:attribute>

            <xsl:for-each select="//tr[1]/td/@col">
                <xsl:variable name="col"><xsl:value-of select="."/></xsl:variable>

                <xsl:element name="tr">
                    <xsl:for-each select="//tr/@row">
                        <xsl:variable name="row"><xsl:value-of select="."/></xsl:variable>
                        
                        <xsl:variable name="col-label">
                            <xsl:value-of select="key('csv-col', concat($row,'|',$col))/@label"/>
                        </xsl:variable>
                        <xsl:variable name="col-value">
                            <xsl:value-of select="key('csv-col', concat($row,'|',$col))/text()"/>
                        </xsl:variable>
                        <xsl:variable name="col-class">
                            <xsl:text>align-top</xsl:text>
                            <xsl:if test="$row = $key_row"> <!-- xtra classes for labels -->
                                <xsl:text> text-end fw-bold</xsl:text>
                            </xsl:if>
                        </xsl:variable>

                        <xsl:element name="td">
                            <xsl:attribute name="class">
                                <xsl:value-of select="$col-class"/>
                            </xsl:attribute>
                            <xsl:value-of select="$col-value" disable-output-escaping="yes"/>
                        </xsl:element>

                    </xsl:for-each>
                </xsl:element>

            </xsl:for-each>
        </xsl:element>

    </xsl:template>

</xsl:stylesheet>