Valid HTML/XHTML output for psql - Mailing list pgsql-patches

From Greg Sabino Mullane
Subject Valid HTML/XHTML output for psql
Date
Msg-id e6b44dcb50a892be66f4d82b9c0e8abd@biglumber.com
Whole thread Raw
Responses Re: Valid HTML/XHTML output for psql  (Peter Eisentraut <peter_e@gmx.net>)
Re: Valid HTML/XHTML output for psql  (Bruce Momjian <pgman@candle.pha.pa.us>)
Re: Valid HTML/XHTML output for psql  (Bruce Momjian <pgman@candle.pha.pa.us>)
List pgsql-patches
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message


Attached is a patch that enhances the output of psql's HTML mode.
The output now validates as HTML 4.01 Strict, XHTML 1.0 strict,
and XHTML 1.1 (assuming you wrap it in a valid html/body document).

It also wraps the output of PGRES_COMMAND_OK if the HTML tag is on,
for full compliance: this is why html_escaped_print has to be externalized.


--
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200306011737





Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.62
diff -c -r1.62 common.c
*** common.c    25 Mar 2003 02:44:36 -0000    1.62
--- common.c    1 Jun 2003 20:34:41 -0000
***************
*** 525,531 ****
                      success = true;
                      sprintf(buf, "%u", (unsigned int) PQoidValue(results));
                      if (!QUIET())
!                         fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
                      SetVariable(pset.vars, "LASTOID", buf);
                      break;
                  }
--- 525,542 ----
                      success = true;
                      sprintf(buf, "%u", (unsigned int) PQoidValue(results));
                      if (!QUIET())
!                         {
!                             if (pset.popt.topt.format == PRINT_HTML)
!                             {
!                                 fputs("<p>", pset.queryFout);
!                                 html_escaped_print(PQcmdStatus(results), pset.queryFout);
!                                 fputs("</p>\n", pset.queryFout);
!                             }
!                             else
!                             {
!                                 fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
!                             }
!                         }
                      SetVariable(pset.vars, "LASTOID", buf);
                      break;
                  }
Index: print.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.c,v
retrieving revision 1.37
diff -c -r1.37 print.c
*** print.c    4 Apr 2003 15:48:38 -0000    1.37
--- print.c    1 Jun 2003 20:34:42 -0000
***************
*** 577,583 ****
  /**********************/


