| characterData(CharacterDataEvent) |
| interface com.jclark.xml.parse.io.Application |
| void startDocument() |
Inizio del documento |
| void endDocument() |
Fine del documento |
| void startElement(StartElementEvent) |
Inizio di un elemento |
| void endElement(EndElementEvent) |
Fine di un elemento |
| void characterData(CharacterDataEvent event) |
Testo di un tag |
| void endProlog(EndPrologEvent) |
Fine prologo |
Tabella
In tabella 1
sono riportati i metodi della interfaccia com.jclark.xml.parse.io.Application
che va implementata per gestire l'XML. Come vedete si tratta di una cosa
semplicissima: due metodi per l'inizio e la fine del documento, due metodi
per l'inizio e la fine dei tag, e un metodo per i dati che non sono tag
(CharacterData). La conversione del nostro articolo in HTML è solo questione
di decidere a cosa corrispondono i vari elementi: così abbiamo deciso che
il TITOLO diventerà un H1, che il LISTATO verrà tradotto con il PRE, e
così via. All'inizio e alla fine del documento mettiamo il preambolo e
il suffisso standard dell'HTML, e per ogni tag, chiamiamo un metodo che
deciderà cosa fare. Per semplicità di codifica raccogliamo gli attribuiti
di ogni tag in una Hashtable (che è semplice da esaminare) e chiamiamo
un metodo che ha il nome del tag: questo metodo verrà chiamato con la Hashtable
all'inizio del tag e con null alla fine. In questo modo quando si incontra
<TITOLO> o </TITOLO> verrà chiamato il metodo String TITOLO(Hashtable
ht). Fissata questa impostazione, per convertire <TITOLO>…</TITOLO>
in <H1>…</H1> si usa return (ht==null) ? "<H1>" : "</H1>".
Ovviamente le cose poi si possono complicare a volontà…
Notare che nel listato
non si tratta di semplicemente rinominare i tag: per esempio in qualche
caso ad un tag XML corrispondo più tag HTML. Inoltre talvolta si devono
generare dei "side effects". Nell'esempio è prevista la generazione dell'indice.
Queso comporta che quando si incontra un TITOLETTO ci si deve "annotare"
il fatto: il metodo TITOLETTO() imposta il flag inTitoletto, in modo da
sapere quando raccogliere i titoletti per fare l'indice. Alla fine del
documento si stampa l'indice. Il metodo può sembrare poco lineare ma è
sostanzialmente "event-driven" ed occorre in pratica inventarsi solo delle
"regole di traduzione". Teniamo presente comunque che una riformattazione
complessa può richiedere più passate.
import java.io.*;
import java.util.*;
import com.jclark.xml.parse.*;
import com.jclark.xml.parse.io.*;
import com.jclark.xml.output.*;
public
class Articolo2HTML
extends ApplicationImpl
{
//---------------------------------
// Inizializzazioni e avvio
//---------------------------------
String in;
String out;
public Articolo2HTML(String filein, String fileout) {
this.in = filein;
this.out = fileout;
}
public void parse() throws Exception {
EntityManagerImpl em = new EntityManagerImpl();
DocumentParser.parse(
em.openFile(in), em,
this,
java.util.Locale.getDefault());
}
public static void main(String[] args) throws Exception {
new Articolo2HTML(args[0], args[1]).parse();
}
//------------------------------------------
// Parsing
//------------------------------------------
// Apri e chiudi il file di output
PrintWriter wout;
StringBuffer indice;
public void startDocument() throws java.io.IOException {
wout = new PrintWriter(new FileOutputStream(out));
indice = new StringBuffer("<hr>Indice:\n<ul>\n");
}
public void endDocument() throws java.io.IOException {
indice.append("</ul><hr>\n");
wout.println(indice);
wout.flush();
wout.close();
}
// I dati vengono scritti come sono.
boolean inTitoletto = false;
CharArrayWriter caw = new CharArrayWriter();
public void characterData(CharacterDataEvent parm1)
throws java.io.IOException {
parm1.writeChars(wout);
// salva l'indice
if(inTitoletto) {
caw.reset();
parm1.writeChars(caw);
indice.append("<li>").append(caw.toString());
}
}
Hashtable ht = new Hashtable();
// usata per passare i parametri
public void startElement(StartElementEvent parm1)
throws java.io.IOException {
ht.clear();
int max = parm1.getAttributeCount();
for(int i=0; i<max; ++i)
ht.put(parm1.getAttributeName(i).intern(),
parm1.getAttributeValue(i));
select(parm1.getName(), ht);
}
public void endElement(EndElementEvent parm1)
throws java.io.IOException {
select(parm1.getName(), null);
}
private void select(String name, Hashtable ht) {
name = name.toUpperCase().intern();
if(name=="ARTICOLO") ARTICOLO(ht);
else if(name=="TITOLO") TITOLO(ht);
else if(name=="AUTORE") AUTORE(ht);
else if(name=="OCCHIELLO") OCCHIELLO(ht);
else if(name=="TITOLETTO") TITOLETTO(ht);
else if(name=="PARAGRAFO") PARAGRAFO(ht);
else if(name=="LISTATO") LISTATO(ht);
}
//------------------------------------------------
// Gestione dei tag
//------------------------------------------------
void ARTICOLO(Hashtable ht) {
if(ht!=null) {
wout.println("<html>");
wout.println("<head><title>Articolo</title></head>");
wout.println("<body>");
} else
wout.println("</body></html>");
}
void TITOLO(Hashtable ht) {
if(ht!=null)
wout.print("<h1 align=center>");
else
wout.println("</h1>");
}
void AUTORE(Hashtable ht) {
if(ht!=null)
wout.println("<center><b>");
else
wout.println("</b></center>");
}
void OCCHIELLO(Hashtable ht) {
if(ht!=null)
wout.println("<blockquote><i>");
else
wout.println("</i></blockquote>");
}
void TITOLETTO(Hashtable ht) {
inTitoletto = (ht!=null);
if(ht!=null)
wout.print("<h2>");
else
wout.println("</h2>");
}
void PARAGRAFO(Hashtable ht) {
if(ht!=null)
wout.print("<p>");
else
wout.println("</p>");
}
void LISTATO(Hashtable ht) {
if(ht!=null)
wout.print("<pre>");
else
wout.println("</pre>");
}
}
Listato
|