SGML : conversions


DTD

Un document a la structure suivante
<!DOCTYPE document SYSTEM "document.dtd"> 

<DOCUMENT>
  <head>
    <title>Bla bla bla<title>
    <author> Vincent Zoonekynd<author>
    <date>Avril 2000<date>
  </head>
  <body>
    <abstract> 
      <p>
        Bla bla bla
      </p>
    </abstract>
    
    <toc>

<!-- ------------------------------------------------------------ -->

    <sect>
      <stitle>Bla bla bla</stitle>
      <p>
        Bla bla bla
      </p>
    </sect>

    <sect>
      <stitle>Bla bla bla</stitle>

      <sect1>
        <stitle>Bla bla bla</stitle>
        <p>
          Bla bla bla
        </p>
      </sect1>

      <sect1>
        <stitle>Bla bla bla</stitle>
        <p>
          Bla bla bla
        </p>
      </sect1>

    </sect>
  </body>
</document>
    
Il y a éventuellement des images, comme en HTML (ici, il devra y avoir un fichier 1.eps et un autre 1.gif)
  <IMG SRC="1">
    
Les liens sont de deux formes.
  <A HREF="...">...</A>

  <LINK>
    <LINKTEXT>plusieurs</LINKTEXT>
    <href>http://www.math.jussieu.fr/~zoonek/Ecrits/</href>
    <href>http://www.math.jussieu.fr/~zoonek/LaTeX/</href>
    <href>http://www.math.jussieu.fr/~zoonek/Images/</href>
    <href>http://www.math.jussieu.fr/~zoonek/Politique/</href>
  </LINK>.
    
Voici enfin le DTD.
<!ENTITY % text "#PCDATA|img|ref|label|a|link|itemize|enum|descrip|verb|perl|tt|em|html|latex">
<!ENTITY % simpletext "#PCDATA|tt|em">

