Bisher habe ich euch nur einen Weg gezeigt, einen Parser zu instantiieren,
nämlich
Parser parser = new Parser();
So, oder so ähnlich hat das für alle Parser ausgesehen. Das
ist ja nun weiter nichts besonderes.
Es gibt aber noch einen zweiten Weg einen Parser zu instantiieren. Dieser
Weg führt (ich weiß, daß das eine Überraschung nach
dieser Überschrift ist) über die Klasse ParserFactory.
Diese Klasse bietet eine einfache und bequeme Möglichkeit ein Parser-Objekt
zu erzeugen, auch wenn innerhalb einer Anwendung verschiedene Parser benutzt
werden sollen.
Was meine ich nun damit? Nun, ich denke, daß wird spätesten
nach einem Beispiel klar. Aber zunächst möchte ich die Benutzung
dieser Klasse näher erklären.
Parser parser = ParserFactory.makeParser(parserName);
Diese Zeile erzeugt einen Parser, soviel dürfte klar sein. Aber
welchen Parser? Das hängt von dem String ab, den ihr makeParser
übergebt. Zum Beispiel wird mit "com.ibm.xml.parsers.SAXParser"
ein SAX-Parser von IBM erzeugt, und mit "com.sun.xml.parser.Parser"
das entsprechende Pendant von Sun. Zurückgegeben wird aber in jedem
Fall ein Objekt vom Typ org.xml.sax.Parser. Das bedeutet jetzt
aber nicht, daß ihr nicht auch DOM-Parser erzeugen könnt. Mit
"com.ibm.xml.parsers.DOMParser" wäre das zum Beispiel
der Fall.
Kommen wir nun zum versprochenen Beispiel. Was würde sich da besser
eignen, als ein kleiner Benchmark? Um die Übersichtlichkeit zu wahren,
habe ich nur die verschiedenen SAX-Parser verglichen, also jeweils den
validierenden und den nichvalidierenden SAX-Parser von Sun und IBM. Beim
Aufruf des Programms, wird ein Dateiname mit angegeben, das zu parsende
XML-Dokument.
Dieses Dokument wird nun mit jedem Parser 10 mal geparst. Das Dokument
sollte auf jeden Fall valide sein, und ausreichen groß, um nicht
in ein paar Millisekunden durchgeparst werden zu können. Die Parser
werden der Reihe nach aufgerufen, und das 10 mal, anstatt einen Parser
10 mal parsen zu lassen, und das bei jedem Parser. Das hat den Vorteil,
daß sich eventuelle Änderungen der Voraussetzungen (Starten
von Programmen auf dem Computer etc.) weniger stark verzerrend auswirken.
Ausgegeben wird dann für jeden Parser ein Durchschnittswert der
benötigten Zeit, sowie das Minimum und das Maximum.
import org.xml.sax.*;
import org.xml.sax.helpers.ParserFactory;
import java.util.Date;
public class TimeTest
{
public static void main(String[] args)
{
TimeTest time = new TimeTest();
time.test(args[0]);
}
private long parseIt(String file, String parserName)
{
long time = 0;
try
{
long start = (new Date()).getTime();
Parser parser = ParserFactory.makeParser(parserName);
if (parserName.startsWith("com.sun"))
parser.parse(com.sun.xml.parser.Resolver.createInputSource
(new java.io.File(file)));
else
parser.parse(file);
time = (new Date()).getTime() - start;
}
catch (Exception e)
{
System.err.println("Fehler: ");
System.err.println(e);
}
return time;
}
public void test(String file)
{
long[] ibmSAX = new long[] {Long.MAX_VALUE, Long.MIN_VALUE, 0};
long[] ibmSAXval = new long[] {Long.MAX_VALUE, Long.MIN_VALUE, 0};
long[] sunSAX = new long[] {Long.MAX_VALUE, Long.MIN_VALUE, 0};
long[] sunSAXval = new long[] {Long.MAX_VALUE, Long.MIN_VALUE, 0};
int anzahl = 10;
long zeit = 0;
for (int i = 0; i < anzahl; i++)
{
zeit = parseIt(file, "com.ibm.xml.parsers.SAXParser");
if (zeit < ibmSAX[0])
ibmSAX[0] = zeit;
if (zeit > ibmSAX[1])
ibmSAX[1] = zeit;
ibmSAX[2] += (zeit / anzahl);
zeit = parseIt(file, "com.ibm.xml.parsers.ValidatingSAXParser");
if (zeit < ibmSAXval[0])
ibmSAXval[0] = zeit;
if (zeit > ibmSAXval[1])
ibmSAXval[1] = zeit;
ibmSAXval[2] += (zeit / anzahl);
zeit = parseIt(file, "com.sun.xml.parser.Parser");
if (zeit < sunSAX[0])
sunSAX[0] = zeit;
if (zeit > sunSAX[1])
sunSAX[1] = zeit;
sunSAX[2] += (zeit / anzahl);
zeit = parseIt(file, "com.sun.xml.parser.ValidatingParser");
if (zeit < sunSAXval[0])
sunSAXval[0] = zeit;
if (zeit > sunSAXval[1])
sunSAXval[1] = zeit;
sunSAXval[2] += (zeit / anzahl);
System.out.println(i + 1 + ". Durchlauf geschafft…");
}
System.out.println("IBM SAX : av: " + ibmSAX[2]
+ "ttmin: " + ibmSAX[0] + "ttmax: " + ibmSAX[1]);
System.out.println("Sun SAX : av: " + sunSAX[2]
+ "ttmin: " + sunSAX[0] + "ttmax: " + sunSAX[1]);
System.out.println("validating IBM SAX: av: " + ibmSAXval[2]
+ "ttmin: 2 + ibmSAXval[0] + "ttmax: " + ibmSAXval[1]);
System.out.println("validating Sun SAX: av: " + sunSAXval[2]
+ "ttmin: " + sunSAXval[0] + "ttmax: " + sunSAXval[1]);
}
}
Eine Sache, die vielleicht nicht auf den ersten Blick klar wird, möchte
ich noch schnell erklären. Zu jedem Parser gehört ein Feld,
in dem die Zeiten gespeichert werden. Auf dem ersten Index wird das Minimum
gespeichert, auf dem zweiten Index das Maximum, und auf dem dritten der
Durchschnitt.
Das Ergebnis dieses kleinen Benchmarks gebe ich hier natürlich nicht
bekannt, ich will ja, daß ihr das auch mal selbst ausprobiert! 😉