! static void
  html_escaped_print(const char *in, FILE *fout)
  {
      const char *p;
--- 577,583 ----
  /**********************/


! void
  html_escaped_print(const char *in, FILE *fout)
  {
      const char *p;
***************
*** 595,601 ****
                  fputs(">", fout);
                  break;
              case '\n':
!                 fputs("<br>", fout);
                  break;
              default:
                  fputc(*p, fout);
--- 595,607 ----
                  fputs(">", fout);
                  break;
              case '\n':
!                 fputs("<br />\n", fout);
!                 break;
!             case '"':
!                 fputs(""", fout);
!                 break;
!             case '\'':
!                 fputs("'", fout);
                  break;
              default:
                  fputc(*p, fout);
***************
*** 615,621 ****
      unsigned int i;
      const char *const * ptr;

!     fprintf(fout, "<table border=%d", opt_border);
      if (opt_table_attr)
          fprintf(fout, " %s", opt_table_attr);
      fputs(">\n", fout);
--- 621,627 ----
      unsigned int i;
      const char *const * ptr;

!     fprintf(fout, "<table border=\"%d\"", opt_border);
      if (opt_table_attr)
          fprintf(fout, " %s", opt_table_attr);
      fputs(">\n", fout);
***************
*** 636,642 ****
          col_count++;
          if (!opt_barebones)
          {
!             fputs("    <th align=center>", fout);
              html_escaped_print(*ptr, fout);
              fputs("</th>\n", fout);
          }
--- 642,648 ----
          col_count++;
          if (!opt_barebones)
          {
!             fputs("    <th align=\"center\">", fout);
              html_escaped_print(*ptr, fout);
              fputs("</th>\n", fout);
          }
***************
*** 648,659 ****
      for (i = 0, ptr = cells; *ptr; i++, ptr++)
      {
          if (i % col_count == 0)
!             fputs("  <tr valign=top>\n", fout);

!         fprintf(fout, "    <td align=%s>", opt_align[(i) % col_count] == 'r' ? "right" : "left");
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')        /* is string only
!                                                          * whitespace? */
!             fputs(" ", fout);
          else
              html_escaped_print(*ptr, fout);
          fputs("</td>\n", fout);
--- 654,664 ----
      for (i = 0, ptr = cells; *ptr; i++, ptr++)
      {
          if (i % col_count == 0)
!             fputs("  <tr valign=\"top\">\n", fout);

!         fprintf(fout, "    <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')  /* is string only whitespace? */
!             fputs("  ", fout);
          else
              html_escaped_print(*ptr, fout);
          fputs("</td>\n", fout);
***************
*** 666,678 ****

      /* print footers */

!     if (footers && !opt_barebones)
          for (ptr = footers; *ptr; ptr++)
          {
              html_escaped_print(*ptr, fout);
!             fputs("<br>\n", fout);
          }
!
      fputc('\n', fout);
  }

--- 671,686 ----

      /* print footers */

!     if (!opt_barebones && footers && *footers)
!     {
!         fputs("<p>", fout);
          for (ptr = footers; *ptr; ptr++)
          {
              html_escaped_print(*ptr, fout);
!             fputs("<br />\n", fout);
          }
!         fputs("</p>", fout);
!     }
      fputc('\n', fout);
  }

***************
*** 690,696 ****
      unsigned int record = 1;
      const char *const * ptr;

!     fprintf(fout, "<table border=%d", opt_border);
      if (opt_table_attr)
          fprintf(fout, " %s", opt_table_attr);
      fputs(">\n", fout);
--- 698,704 ----
      unsigned int record = 1;
      const char *const * ptr;

!     fprintf(fout, "<table border=\"%d\"", opt_border);
      if (opt_table_attr)
          fprintf(fout, " %s", opt_table_attr);
      fputs(">\n", fout);
***************
*** 713,731 ****
          if (i % col_count == 0)
          {
              if (!opt_barebones)
!                 fprintf(fout, "\n  <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
              else
!                 fputs("\n  <tr><td colspan=2> </td></tr>\n", fout);
          }
!         fputs("  <tr valign=top>\n"
                "    <th>", fout);
          html_escaped_print(headers[i % col_count], fout);
          fputs("</th>\n", fout);

!         fprintf(fout, "    <td align=%s>", opt_align[i % col_count] == 'r' ? "right" : "left");
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')        /* is string only
!                                                          * whitespace? */
!             fputs(" ", fout);
          else
              html_escaped_print(*ptr, fout);
          fputs("</td>\n  </tr>\n", fout);
--- 721,738 ----
          if (i % col_count == 0)
          {
              if (!opt_barebones)
!                 fprintf(fout, "\n  <tr><td colspan=\"2\" align=\"center\">Record %d</td></tr>\n", record++);
              else
!                 fputs("\n  <tr><td colspan=\"2\"> </td></tr>\n", fout);
          }
!         fputs("  <tr valign=\"top\">\n"
                "    <th>", fout);
          html_escaped_print(headers[i % col_count], fout);
          fputs("</th>\n", fout);

!         fprintf(fout, "    <td align=\"%s\">", opt_align[i % col_count] == 'r' ? "right" : "left");
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0') /* is string only whitespace? */
!             fputs("  ", fout);
          else
              html_escaped_print(*ptr, fout);
          fputs("</td>\n  </tr>\n", fout);
***************
*** 734,746 ****
      fputs("</table>\n", fout);

      /* print footers */
!     if (footers && !opt_barebones)
          for (ptr = footers; *ptr; ptr++)
          {
              html_escaped_print(*ptr, fout);
!             fputs("<br>\n", fout);
          }
!
      fputc('\n', fout);
  }

--- 741,756 ----
      fputs("</table>\n", fout);

      /* print footers */
!     if (!opt_barebones && footers && *footers)
!     {
!         fputs("<p>", fout);
          for (ptr = footers; *ptr; ptr++)
          {
              html_escaped_print(*ptr, fout);
!             fputs("<br />\n", fout);
          }
!         fputs("</p>", fout);
!     }
      fputc('\n', fout);
  }

***************
*** 1114,1119 ****
--- 1124,1130 ----
      char      **footers;
      char       *align;
      int            i;
+

      /* extract headers */

Index: print.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.h,v
retrieving revision 1.16
diff -c -r1.16 print.h
*** print.h    18 Mar 2003 22:15:44 -0000    1.16
--- print.h    1 Jun 2003 20:34:43 -0000
***************
*** 13,18 ****
--- 13,19 ----

  extern FILE *PageOutput(int lines, unsigned short int pager);

+ extern void html_escaped_print(const char *in, FILE *fout);

  enum printFormat
  {


-----BEGIN PGP SIGNATURE-----
Comment: http://www.turnstep.com/pgp.html

iD8DBQE+2nNjvJuQZxSWSsgRAiuWAKCnpa1SzCe6A8i55EXBAIlS0KnspQCdGiWK
H3bbC9FnvDMWQxYOi+vMRGY=
=sLzN
-----END PGP SIGNATURE-----



pgsql-patches by date:

Previous
From: Kurt Roeckx
Date:
Subject: Ipv6 network cleanup patch #2.
Next
From: "Tebaldi Mirko"
Date:
Subject: PGSQL translation to italian - Proposal n° 2