<!ELEMENT document  - - (head,body)>
<!ELEMENT head      O O (title, author?, date?)>
<!ELEMENT title     - O (#PCDATA)>
<!ELEMENT author    - O (#PCDATA)>
<!ELEMENT date      - O (#PCDATA)>
<!ELEMENT body      O O (abstract?,toc?,sect*)>
<!ELEMENT abstract  - O (p+)>
<!ELEMENT toc       - O EMPTY>
<!ELEMENT sect      - O (stitle, (p|sect1)+)>
<!ELEMENT sect1     - O (stitle, (p|sect2)+)>
<!ELEMENT sect2     - O (stitle, p+)>
<!ELEMENT stitle    O O (%simpletext)+>
<!ELEMENT p         O O (%text)+>

<!ELEMENT tt        - - (#PCDATA)>
<!ELEMENT em        - - (#PCDATA)>

<!ELEMENT html      - O EMPTY>
<!ATTLIST html
          src       CDATA   #REQUIRED>
<!ELEMENT latex     - O EMPTY>
<!ATTLIST latex
          src       CDATA   #REQUIRED>

<!ELEMENT img       - O EMPTY>
<!ATTLIST img 
          src       CDATA   #REQUIRED>

<!ELEMENT a         - - (%simpletext)+>
<!ATTLIST a
          href      CDATA   #REQUIRED>
<!ELEMENT link      - - (linktext, href+)>
<!ELEMENT href      - - (#PCDATA)>
<!ELEMENT linktext  - - (%simpletext)+>

<!ATTLIST sect
          id        ID      #IMPLIED>
<!ATTLIST sect1
          id        ID      #IMPLIED>
<!ATTLIST sect2
          id        ID      #IMPLIED>
<!ELEMENT label     - O  EMPTY>
<!ATTLIST label
          id        ID      #REQUIRED>
<!ELEMENT ref       - O  EMPTY>
<!ATTLIST ref
          id        IDREF   #REQUIRED>

<!ELEMENT itemize   - - (item+)>
<!ELEMENT enum      - - (item+)>
<!ELEMENT item      - O (p+)>

<!ELEMENT descrip   - - (tag,p+)+>
<!ELEMENT tag       - - (%simpletext)+> 

<!ELEMENT verb      - - (#PCDATA)>
<!ATTLIST verb
          lang      (tex|perl|shell) tex>

<!ENTITY  LaTeX     "LaTeX">
<!ENTITY  latex     "LaTeX">
<!ENTITY  TeX       "TeX">
<!ENTITY  tex       "TeX">
<!ENTITY  lt        "<">
<!ENTITY  gt        ">">
<!ENTITY  amp       "&">
<!ENTITY  dollar    "$">
<!ENTITY  oe        "oe">
<!ENTITY  OE        "OE">
    

Modification du fichier SGML

Le script suivant enlève les & et les < à l'intérieur de <VERB>.
#! perl -w

# Transforme des fichiers « presque SGML », avec des < et des & 
# dans les <VERB>...</VERB> en un fichier SGML correct.

##
## BUGS :
##
## - Ne jamais mettre de <VERB> à l'intérieur de <VERB>...</VERB>
## - Ne jamais mettre de &amp; ou de &lt; à l'intrieur de <VERB>...</VERB>
## - Les « &amp; », etc. qui apparaissent à l'intérieur restent « &amp; », etc.
##
## Corollaire : On aura des problèmes à utiliser ce genre de 
## « bidouille » pour écrire une documentation sur SGML...
##

$all = join('', <>);

sub correct_spaces {
  my ($a) = @_;
  $a =~ s/\n\s*\n+/RETOURALALIGNE/gsm;
  $a =~ s/\n/ /gsm;
  $a =~ s/RETOURALALIGNE/\n\n/gsm;
  $a;
}

$resultat = "";

while($all =~ m#<VERB(.*?)>(.*?)(</VERB>|</>)#smi){
  $arguments = $1;
  $milieu = $2;
  $avant = $`;
  $all = $';
  # On remplace les caractères posant problème : & et <
  $milieu =~ s/\&/\&amp\;/g;
  $milieu =~ s/\</\&lt\;/g;
  # On enlève tous les \s et \n qui se trouvent à la fin
  $milieu =~ s/\s*$//;
  # On enlève aussi (presque) tous les espaces qui se trouvent au début
  $milieu =~ s/^\s*\n(\s*)/$1/;
  $avant = correct_spaces($avant);
  $resultat .= "$avant<VERB$arguments>$milieu</VERB>";
#  print "(*** RESULTAT\n$resultat\n***)\n";
}

$resultat .= correct_spaces($all);

$resultat =~ s/\&amp\;amp\;/\&amp\;/g;
$resultat =~ s/\&amp\;lt\;/\&lt\;/g;
$resultat =~ s/\&amp\;gt\;/\&gt\;/g;

$resultat =~ s/<VERB>(\s*\n)+/<VERB>/g;

print $resultat;
    

Conversion vers HTML

À l'aide de sgmlspl.
##
## À FAIRE
##
## <URL URL="..." NAME="..."> (mettre l'URL en note de bas de page)
## Les caractères spéciaux de LaTeX
## La chaîne de caractères « LateX » doit être transformée en {\LaTeX}
## <VERB> 
##        (n'y a-t-il pas de problème d'espaces superflus ???)
##        Et s'il y a des < et des > à l'intérieur ???
##        (Il y en a...)	  
## <TSCREEN> : à enlever... Non...
## <EM>
##
## Dans le même ordre d'idées, prévoir un convertisseur SGML -> SGML.
## qui rajouterait toutes les balises manquantes.
## Ça existe déjà, ça s'appelle sgmlnorm.
##

use SGMLS;
use SGMLS::Output;
use SGMLS::Refs;

##
## Constantes, à modifier
##
# Si on écrit en blanc :
$couleur_fond_latex = "#500000";
$couleur_texte_latex = "#000000";
$couleur_fond_perl = "#505000";
$couleur_texte_perl = "#000000";
$couleur_fond_shell = "#005050";
$couleur_texte_shel = "#000000";
# J'écris maintenant en noir sur fond jaune :
$couleur_fond = "#F5DEB3"; # Jaune clair
$couleur_texte ="#000000";
$couleur_fond_latex = "#FF8080"; # rouge
$couleur_fond_latex = "#F5DEB3"; # le rouge était illisible...
$couleur_texte_latex = "#000000";
$couleur_fond_perl = "#F0F000"; # jaune
$couleur_texte_perl = "#000000";
$couleur_fond_shell = "#A0F0F0"; # bleu pastel
$couleur_fond_shell = "#80C0C0"; # bleu moins pastel
$couleur_texte_shell = "#000000";


$basename = shift;

sgml('start', sub {
    system("touch .redo_$basename");
    $Refs = new SGMLS::Refs("$basename.refs");
    rename ".tmp.toc", ".tmp.toc.old";
});

my $toc="";

sgml('end', sub {
    unlink(".redo_$basename") unless $Refs->warn;
    open(TOC,">.tmp.toc");
    print TOC $toc;
    close(TOC);
});

######################################################################

sgml('cdata', sub { 
  my($text,$event) = @_;
#  unless($event->element->name eq 'VERB'){
    $text =~ s/\&/\&amp;/g;
    $text =~ s/\</\&lt;/g;
    $text =~ s/\>/\&gt;/g;
#  }
  output $text;
});
  
######################################################################

sgml('<DOCUMENT>', "");
sgml('</DOCUMENT>', "</BODY></HTML>\n");

sgml('<TITLE>', sub{ push_output 'string'; });
sgml('</TITLE>', sub {
  my $t = pop_output;
  output "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n";
  output "<HTML><HEAD><TITLE>$t</TITLE>\n";
  output "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">\n";
  output "</HEAD>";
  output "<BODY BGCOLOR=$couleur_fond TEXT=$couleur_texte><HR WIDTH=80\%><CENTER><H1>$t<P>\n";
});

sgml('<AUTHOR>', "<P><EM>");
sgml('</AUTHOR>', "</EM>\n");

sgml('<DATE>', "<P>");
sgml('</DATE>', "</P>\n");

sgml('</HEAD>', '</H1></CENTER><HR WIDTH=80%>'."\n");

sgml('<ABSTRACT>',  "<CENTER><H2>Résumé</H2></CENTER>\n");
sgml('</ABSTRACT>', "<P><HR WIDTH=80\%>\n\n");

sgml('<TOC>', sub{
  open(TOC, ".tmp.toc.old");
  while(<TOC>){output $_;}
  close(TOC);
  output "<P><HR WIDTH=80\%>\n";
});

#####################
my $current_number="";
my $chapter = 0;
my $section = 0;
my $subsection = 0;
sgml('<SECT>', sub { 
  my $element = shift;
  $chapter++; 
  $section = $subsection=0;
  $current_number="$chapter"; 
  output "<P><HR WIDTH=80\%><P><H1><A NAME=\"$current_number\">$chapter</A> "; 
  if( $element->attribute('ID') ){ 
    $Refs->put("ref:". $element->attribute('ID')->value, $current_number); 
  }
  $toc .= "<P><P><A HREF=\"\#$current_number\"><STRONG>$current_number</STRONG> ";
});
sgml('<SECT1>', sub { 
  my $element = shift;
  $section++; 
  $subsection=0; 
  $current_number="$chapter.$section"; 
  output "<H1><A NAME=\"$current_number\">$chapter.$section</A> "; 
  if( $element->attribute('ID') ){ 
    $Refs->put("ref:". $element->attribute('ID')->value, $current_number); 
  }
  $toc .= "<BR><A HREF=\"\#$current_number\">$current_number ";
});
sgml('<SECT2>', sub { 
  my $element = shift;
  $subsection++; 
  $current_number="$chapter.$section.$subsection"; 
  output "<H1><A NAME=\"$current_number\">$chapter.$section.$subsection</A> "; 
  if( $element->attribute('ID') ){ 
    $Refs->put("ref:". $element->attribute('ID')->value, $current_number); 
  }
  $toc .= "<BR><A HREF=\"\#$current_number\">$current_number ";
});
sgml('<STITLE>', sub{ push_output 'string'; });
sgml('</STITLE>', sub {
  my $t = pop_output;
  output "$t</H1>";
  $toc .= "$t</A>\n";
});
sgml('<P>', "<P>");

sgml('<TT>', "<TT>");
sgml('</TT>', "</TT>");

sgml('<EM>', "<EM>");
sgml('</EM>', "</EM>");

sgml('<EXAMPLE>', "<PRE>\n");
sgml('</EXAMPLE>', "</PRE>\n");

sgml('<A>', sub {
       my $element = shift;
       my $url = $element->attribute('HREF')->value;
       output "<A HREF=\"$url\">";
  });
sgml('</A>', sub {
       output "</A>";
     });

my $link_number = 0;
sgml('<LINK>', sub {
       open(LINK, ">$basename.link_$link_number.html") || die "Cannot open link file";
       output "<A HREF=\"$basename.link_$link_number.html\">";
     });
sgml('<LINKTEXT>', sub { push_output 'string'; });
sgml('</LINKTEXT>', sub { 
       my $a = pop_output;
       output "$a</A>";
       print LINK "$a\n";
       print LINK "<UL>\n";
     });
sgml('<HREF>', sub { push_output 'string'; });
sgml('</HREF>', sub {
       my $a = pop_output;
       print LINK "<LI><A HREF=\"$a\">$a</A>\n";
     });
sgml('</LINK>', sub {
       print LINK "</UL>\n";
       close LINK;
       $link_number++;
     });

sgml('<HTML>', sub {
    my $element = shift;
    my $html = $element->attribute('SRC')->value;
    open(H, "$html") || warn "Cannot open $html: $!";
    while(<H>){output $_;}
    close H;
});

sgml('<IMG>', sub {
    my $element = shift;
    my $img = $element->attribute('SRC')->value;
    unless( $img =~ s/\.eps$/.gif/i ){ $img =~ s/$/.gif/i; }
#    output "<CENTER><IMG SRC=\"$img\"></CENTER>\n";
    output "<TABLE><TR><TD WIDTH=50></TD><TD><IMG SRC=\"$img\"></TD></TR></TABLE>\n";
});

sgml('<REF>', sub {
    my $element = shift;
    my $ref = $element->attribute('ID')->value;
    my $n = $Refs->get("ref:$ref");
    output "<A HREF=\"\#$n\">$n</A>";
});

sgml('<LABEL>', sub {
    my $element = shift;
    my $ref = $element->attribute('ID')->value;
    $Refs->put("ref:$ref", $current_number);
});

sgml('<ITEMIZE>', "<UL>");
sgml('</ITEMIZE>', "</UL>\n");

sgml('<ENUM>', "<UL>");
sgml('</ENUM>', "</UL>\n");

sgml('<ITEM>', "<LI>");

sgml('<DESCRIP>', "<DL>");
sgml('</DESCRIP>', "</DL>\n");

sgml('<TAG>', "<P><DT><STRONG>");
sgml('</TAG>', "</STRONG><DD>");

sgml('<VERB>',  sub {
    my $element = shift;
    my $lang = $element->attribute('LANG')->value;
    if( $lang eq "TEX" ){
      output "<TABLE><TR><TD WIDTH=50></TD><TD BGCOLOR=$couleur_fond_latex><font color=$couleur_texte_latex><PRE>";
    } elsif( $lang eq "PERL" ) {
      output "<TABLE><TR><TD WIDTH=50></TD><TD BGCOLOR=$couleur_fond_perl><font color=$couleur_texte_perl><PRE>";
    } else {
      output "<TABLE><TR><TD WIDTH=50></TD><TD BGCOLOR=$couleur_fond_shell><font color=$couleur_texte_shell><PRE>";
    }
	  });
sgml('</VERB>', "<!PRE></font></TD></TR></TABLE>");


######################################################################

## ???

sgml('&latex;', "\\LaTeX\xspace ");
sgml('&latex;', "\\LaTeX\xspace ");

    

Correction des fichiers HTML

Toujours à l'aide de sgmlspl.
#! perl -w
use strict;

die "usage: $1 file.html" unless $ARGV[0];
open(HTML,$ARGV[0]) || die "Cannot open $ARGV[0] for reading: $!";
my $tout = join('',<HTML>);
close HTML;

my $new = "";
while( $tout =~ s/^(.*?)SRC\=\"([^"]*)\"//s ){ #"
  my $avant = $1;
  my $file = $2;
  print STDERR "Looking for the size of $file\n";
  open(SIZE, "file $file /dev/null|") || 
    warn "Cannot run `file $file /dev/null': $!";
#    warn "Cannot run `convert -verbose $file /dev/null': $!";
  my $tmp = join('',<SIZE>);
  close SIZE;
  my($width,$height)=(10,10);
  if($tmp =~ m/([0-9]+) x ([0-9]+)/){
    $width = $1;
    $height = $2;
  }
  print STDERR " width: $width height: $height\n";
  $new .= "$avant WIDTH=$width HEIGHT=$height SRC=\"$file\" ";
}
$new .= $tout;

open(HTML, ">$ARGV[0]") || die "Cannot open $ARGV[0] for writing: $!";
print HTML $new;
close HTML;
    

Conversion vers LaTeX

##
## À FAIRE
##
## <URL URL="..." NAME="..."> (mettre l'URL en note de bas de page)
## Les caractères spéciaux de LaTeX
## La chaîne de caractères « LateX » doit être transformée en {\LaTeX}
## <VERB> 
##        (n'y a-t-il pas de problème d'espaces superflus ???)
##        Et s'il y a des < et des > à l'intérieur ???
##        (Il y en a...)	  
## <TSCREEN> : à enlever... Non... Si...
## <EM>
##
## Dans le même ordre d'idées, prévoir un convertisseur SGML -> SGML.
## qui rajouterait toutes les balises manquantes.
##

use SGMLS;
use SGMLS::Output;
use SGMLS::Refs;

$basename = shift;

sgml('start', sub {
    system("touch .redo_$basename");
    $Refs = new SGMLS::Refs("$basename.refs");
});
sgml('end', sub {
    unlink(".redo_$basename") unless $Refs->warn;
});

######################################################################

sgml('cdata', sub { 
  my($text,$event) = @_;
  unless($event->element->name eq 'VERB'){
    $text =~ s/\\/\\textbackslash /g;
    $text =~ s/\{/\\\{/g;
    $text =~ s/\}/\\\}/g;
    $text =~ s/\\textbackslash /\{\\textbackslash\}/g;
    $text =~ s/\&/\\\&/g;
    $text =~ s/\~/{\\textasciitilde}/g;
    $text =~ s/\#/\\\#/g;
    $text =~ s/\_/{\\textunderscore}/g;
    $text =~ s/\^/{\\textasciicircum}/g;
    $text =~ s/\$/{\\textdollar}/g;
    $text =~ s/\%/\\\%/g;
    $text =~ s/\*/{\\textasterixcentered}/g;
    $text =~ s/\</{\\textless}/g;
    $text =~ s/\>/{\\textgreater}/g;
  }
  output $text;
});
  
######################################################################

sgml('<DOCUMENT>', "\\documentclass[openany]{book}\n\n" .
     "\\usepackage[latin1]{inputenc}\n" .
     "\\usepackage[T1]{fontenc}\n" .
     "\\usepackage{url}\n" .
     "\\usepackage{frxspace}\n" .
     "\\usepackage[left=1cm,right=1cm,top=1cm,bottom=1cm,nofoot]{geometry}\n" .
     "\\usepackage{graphicx}\n" .
     "\\usepackage{longtable}\n" .
     "\\usepackage{textcomp,wasysym,pifont,marvosym,stmaryrd,yhmath,amsmath,amssymb}\n" .
     "\\usepackage{french}\n" .
     "\\usepackage{boites,boites_exemples}\n" .
     "\\providecommand{\\textasterixcentered}{*}\n".
     "\\newenvironment{example}{\\par\\bigskip\\noindent\\textbf{Exemple : }}{\\bigskip}\n".
     "\\newenvironment{simpleverb}{\\par\\medskip\\parindent=0pt\\obeylines\\obeyspaces\\ttfamily}{\\medskip}\n".
     "\\newenvironment{tscreen}{\\begin{boitecoloriee}}{\\end{boitecoloriee}}\n".
     "");

sgml('</DOCUMENT>', "\\end{document}\n");

sgml('<TITLE>', "\\title{");
sgml('</TITLE>', "}\n");

sgml('<AUTHOR>', "\\author{");
sgml('</AUTHOR>', "}\n");

sgml('<DATE>', "\\date{");
sgml('</DATE>', "}\n");

sgml('</HEAD>', "\\begin{document}\n\\maketitle\n\n");

sgml('<ABSTRACT>',  "\\begin{abstract}\n");
sgml('</ABSTRACT>', "\\end{abstract}\n\n");

sgml('<TOC>', "\\tableofcontents\n\n");

my $next_label=undef;
sgml('<SECT>', sub {
    my $element = shift;
    output "\n\\chapter";
    if( $element->attribute('ID') ){ $next_label = $element->attribute('ID')->value; }
});
sgml('<SECT1>', sub {
    my $element = shift;
    output "\n\\section";
    if( $element->attribute('ID') ){ $next_label = $element->attribute('ID')->value; }
});
sgml('<SECT2>', sub {
    my $element = shift;
    output "\n\\subsection";
    if( $element->attribute('ID') ){ $next_label = $element->attribute('ID')->value; }
});
sgml('<STITLE>', "{");
sgml('</STITLE>', sub {
  if( $next_label ){ output "}\\label{$next_label}\n\n"; }
  else { output "}\n\n"; }
  $next_label = undef;
});

sgml('</P>', "\n\n");

sgml('<TT>', "\\texttt{");
sgml('</TT>', "}");

sgml('<EM>', "\\emph{");
sgml('</EM>', "}");

sgml('<EXAMPLE>', "\\begin{example}\n");
sgml('</EXAMPLE>', "\\end{example}");

my $url;
sgml('<A>', sub {
       my $element = shift;
       $url = $element->attribute('HREF')->value;
     });
sgml('</A>', sub { output "\\footnote{\\url{$url}}"; });

sgml('<IMG>', sub {
    my $element = shift;
    my $img = $element->attribute('SRC')->value;
    unless( $img =~ s/\.gif$/.eps/i ){ $img =~ s/\$/.eps/i; }
#    output "\\begin{center}\\includegraphics{$img}\\end{center}";
    output "\\begin{center}\\begin{boiteavecunelignequiondulesurlecote}\\includegraphics{$img}\\end{boiteavecunelignequiondulesurlecote}\\end{center}";
});

sgml('<LATEX>', sub {
    my $element = shift;
    my $latex = $element->attribute('SRC')->value;
    open(L, "$latex") || warn "Cannot open $latex: $!";
    while(<L>){output $_;}
    close L;
});

sgml('<LINK>',      sub {} );
sgml('<LINKTEXT>',  sub {} );
sgml('</LINKTEXT>', sub {} );
my $first_link = TRUE;
sgml('<HREF>',      sub { 
       output "\\textsuperscript{,}" unless $first_link;
       $first_link = FALSE;
       output "\\footnote{\\url{";
     });
sgml('</HREF>',     sub { 
       output "}}"; 
     });
sgml('</LINK>',     sub { 
       $first_link = TRUE;
     });

sgml('<REF>', sub {
    my $element = shift;
    my $ref = $element->attribute('ID')->value;
    output "\\ref{$ref}";
});

sgml('<LABEL>', sub {
    my $element = shift;
    my $ref = $element->attribute('ID')->value;
    output "\\label{$ref}";
});

sgml('<ITEMIZE>', "\\begin{itemize}");
sgml('</ITEMIZE>', "\\end{itemize}\n");

sgml('<ENUM>', "\\begin{enumerate}");
sgml('</ENUM>', "\\end{enumerate}\n");

sgml('<ITEM>', "\\item ");

sgml('<DESCRIP>', "\\begin{description}");
sgml('</DESCRIP>', "\\end{description}\n");

sgml('<TAG>', "\\item[");
sgml('</TAG>', "]");

#sgml('<VERB>', "\\begin{simpleverb}\n");
#sgml('</VERB>', "\\end{simpleverb}");

sgml('<VERB>', "\\begin{tscreen}\\begin{verbatim}\n");
sgml('</VERB>', "\\end{verbatim}\\end{tscreen}");

#sgml('<HTML>', sub { push_output 'nul' } );
#sgml('</HTML>', sub { pop_output } );
#sgml('<LATEX>', '');
#sgml('</LATEX>', '');

######################################################################

## ???

sgml('&latex;', "\\LaTeX\xspace ");
sgml('&latex;', "\\LaTeX\xspace ");
    

Vincent Zoonekynd (zoonek@math.jussieu.fr)
Last modified: Mon Aug 7 13:51:30 CEST 2000