Create an HTML table.

 The table body should have at least three rows of three columns.
 Each of these three columns should be labelled "X", "Y", and "Z". 
 An extra column should be added at either the extreme left or the extreme right of the table that has no heading, but is filled with sequential row numbers. 
 The rows of the "X", "Y", and "Z" columns should be filled with random or sequential integers having 4 digits or less. 
 The numbers should be aligned in the same fashion for all columns.


/* NetRexx */
options replace format comments java crossref symbols nobinary
 
-- create some test data.  Put the data in a Rexx indexed string
maxI = 1000
rng = Random()
xyz = ''
xyz[0] = 1; xyz[1] = '. X Y Z' -- use a dot to indicate an empty cell
loop r_ = 1 for 5
  ra = r_ rng.nextInt(maxI) rng.nextInt(maxI) rng.nextInt(maxI)
  xyz[0] = r_ + 1; xyz[r_ + 1] = ra
  end r_
 
-- build an HTML string
html = htmlHeader()
html = html || htmlTable(xyz)
html = html || htmlFooter()
 
-- display HTML at standard output device
say html
 
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- HTML boilerplate header
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method htmlHeader() public static returns Rexx
  html = '<?xml version="1.0" encoding="UTF-8"?>\n' -
      || '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n' -
      || '<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">\n' -
      || '<head>\n' -
      || '<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>\n' -
      || '<title>RCreateHTMLTable</title>\n' -
      || '<style type="text/css">\n' -
      || '<!--\n' -
      || '/* <![DATA[ */\n' -
      || 'body {font-family: "Lucida Grande", "Geneva", "Verdana", "Helvetica Neue", "Helvetica", "DejaVu Sans", "Arial", sans-serif;}\n' -
      || 'table, th, td {table-layout: fixed; border: 1px solid black; border-collapse: collapse; padding: 0.25em; font-size: 85%;}\n' -
      || 'th, td {width: 6em;}\n' -
      || 'th {color: white; background-color: green;}\n' -
      || 'td {text-align: right;}\n' -
      || 'p.classname {\n' -
      || '  font-size: inherit;\n' -
      || '}\n' -
      || '/* ]] */\n' -
      || '//-->\n' -
      || '</style>\n' -
      || '</head>\n' -
      || '<body>\n' -
      || '<h1>Rosetta Code &ndash; NetRexx Sample Output</h2>\n' -
      || '<h2><a href="http://rosettacode.org/wiki/Create_an_HTML_table">Create an HTML table</a></h2>\n' -
      || ''
 
  return html
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- HTML footer
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method htmlFooter() public static returns Rexx
  html = '</body>\n' -
      || '</html>\n' -
      || ''
  return html
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Create the table
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method htmlTable(rows, caption = '') public static returns Rexx
  html = '<table>\n'
  if caption.length() > 0 then do
    html = html -
        || '<caption>'caption'</caption>\n' -
        || '<thead>\n' -
        || ''
    end
  html = html -
      || htmlCsvTableRow(rows[1], 'th')'\n' -
      || '</thead>\n' -
      || '<tbody>\n' -
      || ''
  loop r_ = 2 to rows[0]
    html = html -
        || htmlCsvTableRow(rows[r_])
    end r_
  html = html -
      || '</tbody>\n' -
      || '</table>\n' -
      || ''
  return html
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Add a row to the table
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method htmlCsvTableRow(row, tag = 'td', sep = ' ', emptyCell = '.') public static returns Rexx
  if tag = null then tag = 'td'
  row = row.strip('t')
  -- replace HTML special characters with symbol entities
  row = row.changestr('&', '&amp;') -- need to do this one first to avoid double translation
  row = row.changestr('"', '&quot;')
  row = row.changestr("'", '&apos;')
  row = row.changestr('<', '&lt;')
  row = row.changestr('>', '&gt;')
  elmts = ''
  elmts[0] = 0
  e_ = 0
  loop while row.length() > 0
    parse row elmt (sep) row
    if elmt == emptyCell then elmt = '&nbsp;' -- replace empy cells with non-breaking spaces
    e_ = e_ + 1; elmts[0] = e_; elmts[e_] = elmt
    end
  html = '<tr>\n' -
      || ''
  loop e_ = 1 to elmts[0]
    html = html -
        || '<'tag'>'elmts[e_]'</'tag'>\n' -
        || ''
    end e_
  html = html -
      || '</tr>\n' -
      || ''
  return html
 
 