Java Getriebe

Java und NetBeans

Fehler beim Parsen von XSLT Stylesheets abfangen

Die meisten XSLT Umwandlungen habe ich bisher im Browser erledigt. XML im Browser laden und als HTML darstellen lassen. Das begrenzt mich zwar größtenteils auf XSLT 1.0, aber ich kann mir diverse Ergebnisse, die hier erzeugt werden wunderbar im Browser anschauen und dank SVG sogar mit hübschen bunten Bildern.

An verschiedenen Stellen lasse ich allerdings aus diesen XML Daten auch mal statische HTML Seiten erzeugen. Dank der in Java eingebauten XML Bibliotheken Xalan und Xerces ist die Transformation recht simpel.

1
2
3
4
5
6
7
8
9
10
11
12
13
// prepare Input and Output
Result htmlResult = new StreamResult(
    Files.newBufferedWriter(outfile, StandardCharsets.UTF_8));
SAXSource source = new SAXSource(
    new InputSource(Files.newInputStream(infile)));

// read XSLT
Transformer transformer =
    TransformerFactory.newInstance().newTransformer(
        new StreamSource(DEFAULT_XSLT));

// do transformation
transformer.transform(source, htmlResult);

Das Ganze funktioniert wunderbar, auch dank der Tatsache, dass ich das Skript vorher im Browser testen kann und dort schon direkt Fehler angezeigt werden.

Zu einem Problem kommt es immer dann, wenn der Browser einen Fehler im XSLT Skript nicht erkennt oder ihn einfach stillschweigend übergeht, weil er „weiß“, wie es richtig gemeint war. Der Xalan Transformator ist leider nicht so großzügig. Hier werden mehr Probleme angezeigt, die nicht dem Standard entsprechen.

Allerdings haben die Entwickler dieser Bibliothek auch einen gewaltigen Fehler begangen und leiten die auftretenden Exceptions nicht korrekt an die aufrufenden Methoden weiter. Viel schlimmer noch, an diversen Stellen wird nach einem catch(Exception e) einfach nur ein e.printStackTrace() aufgerufen. Keine Chance für den Anwender der Bibliothek hier sinnvoll auf die Exception zu reagieren. An manchen Stellen wird zwar einfach so der StackTrace ausgegeben, aber immerhin die entsprechende Exception in einer anderen „Bibliohteks-Exception“ gekapselt. Aber wie gesagt, nicht überall und nicht konsequent.

Das ganze kann dazu führen, dass die HTML Ausgabe im günstigsten Fall nur unvollständig ist, aber häufig auch total zerschossen wird, da der Transformer scheinbar korrekt erstellt wird.

Die einzige Möglichkeit, die ich bisher gefunden habe, ist den Datenstrom von „Standard-Error“ abzufangen. Hier kommt uns zugute, dass printStackTrace alle Ausgaben auf „Standard-Error“ ausgibt. Bevor der Transformer erstellt wird leite ich den Datenstrom in einen eigenen ByteArrayOutputStream um, um diesen nach dem Parsen der XSLT Datei auszuwerten. Ist kein Fehler passiert beim Einlesen, so sollte der OutputStream leer sein, ansonsten kann ich jetzt eine eigene Exception werfen, die dann wieder an „geeigneter“ Stelle abgefangen werden kann.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// prepare StdError redirection
PrintStream old = System.err;
ByteArrayOutputStream redirect = new ByteArrayOutputStream();
System.setErr(new PrintStream(redirect));
// read XSLT
Transformer transformer =
    TransformerFactory.newInstance().newTransformer(
        new StreamSource(DEFAULT_XSLT));
// reset redirection
System.setErr(old);
// reset redirection
if(redirect.size() > 0) {
  throw new IOException(
          "Error while reading StyleSheet.\n" +
          "Caused by: " + redirect.toString());
}

Keine schöne Sache, aber immerhin bricht die Tranformation „korrekt“ ab und erzeugt keine fehlerhaften HTML Ausgaben. Es wäre wünschenswert, wenn alle e.printStackTrace() aus den Bibliotheken verschwinden würden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.