Example 1 - Hello OpenEXI

This first "bare bones" example lets you encode an XML file as EXI, then decode the EXI file to restore the XML information.

What Example 1 Demonstrates

OpenEXI can optimize and restore any XML-compliant document. If there is no schema available, OpenEXI can build the grammar model by learning and inferring one as it processes a document. Using the default transformation options, you can encode an XML file by providing only an input stream and an output stream.

You can reverse the process to restore the content (e.g. element tags, values, and attributes) of the XML file. By default, non-essential information such as comments, processing instructions, and non-significant whitespaces are not encoded. Example 3 will demonstrate how you can set options to retain these types of information, if your solution requires that they be preserved.

 
 

How to Use Example 1

To install and run Example 1:

  1. Download and expand OpenEXI_Example1.zip. This zip archive contains the compiled example application classes and Java source code. Expanding the file creates a directory of name "OpenEXI_Example1".
  2. From command line, move into the "OpenEXI_Example1" directory.
  3. Enter the command:
    java -jar OpenEXI_Example1.jar

To encode an XML file to EXI:

  1. Click Browse... to select an XML file to encode. The selected file name appears in the Source File field. A suggested name is displayed in the Destination File field, but you can edit the location or file name according to your needs.
  2. Click Encode.

To decode an EXI file to XML:

  1. Click Browse... to select an EXI file to decode. The selected file name appears in the Source File field. A suggested name is displayed in the Destination File field, but you can edit the location or file name according to your needs.
  2. Click Decode.

Code Highlights

Complete, commented source code is included in the src directory in OpenEXI_Example1.zip. This section highlights the important updates in each iteration as the examples build on one another.

EncodeEXI

This example uses default encoding behavior without a schema. The only arguments needed are the names of the source and destination files. The method uses those names to create file input and output streams.

    public void encodeEXI(String sourceFile, String destinationFile) 
        throws FileNotFoundException, IOException, ClassNotFoundException, 
               TransmogrifierException, EXIOptionsException {

        FileInputStream in = null;
        FileOutputStream out = null;

The Grammar Cache stores options used during the transformation of the XML file to EXI. The options can be expressed as a short integer value. STRICT_OPTIONS(1) uses a predefined set of options in combination with a schema to generate the smallest possible output stream. DEFAULT_OPTIONS(2) can be used when no schema is available: the schema is inferred from the structure of the XML code and constructed in real time as the file is converted. Values greater than 2 set additional options, which are discussed in Example 3.

        GrammarCache grammarCache;
        try {

Encoding always follows these steps.

Instantiate a Transmogrifier. The Transmogrifier is the class that actualy performs the conversion from XML to EXI.

            Transmogrifier transmogrifier = new Transmogrifier();

Initialize the input and output streams. In this case, they happen to be file streams, but you can use any type of stream that meets the requirements of your application.

            in = new FileInputStream(sourceFile);
            out = new FileOutputStream(destinationFile);

Set the schema and EXI options in the Grammar Cache. This example uses default options and no schema.

            grammarCache = new GrammarCache((EXISchema)null, 
                GrammarOptions.DEFAULT_OPTIONS);

Pass the Grammar Cache information to the Transmogrifier using the setGrammarCache method.

            transmogrifier.setGrammarCache(grammarCache);

Set the output stream.

            transmogrifier.setOutputStream(out);

Encode the input stream.

            transmogrifier.encode(new InputSource(in));

The Transmogrifier is a black-box utility. When you work with OpenEXI, your job is to set options that optimize the resulting EXI document for your needs. OpenEXI does the heavy lifting of compiling the information for you.

When you compile an EXI file without a schema, the Transmogrifier does its best to reduce the file size without data loss. While it might remove some non-significant whitespace, very conservative rules are used for determining what is or is not significant. Files can be further optimized when compiled and restored using a schema, as demonstrated in Example 4.

DecodeEXI

DecodeEXI reverses the process and restores the original XML content. When you use the default options, comments and non-significant whitespace are not preserved. All the significant data are preserved, but the file is not restored to its original form in this example. Example 3 demonstrates settings that enable you to keep some or all of this information intact, while still enabling OpenEXI to greatly reduce the size of the XML information.

As with EncodeEXI, the only arguments required are the name of the EXI file to be transformed, and the destination name for the XML file.

    public void decodeEXI(String sourceFile, String destinationFile) throws 
        FileNotFoundException, IOException, SAXException,
        EXIOptionsException, TransformerConfigurationException {

        FileInputStream in = null;
        FileWriter out = null;

        StringWriter stringWriter = new StringWriter();

The Grammar Cache stores schema and EXI option information. The settings must match when encoding and subsequently decoding an XML data set. This example uses the DEFAULT_OPTIONS (short integer value 2).

        GrammarCache grammarCache;
        short options = GrammarOptions.DEFAULT_OPTIONS;

The standard JAXP SAX transformer handler accepts SAX content and lexical values and converts them to XML text values.

        SAXTransformerFactory saxTransformerFactory = 
            (SAXTransformerFactory)SAXTransformerFactory.newInstance();
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        saxParserFactory.setNamespaceAware(true);
        TransformerHandler transformerHandler = 
            saxTransformerFactory.newTransformerHandler();

EXIReader infers and reconstructs the XML file structure.

            EXIReader reader = new EXIReader();

To decode the EXI source, you will roughly follow these remaining steps.

Prepare the input and output sources. The output will be human-readable text, so FileWriter is a good choice to save the results.

            File inputFile = new File(sourceFile);
            in = new FileInputStream(inputFile);
            out = new FileWriter(destinationFile);

Set the schema and EXI Options in the Grammar Cache. In this case, no schema is used, and the options are set to default values.

            grammarCache = new GrammarCache((EXISchema)null, 
                GrammarOptions.DEFAULT_OPTIONS);

Pass the Grammar Cache to the EXIReader to set the schema.

            reader.setGrammarCache(grammarCache);

Choose a destination for the results. In this example, the transformer writes the results to a StringWriter object.

            transformerHandler.setResult(new StreamResult(stringWriter));

Read the input stream into a byte array.

            byte fileContent[] = new byte[(int)inputFile.length()];
            in.read(fileContent);

Assign the transformer handler to interpret the XML content.

            reader.setContentHandler(transformerHandler);

Parse the file content.

            reader.parse(new InputSource(new ByteArrayInputStream(fileContent)));

Get the resulting string, write it to the output stream (in this case, a file), and flush the buffer contents.

            final String reconstitutedString;
            reconstitutedString = stringWriter.getBuffer().toString();
            out.write(reconstitutedString);
            out.flush();

This example demonstrated the minimal settings required to transform XML to EXI format and back again. Example 2 enhances these capabilities with options for compression that further reduce the size of compiled EXI files.


Updated August 23, 2013.
Tutorial by Dennis Dawson with Takuki Kamiya of Fujitsu Laboratories of America.