Common points useful for programming

In this chapter, we will discuss different aspects common to each process of transformation (XML to GRP, GRP to SVG, and XML to SVG) that you should be aware of when programming if you don't want to wonder for a long time why some thing happened.

1. Progress, warning, and error messages

1.1. The different kinds of message

When you transform a document, many messages may be displayed in the console :

1.1.1. Progress messages

These messages are displayed to tell you what is going on. Here are some progress messages examples :

    Applying XSL transformations to file ../XML/XML/ex1.cd

    Parsing file ../XML/XML/definitionsCD.def

    Generating GRP file ../XML/XML/ex1.cd.grp

    Creating SVG document

    Generating SVG file ../XML/XML/ex1.cd.svg
  

These messages are displayed on the standard output stream.

1.1.2. Warning messages

These messages are displayed to tell you that something wrong happened during the process of transformation. The cause of these messages do not prevent the process of transformation from carrying on. Here are some warning messages examples :

    Warning: vertical box whose id is 'vbox' contains 2 boxes (id 'tbox2' & 'tbox1') with different widths (95.0 & 109.0)

    BoxLink not added: Box whose id is 'tbox1' doesn't exist.

    Warning : a reference points to an incorrect id : 'N2f83581'
  

These messages are displayed on the error output stream.

1.1.3. Error messages

These messages are displayed to tell you that a fatal error happened during the process of transformation. The cause of these messages prevent the process of transformation from carrying on. Here is some error message example :

    file:///D:/editor/XML/XML/CDtoGRP.xsl; Line 243; Column 17
    XSL Error: Could not parse CDtoGRP.xsl document!
    XSL Error: SAX Exception
    Exception in thread "main" org.apache.xalan.xslt.XSLProcessorException: The end-tag for element type "xsl:stylesheet" must end with a '>' delimiter.
            at org.apache.xalan.xslt.XSLTEngineImpl.error(XSLTEngineImpl.java:1753)
            at org.apache.xalan.xslt.XSLTEngineImpl.processStylesheet(XSLTEngineImpl.java:813)
            at org.apache.xalan.xslt.XSLTEngineImpl.process(XSLTEngineImpl.java:647)
            at fr.loria.taxi.transformer.Transformer.createDocumentGRPFromXSL(Transformer.java:118)
            at fr.loria.taxi.transformer.Transformer.createDocumentGRPFromXSL(Transformer.java:95)
            at fr.loria.taxi.transformer.TransformerXMLToGRP.process(TransformerXMLToGRP.java:17)
            at fr.loria.taxi.transformer.TransformerXMLToGRP.main(TransformerXMLToGRP.java:34)
  

These messages, thrown by the XML parser and serializer, are displayed on the error output stream.

1.2. Redirecting the messages

If you don't want these messages to appear on the console, the only thing you have to do is to redirect the standard output stream and/or the error output stream. To do so, just use the Java methods System.setOut(PrintStream out) and System.setErr(PrintStream err). All you have to provide as parameter for these methods is an object that inherits java.io.PrintStream.

Note : this is exactly what is done with TAXI. Streams are redirected to write to a javax.swing.text.StyledDocument. The object passed to methods System.setOut(PrintStream out) and System.setErr(PrintStream err) is an editor.io.DocumentPrintStream.

2. Stop after parsing error

The default behavior of the XML parser used by the process of transformation is to stop the application as soon as a parsing error occurs.

2.1. Example : default behavior

2.1.1. Code

Save the following code under editor/test/ParsingErrorTest.java :

    import fr.loria.taxi.transformer.TransformerXMLToSVG;
    import fr.loria.taxi.transformer.util.Parameters;
    import fr.loria.taxi.transformer.util.XMLToSVGParameters;


    public class ParsingErrorTest {
      /**
       * This method prepares the parameters needed by the process of transformation. If any
       * error happens, we display an error message and leave the application.
       *
       * @return The list of parameters as an XMLToSVGParameters object.
       */
      public static XMLToSVGParameters getParameters() {
        XMLToSVGParameters parameters = null;

        try {
          // The array containing the parameters
          String[] args = new String[10];

          // GRP document to transform
          args[0] = Parameters.PARAMETER_SIGN + Parameters.XML_IN;  // -xml_in
          args[1] = "foo.xml";

          // XSLT stylesheet to use
          args[2] = Parameters.PARAMETER_SIGN + Parameters.XSL;     // -xsl
          args[3] = "../XML/Generic/genericHorizontal.xsl";

          // GRP DTD
          args[4] = Parameters.PARAMETER_SIGN + Parameters.GRP_DTD; // -grp_dtd
          args[5] = "../grp.dtd";

          // Definitions document to use
          args[6] = Parameters.PARAMETER_SIGN + Parameters.DEFS;    // -defs
          args[7] = "../XML/Generic/generic.def";

          // SVG DTD
          args[8] = Parameters.PARAMETER_SIGN + Parameters.SVG_DTD; // -svg_dtd
          args[9] = "../svg.dtd";

          parameters = new XMLToSVGParameters(args);
        } catch (Exception e) {
          // We report any error that might happen with the parameters and leave the application
          System.err.println("-- Something wrong with the parameters --");
          System.err.println(e.getMessage());
          System.exit(1);
        }

        return parameters;
      }


      /**
       * Main method.
       */
      public static void main(String[] args) {
        try {
          // Prepares the list of parameters
          XMLToSVGParameters parameters = getParameters();

          // Creates the Transformer and calls the process() method that operates the process
          // of transformation
          TransformerXMLToSVG transformer = new TransformerXMLToSVG(parameters);
          fr.loria.taxi.transformer.process();

          // We force the exit of the application because an instance of an AWT object has been
          // created during the process of transformation, thus, the system doesn't relinquish
          // control as it assumes that some GUI is running.
          System.exit(0);
        } catch (Exception e) {
          // We report any error that might happen during the process of transformation
          System.err.println("-- Something wrong happened during the transformation --");
          System.err.println(e.getMessage());
        }

        System.out.println("Finished");
      }
    }
  

Open a console, go to directory editor/test and compile ParsingErrorTest.java with the following command :

    javac -classpath ../lib/taxi.jar ParsingErrorTest.java
  

Note : classes and sources are usually not saved in the same directory. This is not the case with the previous command line used for compiling. I chose to do that to focus only on the process of transformation and use the minimum number of necessary options on the command line.

2.1.2. Explaining the code

Most of the code is taken back from examples of the previous chapter. If you didn't read it, please refer to it for explanations about most of lines of code of the example above.

In method getParameters(), we specify that we want to transform the XML document foo.xml that does not exist.

In method main(String[] args), we apply transformation, report any Exception that might occur during the process of transformation, and then write the message Finished. This is at least what we want to happen.

2.1.3. Running the code

Run the example with this command (depending on the OS you run it, you will not use the same classpath separator) :

    java -classpath ../lib/taxi.jar;. ParsingErrorTest (under Windows)
    java -classpath ../lib/taxi.jar:. ParsingErrorTest (under other OS)
  

You get the following output :

    Applying XSL transformations to file foo.xml
    [Fatal Error] :0:0: File "file:///D:/editor/test/foo.xml" not found.
  

The XML parser didn't find the document foo.xml. Of course, this document doesn't exist. The error has been reported and the application has been stopped ! Thus, we have never executed the code that handles Exception that might happen during the process of transformation, and so never the code that displays Finished. Why ? Because, by default, the XML parser used by the process of transformation stops the application if a parsing error occurs, like transforming an XML document that does not exist.

2.2. Example 2 : handling parsing errors

2.2.1. Code

Modify editor/test/ParsingErrorTest.java (changes are in bold) :

    import fr.loria.taxi.transformer.TransformerXMLToSVG;
    import fr.loria.taxi.transformer.util.Parameters;
    import fr.loria.taxi.transformer.util.XMLToSVGParameters;


    public class ParsingErrorTest {
      /**
       * This method prepares the parameters needed by the process of transformation. If any
       * error happens, we display an error message and leave the application.
       *
       * @return The list of parameters as an XMLToSVGParameters object.
       */
      public static XMLToSVGParameters getParameters() {
        XMLToSVGParameters parameters = null;

        try {
          // The array containing the parameters
          String[] args = new String[10];

          // GRP document to transform
          args[0] = Parameters.PARAMETER_SIGN + Parameters.XML_IN;  // -xml_in
          args[1] = "foo.xml";

          // XSLT stylesheet to use
          args[2] = Parameters.PARAMETER_SIGN + Parameters.XSL;     // -xsl
          args[3] = "../XML/Generic/genericHorizontal.xsl";

          // GRP DTD
          args[4] = Parameters.PARAMETER_SIGN + Parameters.GRP_DTD; // -grp_dtd
          args[5] = "../grp.dtd";

          // Definitions document to use
          args[6] = Parameters.PARAMETER_SIGN + Parameters.DEFS;    // -defs
          args[7] = "../XML/Generic/generic.def";

          // SVG DTD
          args[8] = Parameters.PARAMETER_SIGN + Parameters.SVG_DTD; // -svg_dtd
          args[9] = "../svg.dtd";

          parameters = new XMLToSVGParameters(args);
        } catch (Exception e) {
          // We report any error that might happen with the parameters and leave the application
          System.err.println("-- Something wrong with the parameters --");
          System.err.println(e.getMessage());
          System.exit(1);
        }

        return parameters;
      }


      /**
       * Main method.
       */
      public static void main(String[] args) {
        try {
          // Prepares the list of parameters
          XMLToSVGParameters parameters = getParameters();

          // Creates the Transformer and calls the process() method that operates the process
          // of transformation
          TransformerXMLToSVG transformer = new TransformerXMLToSVG(parameters);
          transformer.setStopAfterParsingError(false);
          fr.loria.taxi.transformer.process();

          // We force the exit of the application because an instance of an AWT object has been
          // created during the process of transformation, thus, the system doesn't relinquish
          // control as it assumes that some GUI is running.
          System.exit(0);
        } catch (Exception e) {
          // We report any error that might happen during the process of transformation
          System.err.println("-- Something wrong happened during the transformation --");
          System.err.println(e.getMessage());
        }

        System.out.println("Finished");
      }
    }
  

Open a console, go to directory editor/test and compile ParsingErrorTest.java with the following command :

    javac -classpath ../lib/taxi.jar ParsingErrorTest.java
  

2.2.2. Explaining the code

We just add the line transformer.setStopAfterParsingError(false); to ask the Transformer to tell the XML parser not to stop the application if a parsing error occurs during the process of transformation.

2.2.3. Running the code

Run the example with this command (depending on the OS you run it, you will not use the same classpath separator) :

    java -classpath ../lib/taxi.jar;. ParsingErrorTest (under Windows)
    java -classpath ../lib/taxi.jar:. ParsingErrorTest (under other OS)
  

You get the following output :

    Applying XSL transformations to file foo.xml
    [Fatal Error] :0:0: File "file:///D:/editor/test/foo.xml" not found.
    -- Something wrong happened during the transformation --
    Stopping after fatal error: File "file:///D:/editor/test/foo.xml" not found.
    Finished
  

As in the previous example, the XML parser didn't find the document foo.xml. The error has been reported, but this time, the application has not been stopped ! Thus, we have executed the code that handles Exception that might happen during the process of transformation, and so the code that displays Finished.